commit 6d835bc44cb3b5f5e9a14965be1d750cd1bd9528 Author: Alex Date: Mon Sep 14 16:00:05 2026 +0300 Initial import: ESP32 ZiFi32 firmware with SMB2/3 VFS bridge Based on https://github.com/tslabs/zx-evo/tree/master/pentevo/esp32, extended with an SMB2/3 server that exposes the ZX Evolution's real SD card as a network share (browse/download/upload/delete), plus assorted stability and protocol-correctness fixes in vfs_bridge.cpp and the vendored libsmb2 - see firmware/README.md for the detailed changelog and current status. Also adds: - firmware/: ready-to-flash compiled binaries + flashing instructions - hardware/: adapter board connection diagram, PCB photo, and Gerber files - src/third_party/libsmb2: vendored from sahlberg/libsmb2 (LGPL-2.1, see its own COPYING/LICENCE files), de-submoduled to a plain snapshot with local patches applied directly Co-Authored-By: Claude Sonnet 5 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f675394 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# ESP-IDF build output (regenerate with `idf.py build`) +build/ +.test-build/ +managed_components/ +sdkconfig.old + +# Editor/IDE cruft +.vscode/ +.idea/ +*.user + +# OS cruft +Thumbs.db +.DS_Store diff --git a/doc/cli.patch b/doc/cli.patch new file mode 100644 index 0000000..fcd3589 --- /dev/null +++ b/doc/cli.patch @@ -0,0 +1,31 @@ +diff --git a/components/console/linenoise/linenoise.c b/components/console/linenoise/linenoise.c +index 64fcf23a12..637e5cf8c0 100644 +--- a/components/console/linenoise/linenoise.c ++++ b/components/console/linenoise/linenoise.c +@@ -930,14 +930,18 @@ static int linenoiseEdit(char *buf, size_t buflen, const char *prompt) + return l.len; + } + +- if ( (getMillis() - t1) < LINENOISE_PASTE_KEY_DELAY && c != ENTER) { +- /* Pasting data, insert characters without formatting. +- * This can only be performed when the cursor is at the end of the +- * line. */ +- if (linenoiseInsertPastedChar(&l,c)) { +- return -1; +- } +- continue; ++ unsigned char uc = (unsigned char)c; ++ ++ if ((getMillis() - t1) < LINENOISE_PASTE_KEY_DELAY && ++ uc >= 0x20 && ++ uc != BACKSPACE && ++ c != ENTER) { ++ /* Fast path only for printable pasted bytes. ++ * Control keys must go through normal key handling. */ ++ if (linenoiseInsertPastedChar(&l, c)) { ++ return -1; ++ } ++ continue; + } + + /* Only autocomplete when the callback is set. It returns < 0 when diff --git a/doc/esp32-spi-wifi.md b/doc/esp32-spi-wifi.md new file mode 100644 index 0000000..5ce9e8f --- /dev/null +++ b/doc/esp32-spi-wifi.md @@ -0,0 +1,557 @@ +# ESP32 SPI WiFi + +## Description + +The module is based on ESP32-S2 and provides high-speed WiFi access via SPI bus. + +The key-features are: + +- 4-wire 1-bit SPI interface, Slave Mode. +- Up to 14Mbit/s data transfer speed. +- DMA capable transfers. + +## Programming + +### Communication protocol + +The SPI Slave communication protocol provides a few types of transactions: ***READ_REGS***, ***WRITE_REGS***, ***READ_DATA***, ***WRITE_DATA***. + + + +#### READ_REGS + +This type of transaction allows reading a number of bytes from the register memory. It can be used to read a register value or a status. + +##### Scenario + +| Step | Action | +| ---- | ---------------------------------------- | +| 1 | Assert SPI_CS. | +| 2 | Write SPI_DATA with **0x02**. | +| 3 | Write SPI_DATA with register number. | +| 4 | Write SPI_DATA with **two** dummy bytes. | +| 5 | Read one or more bytes from SPI_DATA. | +| 6 | De-assert SPI_CS. | + + + +##### Read 1-byte register in C + +```c +__sfr __at 0x57 SPI_DATA; +__sfr __at 0x77 SPI_CTRL; +#define SPI_ESP_CS_ON 0x0B +#define SPI_ESP_CS_OFF 0x03 + +u8 esp_rd_reg(u8 reg_num) +{ + SPI_CTRL = SPI_ESP_CS_ON; + SPI_DATA = 0x02; + SPI_DATA = reg_num; + SPI_DATA; // dummy + SPI_DATA; + u8 rc = SPI_DATA; + SPI_CTRL = SPI_ESP_CS_OFF; + + return rc; +} +``` + + + +#### WRITE_REGS + +This type of transaction allows writing a number of bytes in the register memory. Not used except for command issuing. +Each WRITE_REGS transaction triggers the command execution. Thus, all arguments **must** be transmitted in the same transaction along with the command. + +##### Scenario + +| Step | Action | +| ---- | --------------------------------------- | +| 1 | Assert SPI_CS. | +| 2 | Write SPI_DATA with **0x01**. | +| 3 | Write SPI_DATA with register number. | +| 4 | Write SPI_DATA with **one** dummy byte. | +| 5 | Write SPI_DATA with one or more bytes. | +| 6 | De-assert SPI_CS. | + + + +##### Write 1-byte register in C + +The following code snippet is just an example not to use. Please refer to 'Write command' snippet for more practical case. + +```c +__sfr __at 0x57 SPI_DATA; +__sfr __at 0x77 SPI_CTRL; +#define SPI_ESP_CS_ON 0x0B +#define SPI_ESP_CS_OFF 0x03 + +void esp_rd_reg(u8 reg_num, u8 reg_value) +{ + SPI_CTRL = SPI_ESP_CS_ON; + SPI_DATA = 0x01; + SPI_DATA = reg_num; + SPI_DATA; // dummy + SPI_DATA = reg_value; + SPI_CTRL = SPI_ESP_CS_OFF; +} +``` + + + +#### WRITE COMMAND + +This is a most used WRITE_REGS case, which triggers a command execution. + +##### Write command in C + +The following code snippet is just an example not to use. Please refer to 'Write command' snippet for more practical case. + +```c +__sfr __at 0x57 SPI_DATA; +__sfr __at 0x77 SPI_CTRL; +#define SPI_ESP_CS_ON 0x0B +#define SPI_ESP_CS_OFF 0x03 + +void esp_cmd(u8 cmd) +{ + SPI_CTRL = SPI_ESP_CS_ON; + SPI_DATA = 0x01; + SPI_DATA = 0x00; // ESP_REG_COMMAND + SPI_DATA; // dummy + SPI_DATA = cmd; // Command + SPI_DATA = 0x00; // Reset status + SPI_CTRL = SPI_ESP_CS_OFF; +} +``` + + + +#### READ_DATA + +The transaction must only be launched when STATUS register contains DATA_S2M status. + +The number of bytes to transfer must be read from xx_SIZE register before the transaction. + + + +##### Scenario + +| Step | Action | +| ---- | ------------------------------------------ | +| 1 | Assert SPI_CS. | +| 2 | Write SPI_DATA with **0x04**. | +| 4 | Write SPI_DATA with **three** dummy bytes. | +| 5 | Read one or more bytes from SPI_DATA. | +| 6 | De-assert SPI_CS. | +| 7 | Execute `esp_cmd(DATA_END);` | + + + +##### Read a data array in C + +```c +__sfr __at 0x57 SPI_DATA; +__sfr __at 0x77 SPI_CTRL; +#define SPI_ESP_CS_ON 0x0B +#define SPI_ESP_CS_OFF 0x03 + +void esp_recv(u8 *addr, u16 num) +{ + SPI_CTRL = SPI_ESP_CS_ON; + SPI_DATA = 0x04; + SPI_DATA; // dummy read means write with 0xFF + SPI_DATA; + SPI_DATA; + while (num--) *addr++ = SPI_DATA; + SPI_CTRL = SPI_ESP_CS_OFF; + esp_cmd(ESP_CMD_DATA_END); +} +``` + + + +#### WRITE_DATA + +The transaction must only be launched when STATUS register contains DATA_M2S status. + +The number of bytes to transfer must be read or written from/to xx_SIZE register before the transaction. + +**ATTENTION!** +When writing data, all transactions **must** be truncated to 4 bytes. If we need to write 1 byte only, we must write 4 bytes and so on. + +*To do: add code example.* + + + +### Registers + +All registers are read/writeable from both SPI Master via SPI and Slave firmware. At a low level, they're a shared memory cells inside ESP32 Slave. The total number of registers is 64. + +Common registers are COMMAND and STATUS. Registers with addresses 2-63 are used by the ESP32 firmware for different functions depending on a command. + + + +#### Register summary + +| Name | Register address, HEX | Size | Description | +| ---------- | ------------ | ----- | ------------------------------------------------------------ | +| COMMAND | 00 | 1 | Command. Set by Master. | +| STATUS | 01 | 1 | Status of device. Set by Slave while the command is being executed or after its execution. Must be zeroed by Master in the same transaction as the command issued, to ensure the correct synchronization. | +| PARAM/RESP | 02 | 0..61 | If written, **must** be sent in the same transaction as the command issued.
See parameter/response list for individual commands. | + + + +#### STATUS register + +| Name | Code, HEX | Description | +| -------- | --------- | ------------------------------------------------------------ | +| IDLE | 00 | No status. Must be set by Master along every command issued. | +| BUSY | 01 | Device is busy executing a command. | +| READY | 02 | Device has completed command execution and is ready for a new command. | +| ERROR | 03 | Error happened. Use GET_ERROR command to get the error code. | +| DATA_M2S | 04 | Device is ready to receive data from host. | +| DATA_S2M | 05 | Device is ready to send data to host. | + + + +#### ERROR register + +If a command has been completed with an error, the register 02 automatically indicates error code. + +| Name | Register address, HEX | Size | Description | +| ----- | ------------ | ---- | ----------- | +| ERROR | 02 | 1 | Error. | + + + +The following table contains error codes. + +| Name | Code, HEX | Description | +| --------------- | --------- | -------------------------------------------- | +| NONE | 00 | No error. | +| WRONG_PARAMETER | 01 | Wrong parameter. | +| INVALID_COMMAND | 02 | Invalid command. | +| WRONG_STATE | 03 | Command cannot be executed in current state. | +| AP_NOT_CONN | 10 | Cannot connect AP. | +| RESET | FE | Is set when reset happened. | + + + +### Commands + +#### Command summary + +| Name | Code, HEX | Description | +| ---------------- | --------- | ------------------------------------------------------------ | +| NOP | 00 | No operation. Issuing this command has no effect. | +| GET_ERROR | | Get extended error info. | +| GET_INFO | 02 | Get device info string. | +| GET_CHIP_INFO | 03 | Get chip info. | +| GET_CAPS | | Get device capabilities. | +| GET_HEAP | | Get heap size. | +| GET_NET_CAPS | | Get network capabilities. | +| GET_NETSTATE | 11 | Get network connection state. | +| WSCAN | 12 | Scan Wi-Fi APs. | +| SET_AP_NAME | 13 | Set Wi-Fi AP name. | +| SET_AP_PWD | 14 | Set Wi-Fi AP password. | +| GET_AP_NAME | 15 | Get Wi-Fi AP name. | +| AP_CONNECT | 16 | Connect to selected AP. | +| AP_DISCONNECT | 17 | Disconnect from AP. | +| SET_AUTOCONNECT | 18 | Set AP auto-connect. | +| GET_IP | 19 | Get own Wi-Fi IP, net mask, net gateway. | +| RESOLVE_DNS | | Resolve DNS name. | +| OPEN_UDP | | | +| CLOSE_UDP | | | +| STATUS_UDP | | | +| SEND_DATAGR | | | +| RECV_DATAGR | | | +| OPEN_TCP | | | +| CLOSE_TCP | | | +| STATUS_TCP | | | +| SEND_TCP | | | +| RECV_TCP | | | +| | | | +| SET_WSCAN_PARAMS | | Set parameters for Wi-Fi AP scan. | +| | | | +| EXT_STATUS_TCP | | ? | +| CONF_AUTO_IP | | ? | +| CONF_IP | | ? | +| | | | +| DATA_END | D0 | End DATA transaction. (A workaround for S3 CMD8 bug). | +| BREAK | E0 | Break an operation. | +| RESET | EE | Reset device. To be issued in the case of an unpredicted behavior. The reset takes milliseconds to complete. The STATUS register after the reset must contain READY value. The EXT_STAT register must contain RESET value. | +| GET_RND | F0 | Generate random numbers array. | +| TEST2 | F1 | Generate tunnel DL for FT812. | +| TEST3 | F2 | Generate 3D model DL for FT812. | + + + +#### Miscellaneous commands + + + +##### GET_INFO + +Get device information string. The string is **not** 0-terminated. + +**In:** none. + +**Out:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| INFO_SIZE | 02 | 1 | Info string size. | + +[DATA] - Info string. + + + +##### GET_CHIP_INFO + +Get ESP module hardware parameters. + +**In:** none. + +**Out:** See table below. + +| Name | Register address, HEX | Size, bytes | Description | +| --------- | ------------ | ---- | -------------------------------- | +| CPU_TYPE | 02 | 1 | ESP chip type, hex:
02 - ESP32-S3 | +| CPU_CORES | 03 | 1 | Number of CPU cores. | +| CPU_FREQ | 04 | 2 | CPU frequency, MHz. | +| CPU_SI_REV | 06 | 1 | Silicon revision. | +| WIFI | 07 | 1 | | +| BLE | 08 | 1 | | +| FLASH_SIZE | 09 | 1 | Flash size, MB. | +| FLASH_TYPE | 0A | 1 | | +| FLASH_FREQ | 0B | 1 | | +| PSRAM_SIZE | 0C | 1 | PSRAM size, MB. | +| PSRAM_TYPE | 0D | 1 | | +| PSRAM_FREQ | 0E | 1 | | + + + +##### GET_CAPS + +Read device capabilities. + +**In:** none. + +**Out:** + +| Name | Bit | Mask, Hex | Description | +| ---- | ---- | --------- | ----------- | +| | | | | + + + +##### BREAK + +Break execution of current command. If no command is being executed, this has no effect. + +**In:** none. + +**Out:** none. + + + +#### Wi-Fi commands + +Most Wi-Fi commands require time to complete. While in progress, the STATUS register indicates BUSY state. It changes to READY upon command completion if successful, or to ERROR, if not. + + + +##### GET_NETSTATE + +Get network state. + +**In:** none. + +**Out:** Network state. See the table below. + +| Name | Register address, HEX | Size | Description | +| -------- | ------------ | ---- | -------------- | +| NETSTATE | 02 | 1 | Network state. | + + + +**NETSTATE** + +| Name | Code, HEX | Description | +| --------------- | --------- | ---------------------------------- | +| NETWORK_CLOSED | 00 | No network connection established. | +| NETWORK_OPENING | 01 | Network connection in progress. | +| NETWORK_OPEN | 02 | Network connection established. | +| NETWORK_CLOSING | 03 | Network disconnection in progress. | +| NETWORK_UNKNOWN | FF | Network state undefined. | + + + +##### WSCAN + +Scan for Wi-Fi APs. Scanned APs are sorted by RSSI, highest first. +Requires STATUS register polling to check completion. + +**In:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| AP_MAX | 02 | 1 | Max number of AP to scan. | + +**Out:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| AP_TABLE_SIZE | 02 | 2 | AP table size. | + +[DATA] - scanned AP table. See the format below. + +| Name | Size, bytes | Description | +| ------------------------------ | ------------- | ---------------------- | +| NUM_APS | 1 | Number of APs scanned. | +| AP_AUTH | 1 | AP authorization type. | +| AP_RSSI | 1 | AP RSSI, dB. | +| AP_CHAN | 1 | AP primary channel | +| AP_SSID_LEN | 1 | AP SSID length. | +| AP_SSID | | AP SSID. | +| ... repeat AP_xx for | | | + + + +**APn_AUTH** + +| Name | Value, HEX | Description | +| ------------------ | ---------- | ----------- | +| AP_AUTH_OPEN | 00 | Open | +| AUTH_WEP | 01 | | +| AUTH_WPA_PSK | 02 | | +| AUTH_WPA2_PSK | 03 | | +| AUTH_WPA_WPA2_PSK | 04 | | +| AUTH_EAP | 05 | | +| AUTH_WPA3_PSK | 06 | | +| AUTH_WPA2_WPA3_PSK | 07 | | +| AUTH_WAPI_PSK | 08 | | +| AUTH_OWE | 09 | | +| AUTH_WPA3_ENT_192 | 0A | | +| AUTH_MAX | 0B | | + + + +##### SET_AP_NAME + +Set AP name. 32 bytes max. + +**In:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| AP_NAME_LEN | 02 | 1 | AP name length. | +| AP_NAME | 03 | | AP name. | + +**Out:** none. + + + +##### SET_AP_PWD + +Set AP password. 61 bytes max. + +**In:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| AP_PWD_LEN | 02 | 1 | AP password length. | +| AP_PWD | 03 | | AP password. | + +**Out:** none. + + + +##### GET_AP_NAME + +Set AP name. 32 bytes max. + +**In:** none. + +**Out:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| AP_NAME_LEN | 02 | 1 | AP name length. | +| AP_NAME | 03 | | AP name. | + + + +##### **AP_**CONNECT + +Connect to the selected AP. +Requires STATUS register polling to check completion. + +**In:** none. + +**Out:** none. + + + +##### AP_DISCONNECT + +Disconnect AP. +Requires STATUS register polling to check completion. + +**In:** none. + +**Out:** none. + + + +##### SET_AUTOCONNECT + +Enable or disable auto-connect. +SET_AP_NAME and SET_AP_PWD must be set before this command. + +**In:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| AUTOCONNECT | 02 | 1 | Mode:
0 - disabled.
1 - enabled. | + +**Out:** none. + + + +##### GET_IP + +Get network IP addresses. + +**In:** none. + +**Out:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| IP | 02 | 4 | Last DNS resolved IP address. | +| OWN_IP | 06 | 4 | Own IP address. | +| MASK | 0A | 4 | Net mask. | +| GATE | 0E | 4 | Net gateway. | + + + +##### RESOLVE_DNS + +Resolve IP address from domain name, which length must not be longer than 255 symbols. +Requires STATUS register polling to check completion. + +**In:** + +| Name | Register address, HEX | Size | Description | +| --------- | ------------ | ---- | -------------------------------- | +| DNAME_LEN | 02 | 1 | Domain name length. | +| DNAME | 03..3F | 1..61 | Domain name. | + +If DNAME_LEN<= 61, then it is sent using registers 03-3F. If it is longer than 61 symbols, send the symbols starting from 62 using DATA transaction (currently not supported). + +**Out:** + +Same as GET_IP. diff --git a/firmware/README.md b/firmware/README.md new file mode 100644 index 0000000..3e59ede --- /dev/null +++ b/firmware/README.md @@ -0,0 +1,111 @@ +# ESP32 firmware (ZX Evolution / TS-Conf ZiFi32 module) + +Compiled firmware for the ESP32-S3-based WiFi/SPI module used by the ZX +Evolution / TS-Conf ("Pentevo") platform. + +**Base source**: this firmware is based on +[tslabs/zx-evo](https://github.com/tslabs/zx-evo/tree/master/pentevo/esp32) — +full source for this fork lives in `pentevo/esp32/src` alongside this folder; +this `firmware/` directory only holds ready-to-flash binaries. + +## Requirements + +The ZX Evolution/TS-Conf board's own core firmware must be built with +**VDAC2** and **ESP32 (ZiFi32)** peripheral support enabled - without both, +the core won't recognize the ESP32 module on the SPI bus at all (no matter +how correct this ESP32-side firmware is), and won't drive the FT8xx video +chip either. Check this before assuming a connection problem is on the +ESP32 side. + +The **RESET jumper on the IDE connector must be installed** as well - see +`../hardware/connection_diagram.webp`. + +## What's changed vs. the upstream source + +Most of the work in this fork is a **VFS bridge that exposes the ZX +Evolution's real SD card as a network share over SMB2/3**, so any Windows/ +macOS/Linux SMB client can browse, download, upload to, and delete files on +the real Wild Commander filesystem without pulling the card. This is still +**actively being worked on** — see "Status" below. + +Changes so far, roughly in the order they were made: + +- **Real filesystem wired up.** `vfs_bridge.cpp`'s SMB2 handlers + (CREATE/READ/WRITE/CLOSE/QUERY_DIRECTORY/QUERY_INFO/etc.) now talk to the + real filesystem via a small request/response bridge (`vfs_request.cpp`) + over the existing SPI link to the Z80 side, instead of the original + hardcoded demo filesystem. +- **Upload (WRITE) and delete support** for files and empty directories, + including proper `FILE_DELETE_ON_CLOSE` handling and a + `SMB2_STATUS_DIRECTORY_NOT_EMPTY` reply when a non-empty directory delete + is rejected. +- **Directory listing fixes**: `SMB2_RETURN_SINGLE_ENTRY` pagination support + (needed by `cmd.exe`'s own SMB2 client, not just Explorer), the missing + non-"ID" directory info classes, synthesized `.`/`..` entries, and a + `NextEntryOffset` encoding bug in the vendored `libsmb2` that silently + corrupted any listing past the second entry. +- **`srvsvc` share-enumeration fix**: the RPC pipe used to always report the + Phase-1 placeholder share name `"test"` regardless of what a client had + actually connected to — fixed to report the real share name. +- **Added `SMB2_FILE_FS_VOLUME_INFORMATION`** support (a bare `dir`/`net use` + needs it; Explorer doesn't ask for it, which is why this was missed at + first). +- **Stability fixes**: a NULL-pointer crash in the named-pipe RPC transceive + path, and a 0-length SPI DMA transaction that could wedge the whole SPI + channel to the Z80 side. +- **`libsmb2` (vendored, `src/third_party/libsmb2`) patches**: + - `SMB2_FSCTL_DFS_GET_REFERRALS` now answers `STATUS_OBJECT_PATH_NOT_FOUND` + instead of `STATUS_NOT_IMPLEMENTED` — the wrong status code was sending + Windows Explorer into a retry storm before it would even attempt to + connect to the share. + - `SET_INFO` parsing is now permissive for info classes this server + doesn't specifically implement (passes the raw buffer through instead of + failing to parse) — a hard parse failure here used to tear down the + *entire* TCP connection instead of just failing that one request, which + showed up as Explorer aborting mid file-copy with a generic error. + - A `close_cmd` return value of `-2` now maps to + `SMB2_STATUS_DIRECTORY_NOT_EMPTY` in the CLOSE reply instead of a generic + `STATUS_NOT_IMPLEMENTED`. +- **Auth simplified** to plain guest/anonymous sessions (`authorize_handler` + always succeeds) — an earlier attempt at forcing NTLMv2 + SMB2 signing + turned out to be unrelated to a since-fixed listing bug, so it was backed + out rather than kept as unnecessary complexity. +- Removed high-frequency per-request debug logging that was originally added + to chase the above bugs, replaced with a single per-connection summary + line. + +## Status + +The SMB2/3 server (read, browse, upload, delete) works against real Windows/ +Samba clients. **This is still in-progress work** — directory/file creation +(`MKDIR`) isn't implemented yet, overwriting an existing file with shorter +content doesn't truncate the old tail, and there's no live-update +(`change_notify`) support, so Explorer can show a stale listing for a moment +after a change until it's refreshed. See the source tree's own code comments +for the current state of any specific handler. + +## Flashing + +Target chip: **ESP32-S3**. Using `esptool.py` directly: + +```bash +esptool.py --chip esp32s3 -p COM5 -b 460800 write_flash \ + --flash-mode dio --flash-freq 80m --flash-size detect \ + 0x0 bootloader.bin \ + 0x8000 partition-table.bin \ + 0x10000 esp-spi.bin +``` + +(replace `COM5` with the actual port; `flasher_args.json` in this folder has +the same offsets in `idf.py`'s own JSON format, for reference or scripting.) + +If you're building from source instead: ESP-IDF **v6.1** (not `v6.1-rc1`) — +`idf.py build flash`. + +## Hardware + +See `../hardware/` for: +- `connection_diagram.webp` — how this module wires up to a ZX Evolution + board. +- `pcb_photo.jpg` — a photo of the adapter board. +- `gerber/` — Gerber files for the adapter PCB. diff --git a/firmware/bootloader.bin b/firmware/bootloader.bin new file mode 100644 index 0000000..960e142 Binary files /dev/null and b/firmware/bootloader.bin differ diff --git a/firmware/esp-spi.bin b/firmware/esp-spi.bin new file mode 100644 index 0000000..d6f43ac Binary files /dev/null and b/firmware/esp-spi.bin differ diff --git a/firmware/flasher_args.json b/firmware/flasher_args.json new file mode 100644 index 0000000..d8ffd2c --- /dev/null +++ b/firmware/flasher_args.json @@ -0,0 +1,24 @@ +{ + "write_flash_args" : [ "--flash-mode", "dio", + "--flash-size", "detect", + "--flash-freq", "80m" ], + "flash_settings" : { + "flash_mode": "dio", + "flash_size": "detect", + "flash_freq": "80m" + }, + "flash_files" : { + "0x0" : "bootloader/bootloader.bin", + "0x8000" : "partition_table/partition-table.bin", + "0x10000" : "esp-spi.bin" + }, + "bootloader" : { "offset" : "0x0", "file" : "bootloader/bootloader.bin", "encrypted" : "false" }, + "partition-table" : { "offset" : "0x8000", "file" : "partition_table/partition-table.bin", "encrypted" : "false" }, + "app" : { "offset" : "0x10000", "file" : "esp-spi.bin", "encrypted" : "false" }, + "extra_esptool_args" : { + "after" : "hard-reset", + "before" : "default-reset", + "stub" : true, + "chip" : "esp32s3" + } +} diff --git a/firmware/partition-table.bin b/firmware/partition-table.bin new file mode 100644 index 0000000..46bfb22 Binary files /dev/null and b/firmware/partition-table.bin differ diff --git a/hardware/connection_diagram.webp b/hardware/connection_diagram.webp new file mode 100644 index 0000000..007fd12 Binary files /dev/null and b/hardware/connection_diagram.webp differ diff --git a/hardware/gerber/Drill_PTH_Through.DRL b/hardware/gerber/Drill_PTH_Through.DRL new file mode 100644 index 0000000..c0ab774 --- /dev/null +++ b/hardware/gerber/Drill_PTH_Through.DRL @@ -0,0 +1,216 @@ +;TYPE=PLATED +;Layer: PTH_Through +;EasyEDA Pro v3.2.148, 2026-08-18 14:31:00 +;Gerber Generator version 0.3 +M48 +METRIC,LZ,0000.00000 +;Hole size 1 = 0.91440 METRIC +T01C0.91440 +;Hole size 2 = 0.96520 METRIC +T02C0.96520 +;Hole size 3 = 1.00000 METRIC +T03C1.00000 +% +G05 +G90 +T01 +X27.33397Y125.72895 +X27.33397Y123.18895 +X27.33397Y120.64895 +X27.33397Y118.10895 +X27.33397Y115.56895 +X27.33397Y113.02895 +X27.33397Y110.48895 +X27.33397Y107.94895 +X27.33397Y105.40895 +X27.33397Y102.86895 +X27.33397Y100.32895 +X27.33397Y97.78895 +X27.33397Y95.24895 +X27.33397Y92.70895 +X27.33397Y90.16895 +X27.33397Y87.62895 +X27.33397Y85.08895 +X27.33397Y82.54895 +X27.33397Y80.00895 +X27.33397Y77.46895 +X27.33397Y74.92895 +X27.33397Y72.38895 +X1.93402Y72.38895 +X1.93402Y74.92895 +X1.93402Y77.46895 +X1.93402Y80.00895 +X1.93402Y82.54895 +X1.93402Y85.08895 +X1.93402Y87.62895 +X1.93402Y90.16895 +X1.93402Y92.70895 +X1.93402Y95.24895 +X1.93402Y97.78895 +X1.93402Y100.32895 +X1.93402Y102.86895 +X1.93402Y105.40895 +X1.93402Y107.94895 +X1.93402Y110.48895 +X1.93402Y113.02895 +X1.93402Y115.56895 +X1.93402Y118.10895 +X1.93402Y120.64895 +X1.93402Y123.18895 +X1.93402Y125.72895 +X-2.765Y74.929 +X-2.765Y77.469 +X-2.765Y80.009 +X-2.765Y82.549 +X-2.765Y85.089 +X-2.765Y87.629 +X-2.765Y90.169 +X-2.765Y92.709 +X-2.765Y95.249 +X-23.085Y90.169 +X-23.085Y87.629 +X-23.085Y85.089 +X-23.085Y82.549 +X-23.085Y80.009 +X-23.085Y77.469 +X6.125Y5.46 +X3.585Y5.46 +X6.125Y8.0 +X3.585Y8.0 +X6.125Y10.54 +X3.585Y10.54 +X6.125Y13.08 +X3.585Y13.08 +X6.125Y15.62 +X3.585Y15.62 +X6.125Y18.16 +X3.585Y18.16 +X6.125Y20.7 +X3.585Y20.7 +X6.125Y23.24 +X3.585Y23.24 +X6.125Y25.78 +X3.585Y25.78 +X6.125Y28.32 +X3.585Y28.32 +X6.125Y30.86 +X3.585Y30.86 +X6.125Y33.4 +X3.585Y33.4 +X6.125Y35.94 +X3.585Y35.94 +X6.125Y38.48 +X3.585Y38.48 +X6.125Y41.02 +X3.585Y41.02 +X6.125Y43.56 +X3.585Y43.56 +X6.125Y46.1 +X3.585Y46.1 +X6.125Y48.64 +X3.585Y48.64 +X6.125Y51.18 +X3.585Y51.18 +X6.125Y53.72 +X3.585Y53.72 +X38.2941Y60.08016 +X35.7541Y60.08016 +X38.2941Y62.62016 +X35.7541Y62.62016 +X38.2941Y65.16016 +X35.7541Y65.16016 +X38.2941Y67.70016 +X35.7541Y67.70016 +X38.2941Y70.24016 +X35.7541Y70.24016 +X38.2941Y72.78016 +X35.7541Y72.78016 +X38.2941Y75.32016 +X35.7541Y75.32016 +X38.2941Y77.86016 +X35.7541Y77.86016 +X38.2941Y80.40016 +X35.7541Y80.40016 +X38.2941Y82.94016 +X35.7541Y82.94016 +X35.5Y96.19 +X32.96Y96.19 +X35.5Y98.73 +X32.96Y98.73 +X35.5Y101.27 +X32.96Y101.27 +X35.5Y103.80997 +X32.96Y103.80997 +X35.5Y106.34997 +X32.96Y106.34997 +X20.91542Y100.08008 +X20.91542Y97.54008 +X18.37542Y100.08008 +X18.37542Y97.54008 +X15.83542Y100.08008 +X15.83542Y97.54008 +X13.29542Y100.08008 +X13.29542Y97.54008 +X10.75542Y100.08008 +X10.75542Y97.54008 +X45.5Y96.19 +X42.96Y96.19 +X45.5Y98.73 +X42.96Y98.73 +X45.5Y101.27 +X42.96Y101.27 +X45.5Y103.80997 +X42.96Y103.80997 +X45.5Y106.34997 +X42.96Y106.34997 +X-23.085Y107.822 +X-20.545Y107.822 +X-18.005Y107.822 +X-15.465Y107.822 +T02 +X11.967Y35.94 +X11.967Y38.48 +T03 +X19.46Y53.72 +X22.0Y53.72 +X19.46Y51.18 +X22.0Y51.18 +X19.46Y48.64 +X22.0Y48.64 +X19.46Y46.1 +X22.0Y46.1 +X19.46Y43.56 +X22.0Y43.56 +X19.46Y41.02 +X22.0Y41.02 +X19.46Y38.48 +X22.0Y38.48 +X19.46Y35.94 +X22.0Y35.94 +X19.46Y33.4 +X22.0Y33.4 +X19.46Y30.86 +X22.0Y30.86 +X19.46Y28.32 +X22.0Y28.32 +X19.46Y25.78 +X22.0Y25.78 +X19.46Y23.24 +X22.0Y23.24 +X19.46Y20.7 +X22.0Y20.7 +X19.46Y18.16 +X22.0Y18.16 +X19.46Y15.62 +X22.0Y15.62 +X19.46Y13.08 +X22.0Y13.08 +X19.46Y10.54 +X22.0Y10.54 +X19.46Y8.0 +X22.0Y8.0 +X19.46Y5.46 +X22.0Y5.46 +X15.777Y42.10107 +X15.777Y33.40096 +M30 \ No newline at end of file diff --git a/hardware/gerber/FlyingProbeTesting.json b/hardware/gerber/FlyingProbeTesting.json new file mode 100644 index 0000000..2621a5a --- /dev/null +++ b/hardware/gerber/FlyingProbeTesting.json @@ -0,0 +1,996 @@ +{ +"lengthUnit": "mil", +"remark": [], +"components": { + "fields": ["COMPONENT_NO", "COMPONENT_NAME", "LAYER", "X_COORDINATE", "Y_COORDINATE", "ANGLE"], + "rows": [ + [1, "C65", "T", 726.1417, 2454.9606, 180], + [2, "J1", "T", 471.1417, 1464.9606, 270], + [3, "R1", "B", 228.7417, 3852.4908, 180], + [4, "R2", "B", 255.7417, 3250.4908, 0], + [5, "U1", "T", 576.1417, 3949.9606, 0], + [6, "U3", "T", -508.8583, 3349.9606, 90], + [7, "VD1", "T", 621.1417, 1486.2606, 270], + [8, "X1", "T", 816.1417, 1164.9606, 90], + [9, "X2", "T", 191.1417, 1164.9606, 90], + [10, "X3", "T", 1457.6417, 2815.3606, 270], + [11, "X4", "T", 1347.6378, 3987.0078, 90], + [12, "X5", "T", 623.4417, 3890.1606, 0], + [13, "X6", "T", 1741.3386, 3987.0078, 90], + [14, "X7", "T", -758.8583, 4244.9606, 0], + [15, "PAD1", "T", 471.1417, 1414.9606, 0], + [16, "PAD1", "T", 471.1417, 1414.9606, 0], + [17, "PAD2", "T", 471.1417, 1514.9606, 0], + [18, "PAD2", "T", 471.1417, 1514.9606, 0], + [19, "PAD3", "B", 189.3717, 3852.4908, 0], + [20, "PAD4", "B", 268.1117, 3852.4908, 0], + [21, "PAD5", "B", 295.1117, 3250.4908, 0], + [22, "PAD6", "B", 216.3717, 3250.4908, 0], + [23, "PAD7", "T", 1076.1417, 4949.9606, 0], + [24, "PAD7", "T", 1076.1417, 4949.9606, 0], + [25, "PAD8", "T", 1076.1417, 2949.9606, 0], + [26, "PAD8", "T", 1076.1417, 2949.9606, 0], + [27, "PAD9", "T", 1076.1417, 2849.9606, 0], + [28, "PAD9", "T", 1076.1417, 2849.9606, 0], + [29, "PAD10", "T", 76.1417, 2849.9606, 0], + [30, "PAD10", "T", 76.1417, 2849.9606, 0], + [31, "PAD11", "T", 76.1417, 2949.9606, 0], + [32, "PAD11", "T", 76.1417, 2949.9606, 0], + [33, "PAD12", "T", 76.1417, 3149.9606, 0], + [34, "PAD12", "T", 76.1417, 3149.9606, 0], + [35, "PAD13", "T", 76.1417, 3249.9606, 0], + [36, "PAD13", "T", 76.1417, 3249.9606, 0], + [37, "PAD14", "T", 76.1417, 3349.9606, 0], + [38, "PAD14", "T", 76.1417, 3349.9606, 0], + [39, "PAD15", "T", 76.1417, 3449.9606, 0], + [40, "PAD15", "T", 76.1417, 3449.9606, 0], + [41, "PAD16", "T", 76.1417, 3849.9606, 0], + [42, "PAD16", "T", 76.1417, 3849.9606, 0], + [43, "PAD17", "T", 76.1417, 3949.9606, 0], + [44, "PAD17", "T", 76.1417, 3949.9606, 0], + [45, "PAD18", "T", 76.1417, 4049.9606, 0], + [46, "PAD18", "T", 76.1417, 4049.9606, 0], + [47, "PAD19", "T", 76.1417, 4149.9606, 0], + [48, "PAD19", "T", 76.1417, 4149.9606, 0], + [49, "PAD20", "T", 76.1417, 4249.9606, 0], + [50, "PAD20", "T", 76.1417, 4249.9606, 0], + [51, "PAD21", "T", -108.8583, 2949.9606, 0], + [52, "PAD21", "T", -108.8583, 2949.9606, 0], + [53, "PAD22", "T", -108.8583, 3149.9606, 0], + [54, "PAD22", "T", -108.8583, 3149.9606, 0], + [55, "PAD23", "T", -108.8583, 3249.9606, 0], + [56, "PAD23", "T", -108.8583, 3249.9606, 0], + [57, "PAD24", "T", -108.8583, 3349.9606, 0], + [58, "PAD24", "T", -108.8583, 3349.9606, 0], + [59, "PAD25", "T", -108.8583, 3449.9606, 0], + [60, "PAD25", "T", -108.8583, 3449.9606, 0], + [61, "PAD26", "T", -108.8583, 3549.9606, 0], + [62, "PAD26", "T", -108.8583, 3549.9606, 0], + [63, "PAD27", "T", -108.8583, 3649.9606, 0], + [64, "PAD27", "T", -108.8583, 3649.9606, 0], + [65, "PAD28", "T", -108.8583, 3749.9606, 0], + [66, "PAD28", "T", -108.8583, 3749.9606, 0], + [67, "PAD29", "T", 766.1417, 2114.9606, 0], + [68, "PAD29", "T", 766.1417, 2114.9606, 0], + [69, "PAD30", "T", 866.1417, 2114.9606, 0], + [70, "PAD30", "T", 866.1417, 2114.9606, 0], + [71, "PAD31", "T", 766.1417, 2014.9606, 0], + [72, "PAD31", "T", 766.1417, 2014.9606, 0], + [73, "PAD32", "T", 866.1417, 2014.9606, 0], + [74, "PAD32", "T", 866.1417, 2014.9606, 0], + [75, "PAD33", "T", 766.1417, 1914.9606, 0], + [76, "PAD33", "T", 766.1417, 1914.9606, 0], + [77, "PAD34", "T", 866.1417, 1914.9606, 0], + [78, "PAD34", "T", 866.1417, 1914.9606, 0], + [79, "PAD35", "T", 866.1417, 1814.9606, 0], + [80, "PAD35", "T", 866.1417, 1814.9606, 0], + [81, "PAD36", "T", 766.1417, 1614.9606, 0], + [82, "PAD36", "T", 766.1417, 1614.9606, 0], + [83, "PAD37", "T", 866.1417, 1514.9606, 0], + [84, "PAD37", "T", 866.1417, 1514.9606, 0], + [85, "PAD38", "T", 766.1417, 1414.9606, 0], + [86, "PAD38", "T", 766.1417, 1414.9606, 0], + [87, "PAD39", "T", 866.1417, 1414.9606, 0], + [88, "PAD39", "T", 866.1417, 1414.9606, 0], + [89, "PAD40", "T", 766.1417, 1314.9606, 0], + [90, "PAD40", "T", 766.1417, 1314.9606, 0], + [91, "PAD41", "T", 866.1417, 1314.9606, 0], + [92, "PAD41", "T", 866.1417, 1314.9606, 0], + [93, "PAD42", "T", 766.1417, 1214.9606, 0], + [94, "PAD42", "T", 766.1417, 1214.9606, 0], + [95, "PAD43", "T", 766.1417, 1114.9606, 0], + [96, "PAD43", "T", 766.1417, 1114.9606, 0], + [97, "PAD44", "T", 866.1417, 1114.9606, 0], + [98, "PAD44", "T", 866.1417, 1114.9606, 0], + [99, "PAD45", "T", 766.1417, 1014.9606, 0], + [100, "PAD45", "T", 766.1417, 1014.9606, 0], + [101, "PAD46", "T", 866.1417, 1014.9606, 0], + [102, "PAD46", "T", 866.1417, 1014.9606, 0], + [103, "PAD47", "T", 766.1417, 914.9606, 0], + [104, "PAD47", "T", 766.1417, 914.9606, 0], + [105, "PAD48", "T", 866.1417, 914.9606, 0], + [106, "PAD48", "T", 866.1417, 914.9606, 0], + [107, "PAD49", "T", 766.1417, 814.9606, 0], + [108, "PAD49", "T", 766.1417, 814.9606, 0], + [109, "PAD50", "T", 866.1417, 814.9606, 0], + [110, "PAD50", "T", 866.1417, 814.9606, 0], + [111, "PAD51", "T", 766.1417, 714.9606, 0], + [112, "PAD51", "T", 766.1417, 714.9606, 0], + [113, "PAD52", "T", 866.1417, 714.9606, 0], + [114, "PAD52", "T", 866.1417, 714.9606, 0], + [115, "PAD53", "T", 766.1417, 614.9606, 0], + [116, "PAD53", "T", 766.1417, 614.9606, 0], + [117, "PAD54", "T", 866.1417, 614.9606, 0], + [118, "PAD54", "T", 866.1417, 614.9606, 0], + [119, "PAD55", "T", 766.1417, 514.9606, 0], + [120, "PAD55", "T", 766.1417, 514.9606, 0], + [121, "PAD56", "T", 866.1417, 514.9606, 0], + [122, "PAD56", "T", 866.1417, 514.9606, 0], + [123, "PAD57", "T", 766.1417, 414.9606, 0], + [124, "PAD57", "T", 766.1417, 414.9606, 0], + [125, "PAD58", "T", 866.1417, 414.9606, 0], + [126, "PAD58", "T", 866.1417, 414.9606, 0], + [127, "PAD59", "T", 766.1417, 314.9606, 0], + [128, "PAD59", "T", 766.1417, 314.9606, 0], + [129, "PAD60", "T", 866.1417, 314.9606, 0], + [130, "PAD60", "T", 866.1417, 314.9606, 0], + [131, "PAD61", "T", 766.1417, 214.9606, 0], + [132, "PAD61", "T", 766.1417, 214.9606, 0], + [133, "PAD62", "T", 866.1417, 214.9606, 0], + [134, "PAD62", "T", 866.1417, 214.9606, 0], + [135, "PAD63", "T", 241.1417, 214.9606, 0], + [136, "PAD63", "T", 241.1417, 214.9606, 0], + [137, "PAD64", "T", 241.1417, 314.9606, 0], + [138, "PAD64", "T", 241.1417, 314.9606, 0], + [139, "PAD65", "T", 141.1417, 314.9606, 0], + [140, "PAD65", "T", 141.1417, 314.9606, 0], + [141, "PAD66", "T", 241.1417, 414.9606, 0], + [142, "PAD66", "T", 241.1417, 414.9606, 0], + [143, "PAD67", "T", 141.1417, 414.9606, 0], + [144, "PAD67", "T", 141.1417, 414.9606, 0], + [145, "PAD68", "T", 241.1417, 514.9606, 0], + [146, "PAD68", "T", 241.1417, 514.9606, 0], + [147, "PAD69", "T", 141.1417, 514.9606, 0], + [148, "PAD69", "T", 141.1417, 514.9606, 0], + [149, "PAD70", "T", 241.1417, 614.9606, 0], + [150, "PAD70", "T", 241.1417, 614.9606, 0], + [151, "PAD71", "T", 141.1417, 614.9606, 0], + [152, "PAD71", "T", 141.1417, 614.9606, 0], + [153, "PAD72", "T", 241.1417, 714.9606, 0], + [154, "PAD72", "T", 241.1417, 714.9606, 0], + [155, "PAD73", "T", 141.1417, 714.9606, 0], + [156, "PAD73", "T", 141.1417, 714.9606, 0], + [157, "PAD74", "T", 241.1417, 814.9606, 0], + [158, "PAD74", "T", 241.1417, 814.9606, 0], + [159, "PAD75", "T", 141.1417, 814.9606, 0], + [160, "PAD75", "T", 141.1417, 814.9606, 0], + [161, "PAD76", "T", 241.1417, 914.9606, 0], + [162, "PAD76", "T", 241.1417, 914.9606, 0], + [163, "PAD77", "T", 141.1417, 914.9606, 0], + [164, "PAD77", "T", 141.1417, 914.9606, 0], + [165, "PAD78", "T", 241.1417, 1014.9606, 0], + [166, "PAD78", "T", 241.1417, 1014.9606, 0], + [167, "PAD79", "T", 141.1417, 1014.9606, 0], + [168, "PAD79", "T", 141.1417, 1014.9606, 0], + [169, "PAD80", "T", 241.1417, 1114.9606, 0], + [170, "PAD80", "T", 241.1417, 1114.9606, 0], + [171, "PAD81", "T", 141.1417, 1114.9606, 0], + [172, "PAD81", "T", 141.1417, 1114.9606, 0], + [173, "PAD82", "T", 141.1417, 1214.9606, 0], + [174, "PAD82", "T", 141.1417, 1214.9606, 0], + [175, "PAD83", "T", 241.1417, 1314.9606, 0], + [176, "PAD83", "T", 241.1417, 1314.9606, 0], + [177, "PAD84", "T", 141.1417, 1314.9606, 0], + [178, "PAD84", "T", 141.1417, 1314.9606, 0], + [179, "PAD85", "T", 241.1417, 1414.9606, 0], + [180, "PAD85", "T", 241.1417, 1414.9606, 0], + [181, "PAD86", "T", 141.1417, 1414.9606, 0], + [182, "PAD86", "T", 141.1417, 1414.9606, 0], + [183, "PAD87", "T", 241.1417, 1514.9606, 0], + [184, "PAD87", "T", 241.1417, 1514.9606, 0], + [185, "PAD88", "T", 141.1417, 1614.9606, 0], + [186, "PAD88", "T", 141.1417, 1614.9606, 0], + [187, "PAD89", "T", 241.1417, 1814.9606, 0], + [188, "PAD89", "T", 241.1417, 1814.9606, 0], + [189, "PAD90", "T", 241.1417, 1914.9606, 0], + [190, "PAD90", "T", 241.1417, 1914.9606, 0], + [191, "PAD91", "T", 141.1417, 1914.9606, 0], + [192, "PAD91", "T", 141.1417, 1914.9606, 0], + [193, "PAD92", "T", 241.1417, 2014.9606, 0], + [194, "PAD92", "T", 241.1417, 2014.9606, 0], + [195, "PAD93", "T", 141.1417, 2014.9606, 0], + [196, "PAD93", "T", 141.1417, 2014.9606, 0], + [197, "PAD94", "T", 241.1417, 2114.9606, 0], + [198, "PAD94", "T", 241.1417, 2114.9606, 0], + [199, "PAD95", "T", 141.1417, 2114.9606, 0], + [200, "PAD95", "T", 141.1417, 2114.9606, 0], + [201, "PAD96", "T", 1507.6417, 2365.3606, 0], + [202, "PAD96", "T", 1507.6417, 2365.3606, 0], + [203, "PAD97", "T", 1407.6417, 2365.3606, 0], + [204, "PAD97", "T", 1407.6417, 2365.3606, 0], + [205, "PAD98", "T", 1507.6417, 2465.3606, 0], + [206, "PAD98", "T", 1507.6417, 2465.3606, 0], + [207, "PAD99", "T", 1407.6417, 2465.3606, 0], + [208, "PAD99", "T", 1407.6417, 2465.3606, 0], + [209, "PAD100", "T", 1507.6417, 2565.3606, 0], + [210, "PAD100", "T", 1507.6417, 2565.3606, 0], + [211, "PAD101", "T", 1407.6417, 2565.3606, 0], + [212, "PAD101", "T", 1407.6417, 2565.3606, 0], + [213, "PAD102", "T", 1507.6417, 2665.3606, 0], + [214, "PAD102", "T", 1507.6417, 2665.3606, 0], + [215, "PAD103", "T", 1407.6417, 2665.3606, 0], + [216, "PAD103", "T", 1407.6417, 2665.3606, 0], + [217, "PAD104", "T", 1507.6417, 2765.3606, 0], + [218, "PAD104", "T", 1507.6417, 2765.3606, 0], + [219, "PAD105", "T", 1407.6417, 2765.3606, 0], + [220, "PAD105", "T", 1407.6417, 2765.3606, 0], + [221, "PAD106", "T", 1507.6417, 2865.3606, 0], + [222, "PAD106", "T", 1507.6417, 2865.3606, 0], + [223, "PAD107", "T", 1407.6417, 2865.3606, 0], + [224, "PAD107", "T", 1407.6417, 2865.3606, 0], + [225, "PAD108", "T", 1507.6417, 2965.3606, 0], + [226, "PAD108", "T", 1507.6417, 2965.3606, 0], + [227, "PAD109", "T", 1407.6417, 2965.3606, 0], + [228, "PAD109", "T", 1407.6417, 2965.3606, 0], + [229, "PAD110", "T", 1507.6417, 3065.3606, 0], + [230, "PAD110", "T", 1507.6417, 3065.3606, 0], + [231, "PAD111", "T", 1407.6417, 3065.3606, 0], + [232, "PAD111", "T", 1407.6417, 3065.3606, 0], + [233, "PAD112", "T", 1507.6417, 3165.3606, 0], + [234, "PAD112", "T", 1507.6417, 3165.3606, 0], + [235, "PAD113", "T", 1407.6417, 3165.3606, 0], + [236, "PAD113", "T", 1407.6417, 3165.3606, 0], + [237, "PAD114", "T", 1507.6417, 3265.3606, 0], + [238, "PAD114", "T", 1507.6417, 3265.3606, 0], + [239, "PAD115", "T", 1407.6417, 3265.3606, 0], + [240, "PAD115", "T", 1407.6417, 3265.3606, 0], + [241, "PAD116", "T", 1397.6378, 3787.0078, 0], + [242, "PAD116", "T", 1397.6378, 3787.0078, 0], + [243, "PAD117", "T", 1297.6378, 3787.0078, 0], + [244, "PAD117", "T", 1297.6378, 3787.0078, 0], + [245, "PAD118", "T", 1397.6378, 3887.0078, 0], + [246, "PAD118", "T", 1397.6378, 3887.0078, 0], + [247, "PAD119", "T", 1297.6378, 3887.0078, 0], + [248, "PAD119", "T", 1297.6378, 3887.0078, 0], + [249, "PAD120", "T", 1397.6378, 3987.0078, 0], + [250, "PAD120", "T", 1397.6378, 3987.0078, 0], + [251, "PAD121", "T", 1297.6378, 3987.0078, 0], + [252, "PAD121", "T", 1297.6378, 3987.0078, 0], + [253, "PAD122", "T", 1397.6378, 4087.0078, 0], + [254, "PAD122", "T", 1397.6378, 4087.0078, 0], + [255, "PAD123", "T", 1297.6378, 4087.0078, 0], + [256, "PAD123", "T", 1297.6378, 4087.0078, 0], + [257, "PAD124", "T", 1397.6378, 4187.0078, 0], + [258, "PAD124", "T", 1397.6378, 4187.0078, 0], + [259, "PAD125", "T", 823.4417, 3940.1606, 0], + [260, "PAD125", "T", 823.4417, 3940.1606, 0], + [261, "PAD126", "T", 823.4417, 3840.1606, 0], + [262, "PAD126", "T", 823.4417, 3840.1606, 0], + [263, "PAD127", "T", 523.4417, 3840.1606, 0], + [264, "PAD127", "T", 523.4417, 3840.1606, 0], + [265, "PAD128", "T", 423.4417, 3940.1606, 0], + [266, "PAD128", "T", 423.4417, 3940.1606, 0], + [267, "PAD129", "T", 1791.3386, 3787.0078, 0], + [268, "PAD129", "T", 1791.3386, 3787.0078, 0], + [269, "PAD130", "T", 1691.3386, 3787.0078, 0], + [270, "PAD130", "T", 1691.3386, 3787.0078, 0], + [271, "PAD131", "T", 1791.3386, 3887.0078, 0], + [272, "PAD131", "T", 1791.3386, 3887.0078, 0], + [273, "PAD132", "T", 1691.3386, 3887.0078, 0], + [274, "PAD132", "T", 1691.3386, 3887.0078, 0], + [275, "PAD133", "T", 1791.3386, 3987.0078, 0], + [276, "PAD133", "T", 1791.3386, 3987.0078, 0], + [277, "PAD134", "T", 1691.3386, 3987.0078, 0], + [278, "PAD134", "T", 1691.3386, 3987.0078, 0], + [279, "PAD135", "T", 1791.3386, 4087.0078, 0], + [280, "PAD135", "T", 1791.3386, 4087.0078, 0], + [281, "PAD136", "T", 1691.3386, 4087.0078, 0], + [282, "PAD136", "T", 1691.3386, 4087.0078, 0], + [283, "PAD137", "T", 1791.3386, 4187.0078, 0], + [284, "PAD137", "T", 1791.3386, 4187.0078, 0], + [285, "PAD138", "T", -908.8583, 4244.9606, 0], + [286, "PAD138", "T", -908.8583, 4244.9606, 0], + [287, "PAD139", "T", -808.8583, 4244.9606, 0], + [288, "PAD139", "T", -808.8583, 4244.9606, 0], + [289, "PAD140", "T", -708.8583, 4244.9606, 0], + [290, "PAD140", "T", -708.8583, 4244.9606, 0], + [291, "PAD141", "T", -608.8583, 4244.9606, 0], + [292, "PAD141", "T", -608.8583, 4244.9606, 0], + [293, "PAD142", "T", 623.7817, 2454.9606, 0], + [294, "PAD143", "T", 828.5017, 2454.9606, 0], + [295, "PAD144", "T", 621.1417, 1657.5206, 0], + [296, "PAD144", "T", 621.1417, 1657.5206, 0], + [297, "PAD145", "T", 621.1417, 1315.0006, 0], + [298, "PAD145", "T", 621.1417, 1315.0006, 0] + ] +}, +"pins": { + "fields": ["PIN_NO", "PIN_NAME", "PIN_X", "PIN_Y", "LAYER", "PIN_TYPE", "NET_NAME", "NET_TYPE", "PAD_SHAPE", "PAD_SIZEX", "PAD_SIZEY", "HOLE_SIZE", "HOLE_LEN", "PAD_ANGLE"], + "rows": [ + [1, "C65_1", 623.7817, 2454.9606, "T", "SMD", "VCC5", "", "R", 74.803, 93.543, 0, 0, 180], + [2, "C65_2", 828.5017, 2454.9606, "T", "SMD", "GND", "GND", "R", 74.803, 93.543, 0, 0, 180], + [3, "J1_1", 471.1417, 1514.9606, "T", "DIP", "VCC5", "", "R", 65, 65, 38, 38, 270], + [4, "J1_1", 471.1417, 1514.9606, "T", "DIP", "VCC5", "", "R", 65, 65, 38, 38, 270], + [5, "J1_2", 471.1417, 1414.9606, "T", "DIP", "IDE5V", "", "C", 65, 65, 38, 38, 270], + [6, "J1_2", 471.1417, 1414.9606, "T", "DIP", "IDE5V", "", "C", 65, 65, 38, 38, 270], + [7, "R1_1", 268.1117, 3852.4908, "B", "SMD", "ZIFI_RX", "", "R", 44.588, 54.213, 0, 0, 180], + [8, "R1_2", 189.3717, 3852.4908, "B", "SMD", "$1N45", "", "R", 44.588, 54.213, 0, 0, 180], + [9, "R2_1", 216.3717, 3250.4908, "B", "SMD", "ESP_SCK", "", "R", 44.588, 54.213, 0, 0, 0], + [10, "R2_2", 295.1117, 3250.4908, "B", "SMD", "$1N192", "", "R", 44.588, 54.213, 0, 0, 0], + [11, "U1_1", 76.1417, 4949.9606, "T", "DIP", "NET_1", "", "R", 75, 55, 36, 36, 0], + [12, "U1_1", 76.1417, 4949.9606, "T", "DIP", "NET_1", "", "R", 75, 55, 36, 36, 0], + [13, "U1_2", 76.1417, 4849.9606, "T", "DIP", "NET_2", "", "O", 75, 55, 36, 36, 0], + [14, "U1_2", 76.1417, 4849.9606, "T", "DIP", "NET_2", "", "O", 75, 55, 36, 36, 0], + [15, "U1_3", 76.1417, 4749.9606, "T", "DIP", "NET_3", "", "O", 75, 55, 36, 36, 0], + [16, "U1_3", 76.1417, 4749.9606, "T", "DIP", "NET_3", "", "O", 75, 55, 36, 36, 0], + [17, "U1_4", 76.1417, 4649.9606, "T", "DIP", "NET_4", "", "O", 75, 55, 36, 36, 0], + [18, "U1_4", 76.1417, 4649.9606, "T", "DIP", "NET_4", "", "O", 75, 55, 36, 36, 0], + [19, "U1_5", 76.1417, 4549.9606, "T", "DIP", "NET_5", "", "O", 75, 55, 36, 36, 0], + [20, "U1_5", 76.1417, 4549.9606, "T", "DIP", "NET_5", "", "O", 75, 55, 36, 36, 0], + [21, "U1_6", 76.1417, 4449.9606, "T", "DIP", "NET_6", "", "O", 75, 55, 36, 36, 0], + [22, "U1_6", 76.1417, 4449.9606, "T", "DIP", "NET_6", "", "O", 75, 55, 36, 36, 0], + [23, "U1_7", 76.1417, 4349.9606, "T", "DIP", "NET_7", "", "O", 75, 55, 36, 36, 0], + [24, "U1_7", 76.1417, 4349.9606, "T", "DIP", "NET_7", "", "O", 75, 55, 36, 36, 0], + [25, "U1_8", 76.1417, 4249.9606, "T", "DIP", "PCM_BLK", "", "O", 75, 55, 36, 36, 0], + [26, "U1_8", 76.1417, 4249.9606, "T", "DIP", "PCM_BLK", "", "O", 75, 55, 36, 36, 0], + [27, "U1_9", 76.1417, 4149.9606, "T", "DIP", "PCM_LRCK", "", "O", 75, 55, 36, 36, 0], + [28, "U1_9", 76.1417, 4149.9606, "T", "DIP", "PCM_LRCK", "", "O", 75, 55, 36, 36, 0], + [29, "U1_10", 76.1417, 4049.9606, "T", "DIP", "PCM_DIN", "", "O", 75, 55, 36, 36, 0], + [30, "U1_10", 76.1417, 4049.9606, "T", "DIP", "PCM_DIN", "", "O", 75, 55, 36, 36, 0], + [31, "U1_11", 76.1417, 3949.9606, "T", "DIP", "ZIFI_TX", "", "O", 75, 55, 36, 36, 0], + [32, "U1_11", 76.1417, 3949.9606, "T", "DIP", "ZIFI_TX", "", "O", 75, 55, 36, 36, 0], + [33, "U1_12", 76.1417, 3849.9606, "T", "DIP", "$1N45", "", "O", 75, 55, 36, 36, 0], + [34, "U1_12", 76.1417, 3849.9606, "T", "DIP", "$1N45", "", "O", 75, 55, 36, 36, 0], + [35, "U1_13", 76.1417, 3749.9606, "T", "DIP", "NET_8", "", "O", 75, 55, 36, 36, 0], + [36, "U1_13", 76.1417, 3749.9606, "T", "DIP", "NET_8", "", "O", 75, 55, 36, 36, 0], + [37, "U1_14", 76.1417, 3649.9606, "T", "DIP", "NET_9", "", "O", 75, 55, 36, 36, 0], + [38, "U1_14", 76.1417, 3649.9606, "T", "DIP", "NET_9", "", "O", 75, 55, 36, 36, 0], + [39, "U1_15", 76.1417, 3549.9606, "T", "DIP", "NET_10", "", "O", 75, 55, 36, 36, 0], + [40, "U1_15", 76.1417, 3549.9606, "T", "DIP", "NET_10", "", "O", 75, 55, 36, 36, 0], + [41, "U1_16", 76.1417, 3449.9606, "T", "DIP", "ESP_CS", "", "O", 75, 55, 36, 36, 0], + [42, "U1_16", 76.1417, 3449.9606, "T", "DIP", "ESP_CS", "", "O", 75, 55, 36, 36, 0], + [43, "U1_17", 76.1417, 3349.9606, "T", "DIP", "ESP_MISO", "", "O", 75, 55, 36, 36, 0], + [44, "U1_17", 76.1417, 3349.9606, "T", "DIP", "ESP_MISO", "", "O", 75, 55, 36, 36, 0], + [45, "U1_18", 76.1417, 3249.9606, "T", "DIP", "ESP_SCK", "", "O", 75, 55, 36, 36, 0], + [46, "U1_18", 76.1417, 3249.9606, "T", "DIP", "ESP_SCK", "", "O", 75, 55, 36, 36, 0], + [47, "U1_19", 76.1417, 3149.9606, "T", "DIP", "ESP_MOSI", "", "O", 75, 55, 36, 36, 0], + [48, "U1_19", 76.1417, 3149.9606, "T", "DIP", "ESP_MOSI", "", "O", 75, 55, 36, 36, 0], + [49, "U1_20", 76.1417, 3049.9606, "T", "DIP", "NET_11", "", "O", 75, 55, 36, 36, 0], + [50, "U1_20", 76.1417, 3049.9606, "T", "DIP", "NET_11", "", "O", 75, 55, 36, 36, 0], + [51, "U1_21", 76.1417, 2949.9606, "T", "DIP", "VCC5", "", "O", 75, 55, 36, 36, 0], + [52, "U1_21", 76.1417, 2949.9606, "T", "DIP", "VCC5", "", "O", 75, 55, 36, 36, 0], + [53, "U1_22", 76.1417, 2849.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [54, "U1_22", 76.1417, 2849.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [55, "U1_23", 1076.1417, 2849.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [56, "U1_23", 1076.1417, 2849.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [57, "U1_24", 1076.1417, 2949.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [58, "U1_24", 1076.1417, 2949.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [59, "U1_25", 1076.1417, 3049.9606, "T", "DIP", "NET_12", "", "O", 75, 55, 36, 36, 0], + [60, "U1_25", 1076.1417, 3049.9606, "T", "DIP", "NET_12", "", "O", 75, 55, 36, 36, 0], + [61, "U1_26", 1076.1417, 3149.9606, "T", "DIP", "NET_13", "", "O", 75, 55, 36, 36, 0], + [62, "U1_26", 1076.1417, 3149.9606, "T", "DIP", "NET_13", "", "O", 75, 55, 36, 36, 0], + [63, "U1_27", 1076.1417, 3249.9606, "T", "DIP", "NET_14", "", "O", 75, 55, 36, 36, 0], + [64, "U1_27", 1076.1417, 3249.9606, "T", "DIP", "NET_14", "", "O", 75, 55, 36, 36, 0], + [65, "U1_28", 1076.1417, 3349.9606, "T", "DIP", "NET_15", "", "O", 75, 55, 36, 36, 0], + [66, "U1_28", 1076.1417, 3349.9606, "T", "DIP", "NET_15", "", "O", 75, 55, 36, 36, 0], + [67, "U1_29", 1076.1417, 3449.9606, "T", "DIP", "NET_16", "", "O", 75, 55, 36, 36, 0], + [68, "U1_29", 1076.1417, 3449.9606, "T", "DIP", "NET_16", "", "O", 75, 55, 36, 36, 0], + [69, "U1_30", 1076.1417, 3549.9606, "T", "DIP", "NET_17", "", "O", 75, 55, 36, 36, 0], + [70, "U1_30", 1076.1417, 3549.9606, "T", "DIP", "NET_17", "", "O", 75, 55, 36, 36, 0], + [71, "U1_31", 1076.1417, 3649.9606, "T", "DIP", "NET_18", "", "O", 75, 55, 36, 36, 0], + [72, "U1_31", 1076.1417, 3649.9606, "T", "DIP", "NET_18", "", "O", 75, 55, 36, 36, 0], + [73, "U1_32", 1076.1417, 3749.9606, "T", "DIP", "NET_19", "", "O", 75, 55, 36, 36, 0], + [74, "U1_32", 1076.1417, 3749.9606, "T", "DIP", "NET_19", "", "O", 75, 55, 36, 36, 0], + [75, "U1_33", 1076.1417, 3849.9606, "T", "DIP", "NET_20", "", "O", 75, 55, 36, 36, 0], + [76, "U1_33", 1076.1417, 3849.9606, "T", "DIP", "NET_20", "", "O", 75, 55, 36, 36, 0], + [77, "U1_34", 1076.1417, 3949.9606, "T", "DIP", "NET_21", "", "O", 75, 55, 36, 36, 0], + [78, "U1_34", 1076.1417, 3949.9606, "T", "DIP", "NET_21", "", "O", 75, 55, 36, 36, 0], + [79, "U1_35", 1076.1417, 4049.9606, "T", "DIP", "NET_22", "", "O", 75, 55, 36, 36, 0], + [80, "U1_35", 1076.1417, 4049.9606, "T", "DIP", "NET_22", "", "O", 75, 55, 36, 36, 0], + [81, "U1_36", 1076.1417, 4149.9606, "T", "DIP", "NET_23", "", "O", 75, 55, 36, 36, 0], + [82, "U1_36", 1076.1417, 4149.9606, "T", "DIP", "NET_23", "", "O", 75, 55, 36, 36, 0], + [83, "U1_37", 1076.1417, 4249.9606, "T", "DIP", "NET_24", "", "O", 75, 55, 36, 36, 0], + [84, "U1_37", 1076.1417, 4249.9606, "T", "DIP", "NET_24", "", "O", 75, 55, 36, 36, 0], + [85, "U1_38", 1076.1417, 4349.9606, "T", "DIP", "NET_25", "", "O", 75, 55, 36, 36, 0], + [86, "U1_38", 1076.1417, 4349.9606, "T", "DIP", "NET_25", "", "O", 75, 55, 36, 36, 0], + [87, "U1_39", 1076.1417, 4449.9606, "T", "DIP", "NET_26", "", "O", 75, 55, 36, 36, 0], + [88, "U1_39", 1076.1417, 4449.9606, "T", "DIP", "NET_26", "", "O", 75, 55, 36, 36, 0], + [89, "U1_40", 1076.1417, 4549.9606, "T", "DIP", "NET_27", "", "O", 75, 55, 36, 36, 0], + [90, "U1_40", 1076.1417, 4549.9606, "T", "DIP", "NET_27", "", "O", 75, 55, 36, 36, 0], + [91, "U1_41", 1076.1417, 4649.9606, "T", "DIP", "NET_28", "", "O", 75, 55, 36, 36, 0], + [92, "U1_41", 1076.1417, 4649.9606, "T", "DIP", "NET_28", "", "O", 75, 55, 36, 36, 0], + [93, "U1_42", 1076.1417, 4749.9606, "T", "DIP", "NET_29", "", "O", 75, 55, 36, 36, 0], + [94, "U1_42", 1076.1417, 4749.9606, "T", "DIP", "NET_29", "", "O", 75, 55, 36, 36, 0], + [95, "U1_43", 1076.1417, 4849.9606, "T", "DIP", "NET_30", "", "O", 75, 55, 36, 36, 0], + [96, "U1_43", 1076.1417, 4849.9606, "T", "DIP", "NET_30", "", "O", 75, 55, 36, 36, 0], + [97, "U1_44", 1076.1417, 4949.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [98, "U1_44", 1076.1417, 4949.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [99, "U3_1", -108.8583, 2949.9606, "T", "DIP", "VCC5", "", "C", 65, 65, 36, 36, 90], + [100, "U3_1", -108.8583, 2949.9606, "T", "DIP", "VCC5", "", "C", 65, 65, 36, 36, 90], + [101, "U3_2", -108.8583, 3049.9606, "T", "DIP", "NET_31", "", "C", 65, 65, 36, 36, 90], + [102, "U3_2", -108.8583, 3049.9606, "T", "DIP", "NET_31", "", "C", 65, 65, 36, 36, 90], + [103, "U3_3", -108.8583, 3149.9606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 90], + [104, "U3_3", -108.8583, 3149.9606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 90], + [105, "U3_4", -108.8583, 3249.9606, "T", "DIP", "PCM_LRCK", "", "C", 65, 65, 36, 36, 90], + [106, "U3_4", -108.8583, 3249.9606, "T", "DIP", "PCM_LRCK", "", "C", 65, 65, 36, 36, 90], + [107, "U3_5", -108.8583, 3349.9606, "T", "DIP", "PCM_DIN", "", "C", 65, 65, 36, 36, 90], + [108, "U3_5", -108.8583, 3349.9606, "T", "DIP", "PCM_DIN", "", "C", 65, 65, 36, 36, 90], + [109, "U3_6", -108.8583, 3449.9606, "T", "DIP", "PCM_BLK", "", "C", 65, 65, 36, 36, 90], + [110, "U3_6", -108.8583, 3449.9606, "T", "DIP", "PCM_BLK", "", "C", 65, 65, 36, 36, 90], + [111, "U3_7", -108.8583, 3549.9606, "T", "DIP", "L_OUT", "", "C", 65, 65, 36, 36, 90], + [112, "U3_7", -108.8583, 3549.9606, "T", "DIP", "L_OUT", "", "C", 65, 65, 36, 36, 90], + [113, "U3_8", -108.8583, 3649.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 90], + [114, "U3_8", -108.8583, 3649.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 90], + [115, "U3_9", -108.8583, 3749.9606, "T", "DIP", "R_OUT", "", "C", 65, 65, 36, 36, 90], + [116, "U3_9", -108.8583, 3749.9606, "T", "DIP", "R_OUT", "", "C", 65, 65, 36, 36, 90], + [117, "U3_10", -908.8583, 3549.9606, "T", "DIP", "NET_32", "", "C", 65, 65, 36, 36, 90], + [118, "U3_10", -908.8583, 3549.9606, "T", "DIP", "NET_32", "", "C", 65, 65, 36, 36, 90], + [119, "U3_11", -908.8583, 3449.9606, "T", "DIP", "NET_33", "", "C", 65, 65, 36, 36, 90], + [120, "U3_11", -908.8583, 3449.9606, "T", "DIP", "NET_33", "", "C", 65, 65, 36, 36, 90], + [121, "U3_12", -908.8583, 3349.9606, "T", "DIP", "NET_34", "", "C", 65, 65, 36, 36, 90], + [122, "U3_12", -908.8583, 3349.9606, "T", "DIP", "NET_34", "", "C", 65, 65, 36, 36, 90], + [123, "U3_13", -908.8583, 3249.9606, "T", "DIP", "NET_35", "", "C", 65, 65, 36, 36, 90], + [124, "U3_13", -908.8583, 3249.9606, "T", "DIP", "NET_35", "", "C", 65, 65, 36, 36, 90], + [125, "U3_14", -908.8583, 3149.9606, "T", "DIP", "NET_36", "", "C", 65, 65, 36, 36, 90], + [126, "U3_14", -908.8583, 3149.9606, "T", "DIP", "NET_36", "", "C", 65, 65, 36, 36, 90], + [127, "U3_15", -908.8583, 3049.9606, "T", "DIP", "NET_37", "", "C", 65, 65, 36, 36, 90], + [128, "U3_15", -908.8583, 3049.9606, "T", "DIP", "NET_37", "", "C", 65, 65, 36, 36, 90], + [129, "VD1_1", 621.1417, 1657.5206, "T", "DIP", "VCC5", "", "C", 70.866, 70.866, 39.37, 39.37, 270], + [130, "VD1_1", 621.1417, 1657.5206, "T", "DIP", "VCC5", "", "C", 70.866, 70.866, 39.37, 39.37, 270], + [131, "VD1_2", 621.1417, 1315.0006, "T", "DIP", "$1N233", "", "C", 70.866, 70.866, 39.37, 39.37, 270], + [132, "VD1_2", 621.1417, 1315.0006, "T", "DIP", "$1N233", "", "C", 70.866, 70.866, 39.37, 39.37, 270], + [133, "X1_1", 866.1417, 214.9606, "T", "DIP", "ESP_CS", "", "R", 62.992, 62.992, 39.37, 39.37, 90], + [134, "X1_1", 866.1417, 214.9606, "T", "DIP", "ESP_CS", "", "R", 62.992, 62.992, 39.37, 39.37, 90], + [135, "X1_2", 766.1417, 214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [136, "X1_2", 766.1417, 214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [137, "X1_3", 866.1417, 314.9606, "T", "DIP", "ID7", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [138, "X1_3", 866.1417, 314.9606, "T", "DIP", "ID7", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [139, "X1_4", 766.1417, 314.9606, "T", "DIP", "ID8", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [140, "X1_4", 766.1417, 314.9606, "T", "DIP", "ID8", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [141, "X1_5", 866.1417, 414.9606, "T", "DIP", "ID6", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [142, "X1_5", 866.1417, 414.9606, "T", "DIP", "ID6", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [143, "X1_6", 766.1417, 414.9606, "T", "DIP", "ID9", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [144, "X1_6", 766.1417, 414.9606, "T", "DIP", "ID9", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [145, "X1_7", 866.1417, 514.9606, "T", "DIP", "ID5", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [146, "X1_7", 866.1417, 514.9606, "T", "DIP", "ID5", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [147, "X1_8", 766.1417, 514.9606, "T", "DIP", "ID10", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [148, "X1_8", 766.1417, 514.9606, "T", "DIP", "ID10", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [149, "X1_9", 866.1417, 614.9606, "T", "DIP", "ID4", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [150, "X1_9", 866.1417, 614.9606, "T", "DIP", "ID4", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [151, "X1_10", 766.1417, 614.9606, "T", "DIP", "ID11", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [152, "X1_10", 766.1417, 614.9606, "T", "DIP", "ID11", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [153, "X1_11", 866.1417, 714.9606, "T", "DIP", "ID3", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [154, "X1_11", 866.1417, 714.9606, "T", "DIP", "ID3", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [155, "X1_12", 766.1417, 714.9606, "T", "DIP", "ID12", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [156, "X1_12", 766.1417, 714.9606, "T", "DIP", "ID12", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [157, "X1_13", 866.1417, 814.9606, "T", "DIP", "ID2", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [158, "X1_13", 866.1417, 814.9606, "T", "DIP", "ID2", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [159, "X1_14", 766.1417, 814.9606, "T", "DIP", "ID13", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [160, "X1_14", 766.1417, 814.9606, "T", "DIP", "ID13", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [161, "X1_15", 866.1417, 914.9606, "T", "DIP", "ID1", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [162, "X1_15", 866.1417, 914.9606, "T", "DIP", "ID1", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [163, "X1_16", 766.1417, 914.9606, "T", "DIP", "ID14", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [164, "X1_16", 766.1417, 914.9606, "T", "DIP", "ID14", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [165, "X1_17", 866.1417, 1014.9606, "T", "DIP", "ID0", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [166, "X1_17", 866.1417, 1014.9606, "T", "DIP", "ID0", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [167, "X1_18", 766.1417, 1014.9606, "T", "DIP", "ID15", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [168, "X1_18", 766.1417, 1014.9606, "T", "DIP", "ID15", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [169, "X1_19", 866.1417, 1114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [170, "X1_19", 866.1417, 1114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [171, "X1_20", 766.1417, 1114.9606, "T", "DIP", "$1N233", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [172, "X1_20", 766.1417, 1114.9606, "T", "DIP", "$1N233", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [173, "X1_21", 866.1417, 1214.9606, "T", "DIP", "NET_38", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [174, "X1_21", 866.1417, 1214.9606, "T", "DIP", "NET_38", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [175, "X1_22", 766.1417, 1214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [176, "X1_22", 766.1417, 1214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [177, "X1_23", 866.1417, 1314.9606, "T", "DIP", "IWR_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [178, "X1_23", 866.1417, 1314.9606, "T", "DIP", "IWR_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [179, "X1_24", 766.1417, 1314.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [180, "X1_24", 766.1417, 1314.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [181, "X1_25", 866.1417, 1414.9606, "T", "DIP", "IRD_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [182, "X1_25", 866.1417, 1414.9606, "T", "DIP", "IRD_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [183, "X1_26", 766.1417, 1414.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [184, "X1_26", 766.1417, 1414.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [185, "X1_27", 866.1417, 1514.9606, "T", "DIP", "ESP_MISO", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [186, "X1_27", 866.1417, 1514.9606, "T", "DIP", "ESP_MISO", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [187, "X1_28", 766.1417, 1514.9606, "T", "DIP", "NET_39", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [188, "X1_28", 766.1417, 1514.9606, "T", "DIP", "NET_39", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [189, "X1_29", 866.1417, 1614.9606, "T", "DIP", "NET_40", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [190, "X1_29", 866.1417, 1614.9606, "T", "DIP", "NET_40", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [191, "X1_30", 766.1417, 1614.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [192, "X1_30", 766.1417, 1614.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [193, "X1_31", 866.1417, 1714.9606, "T", "DIP", "NET_41", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [194, "X1_31", 866.1417, 1714.9606, "T", "DIP", "NET_41", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [195, "X1_32", 766.1417, 1714.9606, "T", "DIP", "NET_42", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [196, "X1_32", 766.1417, 1714.9606, "T", "DIP", "NET_42", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [197, "X1_33", 866.1417, 1814.9606, "T", "DIP", "ESP_MOSI", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [198, "X1_33", 866.1417, 1814.9606, "T", "DIP", "ESP_MOSI", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [199, "X1_34", 766.1417, 1814.9606, "T", "DIP", "NET_43", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [200, "X1_34", 766.1417, 1814.9606, "T", "DIP", "NET_43", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [201, "X1_35", 866.1417, 1914.9606, "T", "DIP", "$1N192", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [202, "X1_35", 866.1417, 1914.9606, "T", "DIP", "$1N192", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [203, "X1_36", 766.1417, 1914.9606, "T", "DIP", "IA2", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [204, "X1_36", 766.1417, 1914.9606, "T", "DIP", "IA2", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [205, "X1_37", 866.1417, 2014.9606, "T", "DIP", "ICS0_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [206, "X1_37", 866.1417, 2014.9606, "T", "DIP", "ICS0_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [207, "X1_38", 766.1417, 2014.9606, "T", "DIP", "ICS1_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [208, "X1_38", 766.1417, 2014.9606, "T", "DIP", "ICS1_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [209, "X1_39", 866.1417, 2114.9606, "T", "DIP", "DASP_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [210, "X1_39", 866.1417, 2114.9606, "T", "DIP", "DASP_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [211, "X1_40", 766.1417, 2114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [212, "X1_40", 766.1417, 2114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [213, "X2_1", 241.1417, 214.9606, "T", "DIP", "ESP_CS", "", "R", 62.992, 62.992, 36, 36, 90], + [214, "X2_1", 241.1417, 214.9606, "T", "DIP", "ESP_CS", "", "R", 62.992, 62.992, 36, 36, 90], + [215, "X2_2", 141.1417, 214.9606, "T", "DIP", "NET_44", "", "C", 62.992, 62.992, 36, 36, 90], + [216, "X2_2", 141.1417, 214.9606, "T", "DIP", "NET_44", "", "C", 62.992, 62.992, 36, 36, 90], + [217, "X2_3", 241.1417, 314.9606, "T", "DIP", "ID7", "", "C", 62.992, 62.992, 36, 36, 90], + [218, "X2_3", 241.1417, 314.9606, "T", "DIP", "ID7", "", "C", 62.992, 62.992, 36, 36, 90], + [219, "X2_4", 141.1417, 314.9606, "T", "DIP", "ID8", "", "C", 62.992, 62.992, 36, 36, 90], + [220, "X2_4", 141.1417, 314.9606, "T", "DIP", "ID8", "", "C", 62.992, 62.992, 36, 36, 90], + [221, "X2_5", 241.1417, 414.9606, "T", "DIP", "ID6", "", "C", 62.992, 62.992, 36, 36, 90], + [222, "X2_5", 241.1417, 414.9606, "T", "DIP", "ID6", "", "C", 62.992, 62.992, 36, 36, 90], + [223, "X2_6", 141.1417, 414.9606, "T", "DIP", "ID9", "", "C", 62.992, 62.992, 36, 36, 90], + [224, "X2_6", 141.1417, 414.9606, "T", "DIP", "ID9", "", "C", 62.992, 62.992, 36, 36, 90], + [225, "X2_7", 241.1417, 514.9606, "T", "DIP", "ID5", "", "C", 62.992, 62.992, 36, 36, 90], + [226, "X2_7", 241.1417, 514.9606, "T", "DIP", "ID5", "", "C", 62.992, 62.992, 36, 36, 90], + [227, "X2_8", 141.1417, 514.9606, "T", "DIP", "ID10", "", "C", 62.992, 62.992, 36, 36, 90], + [228, "X2_8", 141.1417, 514.9606, "T", "DIP", "ID10", "", "C", 62.992, 62.992, 36, 36, 90], + [229, "X2_9", 241.1417, 614.9606, "T", "DIP", "ID4", "", "C", 62.992, 62.992, 36, 36, 90], + [230, "X2_9", 241.1417, 614.9606, "T", "DIP", "ID4", "", "C", 62.992, 62.992, 36, 36, 90], + [231, "X2_10", 141.1417, 614.9606, "T", "DIP", "ID11", "", "C", 62.992, 62.992, 36, 36, 90], + [232, "X2_10", 141.1417, 614.9606, "T", "DIP", "ID11", "", "C", 62.992, 62.992, 36, 36, 90], + [233, "X2_11", 241.1417, 714.9606, "T", "DIP", "ID3", "", "C", 62.992, 62.992, 36, 36, 90], + [234, "X2_11", 241.1417, 714.9606, "T", "DIP", "ID3", "", "C", 62.992, 62.992, 36, 36, 90], + [235, "X2_12", 141.1417, 714.9606, "T", "DIP", "ID12", "", "C", 62.992, 62.992, 36, 36, 90], + [236, "X2_12", 141.1417, 714.9606, "T", "DIP", "ID12", "", "C", 62.992, 62.992, 36, 36, 90], + [237, "X2_13", 241.1417, 814.9606, "T", "DIP", "ID2", "", "C", 62.992, 62.992, 36, 36, 90], + [238, "X2_13", 241.1417, 814.9606, "T", "DIP", "ID2", "", "C", 62.992, 62.992, 36, 36, 90], + [239, "X2_14", 141.1417, 814.9606, "T", "DIP", "ID13", "", "C", 62.992, 62.992, 36, 36, 90], + [240, "X2_14", 141.1417, 814.9606, "T", "DIP", "ID13", "", "C", 62.992, 62.992, 36, 36, 90], + [241, "X2_15", 241.1417, 914.9606, "T", "DIP", "ID1", "", "C", 62.992, 62.992, 36, 36, 90], + [242, "X2_15", 241.1417, 914.9606, "T", "DIP", "ID1", "", "C", 62.992, 62.992, 36, 36, 90], + [243, "X2_16", 141.1417, 914.9606, "T", "DIP", "ID14", "", "C", 62.992, 62.992, 36, 36, 90], + [244, "X2_16", 141.1417, 914.9606, "T", "DIP", "ID14", "", "C", 62.992, 62.992, 36, 36, 90], + [245, "X2_17", 241.1417, 1014.9606, "T", "DIP", "ID0", "", "C", 62.992, 62.992, 36, 36, 90], + [246, "X2_17", 241.1417, 1014.9606, "T", "DIP", "ID0", "", "C", 62.992, 62.992, 36, 36, 90], + [247, "X2_18", 141.1417, 1014.9606, "T", "DIP", "ID15", "", "C", 62.992, 62.992, 36, 36, 90], + [248, "X2_18", 141.1417, 1014.9606, "T", "DIP", "ID15", "", "C", 62.992, 62.992, 36, 36, 90], + [249, "X2_19", 241.1417, 1114.9606, "T", "DIP", "GND", "GND", "C", 55, 55, 36, 36, 90], + [250, "X2_19", 241.1417, 1114.9606, "T", "DIP", "GND", "GND", "C", 55, 55, 36, 36, 90], + [251, "X2_20", 141.1417, 1114.9606, "T", "DIP", "IDE5V", "", "C", 62.992, 62.992, 36, 36, 90], + [252, "X2_20", 141.1417, 1114.9606, "T", "DIP", "IDE5V", "", "C", 62.992, 62.992, 36, 36, 90], + [253, "X2_21", 241.1417, 1214.9606, "T", "DIP", "NET_45", "", "C", 55, 55, 36, 36, 90], + [254, "X2_21", 241.1417, 1214.9606, "T", "DIP", "NET_45", "", "C", 55, 55, 36, 36, 90], + [255, "X2_22", 141.1417, 1214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [256, "X2_22", 141.1417, 1214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [257, "X2_23", 241.1417, 1314.9606, "T", "DIP", "IWR_", "", "C", 62.992, 62.992, 36, 36, 90], + [258, "X2_23", 241.1417, 1314.9606, "T", "DIP", "IWR_", "", "C", 62.992, 62.992, 36, 36, 90], + [259, "X2_24", 141.1417, 1314.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [260, "X2_24", 141.1417, 1314.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [261, "X2_25", 241.1417, 1414.9606, "T", "DIP", "IRD_", "", "C", 62.992, 62.992, 36, 36, 90], + [262, "X2_25", 241.1417, 1414.9606, "T", "DIP", "IRD_", "", "C", 62.992, 62.992, 36, 36, 90], + [263, "X2_26", 141.1417, 1414.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [264, "X2_26", 141.1417, 1414.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [265, "X2_27", 241.1417, 1514.9606, "T", "DIP", "ESP_MISO", "", "C", 62.992, 62.992, 36, 36, 90], + [266, "X2_27", 241.1417, 1514.9606, "T", "DIP", "ESP_MISO", "", "C", 62.992, 62.992, 36, 36, 90], + [267, "X2_28", 141.1417, 1514.9606, "T", "DIP", "NET_46", "", "C", 62.992, 62.992, 36, 36, 90], + [268, "X2_28", 141.1417, 1514.9606, "T", "DIP", "NET_46", "", "C", 62.992, 62.992, 36, 36, 90], + [269, "X2_29", 241.1417, 1614.9606, "T", "DIP", "NET_47", "", "C", 62.992, 62.992, 36, 36, 90], + [270, "X2_29", 241.1417, 1614.9606, "T", "DIP", "NET_47", "", "C", 62.992, 62.992, 36, 36, 90], + [271, "X2_30", 141.1417, 1614.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [272, "X2_30", 141.1417, 1614.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [273, "X2_31", 241.1417, 1714.9606, "T", "DIP", "NET_48", "", "C", 62.992, 62.992, 36, 36, 90], + [274, "X2_31", 241.1417, 1714.9606, "T", "DIP", "NET_48", "", "C", 62.992, 62.992, 36, 36, 90], + [275, "X2_32", 141.1417, 1714.9606, "T", "DIP", "NET_49", "", "C", 62.992, 62.992, 36, 36, 90], + [276, "X2_32", 141.1417, 1714.9606, "T", "DIP", "NET_49", "", "C", 62.992, 62.992, 36, 36, 90], + [277, "X2_33", 241.1417, 1814.9606, "T", "DIP", "ESP_MOSI", "", "C", 62.992, 62.992, 36, 36, 90], + [278, "X2_33", 241.1417, 1814.9606, "T", "DIP", "ESP_MOSI", "", "C", 62.992, 62.992, 36, 36, 90], + [279, "X2_34", 141.1417, 1814.9606, "T", "DIP", "NET_50", "", "C", 62.992, 62.992, 36, 36, 90], + [280, "X2_34", 141.1417, 1814.9606, "T", "DIP", "NET_50", "", "C", 62.992, 62.992, 36, 36, 90], + [281, "X2_35", 241.1417, 1914.9606, "T", "DIP", "$1N192", "", "C", 62.992, 62.992, 36, 36, 90], + [282, "X2_35", 241.1417, 1914.9606, "T", "DIP", "$1N192", "", "C", 62.992, 62.992, 36, 36, 90], + [283, "X2_36", 141.1417, 1914.9606, "T", "DIP", "IA2", "", "C", 62.992, 62.992, 36, 36, 90], + [284, "X2_36", 141.1417, 1914.9606, "T", "DIP", "IA2", "", "C", 62.992, 62.992, 36, 36, 90], + [285, "X2_37", 241.1417, 2014.9606, "T", "DIP", "ICS0_", "", "C", 62.992, 62.992, 36, 36, 90], + [286, "X2_37", 241.1417, 2014.9606, "T", "DIP", "ICS0_", "", "C", 62.992, 62.992, 36, 36, 90], + [287, "X2_38", 141.1417, 2014.9606, "T", "DIP", "ICS1_", "", "C", 62.992, 62.992, 36, 36, 90], + [288, "X2_38", 141.1417, 2014.9606, "T", "DIP", "ICS1_", "", "C", 62.992, 62.992, 36, 36, 90], + [289, "X2_39", 241.1417, 2114.9606, "T", "DIP", "DASP_", "", "C", 62.992, 62.992, 36, 36, 90], + [290, "X2_39", 241.1417, 2114.9606, "T", "DIP", "DASP_", "", "C", 62.992, 62.992, 36, 36, 90], + [291, "X2_40", 141.1417, 2114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [292, "X2_40", 141.1417, 2114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [293, "X3_1", 1407.6417, 3265.3606, "T", "DIP", "ZXROW0", "", "R", 65, 65, 36, 36, 270], + [294, "X3_1", 1407.6417, 3265.3606, "T", "DIP", "ZXROW0", "", "R", 65, 65, 36, 36, 270], + [295, "X3_2", 1507.6417, 3265.3606, "T", "DIP", "ZXROW1", "", "C", 65, 65, 36, 36, 270], + [296, "X3_2", 1507.6417, 3265.3606, "T", "DIP", "ZXROW1", "", "C", 65, 65, 36, 36, 270], + [297, "X3_3", 1407.6417, 3165.3606, "T", "DIP", "ZXROW2", "", "C", 65, 65, 36, 36, 270], + [298, "X3_3", 1407.6417, 3165.3606, "T", "DIP", "ZXROW2", "", "C", 65, 65, 36, 36, 270], + [299, "X3_4", 1507.6417, 3165.3606, "T", "DIP", "ZXROW3", "", "C", 65, 65, 36, 36, 270], + [300, "X3_4", 1507.6417, 3165.3606, "T", "DIP", "ZXROW3", "", "C", 65, 65, 36, 36, 270], + [301, "X3_5", 1407.6417, 3065.3606, "T", "DIP", "ZXROW4", "", "C", 65, 65, 36, 36, 270], + [302, "X3_5", 1407.6417, 3065.3606, "T", "DIP", "ZXROW4", "", "C", 65, 65, 36, 36, 270], + [303, "X3_6", 1507.6417, 3065.3606, "T", "DIP", "ZXROW5", "", "C", 65, 65, 36, 36, 270], + [304, "X3_6", 1507.6417, 3065.3606, "T", "DIP", "ZXROW5", "", "C", 65, 65, 36, 36, 270], + [305, "X3_7", 1407.6417, 2965.3606, "T", "DIP", "ZXROW6", "", "C", 65, 65, 36, 36, 270], + [306, "X3_7", 1407.6417, 2965.3606, "T", "DIP", "ZXROW6", "", "C", 65, 65, 36, 36, 270], + [307, "X3_8", 1507.6417, 2965.3606, "T", "DIP", "ZXROW7", "", "C", 65, 65, 36, 36, 270], + [308, "X3_8", 1507.6417, 2965.3606, "T", "DIP", "ZXROW7", "", "C", 65, 65, 36, 36, 270], + [309, "X3_9", 1407.6417, 2865.3606, "T", "DIP", "SOFTRST_", "", "C", 65, 65, 36, 36, 270], + [310, "X3_9", 1407.6417, 2865.3606, "T", "DIP", "SOFTRST_", "", "C", 65, 65, 36, 36, 270], + [311, "X3_10", 1507.6417, 2865.3606, "T", "DIP", "ZXCOL4", "", "C", 65, 65, 36, 36, 270], + [312, "X3_10", 1507.6417, 2865.3606, "T", "DIP", "ZXCOL4", "", "C", 65, 65, 36, 36, 270], + [313, "X3_11", 1407.6417, 2765.3606, "T", "DIP", "ZXCOL3", "", "C", 65, 65, 36, 36, 270], + [314, "X3_11", 1407.6417, 2765.3606, "T", "DIP", "ZXCOL3", "", "C", 65, 65, 36, 36, 270], + [315, "X3_12", 1507.6417, 2765.3606, "T", "DIP", "ZXCOL2", "", "C", 65, 65, 36, 36, 270], + [316, "X3_12", 1507.6417, 2765.3606, "T", "DIP", "ZXCOL2", "", "C", 65, 65, 36, 36, 270], + [317, "X3_13", 1407.6417, 2665.3606, "T", "DIP", "ZXCOL1", "", "C", 65, 65, 36, 36, 270], + [318, "X3_13", 1407.6417, 2665.3606, "T", "DIP", "ZXCOL1", "", "C", 65, 65, 36, 36, 270], + [319, "X3_14", 1507.6417, 2665.3606, "T", "DIP", "ZXCOL0", "", "C", 65, 65, 36, 36, 270], + [320, "X3_14", 1507.6417, 2665.3606, "T", "DIP", "ZXCOL0", "", "C", 65, 65, 36, 36, 270], + [321, "X3_15", 1407.6417, 2565.3606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 270], + [322, "X3_15", 1407.6417, 2565.3606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 270], + [323, "X3_16", 1507.6417, 2565.3606, "T", "DIP", "JOYL", "", "C", 65, 65, 36, 36, 270], + [324, "X3_16", 1507.6417, 2565.3606, "T", "DIP", "JOYL", "", "C", 65, 65, 36, 36, 270], + [325, "X3_17", 1407.6417, 2465.3606, "T", "DIP", "JOYR", "", "C", 65, 65, 36, 36, 270], + [326, "X3_17", 1407.6417, 2465.3606, "T", "DIP", "JOYR", "", "C", 65, 65, 36, 36, 270], + [327, "X3_18", 1507.6417, 2465.3606, "T", "DIP", "JOYU", "", "C", 65, 65, 36, 36, 270], + [328, "X3_18", 1507.6417, 2465.3606, "T", "DIP", "JOYU", "", "C", 65, 65, 36, 36, 270], + [329, "X3_19", 1407.6417, 2365.3606, "T", "DIP", "JOYD", "", "C", 65, 65, 36, 36, 270], + [330, "X3_19", 1407.6417, 2365.3606, "T", "DIP", "JOYD", "", "C", 65, 65, 36, 36, 270], + [331, "X3_20", 1507.6417, 2365.3606, "T", "DIP", "JOYF", "", "C", 65, 65, 36, 36, 270], + [332, "X3_20", 1507.6417, 2365.3606, "T", "DIP", "JOYF", "", "C", 65, 65, 36, 36, 270], + [333, "X4_1", 1397.6378, 3787.0078, "T", "DIP", "JOYU", "", "R", 60, 60, 36, 36, 90], + [334, "X4_1", 1397.6378, 3787.0078, "T", "DIP", "JOYU", "", "R", 60, 60, 36, 36, 90], + [335, "X4_2", 1297.6378, 3787.0078, "T", "DIP", "JOYF", "", "C", 60, 60, 36, 36, 90], + [336, "X4_2", 1297.6378, 3787.0078, "T", "DIP", "JOYF", "", "C", 60, 60, 36, 36, 90], + [337, "X4_3", 1397.6378, 3887.0078, "T", "DIP", "JOYD", "", "C", 60, 60, 36, 36, 90], + [338, "X4_3", 1397.6378, 3887.0078, "T", "DIP", "JOYD", "", "C", 60, 60, 36, 36, 90], + [339, "X4_4", 1297.6378, 3887.0078, "T", "DIP", "ZXROW2", "", "C", 60, 60, 36, 36, 90], + [340, "X4_4", 1297.6378, 3887.0078, "T", "DIP", "ZXROW2", "", "C", 60, 60, 36, 36, 90], + [341, "X4_5", 1397.6378, 3987.0078, "T", "DIP", "JOYL", "", "C", 60, 60, 36, 36, 90], + [342, "X4_5", 1397.6378, 3987.0078, "T", "DIP", "JOYL", "", "C", 60, 60, 36, 36, 90], + [343, "X4_6", 1297.6378, 3987.0078, "T", "DIP", "GND", "GND", "C", 60, 60, 36, 36, 90], + [344, "X4_6", 1297.6378, 3987.0078, "T", "DIP", "GND", "GND", "C", 60, 60, 36, 36, 90], + [345, "X4_7", 1397.6378, 4087.0078, "T", "DIP", "JOYR", "", "C", 60, 60, 36, 36, 90], + [346, "X4_7", 1397.6378, 4087.0078, "T", "DIP", "JOYR", "", "C", 60, 60, 36, 36, 90], + [347, "X4_8", 1297.6378, 4087.0078, "T", "DIP", "ZXROW5", "", "C", 60, 60, 36, 36, 90], + [348, "X4_8", 1297.6378, 4087.0078, "T", "DIP", "ZXROW5", "", "C", 60, 60, 36, 36, 90], + [349, "X4_9", 1397.6378, 4187.0078, "T", "DIP", "VCC5", "", "C", 60, 60, 36, 36, 90], + [350, "X4_9", 1397.6378, 4187.0078, "T", "DIP", "VCC5", "", "C", 60, 60, 36, 36, 90], + [351, "X4_10", 1297.6378, 4187.0078, "T", "DIP", "NET_51", "", "C", 60, 60, 36, 36, 90], + [352, "X4_10", 1297.6378, 4187.0078, "T", "DIP", "NET_51", "", "C", 60, 60, 36, 36, 90], + [353, "X5_1", 423.4417, 3840.1606, "T", "DIP", "NET_52", "", "R", 65, 65, 36, 36, 0], + [354, "X5_1", 423.4417, 3840.1606, "T", "DIP", "NET_52", "", "R", 65, 65, 36, 36, 0], + [355, "X5_2", 423.4417, 3940.1606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 0], + [356, "X5_2", 423.4417, 3940.1606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 0], + [357, "X5_3", 523.4417, 3840.1606, "T", "DIP", "ZIFI_RX", "", "C", 65, 65, 36, 36, 0], + [358, "X5_3", 523.4417, 3840.1606, "T", "DIP", "ZIFI_RX", "", "C", 65, 65, 36, 36, 0], + [359, "X5_4", 523.4417, 3940.1606, "T", "DIP", "NET_53", "", "C", 65, 65, 36, 36, 0], + [360, "X5_4", 523.4417, 3940.1606, "T", "DIP", "NET_53", "", "C", 65, 65, 36, 36, 0], + [361, "X5_5", 623.4417, 3840.1606, "T", "DIP", "NET_54", "", "C", 65, 65, 36, 36, 0], + [362, "X5_5", 623.4417, 3840.1606, "T", "DIP", "NET_54", "", "C", 65, 65, 36, 36, 0], + [363, "X5_6", 623.4417, 3940.1606, "T", "DIP", "NET_55", "", "C", 65, 65, 36, 36, 0], + [364, "X5_6", 623.4417, 3940.1606, "T", "DIP", "NET_55", "", "C", 65, 65, 36, 36, 0], + [365, "X5_7", 723.4417, 3840.1606, "T", "DIP", "NET_56", "", "C", 65, 65, 36, 36, 0], + [366, "X5_7", 723.4417, 3840.1606, "T", "DIP", "NET_56", "", "C", 65, 65, 36, 36, 0], + [367, "X5_8", 723.4417, 3940.1606, "T", "DIP", "NET_57", "", "C", 65, 65, 36, 36, 0], + [368, "X5_8", 723.4417, 3940.1606, "T", "DIP", "NET_57", "", "C", 65, 65, 36, 36, 0], + [369, "X5_9", 823.4417, 3840.1606, "T", "DIP", "ZIFI_TX", "", "C", 65, 65, 36, 36, 0], + [370, "X5_9", 823.4417, 3840.1606, "T", "DIP", "ZIFI_TX", "", "C", 65, 65, 36, 36, 0], + [371, "X5_10", 823.4417, 3940.1606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 0], + [372, "X5_10", 823.4417, 3940.1606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 0], + [373, "X6_1", 1791.3386, 3787.0078, "T", "DIP", "ZXCOL3", "", "R", 60, 60, 36, 36, 90], + [374, "X6_1", 1791.3386, 3787.0078, "T", "DIP", "ZXCOL3", "", "R", 60, 60, 36, 36, 90], + [375, "X6_2", 1691.3386, 3787.0078, "T", "DIP", "ZXCOL4", "", "C", 60, 60, 36, 36, 90], + [376, "X6_2", 1691.3386, 3787.0078, "T", "DIP", "ZXCOL4", "", "C", 60, 60, 36, 36, 90], + [377, "X6_3", 1791.3386, 3887.0078, "T", "DIP", "ZXCOL2", "", "C", 60, 60, 36, 36, 90], + [378, "X6_3", 1791.3386, 3887.0078, "T", "DIP", "ZXCOL2", "", "C", 60, 60, 36, 36, 90], + [379, "X6_4", 1691.3386, 3887.0078, "T", "DIP", "ZXROW2", "", "C", 60, 60, 36, 36, 90], + [380, "X6_4", 1691.3386, 3887.0078, "T", "DIP", "ZXROW2", "", "C", 60, 60, 36, 36, 90], + [381, "X6_5", 1791.3386, 3987.0078, "T", "DIP", "ZXCOL1", "", "C", 60, 60, 36, 36, 90], + [382, "X6_5", 1791.3386, 3987.0078, "T", "DIP", "ZXCOL1", "", "C", 60, 60, 36, 36, 90], + [383, "X6_6", 1691.3386, 3987.0078, "T", "DIP", "GND", "GND", "C", 60, 60, 36, 36, 90], + [384, "X6_6", 1691.3386, 3987.0078, "T", "DIP", "GND", "GND", "C", 60, 60, 36, 36, 90], + [385, "X6_7", 1791.3386, 4087.0078, "T", "DIP", "ZXCOL0", "", "C", 60, 60, 36, 36, 90], + [386, "X6_7", 1791.3386, 4087.0078, "T", "DIP", "ZXCOL0", "", "C", 60, 60, 36, 36, 90], + [387, "X6_8", 1691.3386, 4087.0078, "T", "DIP", "ZXROW1", "", "C", 60, 60, 36, 36, 90], + [388, "X6_8", 1691.3386, 4087.0078, "T", "DIP", "ZXROW1", "", "C", 60, 60, 36, 36, 90], + [389, "X6_9", 1791.3386, 4187.0078, "T", "DIP", "VCC5", "", "C", 60, 60, 36, 36, 90], + [390, "X6_9", 1791.3386, 4187.0078, "T", "DIP", "VCC5", "", "C", 60, 60, 36, 36, 90], + [391, "X6_10", 1691.3386, 4187.0078, "T", "DIP", "NET_58", "", "C", 60, 60, 36, 36, 90], + [392, "X6_10", 1691.3386, 4187.0078, "T", "DIP", "NET_58", "", "C", 60, 60, 36, 36, 90], + [393, "X7_1", -908.8583, 4244.9606, "T", "DIP", "L_OUT", "", "R", 65, 65, 36, 36, 0], + [394, "X7_1", -908.8583, 4244.9606, "T", "DIP", "L_OUT", "", "R", 65, 65, 36, 36, 0], + [395, "X7_2", -808.8583, 4244.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 0], + [396, "X7_2", -808.8583, 4244.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 0], + [397, "X7_3", -708.8583, 4244.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 0], + [398, "X7_3", -708.8583, 4244.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 0], + [399, "X7_4", -608.8583, 4244.9606, "T", "DIP", "R_OUT", "", "C", 65, 65, 36, 36, 0], + [400, "X7_4", -608.8583, 4244.9606, "T", "DIP", "R_OUT", "", "C", 65, 65, 36, 36, 0], + [401, "PAD1_2", 471.1417, 1414.9606, "T", "DIP", "IDE5V", "", "C", 65, 65, 38, 38, 270], + [402, "PAD1_2", 471.1417, 1414.9606, "T", "DIP", "IDE5V", "", "C", 65, 65, 38, 38, 270], + [403, "PAD2_1", 471.1417, 1514.9606, "T", "DIP", "VCC5", "", "R", 65, 65, 38, 38, 270], + [404, "PAD2_1", 471.1417, 1514.9606, "T", "DIP", "VCC5", "", "R", 65, 65, 38, 38, 270], + [405, "PAD3_2", 189.3717, 3852.4908, "B", "SMD", "$1N45", "", "R", 44.588, 54.213, 0, 0, 180], + [406, "PAD4_1", 268.1117, 3852.4908, "B", "SMD", "ZIFI_RX", "", "R", 44.588, 54.213, 0, 0, 180], + [407, "PAD5_2", 295.1117, 3250.4908, "B", "SMD", "$1N192", "", "R", 44.588, 54.213, 0, 0, 0], + [408, "PAD6_1", 216.3717, 3250.4908, "B", "SMD", "ESP_SCK", "", "R", 44.588, 54.213, 0, 0, 0], + [409, "PAD7_44", 1076.1417, 4949.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [410, "PAD7_44", 1076.1417, 4949.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [411, "PAD8_24", 1076.1417, 2949.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [412, "PAD8_24", 1076.1417, 2949.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [413, "PAD9_23", 1076.1417, 2849.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [414, "PAD9_23", 1076.1417, 2849.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [415, "PAD10_22", 76.1417, 2849.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [416, "PAD10_22", 76.1417, 2849.9606, "T", "DIP", "GND", "GND", "O", 75, 55, 36, 36, 0], + [417, "PAD11_21", 76.1417, 2949.9606, "T", "DIP", "VCC5", "", "O", 75, 55, 36, 36, 0], + [418, "PAD11_21", 76.1417, 2949.9606, "T", "DIP", "VCC5", "", "O", 75, 55, 36, 36, 0], + [419, "PAD12_19", 76.1417, 3149.9606, "T", "DIP", "ESP_MOSI", "", "O", 75, 55, 36, 36, 0], + [420, "PAD12_19", 76.1417, 3149.9606, "T", "DIP", "ESP_MOSI", "", "O", 75, 55, 36, 36, 0], + [421, "PAD13_18", 76.1417, 3249.9606, "T", "DIP", "ESP_SCK", "", "O", 75, 55, 36, 36, 0], + [422, "PAD13_18", 76.1417, 3249.9606, "T", "DIP", "ESP_SCK", "", "O", 75, 55, 36, 36, 0], + [423, "PAD14_17", 76.1417, 3349.9606, "T", "DIP", "ESP_MISO", "", "O", 75, 55, 36, 36, 0], + [424, "PAD14_17", 76.1417, 3349.9606, "T", "DIP", "ESP_MISO", "", "O", 75, 55, 36, 36, 0], + [425, "PAD15_16", 76.1417, 3449.9606, "T", "DIP", "ESP_CS", "", "O", 75, 55, 36, 36, 0], + [426, "PAD15_16", 76.1417, 3449.9606, "T", "DIP", "ESP_CS", "", "O", 75, 55, 36, 36, 0], + [427, "PAD16_12", 76.1417, 3849.9606, "T", "DIP", "$1N45", "", "O", 75, 55, 36, 36, 0], + [428, "PAD16_12", 76.1417, 3849.9606, "T", "DIP", "$1N45", "", "O", 75, 55, 36, 36, 0], + [429, "PAD17_11", 76.1417, 3949.9606, "T", "DIP", "ZIFI_TX", "", "O", 75, 55, 36, 36, 0], + [430, "PAD17_11", 76.1417, 3949.9606, "T", "DIP", "ZIFI_TX", "", "O", 75, 55, 36, 36, 0], + [431, "PAD18_10", 76.1417, 4049.9606, "T", "DIP", "PCM_DIN", "", "O", 75, 55, 36, 36, 0], + [432, "PAD18_10", 76.1417, 4049.9606, "T", "DIP", "PCM_DIN", "", "O", 75, 55, 36, 36, 0], + [433, "PAD19_9", 76.1417, 4149.9606, "T", "DIP", "PCM_LRCK", "", "O", 75, 55, 36, 36, 0], + [434, "PAD19_9", 76.1417, 4149.9606, "T", "DIP", "PCM_LRCK", "", "O", 75, 55, 36, 36, 0], + [435, "PAD20_8", 76.1417, 4249.9606, "T", "DIP", "PCM_BLK", "", "O", 75, 55, 36, 36, 0], + [436, "PAD20_8", 76.1417, 4249.9606, "T", "DIP", "PCM_BLK", "", "O", 75, 55, 36, 36, 0], + [437, "PAD21_1", -108.8583, 2949.9606, "T", "DIP", "VCC5", "", "C", 65, 65, 36, 36, 90], + [438, "PAD21_1", -108.8583, 2949.9606, "T", "DIP", "VCC5", "", "C", 65, 65, 36, 36, 90], + [439, "PAD22_3", -108.8583, 3149.9606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 90], + [440, "PAD22_3", -108.8583, 3149.9606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 90], + [441, "PAD23_4", -108.8583, 3249.9606, "T", "DIP", "PCM_LRCK", "", "C", 65, 65, 36, 36, 90], + [442, "PAD23_4", -108.8583, 3249.9606, "T", "DIP", "PCM_LRCK", "", "C", 65, 65, 36, 36, 90], + [443, "PAD24_5", -108.8583, 3349.9606, "T", "DIP", "PCM_DIN", "", "C", 65, 65, 36, 36, 90], + [444, "PAD24_5", -108.8583, 3349.9606, "T", "DIP", "PCM_DIN", "", "C", 65, 65, 36, 36, 90], + [445, "PAD25_6", -108.8583, 3449.9606, "T", "DIP", "PCM_BLK", "", "C", 65, 65, 36, 36, 90], + [446, "PAD25_6", -108.8583, 3449.9606, "T", "DIP", "PCM_BLK", "", "C", 65, 65, 36, 36, 90], + [447, "PAD26_7", -108.8583, 3549.9606, "T", "DIP", "L_OUT", "", "C", 65, 65, 36, 36, 90], + [448, "PAD26_7", -108.8583, 3549.9606, "T", "DIP", "L_OUT", "", "C", 65, 65, 36, 36, 90], + [449, "PAD27_8", -108.8583, 3649.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 90], + [450, "PAD27_8", -108.8583, 3649.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 90], + [451, "PAD28_9", -108.8583, 3749.9606, "T", "DIP", "R_OUT", "", "C", 65, 65, 36, 36, 90], + [452, "PAD28_9", -108.8583, 3749.9606, "T", "DIP", "R_OUT", "", "C", 65, 65, 36, 36, 90], + [453, "PAD29_40", 766.1417, 2114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [454, "PAD29_40", 766.1417, 2114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [455, "PAD30_39", 866.1417, 2114.9606, "T", "DIP", "DASP_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [456, "PAD30_39", 866.1417, 2114.9606, "T", "DIP", "DASP_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [457, "PAD31_38", 766.1417, 2014.9606, "T", "DIP", "ICS1_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [458, "PAD31_38", 766.1417, 2014.9606, "T", "DIP", "ICS1_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [459, "PAD32_37", 866.1417, 2014.9606, "T", "DIP", "ICS0_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [460, "PAD32_37", 866.1417, 2014.9606, "T", "DIP", "ICS0_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [461, "PAD33_36", 766.1417, 1914.9606, "T", "DIP", "IA2", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [462, "PAD33_36", 766.1417, 1914.9606, "T", "DIP", "IA2", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [463, "PAD34_35", 866.1417, 1914.9606, "T", "DIP", "$1N192", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [464, "PAD34_35", 866.1417, 1914.9606, "T", "DIP", "$1N192", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [465, "PAD35_33", 866.1417, 1814.9606, "T", "DIP", "ESP_MOSI", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [466, "PAD35_33", 866.1417, 1814.9606, "T", "DIP", "ESP_MOSI", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [467, "PAD36_30", 766.1417, 1614.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [468, "PAD36_30", 766.1417, 1614.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [469, "PAD37_27", 866.1417, 1514.9606, "T", "DIP", "ESP_MISO", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [470, "PAD37_27", 866.1417, 1514.9606, "T", "DIP", "ESP_MISO", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [471, "PAD38_26", 766.1417, 1414.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [472, "PAD38_26", 766.1417, 1414.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [473, "PAD39_25", 866.1417, 1414.9606, "T", "DIP", "IRD_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [474, "PAD39_25", 866.1417, 1414.9606, "T", "DIP", "IRD_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [475, "PAD40_24", 766.1417, 1314.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [476, "PAD40_24", 766.1417, 1314.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [477, "PAD41_23", 866.1417, 1314.9606, "T", "DIP", "IWR_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [478, "PAD41_23", 866.1417, 1314.9606, "T", "DIP", "IWR_", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [479, "PAD42_22", 766.1417, 1214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [480, "PAD42_22", 766.1417, 1214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [481, "PAD43_20", 766.1417, 1114.9606, "T", "DIP", "$1N233", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [482, "PAD43_20", 766.1417, 1114.9606, "T", "DIP", "$1N233", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [483, "PAD44_19", 866.1417, 1114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [484, "PAD44_19", 866.1417, 1114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [485, "PAD45_18", 766.1417, 1014.9606, "T", "DIP", "ID15", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [486, "PAD45_18", 766.1417, 1014.9606, "T", "DIP", "ID15", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [487, "PAD46_17", 866.1417, 1014.9606, "T", "DIP", "ID0", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [488, "PAD46_17", 866.1417, 1014.9606, "T", "DIP", "ID0", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [489, "PAD47_16", 766.1417, 914.9606, "T", "DIP", "ID14", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [490, "PAD47_16", 766.1417, 914.9606, "T", "DIP", "ID14", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [491, "PAD48_15", 866.1417, 914.9606, "T", "DIP", "ID1", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [492, "PAD48_15", 866.1417, 914.9606, "T", "DIP", "ID1", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [493, "PAD49_14", 766.1417, 814.9606, "T", "DIP", "ID13", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [494, "PAD49_14", 766.1417, 814.9606, "T", "DIP", "ID13", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [495, "PAD50_13", 866.1417, 814.9606, "T", "DIP", "ID2", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [496, "PAD50_13", 866.1417, 814.9606, "T", "DIP", "ID2", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [497, "PAD51_12", 766.1417, 714.9606, "T", "DIP", "ID12", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [498, "PAD51_12", 766.1417, 714.9606, "T", "DIP", "ID12", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [499, "PAD52_11", 866.1417, 714.9606, "T", "DIP", "ID3", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [500, "PAD52_11", 866.1417, 714.9606, "T", "DIP", "ID3", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [501, "PAD53_10", 766.1417, 614.9606, "T", "DIP", "ID11", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [502, "PAD53_10", 766.1417, 614.9606, "T", "DIP", "ID11", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [503, "PAD54_9", 866.1417, 614.9606, "T", "DIP", "ID4", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [504, "PAD54_9", 866.1417, 614.9606, "T", "DIP", "ID4", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [505, "PAD55_8", 766.1417, 514.9606, "T", "DIP", "ID10", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [506, "PAD55_8", 766.1417, 514.9606, "T", "DIP", "ID10", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [507, "PAD56_7", 866.1417, 514.9606, "T", "DIP", "ID5", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [508, "PAD56_7", 866.1417, 514.9606, "T", "DIP", "ID5", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [509, "PAD57_6", 766.1417, 414.9606, "T", "DIP", "ID9", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [510, "PAD57_6", 766.1417, 414.9606, "T", "DIP", "ID9", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [511, "PAD58_5", 866.1417, 414.9606, "T", "DIP", "ID6", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [512, "PAD58_5", 866.1417, 414.9606, "T", "DIP", "ID6", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [513, "PAD59_4", 766.1417, 314.9606, "T", "DIP", "ID8", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [514, "PAD59_4", 766.1417, 314.9606, "T", "DIP", "ID8", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [515, "PAD60_3", 866.1417, 314.9606, "T", "DIP", "ID7", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [516, "PAD60_3", 866.1417, 314.9606, "T", "DIP", "ID7", "", "C", 62.992, 62.992, 39.37, 39.37, 90], + [517, "PAD61_2", 766.1417, 214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [518, "PAD61_2", 766.1417, 214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 39.37, 39.37, 90], + [519, "PAD62_1", 866.1417, 214.9606, "T", "DIP", "ESP_CS", "", "R", 62.992, 62.992, 39.37, 39.37, 90], + [520, "PAD62_1", 866.1417, 214.9606, "T", "DIP", "ESP_CS", "", "R", 62.992, 62.992, 39.37, 39.37, 90], + [521, "PAD63_1", 241.1417, 214.9606, "T", "DIP", "ESP_CS", "", "R", 62.992, 62.992, 36, 36, 90], + [522, "PAD63_1", 241.1417, 214.9606, "T", "DIP", "ESP_CS", "", "R", 62.992, 62.992, 36, 36, 90], + [523, "PAD64_3", 241.1417, 314.9606, "T", "DIP", "ID7", "", "C", 62.992, 62.992, 36, 36, 90], + [524, "PAD64_3", 241.1417, 314.9606, "T", "DIP", "ID7", "", "C", 62.992, 62.992, 36, 36, 90], + [525, "PAD65_4", 141.1417, 314.9606, "T", "DIP", "ID8", "", "C", 62.992, 62.992, 36, 36, 90], + [526, "PAD65_4", 141.1417, 314.9606, "T", "DIP", "ID8", "", "C", 62.992, 62.992, 36, 36, 90], + [527, "PAD66_5", 241.1417, 414.9606, "T", "DIP", "ID6", "", "C", 62.992, 62.992, 36, 36, 90], + [528, "PAD66_5", 241.1417, 414.9606, "T", "DIP", "ID6", "", "C", 62.992, 62.992, 36, 36, 90], + [529, "PAD67_6", 141.1417, 414.9606, "T", "DIP", "ID9", "", "C", 62.992, 62.992, 36, 36, 90], + [530, "PAD67_6", 141.1417, 414.9606, "T", "DIP", "ID9", "", "C", 62.992, 62.992, 36, 36, 90], + [531, "PAD68_7", 241.1417, 514.9606, "T", "DIP", "ID5", "", "C", 62.992, 62.992, 36, 36, 90], + [532, "PAD68_7", 241.1417, 514.9606, "T", "DIP", "ID5", "", "C", 62.992, 62.992, 36, 36, 90], + [533, "PAD69_8", 141.1417, 514.9606, "T", "DIP", "ID10", "", "C", 62.992, 62.992, 36, 36, 90], + [534, "PAD69_8", 141.1417, 514.9606, "T", "DIP", "ID10", "", "C", 62.992, 62.992, 36, 36, 90], + [535, "PAD70_9", 241.1417, 614.9606, "T", "DIP", "ID4", "", "C", 62.992, 62.992, 36, 36, 90], + [536, "PAD70_9", 241.1417, 614.9606, "T", "DIP", "ID4", "", "C", 62.992, 62.992, 36, 36, 90], + [537, "PAD71_10", 141.1417, 614.9606, "T", "DIP", "ID11", "", "C", 62.992, 62.992, 36, 36, 90], + [538, "PAD71_10", 141.1417, 614.9606, "T", "DIP", "ID11", "", "C", 62.992, 62.992, 36, 36, 90], + [539, "PAD72_11", 241.1417, 714.9606, "T", "DIP", "ID3", "", "C", 62.992, 62.992, 36, 36, 90], + [540, "PAD72_11", 241.1417, 714.9606, "T", "DIP", "ID3", "", "C", 62.992, 62.992, 36, 36, 90], + [541, "PAD73_12", 141.1417, 714.9606, "T", "DIP", "ID12", "", "C", 62.992, 62.992, 36, 36, 90], + [542, "PAD73_12", 141.1417, 714.9606, "T", "DIP", "ID12", "", "C", 62.992, 62.992, 36, 36, 90], + [543, "PAD74_13", 241.1417, 814.9606, "T", "DIP", "ID2", "", "C", 62.992, 62.992, 36, 36, 90], + [544, "PAD74_13", 241.1417, 814.9606, "T", "DIP", "ID2", "", "C", 62.992, 62.992, 36, 36, 90], + [545, "PAD75_14", 141.1417, 814.9606, "T", "DIP", "ID13", "", "C", 62.992, 62.992, 36, 36, 90], + [546, "PAD75_14", 141.1417, 814.9606, "T", "DIP", "ID13", "", "C", 62.992, 62.992, 36, 36, 90], + [547, "PAD76_15", 241.1417, 914.9606, "T", "DIP", "ID1", "", "C", 62.992, 62.992, 36, 36, 90], + [548, "PAD76_15", 241.1417, 914.9606, "T", "DIP", "ID1", "", "C", 62.992, 62.992, 36, 36, 90], + [549, "PAD77_16", 141.1417, 914.9606, "T", "DIP", "ID14", "", "C", 62.992, 62.992, 36, 36, 90], + [550, "PAD77_16", 141.1417, 914.9606, "T", "DIP", "ID14", "", "C", 62.992, 62.992, 36, 36, 90], + [551, "PAD78_17", 241.1417, 1014.9606, "T", "DIP", "ID0", "", "C", 62.992, 62.992, 36, 36, 90], + [552, "PAD78_17", 241.1417, 1014.9606, "T", "DIP", "ID0", "", "C", 62.992, 62.992, 36, 36, 90], + [553, "PAD79_18", 141.1417, 1014.9606, "T", "DIP", "ID15", "", "C", 62.992, 62.992, 36, 36, 90], + [554, "PAD79_18", 141.1417, 1014.9606, "T", "DIP", "ID15", "", "C", 62.992, 62.992, 36, 36, 90], + [555, "PAD80_19", 241.1417, 1114.9606, "T", "DIP", "GND", "GND", "C", 55, 55, 36, 36, 90], + [556, "PAD80_19", 241.1417, 1114.9606, "T", "DIP", "GND", "GND", "C", 55, 55, 36, 36, 90], + [557, "PAD81_20", 141.1417, 1114.9606, "T", "DIP", "IDE5V", "", "C", 62.992, 62.992, 36, 36, 90], + [558, "PAD81_20", 141.1417, 1114.9606, "T", "DIP", "IDE5V", "", "C", 62.992, 62.992, 36, 36, 90], + [559, "PAD82_22", 141.1417, 1214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [560, "PAD82_22", 141.1417, 1214.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [561, "PAD83_23", 241.1417, 1314.9606, "T", "DIP", "IWR_", "", "C", 62.992, 62.992, 36, 36, 90], + [562, "PAD83_23", 241.1417, 1314.9606, "T", "DIP", "IWR_", "", "C", 62.992, 62.992, 36, 36, 90], + [563, "PAD84_24", 141.1417, 1314.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [564, "PAD84_24", 141.1417, 1314.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [565, "PAD85_25", 241.1417, 1414.9606, "T", "DIP", "IRD_", "", "C", 62.992, 62.992, 36, 36, 90], + [566, "PAD85_25", 241.1417, 1414.9606, "T", "DIP", "IRD_", "", "C", 62.992, 62.992, 36, 36, 90], + [567, "PAD86_26", 141.1417, 1414.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [568, "PAD86_26", 141.1417, 1414.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [569, "PAD87_27", 241.1417, 1514.9606, "T", "DIP", "ESP_MISO", "", "C", 62.992, 62.992, 36, 36, 90], + [570, "PAD87_27", 241.1417, 1514.9606, "T", "DIP", "ESP_MISO", "", "C", 62.992, 62.992, 36, 36, 90], + [571, "PAD88_30", 141.1417, 1614.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [572, "PAD88_30", 141.1417, 1614.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [573, "PAD89_33", 241.1417, 1814.9606, "T", "DIP", "ESP_MOSI", "", "C", 62.992, 62.992, 36, 36, 90], + [574, "PAD89_33", 241.1417, 1814.9606, "T", "DIP", "ESP_MOSI", "", "C", 62.992, 62.992, 36, 36, 90], + [575, "PAD90_35", 241.1417, 1914.9606, "T", "DIP", "$1N192", "", "C", 62.992, 62.992, 36, 36, 90], + [576, "PAD90_35", 241.1417, 1914.9606, "T", "DIP", "$1N192", "", "C", 62.992, 62.992, 36, 36, 90], + [577, "PAD91_36", 141.1417, 1914.9606, "T", "DIP", "IA2", "", "C", 62.992, 62.992, 36, 36, 90], + [578, "PAD91_36", 141.1417, 1914.9606, "T", "DIP", "IA2", "", "C", 62.992, 62.992, 36, 36, 90], + [579, "PAD92_37", 241.1417, 2014.9606, "T", "DIP", "ICS0_", "", "C", 62.992, 62.992, 36, 36, 90], + [580, "PAD92_37", 241.1417, 2014.9606, "T", "DIP", "ICS0_", "", "C", 62.992, 62.992, 36, 36, 90], + [581, "PAD93_38", 141.1417, 2014.9606, "T", "DIP", "ICS1_", "", "C", 62.992, 62.992, 36, 36, 90], + [582, "PAD93_38", 141.1417, 2014.9606, "T", "DIP", "ICS1_", "", "C", 62.992, 62.992, 36, 36, 90], + [583, "PAD94_39", 241.1417, 2114.9606, "T", "DIP", "DASP_", "", "C", 62.992, 62.992, 36, 36, 90], + [584, "PAD94_39", 241.1417, 2114.9606, "T", "DIP", "DASP_", "", "C", 62.992, 62.992, 36, 36, 90], + [585, "PAD95_40", 141.1417, 2114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [586, "PAD95_40", 141.1417, 2114.9606, "T", "DIP", "GND", "GND", "C", 62.992, 62.992, 36, 36, 90], + [587, "PAD96_20", 1507.6417, 2365.3606, "T", "DIP", "JOYF", "", "C", 65, 65, 36, 36, 270], + [588, "PAD96_20", 1507.6417, 2365.3606, "T", "DIP", "JOYF", "", "C", 65, 65, 36, 36, 270], + [589, "PAD97_19", 1407.6417, 2365.3606, "T", "DIP", "JOYD", "", "C", 65, 65, 36, 36, 270], + [590, "PAD97_19", 1407.6417, 2365.3606, "T", "DIP", "JOYD", "", "C", 65, 65, 36, 36, 270], + [591, "PAD98_18", 1507.6417, 2465.3606, "T", "DIP", "JOYU", "", "C", 65, 65, 36, 36, 270], + [592, "PAD98_18", 1507.6417, 2465.3606, "T", "DIP", "JOYU", "", "C", 65, 65, 36, 36, 270], + [593, "PAD99_17", 1407.6417, 2465.3606, "T", "DIP", "JOYR", "", "C", 65, 65, 36, 36, 270], + [594, "PAD99_17", 1407.6417, 2465.3606, "T", "DIP", "JOYR", "", "C", 65, 65, 36, 36, 270], + [595, "PAD100_16", 1507.6417, 2565.3606, "T", "DIP", "JOYL", "", "C", 65, 65, 36, 36, 270], + [596, "PAD100_16", 1507.6417, 2565.3606, "T", "DIP", "JOYL", "", "C", 65, 65, 36, 36, 270], + [597, "PAD101_15", 1407.6417, 2565.3606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 270], + [598, "PAD101_15", 1407.6417, 2565.3606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 270], + [599, "PAD102_14", 1507.6417, 2665.3606, "T", "DIP", "ZXCOL0", "", "C", 65, 65, 36, 36, 270], + [600, "PAD102_14", 1507.6417, 2665.3606, "T", "DIP", "ZXCOL0", "", "C", 65, 65, 36, 36, 270], + [601, "PAD103_13", 1407.6417, 2665.3606, "T", "DIP", "ZXCOL1", "", "C", 65, 65, 36, 36, 270], + [602, "PAD103_13", 1407.6417, 2665.3606, "T", "DIP", "ZXCOL1", "", "C", 65, 65, 36, 36, 270], + [603, "PAD104_12", 1507.6417, 2765.3606, "T", "DIP", "ZXCOL2", "", "C", 65, 65, 36, 36, 270], + [604, "PAD104_12", 1507.6417, 2765.3606, "T", "DIP", "ZXCOL2", "", "C", 65, 65, 36, 36, 270], + [605, "PAD105_11", 1407.6417, 2765.3606, "T", "DIP", "ZXCOL3", "", "C", 65, 65, 36, 36, 270], + [606, "PAD105_11", 1407.6417, 2765.3606, "T", "DIP", "ZXCOL3", "", "C", 65, 65, 36, 36, 270], + [607, "PAD106_10", 1507.6417, 2865.3606, "T", "DIP", "ZXCOL4", "", "C", 65, 65, 36, 36, 270], + [608, "PAD106_10", 1507.6417, 2865.3606, "T", "DIP", "ZXCOL4", "", "C", 65, 65, 36, 36, 270], + [609, "PAD107_9", 1407.6417, 2865.3606, "T", "DIP", "SOFTRST_", "", "C", 65, 65, 36, 36, 270], + [610, "PAD107_9", 1407.6417, 2865.3606, "T", "DIP", "SOFTRST_", "", "C", 65, 65, 36, 36, 270], + [611, "PAD108_8", 1507.6417, 2965.3606, "T", "DIP", "ZXROW7", "", "C", 65, 65, 36, 36, 270], + [612, "PAD108_8", 1507.6417, 2965.3606, "T", "DIP", "ZXROW7", "", "C", 65, 65, 36, 36, 270], + [613, "PAD109_7", 1407.6417, 2965.3606, "T", "DIP", "ZXROW6", "", "C", 65, 65, 36, 36, 270], + [614, "PAD109_7", 1407.6417, 2965.3606, "T", "DIP", "ZXROW6", "", "C", 65, 65, 36, 36, 270], + [615, "PAD110_6", 1507.6417, 3065.3606, "T", "DIP", "ZXROW5", "", "C", 65, 65, 36, 36, 270], + [616, "PAD110_6", 1507.6417, 3065.3606, "T", "DIP", "ZXROW5", "", "C", 65, 65, 36, 36, 270], + [617, "PAD111_5", 1407.6417, 3065.3606, "T", "DIP", "ZXROW4", "", "C", 65, 65, 36, 36, 270], + [618, "PAD111_5", 1407.6417, 3065.3606, "T", "DIP", "ZXROW4", "", "C", 65, 65, 36, 36, 270], + [619, "PAD112_4", 1507.6417, 3165.3606, "T", "DIP", "ZXROW3", "", "C", 65, 65, 36, 36, 270], + [620, "PAD112_4", 1507.6417, 3165.3606, "T", "DIP", "ZXROW3", "", "C", 65, 65, 36, 36, 270], + [621, "PAD113_3", 1407.6417, 3165.3606, "T", "DIP", "ZXROW2", "", "C", 65, 65, 36, 36, 270], + [622, "PAD113_3", 1407.6417, 3165.3606, "T", "DIP", "ZXROW2", "", "C", 65, 65, 36, 36, 270], + [623, "PAD114_2", 1507.6417, 3265.3606, "T", "DIP", "ZXROW1", "", "C", 65, 65, 36, 36, 270], + [624, "PAD114_2", 1507.6417, 3265.3606, "T", "DIP", "ZXROW1", "", "C", 65, 65, 36, 36, 270], + [625, "PAD115_1", 1407.6417, 3265.3606, "T", "DIP", "ZXROW0", "", "R", 65, 65, 36, 36, 270], + [626, "PAD115_1", 1407.6417, 3265.3606, "T", "DIP", "ZXROW0", "", "R", 65, 65, 36, 36, 270], + [627, "PAD116_1", 1397.6378, 3787.0078, "T", "DIP", "JOYU", "", "R", 60, 60, 36, 36, 90], + [628, "PAD116_1", 1397.6378, 3787.0078, "T", "DIP", "JOYU", "", "R", 60, 60, 36, 36, 90], + [629, "PAD117_2", 1297.6378, 3787.0078, "T", "DIP", "JOYF", "", "C", 60, 60, 36, 36, 90], + [630, "PAD117_2", 1297.6378, 3787.0078, "T", "DIP", "JOYF", "", "C", 60, 60, 36, 36, 90], + [631, "PAD118_3", 1397.6378, 3887.0078, "T", "DIP", "JOYD", "", "C", 60, 60, 36, 36, 90], + [632, "PAD118_3", 1397.6378, 3887.0078, "T", "DIP", "JOYD", "", "C", 60, 60, 36, 36, 90], + [633, "PAD119_4", 1297.6378, 3887.0078, "T", "DIP", "ZXROW2", "", "C", 60, 60, 36, 36, 90], + [634, "PAD119_4", 1297.6378, 3887.0078, "T", "DIP", "ZXROW2", "", "C", 60, 60, 36, 36, 90], + [635, "PAD120_5", 1397.6378, 3987.0078, "T", "DIP", "JOYL", "", "C", 60, 60, 36, 36, 90], + [636, "PAD120_5", 1397.6378, 3987.0078, "T", "DIP", "JOYL", "", "C", 60, 60, 36, 36, 90], + [637, "PAD121_6", 1297.6378, 3987.0078, "T", "DIP", "GND", "GND", "C", 60, 60, 36, 36, 90], + [638, "PAD121_6", 1297.6378, 3987.0078, "T", "DIP", "GND", "GND", "C", 60, 60, 36, 36, 90], + [639, "PAD122_7", 1397.6378, 4087.0078, "T", "DIP", "JOYR", "", "C", 60, 60, 36, 36, 90], + [640, "PAD122_7", 1397.6378, 4087.0078, "T", "DIP", "JOYR", "", "C", 60, 60, 36, 36, 90], + [641, "PAD123_8", 1297.6378, 4087.0078, "T", "DIP", "ZXROW5", "", "C", 60, 60, 36, 36, 90], + [642, "PAD123_8", 1297.6378, 4087.0078, "T", "DIP", "ZXROW5", "", "C", 60, 60, 36, 36, 90], + [643, "PAD124_9", 1397.6378, 4187.0078, "T", "DIP", "VCC5", "", "C", 60, 60, 36, 36, 90], + [644, "PAD124_9", 1397.6378, 4187.0078, "T", "DIP", "VCC5", "", "C", 60, 60, 36, 36, 90], + [645, "PAD125_10", 823.4417, 3940.1606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 0], + [646, "PAD125_10", 823.4417, 3940.1606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 0], + [647, "PAD126_9", 823.4417, 3840.1606, "T", "DIP", "ZIFI_TX", "", "C", 65, 65, 36, 36, 0], + [648, "PAD126_9", 823.4417, 3840.1606, "T", "DIP", "ZIFI_TX", "", "C", 65, 65, 36, 36, 0], + [649, "PAD127_3", 523.4417, 3840.1606, "T", "DIP", "ZIFI_RX", "", "C", 65, 65, 36, 36, 0], + [650, "PAD127_3", 523.4417, 3840.1606, "T", "DIP", "ZIFI_RX", "", "C", 65, 65, 36, 36, 0], + [651, "PAD128_2", 423.4417, 3940.1606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 0], + [652, "PAD128_2", 423.4417, 3940.1606, "T", "DIP", "GND", "GND", "C", 65, 65, 36, 36, 0], + [653, "PAD129_1", 1791.3386, 3787.0078, "T", "DIP", "ZXCOL3", "", "R", 60, 60, 36, 36, 90], + [654, "PAD129_1", 1791.3386, 3787.0078, "T", "DIP", "ZXCOL3", "", "R", 60, 60, 36, 36, 90], + [655, "PAD130_2", 1691.3386, 3787.0078, "T", "DIP", "ZXCOL4", "", "C", 60, 60, 36, 36, 90], + [656, "PAD130_2", 1691.3386, 3787.0078, "T", "DIP", "ZXCOL4", "", "C", 60, 60, 36, 36, 90], + [657, "PAD131_3", 1791.3386, 3887.0078, "T", "DIP", "ZXCOL2", "", "C", 60, 60, 36, 36, 90], + [658, "PAD131_3", 1791.3386, 3887.0078, "T", "DIP", "ZXCOL2", "", "C", 60, 60, 36, 36, 90], + [659, "PAD132_4", 1691.3386, 3887.0078, "T", "DIP", "ZXROW2", "", "C", 60, 60, 36, 36, 90], + [660, "PAD132_4", 1691.3386, 3887.0078, "T", "DIP", "ZXROW2", "", "C", 60, 60, 36, 36, 90], + [661, "PAD133_5", 1791.3386, 3987.0078, "T", "DIP", "ZXCOL1", "", "C", 60, 60, 36, 36, 90], + [662, "PAD133_5", 1791.3386, 3987.0078, "T", "DIP", "ZXCOL1", "", "C", 60, 60, 36, 36, 90], + [663, "PAD134_6", 1691.3386, 3987.0078, "T", "DIP", "GND", "GND", "C", 60, 60, 36, 36, 90], + [664, "PAD134_6", 1691.3386, 3987.0078, "T", "DIP", "GND", "GND", "C", 60, 60, 36, 36, 90], + [665, "PAD135_7", 1791.3386, 4087.0078, "T", "DIP", "ZXCOL0", "", "C", 60, 60, 36, 36, 90], + [666, "PAD135_7", 1791.3386, 4087.0078, "T", "DIP", "ZXCOL0", "", "C", 60, 60, 36, 36, 90], + [667, "PAD136_8", 1691.3386, 4087.0078, "T", "DIP", "ZXROW1", "", "C", 60, 60, 36, 36, 90], + [668, "PAD136_8", 1691.3386, 4087.0078, "T", "DIP", "ZXROW1", "", "C", 60, 60, 36, 36, 90], + [669, "PAD137_9", 1791.3386, 4187.0078, "T", "DIP", "VCC5", "", "C", 60, 60, 36, 36, 90], + [670, "PAD137_9", 1791.3386, 4187.0078, "T", "DIP", "VCC5", "", "C", 60, 60, 36, 36, 90], + [671, "PAD138_1", -908.8583, 4244.9606, "T", "DIP", "L_OUT", "", "R", 65, 65, 36, 36, 0], + [672, "PAD138_1", -908.8583, 4244.9606, "T", "DIP", "L_OUT", "", "R", 65, 65, 36, 36, 0], + [673, "PAD139_2", -808.8583, 4244.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 0], + [674, "PAD139_2", -808.8583, 4244.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 0], + [675, "PAD140_3", -708.8583, 4244.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 0], + [676, "PAD140_3", -708.8583, 4244.9606, "T", "DIP", "AGND", "", "C", 65, 65, 36, 36, 0], + [677, "PAD141_4", -608.8583, 4244.9606, "T", "DIP", "R_OUT", "", "C", 65, 65, 36, 36, 0], + [678, "PAD141_4", -608.8583, 4244.9606, "T", "DIP", "R_OUT", "", "C", 65, 65, 36, 36, 0], + [679, "PAD142_1", 623.7817, 2454.9606, "T", "SMD", "VCC5", "", "R", 74.803, 93.543, 0, 0, 180], + [680, "PAD143_2", 828.5017, 2454.9606, "T", "SMD", "GND", "GND", "R", 74.803, 93.543, 0, 0, 180], + [681, "PAD144_1", 621.1417, 1657.5206, "T", "DIP", "VCC5", "", "C", 70.866, 70.866, 39.37, 39.37, 270], + [682, "PAD144_1", 621.1417, 1657.5206, "T", "DIP", "VCC5", "", "C", 70.866, 70.866, 39.37, 39.37, 270], + [683, "PAD145_2", 621.1417, 1315.0006, "T", "DIP", "$1N233", "", "C", 70.866, 70.866, 39.37, 39.37, 270], + [684, "PAD145_2", 621.1417, 1315.0006, "T", "DIP", "$1N233", "", "C", 70.866, 70.866, 39.37, 39.37, 270] + ] +} +} \ No newline at end of file diff --git a/hardware/gerber/Gerber_BoardOutlineLayer.GKO b/hardware/gerber/Gerber_BoardOutlineLayer.GKO new file mode 100644 index 0000000..f554376 --- /dev/null +++ b/hardware/gerber/Gerber_BoardOutlineLayer.GKO @@ -0,0 +1,62 @@ +G04 Layer: BoardOutlineLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%ADD10C,0.254*% +%ADD11C,0.8282*% +G75* + + +G04 PolygonModel Start* +G54D10* +G01X4777706Y5500016D02* +G01X2454000Y5500016D01* +G01X2454000Y5500016D02* +G01X2454000Y150000D01* +G01X4927706Y5650016D02* +G01X4900000Y11150000D01* +G01X2750004Y13499997D02* +G01X150000Y13500000D01* +G01X0Y13350000D02* +G01X0Y10946000D01* +G01X2304000Y0D02* +G01X150000Y0D01* +G01X-2572300Y10796000D02* +G01X-2572300Y6796000D01* +G01X-2422300Y10946000D02* +G01X0Y10946000D01* +G01X-2422300Y6646000D02* +G01X0Y6646000D01* +G01X2900000Y11300000D02* +G01X2900004Y13349997D01* +G01X2900000Y11300000D02* +G01X4750000Y11300000D01* +G01X0Y6646000D02* +G01X0Y150000D01* +G01X2900004Y13349997D02* +G03X2750004Y13499997I-150000J0D01* +G01X150000Y13500000D02* +G03X0Y13350000I0J-150000D01* +G01X4777706Y5500016D02* +G03X4927706Y5650016I0J150000D01* +G01X4900000Y11150000D02* +G03X4750000Y11300000I-150000J0D01* +G01X-2572300Y6796000D02* +G03X-2422300Y6646000I150000J0D01* +G01X-2422300Y10946000D02* +G03X-2572300Y10796000I0J-150000D01* +G01X2304000Y0D02* +G03X2454000Y150000I0J150000D01* +G01X0Y150000D02* +G03X150000Y0I150000J0D01* + +M02* + diff --git a/hardware/gerber/Gerber_BottomLayer.GBL b/hardware/gerber/Gerber_BottomLayer.GBL new file mode 100644 index 0000000..dcd098f --- /dev/null +++ b/hardware/gerber/Gerber_BottomLayer.GBL @@ -0,0 +1,8024 @@ +G04 Layer: BottomLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 85* +%FSLAX45Y45*% +%MOMM*% +%ADD10C,0.2032*% +%ADD11C,0.254*% +%ADD12C,1.651*% +%ADD13R,1.651X1.651*% +%ADD14R,1.13254X1.37701*% +%ADD15O,1.905X1.397*% +%ADD16R,1.9127X1.397*% +%ADD17R,1.905X1.397*% +%ADD18C,1.6*% +%ADD19R,1.6X1.6*% +%ADD20C,1.397*% +%ADD21R,1.524X1.524*% +%ADD22C,1.524*% +%ADD23C,1.8*% +%ADD24C,0.4064*% +%ADD25C,1.016*% +G75* + + +G04 Copper Start* +G36* +G01X-5842Y6762187D02* +G01X-5842Y6681814D01* +G01X-2422300Y6681814D01* +G01X-2442128Y6683549D01* +G01X-2461354Y6688700D01* +G01X-2479393Y6697112D01* +G01X-2495697Y6708528D01* +G01X-2509772Y6722603D01* +G01X-2521188Y6738907D01* +G01X-2529600Y6756946D01* +G01X-2534751Y6776172D01* +G01X-2536486Y6796000D01* +G01X-2536486Y7503821D01* +G01X-394359Y7503821D01* +G01X-394359Y7481979D01* +G01X-390346Y7460508D01* +G01X-382455Y7440141D01* +G01X-370957Y7421570D01* +G01X-356241Y7405428D01* +G01X-338811Y7392265D01* +G01X-319258Y7382529D01* +G01X-298249Y7376551D01* +G01X-276500Y7374536D01* +G01X-276500Y7374536D01* +G01X-254751Y7376551D01* +G01X-233742Y7382529D01* +G01X-214189Y7392265D01* +G01X-196759Y7405428D01* +G01X-182044Y7421570D01* +G01X-170545Y7440141D01* +G01X-162655Y7460508D01* +G01X-158641Y7481979D01* +G01X-158641Y7503821D01* +G01X-162655Y7525292D01* +G01X-170545Y7545659D01* +G01X-182044Y7564230D01* +G01X-196759Y7580372D01* +G01X-214189Y7593535D01* +G01X-233742Y7603271D01* +G01X-254751Y7609249D01* +G01X-276500Y7611264D01* +G01X-298249Y7609249D01* +G01X-319258Y7603271D01* +G01X-338811Y7593535D01* +G01X-356241Y7580372D01* +G01X-370957Y7564230D01* +G01X-382455Y7545659D01* +G01X-390346Y7525292D01* +G01X-394359Y7503821D01* +G01X-2536486Y7503821D01* +G01X-2536486Y7757821D01* +G01X-2426359Y7757821D01* +G01X-2426359Y7735979D01* +G01X-2422346Y7714508D01* +G01X-2414455Y7694141D01* +G01X-2402957Y7675570D01* +G01X-2388241Y7659428D01* +G01X-2370811Y7646265D01* +G01X-2351258Y7636529D01* +G01X-2330249Y7630551D01* +G01X-2308500Y7628536D01* +G01X-2308500Y7628536D01* +G01X-2286751Y7630551D01* +G01X-2265742Y7636529D01* +G01X-2246189Y7646265D01* +G01X-2228759Y7659428D01* +G01X-2214044Y7675570D01* +G01X-2202545Y7694141D01* +G01X-2194655Y7714508D01* +G01X-2190641Y7735979D01* +G01X-2190641Y7757821D01* +G01X-2190641Y7757821D01* +G01X-394359Y7757821D01* +G01X-394359Y7735979D01* +G01X-390346Y7714508D01* +G01X-382455Y7694141D01* +G01X-370957Y7675570D01* +G01X-356241Y7659428D01* +G01X-338811Y7646265D01* +G01X-319258Y7636529D01* +G01X-298249Y7630551D01* +G01X-276500Y7628536D01* +G01X-276500Y7628536D01* +G01X-254751Y7630551D01* +G01X-233742Y7636529D01* +G01X-214189Y7646265D01* +G01X-196759Y7659428D01* +G01X-182044Y7675570D01* +G01X-170545Y7694141D01* +G01X-162655Y7714508D01* +G01X-158641Y7735979D01* +G01X-158641Y7757821D01* +G01X-162655Y7779292D01* +G01X-170545Y7799659D01* +G01X-182044Y7818230D01* +G01X-196759Y7834372D01* +G01X-214189Y7847535D01* +G01X-233742Y7857271D01* +G01X-254751Y7863249D01* +G01X-276500Y7865264D01* +G01X-298249Y7863249D01* +G01X-319258Y7857271D01* +G01X-338811Y7847535D01* +G01X-356241Y7834372D01* +G01X-370957Y7818230D01* +G01X-382455Y7799659D01* +G01X-390346Y7779292D01* +G01X-394359Y7757821D01* +G01X-2190641Y7757821D01* +G01X-2194655Y7779292D01* +G01X-2202545Y7799659D01* +G01X-2214044Y7818230D01* +G01X-2228759Y7834372D01* +G01X-2246189Y7847535D01* +G01X-2265742Y7857271D01* +G01X-2286751Y7863249D01* +G01X-2308500Y7865264D01* +G01X-2330249Y7863249D01* +G01X-2351258Y7857271D01* +G01X-2370811Y7847535D01* +G01X-2388241Y7834372D01* +G01X-2402957Y7818230D01* +G01X-2414455Y7799659D01* +G01X-2422346Y7779292D01* +G01X-2426359Y7757821D01* +G01X-2536486Y7757821D01* +G01X-2536486Y8011821D01* +G01X-2426359Y8011821D01* +G01X-2426359Y7989979D01* +G01X-2422346Y7968508D01* +G01X-2414455Y7948141D01* +G01X-2402957Y7929570D01* +G01X-2388241Y7913428D01* +G01X-2370811Y7900265D01* +G01X-2351258Y7890529D01* +G01X-2330249Y7884551D01* +G01X-2308500Y7882536D01* +G01X-2308500Y7882536D01* +G01X-2286751Y7884551D01* +G01X-2265742Y7890529D01* +G01X-2246189Y7900265D01* +G01X-2228759Y7913428D01* +G01X-2214044Y7929570D01* +G01X-2202545Y7948141D01* +G01X-2194655Y7968508D01* +G01X-2190641Y7989979D01* +G01X-2190641Y8011821D01* +G01X-2190641Y8011821D01* +G01X-394359Y8011821D01* +G01X-394359Y7989979D01* +G01X-390346Y7968508D01* +G01X-382455Y7948141D01* +G01X-370957Y7929570D01* +G01X-356241Y7913428D01* +G01X-338811Y7900265D01* +G01X-319258Y7890529D01* +G01X-298249Y7884551D01* +G01X-276500Y7882536D01* +G01X-276500Y7882536D01* +G01X-254751Y7884551D01* +G01X-233742Y7890529D01* +G01X-214189Y7900265D01* +G01X-196759Y7913428D01* +G01X-182044Y7929570D01* +G01X-170545Y7948141D01* +G01X-162655Y7968508D01* +G01X-158641Y7989979D01* +G01X-158641Y8011821D01* +G01X-162655Y8033292D01* +G01X-170545Y8053659D01* +G01X-182044Y8072230D01* +G01X-196759Y8088372D01* +G01X-214189Y8101535D01* +G01X-233742Y8111271D01* +G01X-254751Y8117249D01* +G01X-276500Y8119264D01* +G01X-298249Y8117249D01* +G01X-319258Y8111271D01* +G01X-338811Y8101535D01* +G01X-356241Y8088372D01* +G01X-370957Y8072230D01* +G01X-382455Y8053659D01* +G01X-390346Y8033292D01* +G01X-394359Y8011821D01* +G01X-2190641Y8011821D01* +G01X-2194655Y8033292D01* +G01X-2202545Y8053659D01* +G01X-2214044Y8072230D01* +G01X-2228759Y8088372D01* +G01X-2246189Y8101535D01* +G01X-2265742Y8111271D01* +G01X-2286751Y8117249D01* +G01X-2308500Y8119264D01* +G01X-2330249Y8117249D01* +G01X-2351258Y8111271D01* +G01X-2370811Y8101535D01* +G01X-2388241Y8088372D01* +G01X-2402957Y8072230D01* +G01X-2414455Y8053659D01* +G01X-2422346Y8033292D01* +G01X-2426359Y8011821D01* +G01X-2536486Y8011821D01* +G01X-2536486Y8265821D01* +G01X-2426359Y8265821D01* +G01X-2426359Y8243979D01* +G01X-2422346Y8222508D01* +G01X-2414455Y8202141D01* +G01X-2402957Y8183570D01* +G01X-2388241Y8167428D01* +G01X-2370811Y8154265D01* +G01X-2351258Y8144529D01* +G01X-2330249Y8138551D01* +G01X-2308500Y8136536D01* +G01X-2308500Y8136536D01* +G01X-2286751Y8138551D01* +G01X-2265742Y8144529D01* +G01X-2246189Y8154265D01* +G01X-2228759Y8167428D01* +G01X-2214044Y8183570D01* +G01X-2202545Y8202141D01* +G01X-2194655Y8222508D01* +G01X-2190641Y8243979D01* +G01X-2190641Y8265821D01* +G01X-2190641Y8265821D01* +G01X-394359Y8265821D01* +G01X-394359Y8243979D01* +G01X-390346Y8222508D01* +G01X-382455Y8202141D01* +G01X-370957Y8183570D01* +G01X-356241Y8167428D01* +G01X-338811Y8154265D01* +G01X-319258Y8144529D01* +G01X-298249Y8138551D01* +G01X-276500Y8136536D01* +G01X-276500Y8136536D01* +G01X-254751Y8138551D01* +G01X-233742Y8144529D01* +G01X-214189Y8154265D01* +G01X-196759Y8167428D01* +G01X-182044Y8183570D01* +G01X-170545Y8202141D01* +G01X-162655Y8222508D01* +G01X-158641Y8243979D01* +G01X-158641Y8265821D01* +G01X-162655Y8287292D01* +G01X-170545Y8307659D01* +G01X-182044Y8326230D01* +G01X-196759Y8342372D01* +G01X-214189Y8355535D01* +G01X-233742Y8365271D01* +G01X-254751Y8371249D01* +G01X-276500Y8373264D01* +G01X-298249Y8371249D01* +G01X-319258Y8365271D01* +G01X-338811Y8355535D01* +G01X-356241Y8342372D01* +G01X-370957Y8326230D01* +G01X-382455Y8307659D01* +G01X-390346Y8287292D01* +G01X-394359Y8265821D01* +G01X-2190641Y8265821D01* +G01X-2194655Y8287292D01* +G01X-2202545Y8307659D01* +G01X-2214044Y8326230D01* +G01X-2228759Y8342372D01* +G01X-2246189Y8355535D01* +G01X-2265742Y8365271D01* +G01X-2286751Y8371249D01* +G01X-2308500Y8373264D01* +G01X-2330249Y8371249D01* +G01X-2351258Y8365271D01* +G01X-2370811Y8355535D01* +G01X-2388241Y8342372D01* +G01X-2402957Y8326230D01* +G01X-2414455Y8307659D01* +G01X-2422346Y8287292D01* +G01X-2426359Y8265821D01* +G01X-2536486Y8265821D01* +G01X-2536486Y8519821D01* +G01X-2426359Y8519821D01* +G01X-2426359Y8497979D01* +G01X-2422346Y8476508D01* +G01X-2414455Y8456141D01* +G01X-2402957Y8437570D01* +G01X-2388241Y8421428D01* +G01X-2370811Y8408265D01* +G01X-2351258Y8398529D01* +G01X-2330249Y8392551D01* +G01X-2308500Y8390536D01* +G01X-2308500Y8390536D01* +G01X-2286751Y8392551D01* +G01X-2265742Y8398529D01* +G01X-2246189Y8408265D01* +G01X-2228759Y8421428D01* +G01X-2214044Y8437570D01* +G01X-2202545Y8456141D01* +G01X-2194655Y8476508D01* +G01X-2190641Y8497979D01* +G01X-2190641Y8499511D01* +G01X-394491Y8499511D01* +G01X-391010Y8478940D01* +G01X-383970Y8459299D01* +G01X-373591Y8441200D01* +G01X-360196Y8425204D01* +G01X-344200Y8411809D01* +G01X-326101Y8401430D01* +G01X-306460Y8394390D01* +G01X-285889Y8390909D01* +G01X-265025Y8391093D01* +G01X-244519Y8394938D01* +G01X-225006Y8402324D01* +G01X-207093Y8413021D01* +G01X-191336Y8426698D01* +G01X-178226Y8442928D01* +G01X-168169Y8461208D01* +G01X-161478Y8480970D01* +G01X-158361Y8501600D01* +G01X-158915Y8522457D01* +G01X-163122Y8542892D01* +G01X11097Y8717111D01* +G01X20017Y8728737D01* +G01X25625Y8742275D01* +G01X27538Y8756804D01* +G01X27538Y9026649D01* +G01X62787Y9026649D01* +G01X62787Y9007150D01* +G01X66370Y8987984D01* +G01X73413Y8969801D01* +G01X83678Y8953223D01* +G01X96815Y8938813D01* +G01X112375Y8927063D01* +G01X129830Y8918371D01* +G01X148584Y8913035D01* +G01X168000Y8911236D01* +G01X218800Y8911236D01* +G01X238216Y8913035D01* +G01X256970Y8918371D01* +G01X274425Y8927063D01* +G01X289985Y8938813D01* +G01X303122Y8953223D01* +G01X313386Y8969801D01* +G01X320430Y8987984D01* +G01X324013Y9007150D01* +G01X324013Y9026649D01* +G01X2602787Y9026649D01* +G01X2602787Y9007150D01* +G01X2606370Y8987984D01* +G01X2613413Y8969801D01* +G01X2623678Y8953223D01* +G01X2636815Y8938813D01* +G01X2652375Y8927063D01* +G01X2669830Y8918371D01* +G01X2688584Y8913035D01* +G01X2708000Y8911236D01* +G01X2758800Y8911236D01* +G01X2778216Y8913035D01* +G01X2796970Y8918371D01* +G01X2814425Y8927063D01* +G01X2829985Y8938813D01* +G01X2843122Y8953223D01* +G01X2853386Y8969801D01* +G01X2860430Y8987984D01* +G01X2864013Y9007150D01* +G01X2864013Y9026649D01* +G01X2860430Y9045816D01* +G01X2853386Y9063998D01* +G01X2843122Y9080577D01* +G01X2829985Y9094987D01* +G01X2814425Y9106737D01* +G01X2796970Y9115429D01* +G01X2778216Y9120765D01* +G01X2758800Y9122564D01* +G01X2758800Y9122564D01* +G01X2708000Y9122564D01* +G01X2688584Y9120765D01* +G01X2669830Y9115429D01* +G01X2652375Y9106737D01* +G01X2636815Y9094987D01* +G01X2623678Y9080577D01* +G01X2613413Y9063998D01* +G01X2606370Y9045816D01* +G01X2602787Y9026649D01* +G01X324013Y9026649D01* +G01X324013Y9026649D01* +G01X320430Y9045816D01* +G01X313386Y9063998D01* +G01X303122Y9080577D01* +G01X289985Y9094987D01* +G01X274425Y9106737D01* +G01X256970Y9115429D01* +G01X238216Y9120765D01* +G01X218800Y9122564D01* +G01X218800Y9122564D01* +G01X168000Y9122564D01* +G01X148584Y9120765D01* +G01X129830Y9115429D01* +G01X112375Y9106737D01* +G01X96815Y9094987D01* +G01X83678Y9080577D01* +G01X73413Y9063998D01* +G01X66370Y9045816D01* +G01X62787Y9026649D01* +G01X27538Y9026649D01* +G01X27538Y9280649D01* +G01X62787Y9280649D01* +G01X62787Y9261150D01* +G01X66370Y9241984D01* +G01X73413Y9223801D01* +G01X83678Y9207223D01* +G01X96815Y9192813D01* +G01X112375Y9181063D01* +G01X129830Y9172371D01* +G01X148584Y9167035D01* +G01X168000Y9165236D01* +G01X218800Y9165236D01* +G01X238216Y9167035D01* +G01X256970Y9172371D01* +G01X274425Y9181063D01* +G01X289985Y9192813D01* +G01X303122Y9207223D01* +G01X313386Y9223801D01* +G01X320430Y9241984D01* +G01X324013Y9261150D01* +G01X324013Y9280649D01* +G01X2602787Y9280649D01* +G01X2602787Y9261150D01* +G01X2606370Y9241984D01* +G01X2613413Y9223801D01* +G01X2623678Y9207223D01* +G01X2636815Y9192813D01* +G01X2652375Y9181063D01* +G01X2669830Y9172371D01* +G01X2688584Y9167035D01* +G01X2708000Y9165236D01* +G01X2758800Y9165236D01* +G01X2778216Y9167035D01* +G01X2796970Y9172371D01* +G01X2814425Y9181063D01* +G01X2829985Y9192813D01* +G01X2843122Y9207223D01* +G01X2853386Y9223801D01* +G01X2860430Y9241984D01* +G01X2864013Y9261150D01* +G01X2864013Y9280649D01* +G01X2860430Y9299816D01* +G01X2853386Y9317998D01* +G01X2843122Y9334577D01* +G01X2829985Y9348987D01* +G01X2814425Y9360737D01* +G01X2796970Y9369429D01* +G01X2778216Y9374765D01* +G01X2758800Y9376564D01* +G01X2758800Y9376564D01* +G01X2708000Y9376564D01* +G01X2688584Y9374765D01* +G01X2669830Y9369429D01* +G01X2652375Y9360737D01* +G01X2636815Y9348987D01* +G01X2623678Y9334577D01* +G01X2613413Y9317998D01* +G01X2606370Y9299816D01* +G01X2602787Y9280649D01* +G01X324013Y9280649D01* +G01X324013Y9280649D01* +G01X320430Y9299816D01* +G01X313386Y9317998D01* +G01X303122Y9334577D01* +G01X289985Y9348987D01* +G01X274425Y9360737D01* +G01X256970Y9369429D01* +G01X238216Y9374765D01* +G01X218800Y9376564D01* +G01X218800Y9376564D01* +G01X168000Y9376564D01* +G01X148584Y9374765D01* +G01X129830Y9369429D01* +G01X112375Y9360737D01* +G01X96815Y9348987D01* +G01X83678Y9334577D01* +G01X73413Y9317998D01* +G01X66370Y9299816D01* +G01X62787Y9280649D01* +G01X27538Y9280649D01* +G01X27538Y9534649D01* +G01X62787Y9534649D01* +G01X62787Y9515150D01* +G01X66370Y9495984D01* +G01X73413Y9477801D01* +G01X83678Y9461223D01* +G01X96815Y9446813D01* +G01X112375Y9435063D01* +G01X129830Y9426371D01* +G01X148584Y9421035D01* +G01X168000Y9419236D01* +G01X218800Y9419236D01* +G01X238216Y9421035D01* +G01X256970Y9426371D01* +G01X274425Y9435063D01* +G01X289985Y9446813D01* +G01X303122Y9461223D01* +G01X313386Y9477801D01* +G01X320430Y9495984D01* +G01X324013Y9515150D01* +G01X324013Y9534649D01* +G01X2602787Y9534649D01* +G01X2602787Y9515150D01* +G01X2606370Y9495984D01* +G01X2613413Y9477801D01* +G01X2623678Y9461223D01* +G01X2636815Y9446813D01* +G01X2652375Y9435063D01* +G01X2669830Y9426371D01* +G01X2688584Y9421035D01* +G01X2708000Y9419236D01* +G01X2758800Y9419236D01* +G01X2778216Y9421035D01* +G01X2796970Y9426371D01* +G01X2814425Y9435063D01* +G01X2829985Y9446813D01* +G01X2843122Y9461223D01* +G01X2853386Y9477801D01* +G01X2860430Y9495984D01* +G01X2864013Y9515150D01* +G01X2864013Y9534649D01* +G01X2860430Y9553816D01* +G01X2853386Y9571998D01* +G01X2843122Y9588577D01* +G01X2829985Y9602987D01* +G01X2814425Y9614737D01* +G01X2796970Y9623429D01* +G01X2778216Y9628765D01* +G01X2758800Y9630564D01* +G01X2758800Y9630564D01* +G01X2708000Y9630564D01* +G01X2688584Y9628765D01* +G01X2669830Y9623429D01* +G01X2652375Y9614737D01* +G01X2636815Y9602987D01* +G01X2623678Y9588577D01* +G01X2613413Y9571998D01* +G01X2606370Y9553816D01* +G01X2602787Y9534649D01* +G01X324013Y9534649D01* +G01X324013Y9534649D01* +G01X320430Y9553816D01* +G01X313386Y9571998D01* +G01X303122Y9588577D01* +G01X289985Y9602987D01* +G01X274425Y9614737D01* +G01X256970Y9623429D01* +G01X238216Y9628765D01* +G01X218800Y9630564D01* +G01X218800Y9630564D01* +G01X168000Y9630564D01* +G01X148584Y9628765D01* +G01X129830Y9623429D01* +G01X112375Y9614737D01* +G01X96815Y9602987D01* +G01X83678Y9588577D01* +G01X73413Y9571998D01* +G01X66370Y9553816D01* +G01X62787Y9534649D01* +G01X27538Y9534649D01* +G01X27538Y9788649D01* +G01X62787Y9788649D01* +G01X62787Y9769150D01* +G01X66370Y9749984D01* +G01X73413Y9731801D01* +G01X83678Y9715223D01* +G01X96815Y9700813D01* +G01X112375Y9689063D01* +G01X129830Y9680371D01* +G01X148584Y9675035D01* +G01X168000Y9673236D01* +G01X218800Y9673236D01* +G01X237735Y9674946D01* +G01X256056Y9680022D01* +G01X273172Y9688299D01* +G01X288527Y9699509D01* +G01X301625Y9713289D01* +G01X312042Y9729193D01* +G01X388563Y9729193D01* +G01X388563Y9729193D01* +G01X388563Y9716476D01* +G01X390316Y9705409D01* +G01X395403Y9695425D01* +G01X403326Y9687502D01* +G01X413310Y9682415D01* +G01X424377Y9680662D01* +G01X537631Y9680662D01* +G01X548698Y9682415D01* +G01X558682Y9687502D01* +G01X566605Y9695425D01* +G01X571692Y9705409D01* +G01X573445Y9716476D01* +G01X573445Y9854177D01* +G01X571692Y9865244D01* +G01X566605Y9875228D01* +G01X558682Y9883151D01* +G01X548698Y9888238D01* +G01X537631Y9889991D01* +G01X424377Y9889991D01* +G01X413310Y9888238D01* +G01X403326Y9883151D01* +G01X395403Y9875228D01* +G01X390316Y9865244D01* +G01X388563Y9854177D01* +G01X388563Y9841461D01* +G01X303953Y9841461D01* +G01X290804Y9856232D01* +G01X275133Y9868295D01* +G01X257489Y9877226D01* +G01X238489Y9882713D01* +G01X218800Y9884564D01* +G01X168000Y9884564D01* +G01X148584Y9882765D01* +G01X129830Y9877429D01* +G01X112375Y9868737D01* +G01X96815Y9856987D01* +G01X83678Y9842577D01* +G01X73413Y9825998D01* +G01X66370Y9807816D01* +G01X62787Y9788649D01* +G01X27538Y9788649D01* +G01X27538Y10041475D01* +G01X88057Y10101994D01* +G01X76431Y10085626D01* +G01X68111Y10067354D01* +G01X63397Y10047839D01* +G01X62460Y10027784D01* +G01X65333Y10007913D01* +G01X71912Y9988945D01* +G01X81961Y9971564D01* +G01X95116Y9956397D01* +G01X110902Y9943992D01* +G01X128749Y9934797D01* +G01X148014Y9929143D01* +G01X168000Y9927236D01* +G01X218800Y9927236D01* +G01X236515Y9928732D01* +G01X253729Y9933176D01* +G01X269954Y9940444D01* +G01X284731Y9950329D01* +G01X297642Y9962552D01* +G01X308320Y9976766D01* +G01X792448Y9976766D01* +G01X925867Y9843347D01* +G01X935100Y9835889D01* +G01X945695Y9830538D01* +G01X957178Y9827535D01* +G01X957178Y9671458D01* +G01X958827Y9660714D01* +G01X963624Y9650961D01* +G01X782055Y9650961D01* +G01X750109Y9682906D01* +G01X759578Y9688175D01* +G01X767038Y9696034D01* +G01X771805Y9705765D01* +G01X773444Y9716476D01* +G01X773444Y9854177D01* +G01X771692Y9865244D01* +G01X766605Y9875228D01* +G01X758681Y9883151D01* +G01X748698Y9888238D01* +G01X737630Y9889991D01* +G01X624377Y9889991D01* +G01X613310Y9888238D01* +G01X603326Y9883151D01* +G01X595403Y9875228D01* +G01X590316Y9865244D01* +G01X588563Y9854177D01* +G01X588563Y9716476D01* +G01X590316Y9705409D01* +G01X595403Y9695425D01* +G01X603326Y9687502D01* +G01X613310Y9682415D01* +G01X624377Y9680662D01* +G01X624870Y9680662D01* +G01X624870Y9672627D01* +G01X626782Y9658098D01* +G01X632390Y9644560D01* +G01X641311Y9632934D01* +G01X719111Y9555134D01* +G01X730737Y9546213D01* +G01X744275Y9540605D01* +G01X758804Y9538693D01* +G01X1170361Y9538693D01* +G01X1170361Y9538693D01* +G01X1184889Y9540605D01* +G01X1198428Y9546213D01* +G01X1210053Y9555134D01* +G01X1295549Y9640630D01* +G01X1295549Y9640630D01* +G01X1316444Y9636371D01* +G01X1337763Y9635930D01* +G01X1358815Y9639321D01* +G01X1378918Y9646434D01* +G01X1397417Y9657039D01* +G01X1413714Y9670791D01* +G01X1427279Y9687244D01* +G01X1437672Y9705864D01* +G01X1444556Y9726046D01* +G01X1447706Y9747136D01* +G01X1447022Y9768448D01* +G01X1442524Y9789293D01* +G01X1434360Y9808991D01* +G01X1422794Y9826906D01* +G01X1490290Y9826906D01* +G01X1490290Y9826906D01* +G01X1479197Y9809884D01* +G01X1471178Y9791215D01* +G01X1466470Y9771450D01* +G01X1465212Y9751171D01* +G01X1467441Y9730975D01* +G01X1473090Y9711458D01* +G01X1481995Y9693195D01* +G01X1493891Y9676724D01* +G01X1508429Y9662530D01* +G01X1525181Y9651032D01* +G01X1543652Y9642568D01* +G01X1563299Y9637388D01* +G01X1583542Y9635644D01* +G01X1583542Y9635644D01* +G01X1603785Y9637388D01* +G01X1623432Y9642568D01* +G01X1641903Y9651032D01* +G01X1658654Y9662530D01* +G01X1673193Y9676724D01* +G01X1685089Y9693195D01* +G01X1693994Y9711458D01* +G01X1699643Y9730975D01* +G01X1701872Y9751171D01* +G01X1700614Y9771450D01* +G01X1695906Y9791215D01* +G01X1687887Y9809884D01* +G01X1676794Y9826906D01* +G01X1744290Y9826906D01* +G01X1744290Y9826906D01* +G01X1733197Y9809884D01* +G01X1725178Y9791215D01* +G01X1720470Y9771450D01* +G01X1719212Y9751171D01* +G01X1721441Y9730975D01* +G01X1727090Y9711458D01* +G01X1735995Y9693195D01* +G01X1747891Y9676724D01* +G01X1762429Y9662530D01* +G01X1779181Y9651032D01* +G01X1797652Y9642568D01* +G01X1817299Y9637388D01* +G01X1837542Y9635644D01* +G01X1837542Y9635644D01* +G01X1857785Y9637388D01* +G01X1877432Y9642568D01* +G01X1895903Y9651032D01* +G01X1912654Y9662530D01* +G01X1927193Y9676724D01* +G01X1939089Y9693195D01* +G01X1947994Y9711458D01* +G01X1953643Y9730975D01* +G01X1955872Y9751171D01* +G01X1954614Y9771450D01* +G01X1949906Y9791215D01* +G01X1941887Y9809884D01* +G01X1930794Y9826906D01* +G01X1939258Y9826906D01* +G01X1978164Y9788000D01* +G01X1973957Y9767565D01* +G01X1973403Y9746708D01* +G01X1976520Y9726078D01* +G01X1983211Y9706316D01* +G01X1993268Y9688036D01* +G01X2006378Y9671806D01* +G01X2022135Y9658129D01* +G01X2040048Y9647432D01* +G01X2059561Y9640046D01* +G01X2080067Y9636201D01* +G01X2100930Y9636017D01* +G01X2121502Y9639498D01* +G01X2141143Y9646538D01* +G01X2159242Y9656917D01* +G01X2175238Y9670312D01* +G01X2188633Y9686308D01* +G01X2199012Y9704407D01* +G01X2206051Y9724048D01* +G01X2209533Y9744619D01* +G01X2209348Y9765483D01* +G01X2205503Y9785989D01* +G01X2204497Y9788649D01* +G01X2602787Y9788649D01* +G01X2602787Y9769150D01* +G01X2606370Y9749984D01* +G01X2613413Y9731801D01* +G01X2623678Y9715223D01* +G01X2636815Y9700813D01* +G01X2652375Y9689063D01* +G01X2669830Y9680371D01* +G01X2688584Y9675035D01* +G01X2708000Y9673236D01* +G01X2758800Y9673236D01* +G01X2778216Y9675035D01* +G01X2796970Y9680371D01* +G01X2814425Y9689063D01* +G01X2829985Y9700813D01* +G01X2843122Y9715223D01* +G01X2853386Y9731801D01* +G01X2860430Y9749984D01* +G01X2864013Y9769150D01* +G01X2864013Y9788649D01* +G01X2860430Y9807816D01* +G01X2853386Y9825998D01* +G01X2843122Y9842577D01* +G01X2829985Y9856987D01* +G01X2814425Y9868737D01* +G01X2796970Y9877429D01* +G01X2778216Y9882765D01* +G01X2758800Y9884564D01* +G01X2758800Y9884564D01* +G01X2708000Y9884564D01* +G01X2688584Y9882765D01* +G01X2669830Y9877429D01* +G01X2652375Y9868737D01* +G01X2636815Y9856987D01* +G01X2623678Y9842577D01* +G01X2613413Y9825998D01* +G01X2606370Y9807816D01* +G01X2602787Y9788649D01* +G01X2204497Y9788649D01* +G01X2198118Y9805502D01* +G01X2187420Y9823415D01* +G01X2173744Y9839172D01* +G01X2157514Y9852282D01* +G01X2139233Y9862339D01* +G01X2119471Y9869030D01* +G01X2098842Y9872147D01* +G01X2077985Y9871593D01* +G01X2057549Y9867386D01* +G01X2002203Y9922733D01* +G01X1990577Y9931653D01* +G01X1977038Y9937261D01* +G01X1962510Y9939174D01* +G01X1933833Y9939174D01* +G01X1944732Y9957805D01* +G01X1952067Y9978107D01* +G01X1955593Y9999402D01* +G01X1955433Y10008008D01* +G01X1973178Y10008008D01* +G01X1975193Y9986259D01* +G01X1981171Y9965250D01* +G01X1990907Y9945697D01* +G01X2004070Y9928267D01* +G01X2020212Y9913551D01* +G01X2038783Y9902053D01* +G01X2059150Y9894162D01* +G01X2080621Y9890149D01* +G01X2102463Y9890149D01* +G01X2123934Y9894162D01* +G01X2144301Y9902053D01* +G01X2162872Y9913551D01* +G01X2179014Y9928267D01* +G01X2192177Y9945697D01* +G01X2201913Y9965250D01* +G01X2207891Y9986259D01* +G01X2209906Y10008008D01* +G01X2207891Y10029757D01* +G01X2204222Y10042649D01* +G01X2602787Y10042649D01* +G01X2602787Y10023150D01* +G01X2606370Y10003984D01* +G01X2613413Y9985801D01* +G01X2623678Y9969223D01* +G01X2636815Y9954813D01* +G01X2652375Y9943063D01* +G01X2669830Y9934371D01* +G01X2688584Y9929035D01* +G01X2708000Y9927236D01* +G01X2758800Y9927236D01* +G01X2778216Y9929035D01* +G01X2796970Y9934371D01* +G01X2814425Y9943063D01* +G01X2829985Y9954813D01* +G01X2843122Y9969223D01* +G01X2853386Y9985801D01* +G01X2860430Y10003984D01* +G01X2864013Y10023150D01* +G01X2864013Y10042649D01* +G01X2860430Y10061816D01* +G01X2853386Y10079998D01* +G01X2843122Y10096577D01* +G01X2829985Y10110987D01* +G01X2814425Y10122737D01* +G01X2796970Y10131429D01* +G01X2778216Y10136765D01* +G01X2772059Y10137335D01* +G01X3184464Y10137335D01* +G01X3184464Y10116665D01* +G01X3188262Y10096346D01* +G01X3195729Y10077071D01* +G01X3206611Y10059496D01* +G01X3220537Y10044221D01* +G01X3237032Y10031764D01* +G01X3255536Y10022550D01* +G01X3275417Y10016893D01* +G01X3296000Y10014986D01* +G01X3296000Y10014986D01* +G01X3316582Y10016893D01* +G01X3336464Y10022550D01* +G01X3354968Y10031764D01* +G01X3371463Y10044221D01* +G01X3385389Y10059496D01* +G01X3396271Y10077071D01* +G01X3403738Y10096346D01* +G01X3407536Y10116665D01* +G01X3407536Y10137335D01* +G01X3438464Y10137335D01* +G01X3438464Y10116665D01* +G01X3442262Y10096346D01* +G01X3449729Y10077071D01* +G01X3460611Y10059496D01* +G01X3474537Y10044221D01* +G01X3491032Y10031764D01* +G01X3509536Y10022550D01* +G01X3529417Y10016893D01* +G01X3550000Y10014986D01* +G01X3550000Y10014986D01* +G01X3570582Y10016893D01* +G01X3590464Y10022550D01* +G01X3608968Y10031764D01* +G01X3625463Y10044221D01* +G01X3639389Y10059496D01* +G01X3650271Y10077071D01* +G01X3657738Y10096346D01* +G01X3661536Y10116665D01* +G01X3661536Y10137335D01* +G01X3657738Y10157654D01* +G01X3650271Y10176929D01* +G01X3639389Y10194503D01* +G01X3625463Y10209779D01* +G01X3608968Y10222236D01* +G01X3590464Y10231450D01* +G01X3570582Y10237107D01* +G01X3550000Y10239014D01* +G01X3529417Y10237107D01* +G01X3509536Y10231450D01* +G01X3491032Y10222236D01* +G01X3474537Y10209779D01* +G01X3460611Y10194503D01* +G01X3449729Y10176929D01* +G01X3442262Y10157654D01* +G01X3438464Y10137335D01* +G01X3407536Y10137335D01* +G01X3403738Y10157654D01* +G01X3396271Y10176929D01* +G01X3385389Y10194503D01* +G01X3371463Y10209779D01* +G01X3354968Y10222236D01* +G01X3336464Y10231450D01* +G01X3316582Y10237107D01* +G01X3296000Y10239014D01* +G01X3275417Y10237107D01* +G01X3255536Y10231450D01* +G01X3237032Y10222236D01* +G01X3220537Y10209779D01* +G01X3206611Y10194503D01* +G01X3195729Y10176929D01* +G01X3188262Y10157654D01* +G01X3184464Y10137335D01* +G01X2772059Y10137335D01* +G01X2758800Y10138564D01* +G01X2758800Y10138564D01* +G01X2708000Y10138564D01* +G01X2688584Y10136765D01* +G01X2669830Y10131429D01* +G01X2652375Y10122737D01* +G01X2636815Y10110987D01* +G01X2623678Y10096577D01* +G01X2613413Y10079998D01* +G01X2606370Y10061816D01* +G01X2602787Y10042649D01* +G01X2204222Y10042649D01* +G01X2201913Y10050766D01* +G01X2192177Y10070319D01* +G01X2179014Y10087749D01* +G01X2162872Y10102464D01* +G01X2144301Y10113963D01* +G01X2123934Y10121853D01* +G01X2102463Y10125867D01* +G01X2080621Y10125867D01* +G01X2059150Y10121853D01* +G01X2038783Y10113963D01* +G01X2020212Y10102464D01* +G01X2004070Y10087749D01* +G01X1990907Y10070319D01* +G01X1981171Y10050766D01* +G01X1975193Y10029757D01* +G01X1973178Y10008008D01* +G01X1973178Y10008008D01* +G01X1955433Y10008008D01* +G01X1955193Y10020984D01* +G01X1950880Y10042134D01* +G01X1942798Y10062149D01* +G01X1931215Y10080364D01* +G01X1916517Y10096172D01* +G01X1899193Y10109049D01* +G01X1879818Y10118565D01* +G01X1859037Y10124404D01* +G01X1837542Y10126372D01* +G01X1816046Y10124404D01* +G01X1795266Y10118565D01* +G01X1775891Y10109049D01* +G01X1758567Y10096172D01* +G01X1743869Y10080364D01* +G01X1732286Y10062149D01* +G01X1724204Y10042134D01* +G01X1719891Y10020984D01* +G01X1719491Y9999402D01* +G01X1723017Y9978107D01* +G01X1730352Y9957805D01* +G01X1741251Y9939174D01* +G01X1679833Y9939174D01* +G01X1690732Y9957805D01* +G01X1698067Y9978107D01* +G01X1701593Y9999402D01* +G01X1701193Y10020984D01* +G01X1696880Y10042134D01* +G01X1688798Y10062149D01* +G01X1677215Y10080364D01* +G01X1662517Y10096172D01* +G01X1645193Y10109049D01* +G01X1625818Y10118565D01* +G01X1605037Y10124404D01* +G01X1583542Y10126372D01* +G01X1562046Y10124404D01* +G01X1541266Y10118565D01* +G01X1521891Y10109049D01* +G01X1504567Y10096172D01* +G01X1489869Y10080364D01* +G01X1478286Y10062149D01* +G01X1470204Y10042134D01* +G01X1465891Y10020984D01* +G01X1465491Y9999402D01* +G01X1469017Y9978107D01* +G01X1476352Y9957805D01* +G01X1487251Y9939174D01* +G01X1425833Y9939174D01* +G01X1436732Y9957805D01* +G01X1444067Y9978107D01* +G01X1447593Y9999402D01* +G01X1447193Y10020984D01* +G01X1442880Y10042134D01* +G01X1434798Y10062149D01* +G01X1423215Y10080364D01* +G01X1408517Y10096172D01* +G01X1391193Y10109049D01* +G01X1371818Y10118565D01* +G01X1351037Y10124404D01* +G01X1329542Y10126372D01* +G01X1308046Y10124404D01* +G01X1287266Y10118565D01* +G01X1267891Y10109049D01* +G01X1250567Y10096172D01* +G01X1235869Y10080364D01* +G01X1224286Y10062149D01* +G01X1216204Y10042134D01* +G01X1211891Y10020984D01* +G01X1211491Y9999402D01* +G01X1215017Y9978107D01* +G01X1222352Y9957805D01* +G01X1233251Y9939174D01* +G01X1171833Y9939174D01* +G01X1182282Y9956854D01* +G01X1189517Y9976075D01* +G01X1193321Y9996257D01* +G01X1193580Y10016792D01* +G01X1190284Y10037063D01* +G01X1183535Y10056460D01* +G01X1173534Y10074397D01* +G01X1160583Y10090336D01* +G01X1145072Y10103797D01* +G01X1127468Y10114374D01* +G01X1108301Y10121748D01* +G01X1088147Y10125699D01* +G01X1067614Y10126106D01* +G01X1047320Y10122958D01* +G01X1027875Y10116349D01* +G01X1009865Y10106479D01* +G01X993832Y10093644D01* +G01X980260Y10078231D01* +G01X969555Y10060704D01* +G01X962042Y10041591D01* +G01X957946Y10021466D01* +G01X957389Y10000937D01* +G01X960390Y9980620D01* +G01X966858Y9961128D01* +G01X855393Y10072593D01* +G01X843767Y10081513D01* +G01X830228Y10087121D01* +G01X815700Y10089034D01* +G01X308320Y10089034D01* +G01X297642Y10103248D01* +G01X284731Y10115471D01* +G01X269954Y10125356D01* +G01X253729Y10132624D01* +G01X236515Y10137068D01* +G01X218800Y10138564D01* +G01X168000Y10138564D01* +G01X149272Y10136891D01* +G01X131137Y10131925D01* +G01X114169Y10123823D01* +G01X98905Y10112843D01* +G01X167301Y10181238D01* +G01X168000Y10181236D01* +G01X218800Y10181236D01* +G01X238216Y10183035D01* +G01X256970Y10188371D01* +G01X274425Y10197063D01* +G01X289985Y10208813D01* +G01X303122Y10223223D01* +G01X313386Y10239801D01* +G01X320430Y10257984D01* +G01X324013Y10277150D01* +G01X324013Y10296649D01* +G01X2602787Y10296649D01* +G01X2602787Y10277150D01* +G01X2606370Y10257984D01* +G01X2613413Y10239801D01* +G01X2623678Y10223223D01* +G01X2636815Y10208813D01* +G01X2652375Y10197063D01* +G01X2669830Y10188371D01* +G01X2688584Y10183035D01* +G01X2708000Y10181236D01* +G01X2758800Y10181236D01* +G01X2778216Y10183035D01* +G01X2796970Y10188371D01* +G01X2814425Y10197063D01* +G01X2829985Y10208813D01* +G01X2843122Y10223223D01* +G01X2853386Y10239801D01* +G01X2860430Y10257984D01* +G01X2864013Y10277150D01* +G01X2864013Y10296649D01* +G01X2860430Y10315816D01* +G01X2853386Y10333998D01* +G01X2843122Y10350577D01* +G01X2829985Y10364987D01* +G01X2814425Y10376737D01* +G01X2796970Y10385429D01* +G01X2778216Y10390765D01* +G01X2758800Y10392564D01* +G01X2758800Y10392564D01* +G01X2708000Y10392564D01* +G01X2688584Y10390765D01* +G01X2669830Y10385429D01* +G01X2652375Y10376737D01* +G01X2636815Y10364987D01* +G01X2623678Y10350577D01* +G01X2613413Y10333998D01* +G01X2606370Y10315816D01* +G01X2602787Y10296649D01* +G01X324013Y10296649D01* +G01X320430Y10315816D01* +G01X313386Y10333998D01* +G01X303122Y10350577D01* +G01X289985Y10364987D01* +G01X274425Y10376737D01* +G01X256970Y10385429D01* +G01X238216Y10390765D01* +G01X218800Y10392564D01* +G01X168000Y10392564D01* +G01X149009Y10390843D01* +G01X130636Y10385737D01* +G01X113481Y10377413D01* +G01X98101Y10366140D01* +G01X84997Y10352287D01* +G01X74597Y10336304D01* +G01X67238Y10318712D01* +G01X63162Y10300084D01* +G01X62499Y10281027D01* +G01X65273Y10262161D01* +G01X71392Y10244100D01* +G01X-68289Y10104419D01* +G01X-77210Y10092794D01* +G01X-82817Y10079255D01* +G01X-84730Y10064727D01* +G01X-84730Y8780055D01* +G01X-242508Y8622278D01* +G01X-262943Y8626485D01* +G01X-283800Y8627039D01* +G01X-304430Y8623922D01* +G01X-324192Y8617231D01* +G01X-342472Y8607174D01* +G01X-358702Y8594064D01* +G01X-372379Y8578307D01* +G01X-383076Y8560394D01* +G01X-390462Y8540881D01* +G01X-394307Y8520375D01* +G01X-394491Y8499511D01* +G01X-2190641Y8499511D01* +G01X-2190641Y8519821D01* +G01X-2194655Y8541292D01* +G01X-2202545Y8561659D01* +G01X-2214044Y8580230D01* +G01X-2228759Y8596372D01* +G01X-2246189Y8609535D01* +G01X-2265742Y8619271D01* +G01X-2286751Y8625249D01* +G01X-2308500Y8627264D01* +G01X-2330249Y8625249D01* +G01X-2351258Y8619271D01* +G01X-2370811Y8609535D01* +G01X-2388241Y8596372D01* +G01X-2402957Y8580230D01* +G01X-2414455Y8561659D01* +G01X-2422346Y8541292D01* +G01X-2426359Y8519821D01* +G01X-2536486Y8519821D01* +G01X-2536486Y8773821D01* +G01X-2426359Y8773821D01* +G01X-2426359Y8751979D01* +G01X-2422346Y8730508D01* +G01X-2414455Y8710141D01* +G01X-2402957Y8691570D01* +G01X-2388241Y8675428D01* +G01X-2370811Y8662265D01* +G01X-2351258Y8652529D01* +G01X-2330249Y8646551D01* +G01X-2308500Y8644536D01* +G01X-2308500Y8644536D01* +G01X-2286751Y8646551D01* +G01X-2265742Y8652529D01* +G01X-2246189Y8662265D01* +G01X-2228759Y8675428D01* +G01X-2214044Y8691570D01* +G01X-2202545Y8710141D01* +G01X-2194655Y8730508D01* +G01X-2190641Y8751979D01* +G01X-2190641Y8773821D01* +G01X-2190641Y8773821D01* +G01X-394359Y8773821D01* +G01X-394359Y8751979D01* +G01X-390346Y8730508D01* +G01X-382455Y8710141D01* +G01X-370957Y8691570D01* +G01X-356241Y8675428D01* +G01X-338811Y8662265D01* +G01X-319258Y8652529D01* +G01X-298249Y8646551D01* +G01X-276500Y8644536D01* +G01X-276500Y8644536D01* +G01X-254751Y8646551D01* +G01X-233742Y8652529D01* +G01X-214189Y8662265D01* +G01X-196759Y8675428D01* +G01X-182044Y8691570D01* +G01X-170545Y8710141D01* +G01X-162655Y8730508D01* +G01X-158641Y8751979D01* +G01X-158641Y8773821D01* +G01X-162655Y8795292D01* +G01X-170545Y8815659D01* +G01X-182044Y8834230D01* +G01X-196759Y8850372D01* +G01X-214189Y8863535D01* +G01X-233742Y8873271D01* +G01X-254751Y8879249D01* +G01X-276500Y8881264D01* +G01X-298249Y8879249D01* +G01X-319258Y8873271D01* +G01X-338811Y8863535D01* +G01X-356241Y8850372D01* +G01X-370957Y8834230D01* +G01X-382455Y8815659D01* +G01X-390346Y8795292D01* +G01X-394359Y8773821D01* +G01X-2190641Y8773821D01* +G01X-2194655Y8795292D01* +G01X-2202545Y8815659D01* +G01X-2214044Y8834230D01* +G01X-2228759Y8850372D01* +G01X-2246189Y8863535D01* +G01X-2265742Y8873271D01* +G01X-2286751Y8879249D01* +G01X-2308500Y8881264D01* +G01X-2330249Y8879249D01* +G01X-2351258Y8873271D01* +G01X-2370811Y8863535D01* +G01X-2388241Y8850372D01* +G01X-2402957Y8834230D01* +G01X-2414455Y8815659D01* +G01X-2422346Y8795292D01* +G01X-2426359Y8773821D01* +G01X-2536486Y8773821D01* +G01X-2536486Y9027821D01* +G01X-2426359Y9027821D01* +G01X-2426359Y9005979D01* +G01X-2422346Y8984508D01* +G01X-2414455Y8964141D01* +G01X-2402957Y8945570D01* +G01X-2388241Y8929428D01* +G01X-2370811Y8916265D01* +G01X-2351258Y8906529D01* +G01X-2330249Y8900551D01* +G01X-2308500Y8898536D01* +G01X-2308500Y8898536D01* +G01X-2286751Y8900551D01* +G01X-2265742Y8906529D01* +G01X-2246189Y8916265D01* +G01X-2228759Y8929428D01* +G01X-2214044Y8945570D01* +G01X-2202545Y8964141D01* +G01X-2194655Y8984508D01* +G01X-2190641Y9005979D01* +G01X-2190641Y9027821D01* +G01X-2194655Y9049292D01* +G01X-2202545Y9069659D01* +G01X-2214044Y9088230D01* +G01X-2228759Y9104372D01* +G01X-2246189Y9117535D01* +G01X-2265742Y9127271D01* +G01X-2286751Y9133249D01* +G01X-2308500Y9135264D01* +G01X-2330249Y9133249D01* +G01X-2351258Y9127271D01* +G01X-2370811Y9117535D01* +G01X-2388241Y9104372D01* +G01X-2402957Y9088230D01* +G01X-2414455Y9069659D01* +G01X-2422346Y9049292D01* +G01X-2426359Y9027821D01* +G01X-2536486Y9027821D01* +G01X-2536486Y10699650D01* +G01X-2426864Y10699650D01* +G01X-2425111Y10688583D01* +G01X-2420024Y10678599D01* +G01X-2412101Y10670676D01* +G01X-2402117Y10665589D01* +G01X-2391050Y10663836D01* +G01X-2269522Y10663836D01* +G01X-582893Y8977207D01* +G01X-571267Y8968286D01* +G01X-557729Y8962679D01* +G01X-543200Y8960766D01* +G01X-380707Y8960766D01* +G01X-369232Y8943341D01* +G01X-354875Y8928202D01* +G01X-338084Y8915818D01* +G01X-319379Y8906576D01* +G01X-299341Y8900761D01* +G01X-278594Y8898554D01* +G01X-257782Y8900025D01* +G01X-237552Y8905128D01* +G01X-218531Y8913703D01* +G01X-201312Y8925484D01* +G01X-186429Y8940106D01* +G01X-174345Y8957114D01* +G01X-165434Y8975980D01* +G01X-159975Y8996117D01* +G01X-158136Y9016900D01* +G01X-159975Y9037683D01* +G01X-165434Y9057820D01* +G01X-174345Y9076685D01* +G01X-186429Y9093693D01* +G01X-201312Y9108315D01* +G01X-218531Y9120097D01* +G01X-237552Y9128672D01* +G01X-257782Y9133775D01* +G01X-278594Y9135245D01* +G01X-299341Y9133039D01* +G01X-319379Y9127224D01* +G01X-338084Y9117982D01* +G01X-354875Y9105598D01* +G01X-369232Y9090459D01* +G01X-380707Y9073034D01* +G01X-519949Y9073034D01* +G01X-2190136Y10743221D01* +G01X-2190136Y10743221D01* +G01X-2190136Y10782200D01* +G01X-2172864Y10782200D01* +G01X-2171025Y10761417D01* +G01X-2165566Y10741280D01* +G01X-2156655Y10722414D01* +G01X-2144571Y10705406D01* +G01X-2129688Y10690784D01* +G01X-2112469Y10679003D01* +G01X-2093449Y10670428D01* +G01X-2073218Y10665325D01* +G01X-2052406Y10663854D01* +G01X-2031659Y10666061D01* +G01X-2011622Y10671876D01* +G01X-1992917Y10681118D01* +G01X-1976125Y10693502D01* +G01X-1961769Y10708641D01* +G01X-1950294Y10726066D01* +G01X-1904707Y10726066D01* +G01X-1893635Y10709152D01* +G01X-1879846Y10694369D01* +G01X-1863744Y10682148D01* +G01X-1845796Y10672846D01* +G01X-1826527Y10666733D01* +G01X-1806499Y10663988D01* +G01X-1786296Y10664691D01* +G01X-1766508Y10668822D01* +G01X-392436Y9294751D01* +G01X-392436Y9294751D01* +G01X-394822Y9274039D01* +G01X-393538Y9253231D01* +G01X-388622Y9232971D01* +G01X-380228Y9213887D01* +G01X-368616Y9196572D01* +G01X-354146Y9181563D01* +G01X-337268Y9169326D01* +G01X-318504Y9160240D01* +G01X-298437Y9154586D01* +G01X-277689Y9152542D01* +G01X-256904Y9154169D01* +G01X-236728Y9159418D01* +G01X-217785Y9168125D01* +G01X-200664Y9180021D01* +G01X-185896Y9194737D01* +G01X-185896Y9194737D01* +G01X-173938Y9211815D01* +G01X-165162Y9230726D01* +G01X-159841Y9250883D01* +G01X-158139Y9271662D01* +G01X-160108Y9292417D01* +G01X-165689Y9312504D01* +G01X-174707Y9331301D01* +G01X-186884Y9348224D01* +G01X-201840Y9362747D01* +G01X-219113Y9374422D01* +G01X-238167Y9382885D01* +G01X-258409Y9387873D01* +G01X-279213Y9389233D01* +G01X-299932Y9386921D01* +G01X-319925Y9381010D01* +G01X-1687122Y10748207D01* +G01X-1682821Y10769487D01* +G01X-1682478Y10791194D01* +G01X-1682545Y10791589D01* +G01X-1664491Y10791589D01* +G01X-1664307Y10770725D01* +G01X-1660462Y10750219D01* +G01X-1653076Y10730706D01* +G01X-1642379Y10712793D01* +G01X-1628702Y10697036D01* +G01X-1612472Y10683926D01* +G01X-1594192Y10673869D01* +G01X-1574430Y10667178D01* +G01X-1553800Y10664061D01* +G01X-1532943Y10664615D01* +G01X-1512508Y10668822D01* +G01X-392436Y9548751D01* +G01X-392436Y9548751D01* +G01X-394822Y9528039D01* +G01X-393538Y9507231D01* +G01X-388622Y9486971D01* +G01X-380228Y9467887D01* +G01X-368616Y9450572D01* +G01X-354146Y9435563D01* +G01X-337268Y9423326D01* +G01X-318504Y9414240D01* +G01X-298437Y9408586D01* +G01X-277689Y9406542D01* +G01X-256904Y9408169D01* +G01X-236728Y9413418D01* +G01X-217785Y9422125D01* +G01X-200664Y9434021D01* +G01X-185896Y9448737D01* +G01X-185896Y9448737D01* +G01X-173938Y9465815D01* +G01X-165162Y9484726D01* +G01X-159841Y9504883D01* +G01X-158139Y9525662D01* +G01X-160108Y9546417D01* +G01X-165689Y9566504D01* +G01X-174707Y9585301D01* +G01X-186884Y9602224D01* +G01X-201840Y9616747D01* +G01X-219113Y9628422D01* +G01X-238167Y9636885D01* +G01X-258409Y9641873D01* +G01X-279213Y9643233D01* +G01X-299932Y9640921D01* +G01X-319925Y9635010D01* +G01X-1235564Y10550649D01* +G01X62787Y10550649D01* +G01X62787Y10531150D01* +G01X66370Y10511984D01* +G01X73413Y10493801D01* +G01X83678Y10477223D01* +G01X96815Y10462813D01* +G01X112375Y10451063D01* +G01X129830Y10442371D01* +G01X148584Y10437035D01* +G01X168000Y10435236D01* +G01X218800Y10435236D01* +G01X238216Y10437035D01* +G01X256970Y10442371D01* +G01X274425Y10451063D01* +G01X289985Y10462813D01* +G01X303122Y10477223D01* +G01X313386Y10493801D01* +G01X320430Y10511984D01* +G01X324013Y10531150D01* +G01X324013Y10550649D01* +G01X2602787Y10550649D01* +G01X2602787Y10531150D01* +G01X2606370Y10511984D01* +G01X2613413Y10493801D01* +G01X2623678Y10477223D01* +G01X2636815Y10462813D01* +G01X2652375Y10451063D01* +G01X2669830Y10442371D01* +G01X2688584Y10437035D01* +G01X2708000Y10435236D01* +G01X2758800Y10435236D01* +G01X2778216Y10437035D01* +G01X2796970Y10442371D01* +G01X2814425Y10451063D01* +G01X2829985Y10462813D01* +G01X2843122Y10477223D01* +G01X2853386Y10493801D01* +G01X2860430Y10511984D01* +G01X2864013Y10531150D01* +G01X2864013Y10550649D01* +G01X2860430Y10569816D01* +G01X2853386Y10587998D01* +G01X2843122Y10604577D01* +G01X2829985Y10618987D01* +G01X2814425Y10630737D01* +G01X2796970Y10639429D01* +G01X2778216Y10644765D01* +G01X2772059Y10645335D01* +G01X3184464Y10645335D01* +G01X3184464Y10624665D01* +G01X3188262Y10604346D01* +G01X3195729Y10585071D01* +G01X3206611Y10567496D01* +G01X3220537Y10552221D01* +G01X3237032Y10539764D01* +G01X3255536Y10530550D01* +G01X3275417Y10524893D01* +G01X3296000Y10522986D01* +G01X3296000Y10522986D01* +G01X3316582Y10524893D01* +G01X3336464Y10530550D01* +G01X3354968Y10539764D01* +G01X3371463Y10552221D01* +G01X3385389Y10567496D01* +G01X3396271Y10585071D01* +G01X3403738Y10604346D01* +G01X3407536Y10624665D01* +G01X3407536Y10645335D01* +G01X3403738Y10665654D01* +G01X3396271Y10684929D01* +G01X3385389Y10702503D01* +G01X3371463Y10717779D01* +G01X3354968Y10730236D01* +G01X3336464Y10739450D01* +G01X3316582Y10745107D01* +G01X3296000Y10747014D01* +G01X3275417Y10745107D01* +G01X3255536Y10739450D01* +G01X3237032Y10730236D01* +G01X3220537Y10717779D01* +G01X3206611Y10702503D01* +G01X3195729Y10684929D01* +G01X3188262Y10665654D01* +G01X3184464Y10645335D01* +G01X2772059Y10645335D01* +G01X2758800Y10646564D01* +G01X2758800Y10646564D01* +G01X2708000Y10646564D01* +G01X2688584Y10644765D01* +G01X2669830Y10639429D01* +G01X2652375Y10630737D01* +G01X2636815Y10618987D01* +G01X2623678Y10604577D01* +G01X2613413Y10587998D01* +G01X2606370Y10569816D01* +G01X2602787Y10550649D01* +G01X324013Y10550649D01* +G01X320430Y10569816D01* +G01X313386Y10587998D01* +G01X303122Y10604577D01* +G01X289985Y10618987D01* +G01X274425Y10630737D01* +G01X256970Y10639429D01* +G01X238216Y10644765D01* +G01X218800Y10646564D01* +G01X218800Y10646564D01* +G01X168000Y10646564D01* +G01X148584Y10644765D01* +G01X129830Y10639429D01* +G01X112375Y10630737D01* +G01X96815Y10618987D01* +G01X83678Y10604577D01* +G01X73413Y10587998D01* +G01X66370Y10569816D01* +G01X62787Y10550649D01* +G01X-1235564Y10550649D01* +G01X-1433122Y10748207D01* +G01X-1428915Y10768643D01* +G01X-1428361Y10789500D01* +G01X-1430650Y10804649D01* +G01X62787Y10804649D01* +G01X62787Y10785150D01* +G01X66370Y10765984D01* +G01X73413Y10747801D01* +G01X83678Y10731223D01* +G01X96815Y10716813D01* +G01X112375Y10705063D01* +G01X129830Y10696371D01* +G01X148584Y10691035D01* +G01X168000Y10689236D01* +G01X218800Y10689236D01* +G01X238216Y10691035D01* +G01X256970Y10696371D01* +G01X274425Y10705063D01* +G01X289985Y10716813D01* +G01X303122Y10731223D01* +G01X313386Y10747801D01* +G01X320430Y10765984D01* +G01X324013Y10785150D01* +G01X324013Y10804649D01* +G01X2602787Y10804649D01* +G01X2602787Y10785150D01* +G01X2606370Y10765984D01* +G01X2613413Y10747801D01* +G01X2623678Y10731223D01* +G01X2636815Y10716813D01* +G01X2652375Y10705063D01* +G01X2669830Y10696371D01* +G01X2688584Y10691035D01* +G01X2708000Y10689236D01* +G01X2758800Y10689236D01* +G01X2778216Y10691035D01* +G01X2796970Y10696371D01* +G01X2814425Y10705063D01* +G01X2829985Y10716813D01* +G01X2843122Y10731223D01* +G01X2853386Y10747801D01* +G01X2860430Y10765984D01* +G01X2864013Y10785150D01* +G01X2864013Y10804649D01* +G01X2860430Y10823816D01* +G01X2853386Y10841998D01* +G01X2843122Y10858577D01* +G01X2829985Y10872987D01* +G01X2814425Y10884737D01* +G01X2796970Y10893429D01* +G01X2778216Y10898765D01* +G01X2758800Y10900564D01* +G01X2758800Y10900564D01* +G01X2708000Y10900564D01* +G01X2688584Y10898765D01* +G01X2669830Y10893429D01* +G01X2652375Y10884737D01* +G01X2636815Y10872987D01* +G01X2623678Y10858577D01* +G01X2613413Y10841998D01* +G01X2606370Y10823816D01* +G01X2602787Y10804649D01* +G01X324013Y10804649D01* +G01X320430Y10823816D01* +G01X313386Y10841998D01* +G01X303122Y10858577D01* +G01X289985Y10872987D01* +G01X274425Y10884737D01* +G01X256970Y10893429D01* +G01X238216Y10898765D01* +G01X218800Y10900564D01* +G01X218800Y10900564D01* +G01X168000Y10900564D01* +G01X148584Y10898765D01* +G01X129830Y10893429D01* +G01X112375Y10884737D01* +G01X96815Y10872987D01* +G01X83678Y10858577D01* +G01X73413Y10841998D01* +G01X66370Y10823816D01* +G01X62787Y10804649D01* +G01X-1430650Y10804649D01* +G01X-1431478Y10810129D01* +G01X-1438169Y10829891D01* +G01X-1448226Y10848172D01* +G01X-1461336Y10864402D01* +G01X-1477093Y10878078D01* +G01X-1495006Y10888776D01* +G01X-1514519Y10896161D01* +G01X-1535025Y10900006D01* +G01X-1555889Y10900191D01* +G01X-1576460Y10896709D01* +G01X-1596101Y10889670D01* +G01X-1614200Y10879291D01* +G01X-1630196Y10865896D01* +G01X-1643591Y10849900D01* +G01X-1653970Y10831801D01* +G01X-1661010Y10812160D01* +G01X-1664491Y10791589D01* +G01X-1682545Y10791589D01* +G01X-1686106Y10812598D01* +G01X-1693582Y10832980D01* +G01X-1704655Y10851654D01* +G01X-1718953Y10867991D01* +G01X-1735993Y10881442D01* +G01X-1755204Y10891554D01* +G01X-1775939Y10897988D01* +G01X-1797500Y10900526D01* +G01X-1819161Y10899084D01* +G01X-1840195Y10893709D01* +G01X-1859894Y10884584D01* +G01X-1877594Y10872014D01* +G01X-1892701Y10856422D01* +G01X-1904707Y10838334D01* +G01X-1950294Y10838334D01* +G01X-1961769Y10855759D01* +G01X-1976125Y10870898D01* +G01X-1992917Y10883282D01* +G01X-2011622Y10892524D01* +G01X-2031659Y10898339D01* +G01X-2052406Y10900545D01* +G01X-2073218Y10899075D01* +G01X-2093449Y10893972D01* +G01X-2112469Y10885397D01* +G01X-2129688Y10873615D01* +G01X-2144571Y10858993D01* +G01X-2156655Y10841985D01* +G01X-2165566Y10823120D01* +G01X-2171025Y10802983D01* +G01X-2172864Y10782200D01* +G01X-2190136Y10782200D01* +G01X-2190136Y10864750D01* +G01X-2191889Y10875817D01* +G01X-2196976Y10885801D01* +G01X-2204899Y10893724D01* +G01X-2214883Y10898811D01* +G01X-2225950Y10900564D01* +G01X-2391050Y10900564D01* +G01X-2402117Y10898811D01* +G01X-2412101Y10893724D01* +G01X-2420024Y10885801D01* +G01X-2425111Y10875817D01* +G01X-2426864Y10864750D01* +G01X-2426864Y10699650D01* +G01X-2536486Y10699650D01* +G01X-2536486Y10796000D01* +G01X-2534751Y10815828D01* +G01X-2529600Y10835054D01* +G01X-2521188Y10853093D01* +G01X-2509772Y10869397D01* +G01X-2495697Y10883471D01* +G01X-2479393Y10894888D01* +G01X-2461354Y10903300D01* +G01X-2442128Y10908451D01* +G01X-2422300Y10910186D01* +G01X0Y10910186D01* +G01X11067Y10911939D01* +G01X21051Y10917026D01* +G01X28974Y10924949D01* +G01X34061Y10934933D01* +G01X35814Y10946000D01* +G01X35814Y11058649D01* +G01X62787Y11058649D01* +G01X62787Y11039150D01* +G01X66370Y11019984D01* +G01X73413Y11001801D01* +G01X83678Y10985223D01* +G01X96815Y10970813D01* +G01X112375Y10959063D01* +G01X129830Y10950371D01* +G01X148584Y10945035D01* +G01X168000Y10943236D01* +G01X218800Y10943236D01* +G01X238216Y10945035D01* +G01X256970Y10950371D01* +G01X274425Y10959063D01* +G01X289985Y10970813D01* +G01X303122Y10985223D01* +G01X313386Y11001801D01* +G01X320430Y11019984D01* +G01X324013Y11039150D01* +G01X324013Y11058649D01* +G01X2602787Y11058649D01* +G01X2602787Y11039150D01* +G01X2606370Y11019984D01* +G01X2613413Y11001801D01* +G01X2623678Y10985223D01* +G01X2636815Y10970813D01* +G01X2652375Y10959063D01* +G01X2669830Y10950371D01* +G01X2688584Y10945035D01* +G01X2708000Y10943236D01* +G01X2758800Y10943236D01* +G01X2778216Y10945035D01* +G01X2796970Y10950371D01* +G01X2814425Y10959063D01* +G01X2829985Y10970813D01* +G01X2843122Y10985223D01* +G01X2853386Y11001801D01* +G01X2860430Y11019984D01* +G01X2864013Y11039150D01* +G01X2864013Y11058649D01* +G01X2860430Y11077816D01* +G01X2853386Y11095998D01* +G01X2843122Y11112577D01* +G01X2829985Y11126987D01* +G01X2814425Y11138737D01* +G01X2796970Y11147429D01* +G01X2778216Y11152765D01* +G01X2758800Y11154564D01* +G01X2758800Y11154564D01* +G01X2708000Y11154564D01* +G01X2688584Y11152765D01* +G01X2669830Y11147429D01* +G01X2652375Y11138737D01* +G01X2636815Y11126987D01* +G01X2623678Y11112577D01* +G01X2613413Y11095998D01* +G01X2606370Y11077816D01* +G01X2602787Y11058649D01* +G01X324013Y11058649D01* +G01X320430Y11077816D01* +G01X313386Y11095998D01* +G01X303122Y11112577D01* +G01X289985Y11126987D01* +G01X274425Y11138737D01* +G01X256970Y11147429D01* +G01X238216Y11152765D01* +G01X218800Y11154564D01* +G01X218800Y11154564D01* +G01X168000Y11154564D01* +G01X148584Y11152765D01* +G01X129830Y11147429D01* +G01X112375Y11138737D01* +G01X96815Y11126987D01* +G01X83678Y11112577D01* +G01X73413Y11095998D01* +G01X66370Y11077816D01* +G01X62787Y11058649D01* +G01X35814Y11058649D01* +G01X35814Y11312649D01* +G01X62787Y11312649D01* +G01X62787Y11293150D01* +G01X66370Y11273984D01* +G01X73413Y11255801D01* +G01X83678Y11239223D01* +G01X96815Y11224813D01* +G01X112375Y11213063D01* +G01X129830Y11204371D01* +G01X148584Y11199035D01* +G01X168000Y11197236D01* +G01X218800Y11197236D01* +G01X238216Y11199035D01* +G01X256970Y11204371D01* +G01X274425Y11213063D01* +G01X289985Y11224813D01* +G01X303122Y11239223D01* +G01X313386Y11255801D01* +G01X320430Y11273984D01* +G01X324013Y11293150D01* +G01X324013Y11312649D01* +G01X320430Y11331816D01* +G01X313386Y11349998D01* +G01X303122Y11366577D01* +G01X289985Y11380987D01* +G01X274425Y11392737D01* +G01X256970Y11401429D01* +G01X238216Y11406765D01* +G01X218800Y11408564D01* +G01X218800Y11408564D01* +G01X168000Y11408564D01* +G01X148584Y11406765D01* +G01X129830Y11401429D01* +G01X112375Y11392737D01* +G01X96815Y11380987D01* +G01X83678Y11366577D01* +G01X73413Y11349998D01* +G01X66370Y11331816D01* +G01X62787Y11312649D01* +G01X35814Y11312649D01* +G01X35814Y11566649D01* +G01X62787Y11566649D01* +G01X62787Y11547150D01* +G01X66370Y11527984D01* +G01X73413Y11509801D01* +G01X83678Y11493223D01* +G01X96815Y11478813D01* +G01X112375Y11467063D01* +G01X129830Y11458371D01* +G01X148584Y11453035D01* +G01X168000Y11451236D01* +G01X218800Y11451236D01* +G01X238216Y11453035D01* +G01X256970Y11458371D01* +G01X274425Y11467063D01* +G01X289985Y11478813D01* +G01X303122Y11493223D01* +G01X313386Y11509801D01* +G01X320430Y11527984D01* +G01X324013Y11547150D01* +G01X324013Y11566649D01* +G01X320430Y11585816D01* +G01X313386Y11603998D01* +G01X303122Y11620577D01* +G01X289985Y11634987D01* +G01X274425Y11646737D01* +G01X256970Y11655429D01* +G01X238216Y11660765D01* +G01X218800Y11662564D01* +G01X218800Y11662564D01* +G01X168000Y11662564D01* +G01X148584Y11660765D01* +G01X129830Y11655429D01* +G01X112375Y11646737D01* +G01X96815Y11634987D01* +G01X83678Y11620577D01* +G01X73413Y11603998D01* +G01X66370Y11585816D01* +G01X62787Y11566649D01* +G01X35814Y11566649D01* +G01X35814Y11820649D01* +G01X62787Y11820649D01* +G01X62787Y11801150D01* +G01X66370Y11781984D01* +G01X73413Y11763801D01* +G01X83678Y11747223D01* +G01X96815Y11732813D01* +G01X112375Y11721063D01* +G01X129830Y11712371D01* +G01X148584Y11707035D01* +G01X168000Y11705236D01* +G01X218800Y11705236D01* +G01X238216Y11707035D01* +G01X256970Y11712371D01* +G01X274425Y11721063D01* +G01X289985Y11732813D01* +G01X303122Y11747223D01* +G01X313386Y11763801D01* +G01X320430Y11781984D01* +G01X324013Y11801150D01* +G01X324013Y11820649D01* +G01X320430Y11839816D01* +G01X313386Y11857998D01* +G01X303122Y11874577D01* +G01X289985Y11888987D01* +G01X274425Y11900737D01* +G01X256970Y11909429D01* +G01X238216Y11914765D01* +G01X218800Y11916564D01* +G01X218800Y11916564D01* +G01X168000Y11916564D01* +G01X148584Y11914765D01* +G01X129830Y11909429D01* +G01X112375Y11900737D01* +G01X96815Y11888987D01* +G01X83678Y11874577D01* +G01X73413Y11857998D01* +G01X66370Y11839816D01* +G01X62787Y11820649D01* +G01X35814Y11820649D01* +G01X35814Y12074649D01* +G01X62787Y12074649D01* +G01X62787Y12055150D01* +G01X66370Y12035984D01* +G01X73413Y12017801D01* +G01X83678Y12001223D01* +G01X96815Y11986813D01* +G01X112375Y11975063D01* +G01X129830Y11966371D01* +G01X148584Y11961035D01* +G01X168000Y11959236D01* +G01X218800Y11959236D01* +G01X238216Y11961035D01* +G01X256970Y11966371D01* +G01X274425Y11975063D01* +G01X289985Y11986813D01* +G01X303122Y12001223D01* +G01X313386Y12017801D01* +G01X320430Y12035984D01* +G01X324013Y12055150D01* +G01X324013Y12074649D01* +G01X320430Y12093816D01* +G01X313386Y12111998D01* +G01X303122Y12128577D01* +G01X289985Y12142987D01* +G01X274425Y12154737D01* +G01X256970Y12163429D01* +G01X238216Y12168765D01* +G01X218800Y12170564D01* +G01X218800Y12170564D01* +G01X168000Y12170564D01* +G01X148584Y12168765D01* +G01X129830Y12163429D01* +G01X112375Y12154737D01* +G01X96815Y12142987D01* +G01X83678Y12128577D01* +G01X73413Y12111998D01* +G01X66370Y12093816D01* +G01X62787Y12074649D01* +G01X35814Y12074649D01* +G01X35814Y12328649D01* +G01X62787Y12328649D01* +G01X62787Y12309150D01* +G01X66370Y12289984D01* +G01X73413Y12271801D01* +G01X83678Y12255223D01* +G01X96815Y12240813D01* +G01X112375Y12229063D01* +G01X129830Y12220371D01* +G01X148584Y12215035D01* +G01X168000Y12213236D01* +G01X218800Y12213236D01* +G01X238216Y12215035D01* +G01X256970Y12220371D01* +G01X274425Y12229063D01* +G01X289985Y12240813D01* +G01X303122Y12255223D01* +G01X313386Y12271801D01* +G01X320430Y12289984D01* +G01X324013Y12309150D01* +G01X324013Y12328649D01* +G01X320430Y12347816D01* +G01X313386Y12365998D01* +G01X303122Y12382577D01* +G01X289985Y12396987D01* +G01X274425Y12408737D01* +G01X256970Y12417429D01* +G01X238216Y12422765D01* +G01X218800Y12424564D01* +G01X218800Y12424564D01* +G01X168000Y12424564D01* +G01X148584Y12422765D01* +G01X129830Y12417429D01* +G01X112375Y12408737D01* +G01X96815Y12396987D01* +G01X83678Y12382577D01* +G01X73413Y12365998D01* +G01X66370Y12347816D01* +G01X62787Y12328649D01* +G01X35814Y12328649D01* +G01X35814Y12642750D01* +G01X62336Y12642750D01* +G01X62336Y12503050D01* +G01X64089Y12491983D01* +G01X69176Y12481999D01* +G01X77099Y12474076D01* +G01X87083Y12468989D01* +G01X98150Y12467236D01* +G01X288650Y12467236D01* +G01X288650Y12467236D01* +G01X299717Y12468989D01* +G01X309701Y12474076D01* +G01X317624Y12481999D01* +G01X322711Y12491983D01* +G01X324464Y12503050D01* +G01X324464Y12642750D01* +G01X322711Y12653817D01* +G01X317624Y12663801D01* +G01X309701Y12671724D01* +G01X299717Y12676811D01* +G01X288650Y12678564D01* +G01X98150Y12678564D01* +G01X87083Y12676811D01* +G01X77099Y12671724D01* +G01X69176Y12663801D01* +G01X64089Y12653817D01* +G01X62336Y12642750D01* +G01X35814Y12642750D01* +G01X35814Y13350000D01* +G01X37549Y13369828D01* +G01X42700Y13389054D01* +G01X51112Y13407093D01* +G01X62528Y13423397D01* +G01X76603Y13437471D01* +G01X92907Y13448888D01* +G01X110946Y13457300D01* +G01X130172Y13462451D01* +G01X150000Y13464186D01* +G01X2750004Y13464183D01* +G01X2769832Y13462448D01* +G01X2789058Y13457296D01* +G01X2807097Y13448884D01* +G01X2823401Y13437468D01* +G01X2837475Y13423394D01* +G01X2848892Y13407090D01* +G01X2857304Y13389050D01* +G01X2862455Y13369825D01* +G01X2864190Y13349997D01* +G01X2864188Y12580525D01* +G01X2860925Y12600018D01* +G01X2854088Y12618562D01* +G01X2843918Y12635508D01* +G01X2830769Y12650265D01* +G01X2815103Y12662314D01* +G01X2797467Y12671235D01* +G01X2778477Y12676716D01* +G01X2758800Y12678564D01* +G01X2708000Y12678564D01* +G01X2688584Y12676765D01* +G01X2669830Y12671429D01* +G01X2652375Y12662737D01* +G01X2636815Y12650987D01* +G01X2623678Y12636577D01* +G01X2613413Y12619998D01* +G01X2606370Y12601816D01* +G01X2602787Y12582649D01* +G01X2602787Y12563150D01* +G01X2606370Y12543984D01* +G01X2613413Y12525801D01* +G01X2623678Y12509223D01* +G01X2636815Y12494813D01* +G01X2652375Y12483063D01* +G01X2669830Y12474371D01* +G01X2688584Y12469035D01* +G01X2708000Y12467236D01* +G01X2758800Y12467236D01* +G01X2778477Y12469084D01* +G01X2797467Y12474565D01* +G01X2815103Y12483486D01* +G01X2830769Y12495535D01* +G01X2843918Y12510291D01* +G01X2854088Y12527238D01* +G01X2860925Y12545782D01* +G01X2864188Y12565274D01* +G01X2864188Y12326532D01* +G01X2864188Y12326532D01* +G01X2860923Y12346023D01* +G01X2854086Y12364566D01* +G01X2843915Y12381512D01* +G01X2830767Y12396267D01* +G01X2815101Y12408315D01* +G01X2797465Y12417236D01* +G01X2778477Y12422716D01* +G01X2758800Y12424564D01* +G01X2708000Y12424564D01* +G01X2688584Y12422765D01* +G01X2669830Y12417429D01* +G01X2652375Y12408737D01* +G01X2636815Y12396987D01* +G01X2623678Y12382577D01* +G01X2613413Y12365998D01* +G01X2606370Y12347816D01* +G01X2602787Y12328649D01* +G01X2602787Y12309150D01* +G01X2606370Y12289984D01* +G01X2613413Y12271801D01* +G01X2623678Y12255223D01* +G01X2636815Y12240813D01* +G01X2652375Y12229063D01* +G01X2669830Y12220371D01* +G01X2688584Y12215035D01* +G01X2708000Y12213236D01* +G01X2758800Y12213236D01* +G01X2778477Y12215084D01* +G01X2797465Y12220564D01* +G01X2815101Y12229485D01* +G01X2830767Y12241533D01* +G01X2843915Y12256288D01* +G01X2854086Y12273233D01* +G01X2860923Y12291776D01* +G01X2864188Y12311268D01* +G01X2864187Y12072538D01* +G01X2860922Y12092029D01* +G01X2854084Y12110571D01* +G01X2843913Y12127515D01* +G01X2830764Y12142269D01* +G01X2815099Y12154317D01* +G01X2797464Y12163236D01* +G01X2778476Y12168716D01* +G01X2758800Y12170564D01* +G01X2708000Y12170564D01* +G01X2688584Y12168765D01* +G01X2669830Y12163429D01* +G01X2652375Y12154737D01* +G01X2636815Y12142987D01* +G01X2623678Y12128577D01* +G01X2613413Y12111998D01* +G01X2606370Y12093816D01* +G01X2602787Y12074649D01* +G01X2602787Y12055150D01* +G01X2606370Y12035984D01* +G01X2613413Y12017801D01* +G01X2623678Y12001223D01* +G01X2636815Y11986813D01* +G01X2652375Y11975063D01* +G01X2669830Y11966371D01* +G01X2688584Y11961035D01* +G01X2708000Y11959236D01* +G01X2758800Y11959236D01* +G01X2778476Y11961084D01* +G01X2797463Y11966564D01* +G01X2815099Y11975483D01* +G01X2830764Y11987531D01* +G01X2843913Y12002285D01* +G01X2854084Y12019229D01* +G01X2860922Y12037771D01* +G01X2864187Y12057261D01* +G01X2864187Y11818545D01* +G01X2864187Y11818545D01* +G01X2860920Y11838035D01* +G01X2854082Y11856575D01* +G01X2843910Y11873518D01* +G01X2830762Y11888271D01* +G01X2815097Y11900318D01* +G01X2797462Y11909237D01* +G01X2778475Y11914716D01* +G01X2758800Y11916564D01* +G01X2708000Y11916564D01* +G01X2688584Y11914765D01* +G01X2669830Y11909429D01* +G01X2652375Y11900737D01* +G01X2636815Y11888987D01* +G01X2623678Y11874577D01* +G01X2613413Y11857998D01* +G01X2606370Y11839816D01* +G01X2602787Y11820649D01* +G01X2602787Y11801150D01* +G01X2606370Y11781984D01* +G01X2613413Y11763801D01* +G01X2623678Y11747223D01* +G01X2636815Y11732813D01* +G01X2652375Y11721063D01* +G01X2669830Y11712371D01* +G01X2688584Y11707035D01* +G01X2708000Y11705236D01* +G01X2758800Y11705236D01* +G01X2778475Y11707084D01* +G01X2797462Y11712563D01* +G01X2815097Y11721482D01* +G01X2830762Y11733528D01* +G01X2843910Y11748281D01* +G01X2854082Y11765224D01* +G01X2860920Y11783765D01* +G01X2864187Y11803255D01* +G01X2864187Y11564551D01* +G01X2864187Y11564551D01* +G01X2860919Y11584040D01* +G01X2854080Y11602580D01* +G01X2843908Y11619522D01* +G01X2830760Y11634274D01* +G01X2815095Y11646319D01* +G01X2797460Y11655237D01* +G01X2778474Y11660716D01* +G01X2758800Y11662564D01* +G01X2708000Y11662564D01* +G01X2688584Y11660765D01* +G01X2669830Y11655429D01* +G01X2652375Y11646737D01* +G01X2636815Y11634987D01* +G01X2623678Y11620577D01* +G01X2613413Y11603998D01* +G01X2606370Y11585816D01* +G01X2602787Y11566649D01* +G01X2602787Y11547150D01* +G01X2606370Y11527984D01* +G01X2613413Y11509801D01* +G01X2623678Y11493223D01* +G01X2636815Y11478813D01* +G01X2652375Y11467063D01* +G01X2669830Y11458371D01* +G01X2688584Y11453035D01* +G01X2708000Y11451236D01* +G01X2758800Y11451236D01* +G01X2778474Y11453084D01* +G01X2797460Y11458563D01* +G01X2815094Y11467481D01* +G01X2830760Y11479526D01* +G01X2843908Y11494278D01* +G01X2854080Y11511220D01* +G01X2860919Y11529759D01* +G01X2864187Y11549248D01* +G01X2864186Y11310558D01* +G01X2864186Y11310558D01* +G01X2860917Y11330046D01* +G01X2854078Y11348584D01* +G01X2843906Y11365525D01* +G01X2830757Y11380276D01* +G01X2815092Y11392320D01* +G01X2797459Y11401238D01* +G01X2778473Y11406716D01* +G01X2758800Y11408564D01* +G01X2708000Y11408564D01* +G01X2688584Y11406765D01* +G01X2669830Y11401429D01* +G01X2652375Y11392737D01* +G01X2636815Y11380987D01* +G01X2623678Y11366577D01* +G01X2613413Y11349998D01* +G01X2606370Y11331816D01* +G01X2602787Y11312649D01* +G01X2602787Y11293150D01* +G01X2606370Y11273984D01* +G01X2613413Y11255801D01* +G01X2623678Y11239223D01* +G01X2636815Y11224813D01* +G01X2652375Y11213063D01* +G01X2669830Y11204371D01* +G01X2688584Y11199035D01* +G01X2708000Y11197236D01* +G01X2758800Y11197236D01* +G01X2778701Y11199127D01* +G01X2797890Y11204733D01* +G01X2815680Y11213852D01* +G01X2831434Y11226159D01* +G01X2844587Y11241212D01* +G01X2854671Y11258474D01* +G01X2861322Y11277326D01* +G01X2864304Y11297093D01* +G01X2866730Y11286744D01* +G01X2872086Y11277562D01* +G01X2879902Y11270357D01* +G01X2889488Y11265764D01* +G01X2900000Y11264186D01* +G01X4750000Y11264186D01* +G01X4769828Y11262451D01* +G01X4789054Y11257300D01* +G01X4807093Y11248888D01* +G01X4823397Y11237472D01* +G01X4837472Y11223397D01* +G01X4848888Y11207093D01* +G01X4857300Y11189054D01* +G01X4862451Y11169828D01* +G01X4864186Y11150000D01* +G01X4891892Y5650013D01* +G01X4891892Y5650013D01* +G01X4890157Y5630186D01* +G01X4885005Y5610960D01* +G01X4876593Y5592922D01* +G01X4865177Y5576618D01* +G01X4851102Y5562544D01* +G01X4834798Y5551128D01* +G01X4816759Y5542716D01* +G01X4797534Y5537565D01* +G01X4777706Y5535830D01* +G01X2454000Y5535830D01* +G01X2444343Y5534503D01* +G01X2435402Y5530622D01* +G01X2427838Y5524474D01* +G01X2427838Y6318227D01* +G01X3026770Y6318227D01* +G01X3028683Y6303698D01* +G01X3034290Y6290160D01* +G01X3043211Y6278534D01* +G01X3353422Y5968323D01* +G01X3365048Y5959402D01* +G01X3378586Y5953795D01* +G01X3393115Y5951882D01* +G01X3471203Y5951882D01* +G01X3482937Y5934132D01* +G01X3497659Y5918770D01* +G01X3514894Y5906291D01* +G01X3534085Y5897100D01* +G01X3554611Y5891494D01* +G01X3575809Y5889653D01* +G01X3596994Y5891636D01* +G01X3617481Y5897381D01* +G01X3636610Y5906701D01* +G01X3653760Y5919295D01* +G01X3668378Y5934757D01* +G01X3679992Y5952585D01* +G01X3688227Y5972205D01* +G01X3692815Y5992982D01* +G01X3693610Y6014245D01* +G01X3690585Y6035307D01* +G01X3683838Y6055487D01* +G01X3673586Y6074133D01* +G01X3683908Y6074133D01* +G01X3716032Y6042008D01* +G01X3711825Y6021573D01* +G01X3711271Y6000716D01* +G01X3714388Y5980086D01* +G01X3721079Y5960324D01* +G01X3731136Y5942044D01* +G01X3744246Y5925814D01* +G01X3760003Y5912137D01* +G01X3777916Y5901440D01* +G01X3797429Y5894054D01* +G01X3817935Y5890209D01* +G01X3838798Y5890025D01* +G01X3859370Y5893506D01* +G01X3879011Y5900546D01* +G01X3897110Y5910925D01* +G01X3913106Y5924320D01* +G01X3926501Y5940316D01* +G01X3936880Y5958415D01* +G01X3943919Y5978056D01* +G01X3947401Y5998627D01* +G01X3947216Y6019491D01* +G01X3943371Y6039997D01* +G01X3935986Y6059510D01* +G01X3925288Y6077423D01* +G01X3911612Y6093180D01* +G01X3895382Y6106290D01* +G01X3877101Y6116347D01* +G01X3857339Y6123038D01* +G01X3836710Y6126155D01* +G01X3815853Y6125601D01* +G01X3795417Y6121394D01* +G01X3746852Y6169959D01* +G01X3735226Y6178880D01* +G01X3721688Y6184488D01* +G01X3707159Y6186401D01* +G01X3666472Y6186401D01* +G01X3678684Y6204184D01* +G01X3687465Y6223888D01* +G01X3692524Y6244858D01* +G01X3693693Y6266398D01* +G01X3692849Y6272937D01* +G01X3711551Y6272937D01* +G01X3711551Y6251095D01* +G01X3715564Y6229624D01* +G01X3723455Y6209257D01* +G01X3734953Y6190686D01* +G01X3749669Y6174544D01* +G01X3767099Y6161381D01* +G01X3786652Y6151645D01* +G01X3807661Y6145667D01* +G01X3829410Y6143652D01* +G01X3851159Y6145667D01* +G01X3872168Y6151645D01* +G01X3891721Y6161381D01* +G01X3909151Y6174544D01* +G01X3923866Y6190686D01* +G01X3935365Y6209257D01* +G01X3943255Y6229624D01* +G01X3947269Y6251095D01* +G01X3947269Y6272937D01* +G01X3943255Y6294408D01* +G01X3935365Y6314775D01* +G01X3923866Y6333346D01* +G01X3909151Y6349488D01* +G01X3891721Y6362651D01* +G01X3872168Y6372387D01* +G01X3851159Y6378365D01* +G01X3829410Y6380380D01* +G01X3829410Y6380380D01* +G01X3807661Y6378365D01* +G01X3786652Y6372387D01* +G01X3767099Y6362651D01* +G01X3749669Y6349488D01* +G01X3734953Y6333346D01* +G01X3723455Y6314775D01* +G01X3715564Y6294408D01* +G01X3711551Y6272937D01* +G01X3692849Y6272937D01* +G01X3690933Y6287793D01* +G01X3684336Y6308332D01* +G01X3674121Y6327332D01* +G01X3660627Y6344163D01* +G01X3644303Y6358265D01* +G01X3625690Y6369170D01* +G01X3605407Y6376516D01* +G01X3584128Y6380058D01* +G01X3562559Y6379680D01* +G01X3541417Y6375394D01* +G01X3443838Y6472973D01* +G01X3443838Y6526937D01* +G01X3457551Y6526937D01* +G01X3457551Y6505095D01* +G01X3461564Y6483624D01* +G01X3469455Y6463257D01* +G01X3480953Y6444686D01* +G01X3495669Y6428544D01* +G01X3513099Y6415381D01* +G01X3532652Y6405645D01* +G01X3553661Y6399667D01* +G01X3575410Y6397652D01* +G01X3597159Y6399667D01* +G01X3618168Y6405645D01* +G01X3637721Y6415381D01* +G01X3655151Y6428544D01* +G01X3669866Y6444686D01* +G01X3681365Y6463257D01* +G01X3689255Y6483624D01* +G01X3693269Y6505095D01* +G01X3693269Y6526937D01* +G01X3689255Y6548408D01* +G01X3681365Y6568775D01* +G01X3669866Y6587346D01* +G01X3655151Y6603488D01* +G01X3637721Y6616651D01* +G01X3618168Y6626387D01* +G01X3597159Y6632365D01* +G01X3575410Y6634380D01* +G01X3575410Y6634380D01* +G01X3553661Y6632365D01* +G01X3532652Y6626387D01* +G01X3513099Y6616651D01* +G01X3495669Y6603488D01* +G01X3480953Y6587346D01* +G01X3469455Y6568775D01* +G01X3461564Y6548408D01* +G01X3457551Y6526937D01* +G01X3443838Y6526937D01* +G01X3443838Y6779405D01* +G01X3457419Y6779405D01* +G01X3457603Y6758541D01* +G01X3461448Y6738035D01* +G01X3468834Y6718522D01* +G01X3479531Y6700609D01* +G01X3493208Y6684852D01* +G01X3509438Y6671742D01* +G01X3527718Y6661685D01* +G01X3547480Y6654994D01* +G01X3568110Y6651877D01* +G01X3588967Y6652431D01* +G01X3609402Y6656638D01* +G01X3659847Y6606194D01* +G01X3671472Y6597273D01* +G01X3685011Y6591665D01* +G01X3699539Y6589753D01* +G01X3736820Y6589753D01* +G01X3736820Y6589753D01* +G01X3725534Y6572759D01* +G01X3717333Y6554080D01* +G01X3712462Y6534270D01* +G01X3711065Y6513918D01* +G01X3713182Y6493628D01* +G01X3718753Y6474003D01* +G01X3727610Y6455627D01* +G01X3739491Y6439044D01* +G01X3754044Y6424747D01* +G01X3770835Y6413162D01* +G01X3789365Y6404632D01* +G01X3809086Y6399410D01* +G01X3829410Y6397652D01* +G01X3829410Y6397652D01* +G01X3849734Y6399410D01* +G01X3869454Y6404632D01* +G01X3887985Y6413162D01* +G01X3904776Y6424747D01* +G01X3919328Y6439044D01* +G01X3931210Y6455627D01* +G01X3940067Y6474003D01* +G01X3945637Y6493628D01* +G01X3947755Y6513918D01* +G01X3946358Y6534270D01* +G01X3941487Y6554080D01* +G01X3933286Y6572759D01* +G01X3922000Y6589753D01* +G01X3956664Y6589753D01* +G01X3971192Y6591665D01* +G01X3984731Y6597273D01* +G01X3996357Y6606194D01* +G01X4786297Y7396134D01* +G01X4795217Y7407760D01* +G01X4800825Y7421298D01* +G01X4802738Y7435827D01* +G01X4802738Y9930396D01* +G01X4800825Y9944924D01* +G01X4795217Y9958463D01* +G01X4786297Y9970089D01* +G01X4658235Y10098150D01* +G01X4661711Y10118765D01* +G01X4661295Y10139666D01* +G01X4657003Y10160127D01* +G01X4648984Y10179433D01* +G01X4637517Y10196913D01* +G01X4623002Y10211958D01* +G01X4605943Y10224044D01* +G01X4586936Y10232749D01* +G01X4566643Y10237771D01* +G01X4545770Y10238934D01* +G01X4525044Y10236198D01* +G01X4505187Y10229659D01* +G01X4486892Y10219544D01* +G01X4470794Y10206206D01* +G01X4470794Y10206206D01* +G01X4457456Y10190108D01* +G01X4447340Y10171813D01* +G01X4440801Y10151956D01* +G01X4438066Y10131230D01* +G01X4439229Y10110357D01* +G01X4444251Y10090063D01* +G01X4452956Y10071056D01* +G01X4465042Y10053998D01* +G01X4480087Y10039483D01* +G01X4497567Y10028016D01* +G01X4516873Y10019996D01* +G01X4537333Y10015704D01* +G01X4558235Y10015289D01* +G01X4578850Y10018765D01* +G01X4690470Y9907144D01* +G01X4690470Y7459078D01* +G01X3933412Y6702021D01* +G01X3926295Y6702021D01* +G01X3926295Y6702021D01* +G01X3936749Y6720132D01* +G01X3943852Y6739800D01* +G01X3947384Y6760411D01* +G01X3947233Y6781322D01* +G01X3943404Y6801880D01* +G01X3936018Y6821444D01* +G01X3925304Y6839402D01* +G01X3952313Y6839402D01* +G01X3966842Y6841315D01* +G01X3980380Y6846922D01* +G01X3992006Y6855843D01* +G01X4589693Y7453530D01* +G01X4598613Y7465156D01* +G01X4604221Y7478694D01* +G01X4606134Y7493223D01* +G01X4606134Y9506986D01* +G01X4626200Y9506986D01* +G01X4637267Y9508739D01* +G01X4647251Y9513826D01* +G01X4655174Y9521749D01* +G01X4660261Y9531733D01* +G01X4662014Y9542800D01* +G01X4662014Y9695200D01* +G01X4660261Y9706267D01* +G01X4655174Y9716251D01* +G01X4647251Y9724174D01* +G01X4637267Y9729261D01* +G01X4626200Y9731014D01* +G01X4487399Y9731014D01* +G01X4521150Y9764765D01* +G01X4541765Y9761289D01* +G01X4562666Y9761704D01* +G01X4583127Y9765996D01* +G01X4602433Y9774016D01* +G01X4619913Y9785483D01* +G01X4634958Y9799998D01* +G01X4647044Y9817056D01* +G01X4655749Y9836063D01* +G01X4660771Y9856357D01* +G01X4661934Y9877230D01* +G01X4659198Y9897956D01* +G01X4652659Y9917813D01* +G01X4642544Y9936108D01* +G01X4629206Y9952206D01* +G01X4613108Y9965544D01* +G01X4594813Y9975659D01* +G01X4574956Y9982198D01* +G01X4554230Y9984934D01* +G01X4533357Y9983771D01* +G01X4513063Y9978749D01* +G01X4494056Y9970044D01* +G01X4476998Y9957958D01* +G01X4462483Y9942913D01* +G01X4451016Y9925433D01* +G01X4442996Y9906127D01* +G01X4438704Y9885666D01* +G01X4438289Y9864765D01* +G01X4441765Y9844150D01* +G01X4376711Y9779097D01* +G01X4367790Y9767471D01* +G01X4362183Y9753932D01* +G01X4360270Y9739404D01* +G01X4360270Y9710741D01* +G01X4342876Y9720734D01* +G01X4323979Y9727463D01* +G01X4304185Y9730714D01* +G01X4284128Y9730383D01* +G01X4264452Y9726479D01* +G01X4245787Y9719129D01* +G01X4228733Y9708567D01* +G01X4213837Y9695133D01* +G01X4201575Y9679258D01* +G01X4192341Y9661450D01* +G01X4186432Y9642280D01* +G01X4184036Y9622364D01* +G01X4185232Y9602340D01* +G01X4189979Y9582851D01* +G01X4198127Y9564520D01* +G01X4209413Y9547937D01* +G01X4223477Y9533633D01* +G01X4239866Y9522066D01* +G01X4239866Y7767857D01* +G01X4239866Y7767857D01* +G01X3863402Y7391394D01* +G01X3863402Y7391394D01* +G01X3842967Y7395601D01* +G01X3822110Y7396155D01* +G01X3801480Y7393038D01* +G01X3781718Y7386347D01* +G01X3763438Y7376290D01* +G01X3747208Y7363180D01* +G01X3733531Y7347423D01* +G01X3722834Y7329510D01* +G01X3715448Y7309997D01* +G01X3711603Y7289491D01* +G01X3711419Y7268627D01* +G01X3714900Y7248056D01* +G01X3721940Y7228415D01* +G01X3732319Y7210316D01* +G01X3745714Y7194320D01* +G01X3761710Y7180925D01* +G01X3779809Y7170546D01* +G01X3799450Y7163506D01* +G01X3820021Y7160025D01* +G01X3840885Y7160209D01* +G01X3861391Y7164054D01* +G01X3880904Y7171440D01* +G01X3898817Y7182137D01* +G01X3914574Y7195814D01* +G01X3927684Y7212044D01* +G01X3937741Y7230324D01* +G01X3944432Y7250086D01* +G01X3947549Y7270716D01* +G01X3946995Y7291573D01* +G01X3942788Y7312008D01* +G01X4335693Y7704913D01* +G01X4344613Y7716539D01* +G01X4350221Y7730077D01* +G01X4352134Y7744606D01* +G01X4352134Y9522066D01* +G01X4360270Y9527258D01* +G01X4360270Y7634261D01* +G01X3863402Y7137394D01* +G01X3863402Y7137394D01* +G01X3842558Y7141647D01* +G01X3821289Y7142101D01* +G01X3800282Y7138740D01* +G01X3780216Y7131673D01* +G01X3761739Y7121128D01* +G01X3745448Y7107446D01* +G01X3731870Y7091068D01* +G01X3731870Y7091068D01* +G01X3721443Y7072525D01* +G01X3714503Y7052414D01* +G01X3711276Y7031387D01* +G01X3711864Y7010121D01* +G01X3716250Y6989304D01* +G01X3724292Y6969608D01* +G01X3735729Y6951670D01* +G01X3727141Y6951670D01* +G01X3688788Y6990023D01* +G01X3692995Y7010459D01* +G01X3693549Y7031316D01* +G01X3690432Y7051945D01* +G01X3683741Y7071707D01* +G01X3673684Y7089988D01* +G01X3660574Y7106218D01* +G01X3644817Y7119894D01* +G01X3626904Y7130592D01* +G01X3607391Y7137977D01* +G01X3586885Y7141822D01* +G01X3566021Y7142007D01* +G01X3545450Y7138525D01* +G01X3525809Y7131486D01* +G01X3507710Y7121107D01* +G01X3491714Y7107712D01* +G01X3478319Y7091716D01* +G01X3467940Y7073617D01* +G01X3460900Y7053976D01* +G01X3457419Y7033405D01* +G01X3457603Y7012541D01* +G01X3461448Y6992035D01* +G01X3468834Y6972522D01* +G01X3479531Y6954609D01* +G01X3493208Y6938852D01* +G01X3509438Y6925742D01* +G01X3527718Y6915685D01* +G01X3547480Y6908994D01* +G01X3568110Y6905877D01* +G01X3588967Y6906431D01* +G01X3609402Y6910638D01* +G01X3664197Y6855843D01* +G01X3675823Y6846922D01* +G01X3689361Y6841315D01* +G01X3703890Y6839402D01* +G01X3733516Y6839402D01* +G01X3733516Y6839402D01* +G01X3722802Y6821444D01* +G01X3715416Y6801880D01* +G01X3711587Y6781322D01* +G01X3711436Y6760411D01* +G01X3714968Y6739800D01* +G01X3722071Y6720132D01* +G01X3732525Y6702021D01* +G01X3722791Y6702021D01* +G01X3688788Y6736023D01* +G01X3692995Y6756459D01* +G01X3693549Y6777316D01* +G01X3690432Y6797945D01* +G01X3683741Y6817707D01* +G01X3673684Y6835988D01* +G01X3660574Y6852218D01* +G01X3644817Y6865894D01* +G01X3626904Y6876592D01* +G01X3607391Y6883977D01* +G01X3586885Y6887822D01* +G01X3566021Y6888007D01* +G01X3545450Y6884525D01* +G01X3525809Y6877486D01* +G01X3507710Y6867107D01* +G01X3491714Y6853712D01* +G01X3478319Y6837716D01* +G01X3467940Y6819617D01* +G01X3460900Y6799976D01* +G01X3457419Y6779405D01* +G01X3443838Y6779405D01* +G01X3443838Y7288937D01* +G01X3457551Y7288937D01* +G01X3457551Y7267095D01* +G01X3461564Y7245624D01* +G01X3469455Y7225257D01* +G01X3480953Y7206686D01* +G01X3495669Y7190544D01* +G01X3513099Y7177381D01* +G01X3532652Y7167645D01* +G01X3553661Y7161667D01* +G01X3575410Y7159652D01* +G01X3597159Y7161667D01* +G01X3618168Y7167645D01* +G01X3637721Y7177381D01* +G01X3655151Y7190544D01* +G01X3669866Y7206686D01* +G01X3681365Y7225257D01* +G01X3689255Y7245624D01* +G01X3693269Y7267095D01* +G01X3693269Y7288937D01* +G01X3689255Y7310408D01* +G01X3681365Y7330775D01* +G01X3669866Y7349346D01* +G01X3655151Y7365488D01* +G01X3637721Y7378651D01* +G01X3618168Y7388387D01* +G01X3597159Y7394365D01* +G01X3575410Y7396380D01* +G01X3575410Y7396380D01* +G01X3553661Y7394365D01* +G01X3532652Y7388387D01* +G01X3513099Y7378651D01* +G01X3495669Y7365488D01* +G01X3480953Y7349346D01* +G01X3469455Y7330775D01* +G01X3461564Y7310408D01* +G01X3457551Y7288937D01* +G01X3443838Y7288937D01* +G01X3443838Y7542937D01* +G01X3457551Y7542937D01* +G01X3457551Y7521095D01* +G01X3461564Y7499624D01* +G01X3469455Y7479257D01* +G01X3480953Y7460686D01* +G01X3495669Y7444544D01* +G01X3513099Y7431381D01* +G01X3532652Y7421645D01* +G01X3553661Y7415667D01* +G01X3575410Y7413652D01* +G01X3597159Y7415667D01* +G01X3618168Y7421645D01* +G01X3637721Y7431381D01* +G01X3655151Y7444544D01* +G01X3669866Y7460686D01* +G01X3681365Y7479257D01* +G01X3689255Y7499624D01* +G01X3693269Y7521095D01* +G01X3693269Y7542937D01* +G01X3711551Y7542937D01* +G01X3711551Y7521095D01* +G01X3715564Y7499624D01* +G01X3723455Y7479257D01* +G01X3734953Y7460686D01* +G01X3749669Y7444544D01* +G01X3767099Y7431381D01* +G01X3786652Y7421645D01* +G01X3807661Y7415667D01* +G01X3829410Y7413652D01* +G01X3851159Y7415667D01* +G01X3872168Y7421645D01* +G01X3891721Y7431381D01* +G01X3909151Y7444544D01* +G01X3923866Y7460686D01* +G01X3935365Y7479257D01* +G01X3943255Y7499624D01* +G01X3947269Y7521095D01* +G01X3947269Y7542937D01* +G01X3943255Y7564408D01* +G01X3935365Y7584775D01* +G01X3923866Y7603346D01* +G01X3909151Y7619488D01* +G01X3891721Y7632651D01* +G01X3872168Y7642387D01* +G01X3851159Y7648365D01* +G01X3829410Y7650380D01* +G01X3829410Y7650380D01* +G01X3807661Y7648365D01* +G01X3786652Y7642387D01* +G01X3767099Y7632651D01* +G01X3749669Y7619488D01* +G01X3734953Y7603346D01* +G01X3723455Y7584775D01* +G01X3715564Y7564408D01* +G01X3711551Y7542937D01* +G01X3693269Y7542937D01* +G01X3689255Y7564408D01* +G01X3681365Y7584775D01* +G01X3669866Y7603346D01* +G01X3655151Y7619488D01* +G01X3637721Y7632651D01* +G01X3618168Y7642387D01* +G01X3597159Y7648365D01* +G01X3575410Y7650380D01* +G01X3575410Y7650380D01* +G01X3553661Y7648365D01* +G01X3532652Y7642387D01* +G01X3513099Y7632651D01* +G01X3495669Y7619488D01* +G01X3480953Y7603346D01* +G01X3469455Y7584775D01* +G01X3461564Y7564408D01* +G01X3457551Y7542937D01* +G01X3443838Y7542937D01* +G01X3443838Y7796937D01* +G01X3457551Y7796937D01* +G01X3457551Y7775095D01* +G01X3461564Y7753624D01* +G01X3469455Y7733257D01* +G01X3480953Y7714686D01* +G01X3495669Y7698544D01* +G01X3513099Y7685381D01* +G01X3532652Y7675645D01* +G01X3553661Y7669667D01* +G01X3575410Y7667652D01* +G01X3597159Y7669667D01* +G01X3618168Y7675645D01* +G01X3637721Y7685381D01* +G01X3655151Y7698544D01* +G01X3669866Y7714686D01* +G01X3681365Y7733257D01* +G01X3689255Y7753624D01* +G01X3693269Y7775095D01* +G01X3693269Y7796937D01* +G01X3689255Y7818408D01* +G01X3681365Y7838775D01* +G01X3669866Y7857346D01* +G01X3655151Y7873488D01* +G01X3637721Y7886651D01* +G01X3618168Y7896387D01* +G01X3597159Y7902365D01* +G01X3575410Y7904380D01* +G01X3575410Y7904380D01* +G01X3553661Y7902365D01* +G01X3532652Y7896387D01* +G01X3513099Y7886651D01* +G01X3495669Y7873488D01* +G01X3480953Y7857346D01* +G01X3469455Y7838775D01* +G01X3461564Y7818408D01* +G01X3457551Y7796937D01* +G01X3443838Y7796937D01* +G01X3443838Y9078652D01* +G01X3782997Y9417811D01* +G01X3791917Y9429437D01* +G01X3797525Y9442975D01* +G01X3799438Y9457504D01* +G01X3799438Y10187696D01* +G01X3797525Y10202224D01* +G01X3791917Y10215763D01* +G01X3782997Y10227389D01* +G01X3658235Y10352150D01* +G01X3658235Y10352150D01* +G01X3661521Y10370501D01* +G01X3661718Y10389142D01* +G01X3658820Y10407557D01* +G01X3652908Y10425238D01* +G01X3644146Y10441692D01* +G01X3632777Y10456466D01* +G01X3682949Y10456466D01* +G01X3852270Y10287145D01* +G01X3852270Y9429955D01* +G01X3671647Y9249332D01* +G01X3662726Y9237707D01* +G01X3657119Y9224168D01* +G01X3655206Y9209640D01* +G01X3655206Y8412380D01* +G01X3492860Y8412380D01* +G01X3481793Y8410627D01* +G01X3471809Y8405540D01* +G01X3463886Y8397617D01* +G01X3458799Y8387633D01* +G01X3457046Y8376566D01* +G01X3457046Y8211466D01* +G01X3458799Y8200399D01* +G01X3463886Y8190415D01* +G01X3471809Y8182492D01* +G01X3481793Y8177405D01* +G01X3492860Y8175652D01* +G01X3655206Y8175652D01* +G01X3655206Y8127438D01* +G01X3655206Y8127438D01* +G01X3638492Y8140169D01* +G01X3619790Y8149745D01* +G01X3599691Y8155863D01* +G01X3578826Y8158331D01* +G01X3557853Y8157071D01* +G01X3537434Y8152122D01* +G01X3518211Y8143642D01* +G01X3500791Y8131896D01* +G01X3485721Y8117256D01* +G01X3473478Y8100181D01* +G01X3464446Y8081211D01* +G01X3458911Y8060943D01* +G01X3457046Y8040016D01* +G01X3457046Y8040016D01* +G01X3458911Y8019089D01* +G01X3464446Y7998820D01* +G01X3473478Y7979850D01* +G01X3485721Y7962776D01* +G01X3500791Y7948136D01* +G01X3518211Y7936390D01* +G01X3537434Y7927909D01* +G01X3557853Y7922961D01* +G01X3578826Y7921701D01* +G01X3599691Y7924169D01* +G01X3619790Y7930287D01* +G01X3638492Y7939863D01* +G01X3655206Y7952594D01* +G01X3655206Y7904086D01* +G01X3657119Y7889557D01* +G01X3662726Y7876019D01* +G01X3671647Y7864393D01* +G01X3716032Y7820008D01* +G01X3711825Y7799573D01* +G01X3711271Y7778716D01* +G01X3714388Y7758086D01* +G01X3721079Y7738324D01* +G01X3731136Y7720044D01* +G01X3744246Y7703814D01* +G01X3760003Y7690137D01* +G01X3777916Y7679440D01* +G01X3797429Y7672054D01* +G01X3817935Y7668209D01* +G01X3838798Y7668025D01* +G01X3859370Y7671506D01* +G01X3879011Y7678546D01* +G01X3897110Y7688925D01* +G01X3913106Y7702320D01* +G01X3926501Y7718316D01* +G01X3936880Y7736415D01* +G01X3943919Y7756056D01* +G01X3947401Y7776627D01* +G01X3947216Y7797491D01* +G01X3943371Y7817997D01* +G01X3935986Y7837510D01* +G01X3925288Y7855423D01* +G01X3911612Y7871180D01* +G01X3895382Y7884290D01* +G01X3877101Y7894347D01* +G01X3857339Y7901038D01* +G01X3836710Y7904155D01* +G01X3815853Y7903601D01* +G01X3795417Y7899394D01* +G01X3767474Y7927338D01* +G01X3767474Y7939150D01* +G01X3767474Y7939150D01* +G01X3786179Y7929829D01* +G01X3806231Y7923944D01* +G01X3827006Y7921676D01* +G01X3847856Y7923098D01* +G01X3868131Y7928164D01* +G01X3887198Y7936718D01* +G01X3904465Y7948491D01* +G01X3919391Y7963118D01* +G01X3931513Y7980141D01* +G01X3940452Y7999031D01* +G01X3945929Y8019199D01* +G01X3947774Y8040016D01* +G01X3947774Y8040016D01* +G01X3945929Y8060833D01* +G01X3940452Y8081000D01* +G01X3931513Y8099891D01* +G01X3919391Y8116914D01* +G01X3904465Y8131541D01* +G01X3887198Y8143314D01* +G01X3868131Y8151867D01* +G01X3847856Y8156934D01* +G01X3827006Y8158356D01* +G01X3806231Y8156088D01* +G01X3786179Y8150203D01* +G01X3767474Y8140882D01* +G01X3767474Y8193150D01* +G01X3767474Y8193150D01* +G01X3786276Y8183791D01* +G01X3806437Y8177903D01* +G01X3827320Y8175670D01* +G01X3848270Y8177164D01* +G01X3868626Y8182337D01* +G01X3887747Y8191026D01* +G01X3905031Y8202958D01* +G01X3919934Y8217757D01* +G01X3931987Y8234957D01* +G01X3931987Y8234957D01* +G01X3940811Y8254017D01* +G01X3946126Y8274336D01* +G01X3947767Y8295274D01* +G01X3945682Y8316173D01* +G01X3939935Y8336374D01* +G01X3930708Y8355242D01* +G01X3918292Y8372182D01* +G01X3903078Y8386661D01* +G01X3885544Y8398223D01* +G01X3885544Y9073481D01* +G01X4125897Y9313834D01* +G01X4134817Y9325460D01* +G01X4140425Y9338998D01* +G01X4142338Y9353527D01* +G01X4142338Y9883335D01* +G01X4184464Y9883335D01* +G01X4184464Y9862665D01* +G01X4188262Y9842346D01* +G01X4195729Y9823071D01* +G01X4206611Y9805496D01* +G01X4220537Y9790221D01* +G01X4237032Y9777764D01* +G01X4255536Y9768550D01* +G01X4275417Y9762893D01* +G01X4296000Y9760986D01* +G01X4296000Y9760986D01* +G01X4316582Y9762893D01* +G01X4336464Y9768550D01* +G01X4354968Y9777764D01* +G01X4371463Y9790221D01* +G01X4385389Y9805496D01* +G01X4396271Y9823071D01* +G01X4403738Y9842346D01* +G01X4407536Y9862665D01* +G01X4407536Y9883335D01* +G01X4403738Y9903654D01* +G01X4396271Y9922929D01* +G01X4385389Y9940503D01* +G01X4371463Y9955779D01* +G01X4354968Y9968236D01* +G01X4336464Y9977450D01* +G01X4316582Y9983107D01* +G01X4296000Y9985014D01* +G01X4275417Y9983107D01* +G01X4255536Y9977450D01* +G01X4237032Y9968236D01* +G01X4220537Y9955779D01* +G01X4206611Y9940503D01* +G01X4195729Y9922929D01* +G01X4188262Y9903654D01* +G01X4184464Y9883335D01* +G01X4142338Y9883335D01* +G01X4142338Y10137335D01* +G01X4184464Y10137335D01* +G01X4184464Y10116665D01* +G01X4188262Y10096346D01* +G01X4195729Y10077071D01* +G01X4206611Y10059496D01* +G01X4220537Y10044221D01* +G01X4237032Y10031764D01* +G01X4255536Y10022550D01* +G01X4275417Y10016893D01* +G01X4296000Y10014986D01* +G01X4296000Y10014986D01* +G01X4316582Y10016893D01* +G01X4336464Y10022550D01* +G01X4354968Y10031764D01* +G01X4371463Y10044221D01* +G01X4385389Y10059496D01* +G01X4396271Y10077071D01* +G01X4403738Y10096346D01* +G01X4407536Y10116665D01* +G01X4407536Y10137335D01* +G01X4403738Y10157654D01* +G01X4396271Y10176929D01* +G01X4385389Y10194503D01* +G01X4371463Y10209779D01* +G01X4354968Y10222236D01* +G01X4336464Y10231450D01* +G01X4316582Y10237107D01* +G01X4296000Y10239014D01* +G01X4275417Y10237107D01* +G01X4255536Y10231450D01* +G01X4237032Y10222236D01* +G01X4220537Y10209779D01* +G01X4206611Y10194503D01* +G01X4195729Y10176929D01* +G01X4188262Y10157654D01* +G01X4184464Y10137335D01* +G01X4142338Y10137335D01* +G01X4142338Y10147952D01* +G01X4267150Y10272765D01* +G01X4287765Y10269289D01* +G01X4308666Y10269704D01* +G01X4329127Y10273996D01* +G01X4348433Y10282016D01* +G01X4365913Y10293483D01* +G01X4380958Y10307998D01* +G01X4393044Y10325056D01* +G01X4401749Y10344063D01* +G01X4406771Y10364357D01* +G01X4407934Y10385230D01* +G01X4407128Y10391335D01* +G01X4438464Y10391335D01* +G01X4438464Y10370665D01* +G01X4442262Y10350346D01* +G01X4449729Y10331071D01* +G01X4460611Y10313496D01* +G01X4474537Y10298221D01* +G01X4491032Y10285764D01* +G01X4509536Y10276550D01* +G01X4529417Y10270893D01* +G01X4550000Y10268986D01* +G01X4550000Y10268986D01* +G01X4570582Y10270893D01* +G01X4590464Y10276550D01* +G01X4608968Y10285764D01* +G01X4625463Y10298221D01* +G01X4639389Y10313496D01* +G01X4650271Y10331071D01* +G01X4657738Y10350346D01* +G01X4661536Y10370665D01* +G01X4661536Y10391335D01* +G01X4657738Y10411654D01* +G01X4650271Y10430929D01* +G01X4639389Y10448503D01* +G01X4625463Y10463779D01* +G01X4608968Y10476236D01* +G01X4590464Y10485450D01* +G01X4570582Y10491107D01* +G01X4550000Y10493014D01* +G01X4529417Y10491107D01* +G01X4509536Y10485450D01* +G01X4491032Y10476236D01* +G01X4474537Y10463779D01* +G01X4460611Y10448503D01* +G01X4449729Y10430929D01* +G01X4442262Y10411654D01* +G01X4438464Y10391335D01* +G01X4407128Y10391335D01* +G01X4405198Y10405956D01* +G01X4398659Y10425813D01* +G01X4388544Y10444108D01* +G01X4375206Y10460206D01* +G01X4359108Y10473544D01* +G01X4340813Y10483659D01* +G01X4320956Y10490198D01* +G01X4300230Y10492934D01* +G01X4279357Y10491771D01* +G01X4259063Y10486749D01* +G01X4240056Y10478044D01* +G01X4222998Y10465958D01* +G01X4208483Y10450913D01* +G01X4197016Y10433433D01* +G01X4188996Y10414127D01* +G01X4184704Y10393666D01* +G01X4184289Y10372765D01* +G01X4187765Y10352150D01* +G01X4046511Y10210897D01* +G01X4037590Y10199271D01* +G01X4031983Y10185732D01* +G01X4030070Y10171204D01* +G01X4030070Y9376778D01* +G01X3789717Y9136425D01* +G01X3780796Y9124800D01* +G01X3775189Y9111261D01* +G01X3773276Y9096733D01* +G01X3773276Y8398223D01* +G01X3767474Y8394882D01* +G01X3767474Y9186388D01* +G01X3948097Y9367011D01* +G01X3957017Y9378637D01* +G01X3962625Y9392175D01* +G01X3964538Y9406704D01* +G01X3964538Y10310396D01* +G01X3962625Y10324925D01* +G01X3957017Y10338463D01* +G01X3948097Y10350089D01* +G01X3745893Y10552293D01* +G01X3734267Y10561213D01* +G01X3720729Y10566821D01* +G01X3706200Y10568734D01* +G01X3640310Y10568734D01* +G01X3650893Y10586341D01* +G01X3658083Y10605584D01* +G01X3661637Y10625817D01* +G01X3661446Y10645335D01* +G01X4184464Y10645335D01* +G01X4184464Y10624665D01* +G01X4188262Y10604346D01* +G01X4195729Y10585071D01* +G01X4206611Y10567496D01* +G01X4220537Y10552221D01* +G01X4237032Y10539764D01* +G01X4255536Y10530550D01* +G01X4275417Y10524893D01* +G01X4296000Y10522986D01* +G01X4296000Y10522986D01* +G01X4316582Y10524893D01* +G01X4336464Y10530550D01* +G01X4354968Y10539764D01* +G01X4371463Y10552221D01* +G01X4385389Y10567496D01* +G01X4396271Y10585071D01* +G01X4403738Y10604346D01* +G01X4407536Y10624665D01* +G01X4407536Y10645335D01* +G01X4438464Y10645335D01* +G01X4438464Y10624665D01* +G01X4442262Y10604346D01* +G01X4449729Y10585071D01* +G01X4460611Y10567496D01* +G01X4474537Y10552221D01* +G01X4491032Y10539764D01* +G01X4509536Y10530550D01* +G01X4529417Y10524893D01* +G01X4550000Y10522986D01* +G01X4550000Y10522986D01* +G01X4570582Y10524893D01* +G01X4590464Y10530550D01* +G01X4608968Y10539764D01* +G01X4625463Y10552221D01* +G01X4639389Y10567496D01* +G01X4650271Y10585071D01* +G01X4657738Y10604346D01* +G01X4661536Y10624665D01* +G01X4661536Y10645335D01* +G01X4657738Y10665654D01* +G01X4650271Y10684929D01* +G01X4639389Y10702503D01* +G01X4625463Y10717779D01* +G01X4608968Y10730236D01* +G01X4590464Y10739450D01* +G01X4570582Y10745107D01* +G01X4550000Y10747014D01* +G01X4529417Y10745107D01* +G01X4509536Y10739450D01* +G01X4491032Y10730236D01* +G01X4474537Y10717779D01* +G01X4460611Y10702503D01* +G01X4449729Y10684929D01* +G01X4442262Y10665654D01* +G01X4438464Y10645335D01* +G01X4407536Y10645335D01* +G01X4403738Y10665654D01* +G01X4396271Y10684929D01* +G01X4385389Y10702503D01* +G01X4371463Y10717779D01* +G01X4354968Y10730236D01* +G01X4336464Y10739450D01* +G01X4316582Y10745107D01* +G01X4296000Y10747014D01* +G01X4275417Y10745107D01* +G01X4255536Y10739450D01* +G01X4237032Y10730236D01* +G01X4220537Y10717779D01* +G01X4206611Y10702503D01* +G01X4195729Y10684929D01* +G01X4188262Y10665654D01* +G01X4184464Y10645335D01* +G01X3661446Y10645335D01* +G01X3661436Y10646359D01* +G01X3657488Y10666519D01* +G01X3649925Y10685618D01* +G01X3639000Y10703015D01* +G01X3625082Y10718125D01* +G01X3608639Y10730439D01* +G01X3590224Y10739542D01* +G01X3570456Y10745130D01* +G01X3550000Y10747014D01* +G01X3529544Y10745130D01* +G01X3509776Y10739542D01* +G01X3491360Y10730439D01* +G01X3474917Y10718125D01* +G01X3461000Y10703015D01* +G01X3450075Y10685618D01* +G01X3442512Y10666519D01* +G01X3438563Y10646359D01* +G01X3438363Y10625817D01* +G01X3441917Y10605584D01* +G01X3449107Y10586341D01* +G01X3459690Y10568734D01* +G01X3427600Y10568734D01* +G01X3413071Y10566821D01* +G01X3399533Y10561213D01* +G01X3387907Y10552293D01* +G01X3324850Y10489235D01* +G01X3304235Y10492711D01* +G01X3283333Y10492295D01* +G01X3262873Y10488003D01* +G01X3243567Y10479984D01* +G01X3226087Y10468517D01* +G01X3211042Y10454002D01* +G01X3198956Y10436943D01* +G01X3190251Y10417936D01* +G01X3185229Y10397643D01* +G01X3184066Y10376770D01* +G01X3186801Y10356044D01* +G01X3193340Y10336187D01* +G01X3203456Y10317892D01* +G01X3216794Y10301794D01* +G01X3232892Y10288456D01* +G01X3251187Y10278341D01* +G01X3271044Y10271801D01* +G01X3291770Y10269066D01* +G01X3312643Y10270229D01* +G01X3332936Y10275251D01* +G01X3351943Y10283956D01* +G01X3369002Y10296042D01* +G01X3383517Y10311087D01* +G01X3394984Y10328567D01* +G01X3403003Y10347873D01* +G01X3407295Y10368333D01* +G01X3407711Y10389235D01* +G01X3404235Y10409850D01* +G01X3450851Y10456466D01* +G01X3467223Y10456466D01* +G01X3467223Y10456466D01* +G01X3454836Y10440084D01* +G01X3445648Y10421716D01* +G01X3439968Y10401979D01* +G01X3437987Y10381537D01* +G01X3439772Y10361077D01* +G01X3445262Y10341287D01* +G01X3454273Y10322831D01* +G01X3454273Y10322831D01* +G01X3466503Y10306332D01* +G01X3481539Y10292342D01* +G01X3498877Y10281333D01* +G01X3517933Y10273674D01* +G01X3538068Y10269623D01* +G01X3558603Y10269317D01* +G01X3578850Y10272765D01* +G01X3687170Y10164444D01* +G01X3687170Y9480755D01* +G01X3348011Y9141597D01* +G01X3339090Y9129971D01* +G01X3333483Y9116432D01* +G01X3331570Y9101904D01* +G01X3331570Y6449722D01* +G01X3333483Y6435193D01* +G01X3339090Y6421655D01* +G01X3348011Y6410029D01* +G01X3462032Y6296008D01* +G01X3458003Y6277036D01* +G01X3457126Y6257661D01* +G01X3459425Y6238402D01* +G01X3464839Y6219778D01* +G01X3473221Y6202287D01* +G01X3484348Y6186401D01* +G01X3459215Y6186401D01* +G01X3291438Y6354178D01* +G01X3291438Y9507079D01* +G01X3309889Y9507850D01* +G01X3327963Y9511643D01* +G01X3345167Y9518354D01* +G01X3361036Y9527800D01* +G01X3375136Y9539725D01* +G01X3387086Y9553805D01* +G01X3396560Y9569656D01* +G01X3403301Y9586849D01* +G01X3407125Y9604916D01* +G01X3407929Y9623366D01* +G01X3405690Y9641697D01* +G01X3400470Y9659411D01* +G01X3392411Y9676027D01* +G01X3381731Y9691093D01* +G01X3424227Y9691093D01* +G01X3437986Y9692805D01* +G01X3437986Y9542800D01* +G01X3439739Y9531733D01* +G01X3444826Y9521749D01* +G01X3452749Y9513826D01* +G01X3462733Y9508739D01* +G01X3473800Y9506986D01* +G01X3626200Y9506986D01* +G01X3637267Y9508739D01* +G01X3647251Y9513826D01* +G01X3655174Y9521749D01* +G01X3660261Y9531733D01* +G01X3662014Y9542800D01* +G01X3662014Y9695200D01* +G01X3660261Y9706267D01* +G01X3655174Y9716251D01* +G01X3647251Y9724174D01* +G01X3637267Y9729261D01* +G01X3626200Y9731014D01* +G01X3487399Y9731014D01* +G01X3521150Y9764765D01* +G01X3541765Y9761289D01* +G01X3562666Y9761704D01* +G01X3583127Y9765996D01* +G01X3602433Y9774016D01* +G01X3619913Y9785483D01* +G01X3634958Y9799998D01* +G01X3647044Y9817056D01* +G01X3655749Y9836063D01* +G01X3660771Y9856357D01* +G01X3661934Y9877230D01* +G01X3659198Y9897956D01* +G01X3652659Y9917813D01* +G01X3642544Y9936108D01* +G01X3629206Y9952206D01* +G01X3613108Y9965544D01* +G01X3594813Y9975659D01* +G01X3574956Y9982198D01* +G01X3554230Y9984934D01* +G01X3533357Y9983771D01* +G01X3513063Y9978749D01* +G01X3494056Y9970044D01* +G01X3476998Y9957958D01* +G01X3462483Y9942913D01* +G01X3451016Y9925433D01* +G01X3442996Y9906127D01* +G01X3438704Y9885666D01* +G01X3438289Y9864765D01* +G01X3441765Y9844150D01* +G01X3400975Y9803361D01* +G01X3383735Y9803361D01* +G01X3395170Y9820919D01* +G01X3403135Y9840300D01* +G01X3407350Y9860825D01* +G01X3407670Y9881776D01* +G01X3404081Y9902420D01* +G01X3396711Y9922035D01* +G01X3385817Y9939933D01* +G01X3371779Y9955490D01* +G01X3355090Y9968160D01* +G01X3336334Y9977500D01* +G01X3316166Y9983184D01* +G01X3295292Y9985012D01* +G01X3274443Y9982920D01* +G01X3254349Y9976982D01* +G01X3235711Y9967406D01* +G01X3219184Y9954526D01* +G01X3205344Y9938793D01* +G01X3194677Y9920758D01* +G01X3187555Y9901052D01* +G01X3184228Y9880364D01* +G01X3184812Y9859419D01* +G01X3189287Y9838948D01* +G01X3197496Y9819670D01* +G01X3209152Y9802257D01* +G01X3198667Y9799055D01* +G01X3189005Y9793877D01* +G01X3180534Y9786919D01* +G01X3043211Y9649597D01* +G01X3034290Y9637971D01* +G01X3028683Y9624432D01* +G01X3026770Y9609904D01* +G01X3026770Y6318227D01* +G01X3026770Y6318227D01* +G01X2427838Y6318227D01* +G01X2427838Y6800827D01* +G01X2425925Y6815355D01* +G01X2420317Y6828894D01* +G01X2411397Y6840519D01* +G01X2003267Y7248649D01* +G01X2602787Y7248649D01* +G01X2602787Y7229150D01* +G01X2606370Y7209984D01* +G01X2613413Y7191801D01* +G01X2623678Y7175223D01* +G01X2636815Y7160813D01* +G01X2652375Y7149063D01* +G01X2669830Y7140371D01* +G01X2688584Y7135035D01* +G01X2708000Y7133236D01* +G01X2758800Y7133236D01* +G01X2778216Y7135035D01* +G01X2796970Y7140371D01* +G01X2814425Y7149063D01* +G01X2829985Y7160813D01* +G01X2843122Y7175223D01* +G01X2853386Y7191801D01* +G01X2860430Y7209984D01* +G01X2864013Y7229150D01* +G01X2864013Y7248649D01* +G01X2860430Y7267816D01* +G01X2853386Y7285998D01* +G01X2843122Y7302577D01* +G01X2829985Y7316987D01* +G01X2814425Y7328737D01* +G01X2796970Y7337429D01* +G01X2778216Y7342765D01* +G01X2758800Y7344564D01* +G01X2758800Y7344564D01* +G01X2708000Y7344564D01* +G01X2688584Y7342765D01* +G01X2669830Y7337429D01* +G01X2652375Y7328737D01* +G01X2636815Y7316987D01* +G01X2623678Y7302577D01* +G01X2613413Y7285998D01* +G01X2606370Y7267816D01* +G01X2602787Y7248649D01* +G01X2003267Y7248649D01* +G01X1749267Y7502649D01* +G01X2602787Y7502649D01* +G01X2602787Y7483150D01* +G01X2606370Y7463984D01* +G01X2613413Y7445801D01* +G01X2623678Y7429223D01* +G01X2636815Y7414813D01* +G01X2652375Y7403063D01* +G01X2669830Y7394371D01* +G01X2688584Y7389035D01* +G01X2708000Y7387236D01* +G01X2758800Y7387236D01* +G01X2778216Y7389035D01* +G01X2796970Y7394371D01* +G01X2814425Y7403063D01* +G01X2829985Y7414813D01* +G01X2843122Y7429223D01* +G01X2853386Y7445801D01* +G01X2860430Y7463984D01* +G01X2864013Y7483150D01* +G01X2864013Y7502649D01* +G01X2860430Y7521816D01* +G01X2853386Y7539998D01* +G01X2843122Y7556577D01* +G01X2829985Y7570987D01* +G01X2814425Y7582737D01* +G01X2796970Y7591429D01* +G01X2778216Y7596765D01* +G01X2758800Y7598564D01* +G01X2758800Y7598564D01* +G01X2708000Y7598564D01* +G01X2688584Y7596765D01* +G01X2669830Y7591429D01* +G01X2652375Y7582737D01* +G01X2636815Y7570987D01* +G01X2623678Y7556577D01* +G01X2613413Y7539998D01* +G01X2606370Y7521816D01* +G01X2602787Y7502649D01* +G01X1749267Y7502649D01* +G01X1495267Y7756649D01* +G01X2602787Y7756649D01* +G01X2602787Y7737150D01* +G01X2606370Y7717984D01* +G01X2613413Y7699801D01* +G01X2623678Y7683223D01* +G01X2636815Y7668813D01* +G01X2652375Y7657063D01* +G01X2669830Y7648371D01* +G01X2688584Y7643035D01* +G01X2708000Y7641236D01* +G01X2758800Y7641236D01* +G01X2778216Y7643035D01* +G01X2796970Y7648371D01* +G01X2814425Y7657063D01* +G01X2829985Y7668813D01* +G01X2843122Y7683223D01* +G01X2853386Y7699801D01* +G01X2860430Y7717984D01* +G01X2864013Y7737150D01* +G01X2864013Y7756649D01* +G01X2860430Y7775816D01* +G01X2853386Y7793998D01* +G01X2843122Y7810577D01* +G01X2829985Y7824987D01* +G01X2814425Y7836737D01* +G01X2796970Y7845429D01* +G01X2778216Y7850765D01* +G01X2758800Y7852564D01* +G01X2758800Y7852564D01* +G01X2708000Y7852564D01* +G01X2688584Y7850765D01* +G01X2669830Y7845429D01* +G01X2652375Y7836737D01* +G01X2636815Y7824987D01* +G01X2623678Y7810577D01* +G01X2613413Y7793998D01* +G01X2606370Y7775816D01* +G01X2602787Y7756649D01* +G01X1495267Y7756649D01* +G01X1241267Y8010649D01* +G01X2602787Y8010649D01* +G01X2602787Y7991150D01* +G01X2606370Y7971984D01* +G01X2613413Y7953801D01* +G01X2623678Y7937223D01* +G01X2636815Y7922813D01* +G01X2652375Y7911063D01* +G01X2669830Y7902371D01* +G01X2688584Y7897035D01* +G01X2708000Y7895236D01* +G01X2758800Y7895236D01* +G01X2778216Y7897035D01* +G01X2796970Y7902371D01* +G01X2814425Y7911063D01* +G01X2829985Y7922813D01* +G01X2843122Y7937223D01* +G01X2853386Y7953801D01* +G01X2860430Y7971984D01* +G01X2864013Y7991150D01* +G01X2864013Y8010649D01* +G01X2860430Y8029816D01* +G01X2853386Y8047998D01* +G01X2843122Y8064577D01* +G01X2829985Y8078987D01* +G01X2814425Y8090737D01* +G01X2796970Y8099429D01* +G01X2778216Y8104765D01* +G01X2758800Y8106564D01* +G01X2758800Y8106564D01* +G01X2708000Y8106564D01* +G01X2688584Y8104765D01* +G01X2669830Y8099429D01* +G01X2652375Y8090737D01* +G01X2636815Y8078987D01* +G01X2623678Y8064577D01* +G01X2613413Y8047998D01* +G01X2606370Y8029816D01* +G01X2602787Y8010649D01* +G01X1241267Y8010649D01* +G01X987267Y8264649D01* +G01X2602787Y8264649D01* +G01X2602787Y8245150D01* +G01X2606370Y8225984D01* +G01X2613413Y8207801D01* +G01X2623678Y8191223D01* +G01X2636815Y8176813D01* +G01X2652375Y8165063D01* +G01X2669830Y8156371D01* +G01X2688584Y8151035D01* +G01X2708000Y8149236D01* +G01X2758800Y8149236D01* +G01X2778216Y8151035D01* +G01X2796970Y8156371D01* +G01X2814425Y8165063D01* +G01X2829985Y8176813D01* +G01X2843122Y8191223D01* +G01X2853386Y8207801D01* +G01X2860430Y8225984D01* +G01X2864013Y8245150D01* +G01X2864013Y8264649D01* +G01X2860430Y8283816D01* +G01X2853386Y8301998D01* +G01X2843122Y8318577D01* +G01X2829985Y8332987D01* +G01X2814425Y8344737D01* +G01X2796970Y8353429D01* +G01X2778216Y8358765D01* +G01X2758800Y8360564D01* +G01X2758800Y8360564D01* +G01X2708000Y8360564D01* +G01X2688584Y8358765D01* +G01X2669830Y8353429D01* +G01X2652375Y8344737D01* +G01X2636815Y8332987D01* +G01X2623678Y8318577D01* +G01X2613413Y8301998D01* +G01X2606370Y8283816D01* +G01X2602787Y8264649D01* +G01X987267Y8264649D01* +G01X955977Y8295939D01* +G01X944351Y8304860D01* +G01X930812Y8310468D01* +G01X916284Y8312381D01* +G01X842024Y8312381D01* +G01X842024Y8325097D01* +G01X840272Y8336164D01* +G01X835185Y8346148D01* +G01X827261Y8354071D01* +G01X817278Y8359158D01* +G01X806210Y8360911D01* +G01X692957Y8360911D01* +G01X681890Y8359158D01* +G01X671906Y8354071D01* +G01X663983Y8346148D01* +G01X658896Y8336164D01* +G01X657143Y8325097D01* +G01X657143Y8187396D01* +G01X658896Y8176329D01* +G01X663983Y8166345D01* +G01X671906Y8158422D01* +G01X681890Y8153335D01* +G01X692957Y8151582D01* +G01X806210Y8151582D01* +G01X817278Y8153335D01* +G01X827261Y8158422D01* +G01X835185Y8166345D01* +G01X840272Y8176329D01* +G01X842024Y8187396D01* +G01X842024Y8200113D01* +G01X893032Y8200113D01* +G01X2315570Y6777575D01* +G01X2315570Y5379511D01* +G01X2315570Y5379511D01* +G01X2312175Y5400804D01* +G01X2304891Y5421099D01* +G01X2293972Y5439692D01* +G01X2279795Y5455938D01* +G01X2262852Y5469275D01* +G01X2243731Y5479240D01* +G01X2223094Y5485488D01* +G01X2201656Y5487802D01* +G01X2180161Y5486102D01* +G01X2180161Y5486102D01* +G01X2159354Y5480447D01* +G01X2139956Y5471033D01* +G01X2122639Y5458186D01* +G01X2108003Y5442352D01* +G01X2096556Y5424079D01* +G01X2088695Y5404001D01* +G01X2084692Y5382814D01* +G01X2084686Y5361252D01* +G01X2088677Y5340062D01* +G01X2049748Y5301134D01* +G01X2037602Y5301134D01* +G01X2037602Y5301134D01* +G01X2049115Y5319272D01* +G01X2057080Y5339225D01* +G01X2061222Y5360306D01* +G01X2061399Y5381789D01* +G01X2057606Y5402936D01* +G01X2049971Y5423017D01* +G01X2038759Y5441344D01* +G01X2024355Y5457284D01* +G01X2007255Y5470289D01* +G01X1988046Y5479912D01* +G01X1967391Y5485821D01* +G01X1946000Y5487814D01* +G01X1946000Y5487814D01* +G01X1924609Y5485821D01* +G01X1903953Y5479912D01* +G01X1884745Y5470289D01* +G01X1867645Y5457284D01* +G01X1853241Y5441344D01* +G01X1842029Y5423017D01* +G01X1834394Y5402936D01* +G01X1830601Y5381789D01* +G01X1830778Y5360306D01* +G01X1834920Y5339225D01* +G01X1842885Y5319272D01* +G01X1854398Y5301134D01* +G01X1385051Y5301134D01* +G01X1274493Y5411693D01* +G01X1262867Y5420613D01* +G01X1249328Y5426221D01* +G01X1234800Y5428134D01* +G01X713801Y5428134D01* +G01X701894Y5445632D01* +G01X687001Y5460670D01* +G01X669621Y5472747D01* +G01X650333Y5481460D01* +G01X629781Y5486517D01* +G01X608653Y5487750D01* +G01X587652Y5485117D01* +G01X567482Y5478706D01* +G01X548815Y5468732D01* +G01X532275Y5455527D01* +G01X518414Y5439533D01* +G01X507695Y5421283D01* +G01X500477Y5401388D01* +G01X496999Y5380511D01* +G01X497379Y5359350D01* +G01X501604Y5338611D01* +G01X509532Y5318987D01* +G01X520898Y5301134D01* +G01X485500Y5301134D01* +G01X470971Y5299221D01* +G01X457433Y5293613D01* +G01X445807Y5284693D01* +G01X390438Y5229323D01* +G01X371407Y5233092D01* +G01X352014Y5233632D01* +G01X332803Y5230927D01* +G01X314314Y5225053D01* +G01X297064Y5216176D01* +G01X281538Y5204543D01* +G01X281538Y5285457D01* +G01X297953Y5273273D01* +G01X316255Y5264166D01* +G01X335873Y5258418D01* +G01X356196Y5256209D01* +G01X376591Y5257608D01* +G01X396422Y5262571D01* +G01X415072Y5270943D01* +G01X431959Y5282464D01* +G01X446557Y5296775D01* +G01X458411Y5313429D01* +G01X467153Y5331909D01* +G01X472510Y5351637D01* +G01X474314Y5372000D01* +G01X472510Y5392363D01* +G01X467153Y5412091D01* +G01X458411Y5430571D01* +G01X446557Y5447225D01* +G01X431959Y5461536D01* +G01X415072Y5473057D01* +G01X396422Y5481429D01* +G01X376591Y5486392D01* +G01X356196Y5487791D01* +G01X335873Y5485582D01* +G01X316255Y5479834D01* +G01X297953Y5470727D01* +G01X281538Y5458543D01* +G01X281538Y6802975D01* +G01X430197Y6951634D01* +G01X439117Y6963260D01* +G01X444725Y6976798D01* +G01X446638Y6991327D01* +G01X446638Y7803796D01* +G01X444725Y7818324D01* +G01X439117Y7831863D01* +G01X430197Y7843489D01* +G01X315462Y7958223D01* +G01X315462Y7958223D01* +G01X321556Y7976279D01* +G01X324307Y7995136D01* +G01X323626Y8014181D01* +G01X319536Y8032793D01* +G01X312169Y8050368D01* +G01X301765Y8066335D01* +G01X288663Y8080172D01* +G01X273288Y8091431D01* +G01X256141Y8099746D01* +G01X237779Y8104845D01* +G01X218800Y8106564D01* +G01X168000Y8106564D01* +G01X148584Y8104765D01* +G01X129830Y8099429D01* +G01X112375Y8090737D01* +G01X96815Y8078987D01* +G01X83678Y8064577D01* +G01X73413Y8047998D01* +G01X66370Y8029816D01* +G01X62787Y8010649D01* +G01X62787Y7991150D01* +G01X66370Y7971984D01* +G01X73413Y7953801D01* +G01X83678Y7937223D01* +G01X96815Y7922813D01* +G01X112375Y7911063D01* +G01X129830Y7902371D01* +G01X148584Y7897035D01* +G01X168000Y7895236D01* +G01X218800Y7895236D01* +G01X219675Y7895240D01* +G01X289383Y7825532D01* +G01X273906Y7837057D01* +G01X256591Y7845575D01* +G01X238016Y7850802D01* +G01X218800Y7852564D01* +G01X168000Y7852564D01* +G01X148584Y7850765D01* +G01X129830Y7845429D01* +G01X112375Y7836737D01* +G01X96815Y7824987D01* +G01X83678Y7810577D01* +G01X73413Y7793998D01* +G01X66370Y7775816D01* +G01X62787Y7756649D01* +G01X62787Y7737150D01* +G01X66370Y7717984D01* +G01X73413Y7699801D01* +G01X83678Y7683223D01* +G01X96815Y7668813D01* +G01X112375Y7657063D01* +G01X129830Y7648371D01* +G01X148584Y7643035D01* +G01X168000Y7641236D01* +G01X218800Y7641236D01* +G01X238948Y7643175D01* +G01X258357Y7648920D01* +G01X276315Y7658261D01* +G01X292162Y7670854D01* +G01X305316Y7686238D01* +G01X315296Y7703849D01* +G01X321735Y7723039D01* +G01X324396Y7743105D01* +G01X323182Y7763310D01* +G01X318138Y7782913D01* +G01X309448Y7801194D01* +G01X297432Y7817483D01* +G01X334370Y7780544D01* +G01X334370Y7014578D01* +G01X185711Y6865919D01* +G01X180954Y6860508D01* +G01X176197Y6865919D01* +G01X53934Y6988182D01* +G01X53934Y7248649D01* +G01X62787Y7248649D01* +G01X62787Y7229150D01* +G01X66370Y7209984D01* +G01X73413Y7191801D01* +G01X83678Y7175223D01* +G01X96815Y7160813D01* +G01X112375Y7149063D01* +G01X129830Y7140371D01* +G01X148584Y7135035D01* +G01X168000Y7133236D01* +G01X218800Y7133236D01* +G01X238216Y7135035D01* +G01X256970Y7140371D01* +G01X274425Y7149063D01* +G01X289985Y7160813D01* +G01X303122Y7175223D01* +G01X313386Y7191801D01* +G01X320430Y7209984D01* +G01X324013Y7229150D01* +G01X324013Y7248649D01* +G01X320430Y7267816D01* +G01X313386Y7285998D01* +G01X303122Y7302577D01* +G01X289985Y7316987D01* +G01X274425Y7328737D01* +G01X256970Y7337429D01* +G01X238216Y7342765D01* +G01X218800Y7344564D01* +G01X218800Y7344564D01* +G01X168000Y7344564D01* +G01X148584Y7342765D01* +G01X129830Y7337429D01* +G01X112375Y7328737D01* +G01X96815Y7316987D01* +G01X83678Y7302577D01* +G01X73413Y7285998D01* +G01X66370Y7267816D01* +G01X62787Y7248649D01* +G01X53934Y7248649D01* +G01X53934Y7502649D01* +G01X62787Y7502649D01* +G01X62787Y7483150D01* +G01X66370Y7463984D01* +G01X73413Y7445801D01* +G01X83678Y7429223D01* +G01X96815Y7414813D01* +G01X112375Y7403063D01* +G01X129830Y7394371D01* +G01X148584Y7389035D01* +G01X168000Y7387236D01* +G01X218800Y7387236D01* +G01X238216Y7389035D01* +G01X256970Y7394371D01* +G01X274425Y7403063D01* +G01X289985Y7414813D01* +G01X303122Y7429223D01* +G01X313386Y7445801D01* +G01X320430Y7463984D01* +G01X324013Y7483150D01* +G01X324013Y7502649D01* +G01X320430Y7521816D01* +G01X313386Y7539998D01* +G01X303122Y7556577D01* +G01X289985Y7570987D01* +G01X274425Y7582737D01* +G01X256970Y7591429D01* +G01X238216Y7596765D01* +G01X218800Y7598564D01* +G01X218800Y7598564D01* +G01X168000Y7598564D01* +G01X148584Y7596765D01* +G01X129830Y7591429D01* +G01X112375Y7582737D01* +G01X96815Y7570987D01* +G01X83678Y7556577D01* +G01X73413Y7539998D01* +G01X66370Y7521816D01* +G01X62787Y7502649D01* +G01X53934Y7502649D01* +G01X53934Y8289871D01* +G01X88057Y8323994D01* +G01X76431Y8307626D01* +G01X68111Y8289354D01* +G01X63397Y8269839D01* +G01X62460Y8249784D01* +G01X65333Y8229913D01* +G01X71912Y8210945D01* +G01X81961Y8193564D01* +G01X95116Y8178397D01* +G01X110902Y8165992D01* +G01X128749Y8156797D01* +G01X148014Y8151143D01* +G01X168000Y8149236D01* +G01X218800Y8149236D01* +G01X236515Y8150732D01* +G01X253729Y8155176D01* +G01X269954Y8162444D01* +G01X284731Y8172329D01* +G01X297642Y8184552D01* +G01X308320Y8198766D01* +G01X457143Y8198766D01* +G01X457143Y8187396D01* +G01X458896Y8176329D01* +G01X463983Y8166345D01* +G01X471906Y8158422D01* +G01X481890Y8153335D01* +G01X492957Y8151582D01* +G01X606211Y8151582D01* +G01X617278Y8153335D01* +G01X627262Y8158422D01* +G01X635185Y8166345D01* +G01X640272Y8176329D01* +G01X642025Y8187396D01* +G01X642025Y8325097D01* +G01X640272Y8336164D01* +G01X635185Y8346148D01* +G01X627262Y8354071D01* +G01X617278Y8359158D01* +G01X606211Y8360911D01* +G01X492957Y8360911D01* +G01X481890Y8359158D01* +G01X471906Y8354071D01* +G01X463983Y8346148D01* +G01X458896Y8336164D01* +G01X457143Y8325097D01* +G01X457143Y8311034D01* +G01X308320Y8311034D01* +G01X297642Y8325248D01* +G01X284731Y8337471D01* +G01X269954Y8347356D01* +G01X253729Y8354624D01* +G01X236515Y8359068D01* +G01X218800Y8360564D01* +G01X168000Y8360564D01* +G01X149272Y8358891D01* +G01X131137Y8353925D01* +G01X114169Y8345823D01* +G01X98905Y8334843D01* +G01X167301Y8403238D01* +G01X168000Y8403236D01* +G01X218800Y8403236D01* +G01X238216Y8405035D01* +G01X256970Y8410371D01* +G01X274425Y8419063D01* +G01X289985Y8430813D01* +G01X303122Y8445223D01* +G01X313386Y8461801D01* +G01X320430Y8479984D01* +G01X324013Y8499150D01* +G01X324013Y8518649D01* +G01X2602787Y8518649D01* +G01X2602787Y8499150D01* +G01X2606370Y8479984D01* +G01X2613413Y8461801D01* +G01X2623678Y8445223D01* +G01X2636815Y8430813D01* +G01X2652375Y8419063D01* +G01X2669830Y8410371D01* +G01X2688584Y8405035D01* +G01X2708000Y8403236D01* +G01X2758800Y8403236D01* +G01X2778216Y8405035D01* +G01X2796970Y8410371D01* +G01X2814425Y8419063D01* +G01X2829985Y8430813D01* +G01X2843122Y8445223D01* +G01X2853386Y8461801D01* +G01X2860430Y8479984D01* +G01X2864013Y8499150D01* +G01X2864013Y8518649D01* +G01X2860430Y8537816D01* +G01X2853386Y8555998D01* +G01X2843122Y8572577D01* +G01X2829985Y8586987D01* +G01X2814425Y8598737D01* +G01X2796970Y8607429D01* +G01X2778216Y8612765D01* +G01X2758800Y8614564D01* +G01X2758800Y8614564D01* +G01X2708000Y8614564D01* +G01X2688584Y8612765D01* +G01X2669830Y8607429D01* +G01X2652375Y8598737D01* +G01X2636815Y8586987D01* +G01X2623678Y8572577D01* +G01X2613413Y8555998D01* +G01X2606370Y8537816D01* +G01X2602787Y8518649D01* +G01X324013Y8518649D01* +G01X320430Y8537816D01* +G01X313386Y8555998D01* +G01X303122Y8572577D01* +G01X289985Y8586987D01* +G01X274425Y8598737D01* +G01X256970Y8607429D01* +G01X238216Y8612765D01* +G01X218800Y8614564D01* +G01X168000Y8614564D01* +G01X149272Y8612891D01* +G01X131137Y8607925D01* +G01X114169Y8599823D01* +G01X98905Y8588843D01* +G01X167301Y8657238D01* +G01X168000Y8657236D01* +G01X218800Y8657236D01* +G01X238216Y8659035D01* +G01X256970Y8664371D01* +G01X274425Y8673063D01* +G01X289985Y8684813D01* +G01X303122Y8699223D01* +G01X313386Y8715801D01* +G01X320430Y8733984D01* +G01X324013Y8753150D01* +G01X324013Y8772649D01* +G01X2602787Y8772649D01* +G01X2602787Y8753150D01* +G01X2606370Y8733984D01* +G01X2613413Y8715801D01* +G01X2623678Y8699223D01* +G01X2636815Y8684813D01* +G01X2652375Y8673063D01* +G01X2669830Y8664371D01* +G01X2688584Y8659035D01* +G01X2708000Y8657236D01* +G01X2758800Y8657236D01* +G01X2778216Y8659035D01* +G01X2796970Y8664371D01* +G01X2814425Y8673063D01* +G01X2829985Y8684813D01* +G01X2843122Y8699223D01* +G01X2853386Y8715801D01* +G01X2860430Y8733984D01* +G01X2864013Y8753150D01* +G01X2864013Y8772649D01* +G01X2860430Y8791816D01* +G01X2853386Y8809998D01* +G01X2843122Y8826577D01* +G01X2829985Y8840987D01* +G01X2814425Y8852737D01* +G01X2796970Y8861429D01* +G01X2778216Y8866765D01* +G01X2758800Y8868564D01* +G01X2758800Y8868564D01* +G01X2708000Y8868564D01* +G01X2688584Y8866765D01* +G01X2669830Y8861429D01* +G01X2652375Y8852737D01* +G01X2636815Y8840987D01* +G01X2623678Y8826577D01* +G01X2613413Y8809998D01* +G01X2606370Y8791816D01* +G01X2602787Y8772649D01* +G01X324013Y8772649D01* +G01X320430Y8791816D01* +G01X313386Y8809998D01* +G01X303122Y8826577D01* +G01X289985Y8840987D01* +G01X274425Y8852737D01* +G01X256970Y8861429D01* +G01X238216Y8866765D01* +G01X218800Y8868564D01* +G01X168000Y8868564D01* +G01X149009Y8866843D01* +G01X130636Y8861737D01* +G01X113481Y8853413D01* +G01X98101Y8842140D01* +G01X84997Y8828287D01* +G01X74597Y8812304D01* +G01X67238Y8794712D01* +G01X63162Y8776084D01* +G01X62499Y8757027D01* +G01X65273Y8738161D01* +G01X71392Y8720100D01* +G01X-131789Y8516919D01* +G01X-140710Y8505294D01* +G01X-146317Y8491755D01* +G01X-148230Y8477227D01* +G01X-148230Y6927827D01* +G01X-146317Y6913298D01* +G01X-140710Y6899760D01* +G01X-131789Y6888134D01* +G01X-5842Y6762187D01* +G37* +G36* +G01X35814Y150000D02* +G01X35814Y827731D01* +G01X231431Y632114D01* +G01X241633Y624044D01* +G01X253418Y618538D01* +G01X266154Y615893D01* +G01X254884Y597735D01* +G01X247142Y577816D01* +G01X243192Y556814D01* +G01X243168Y535443D01* +G01X247072Y514431D01* +G01X254769Y494495D01* +G01X265999Y476312D01* +G01X280378Y460503D01* +G01X297417Y447604D01* +G01X316536Y438056D01* +G01X337085Y432183D01* +G01X358362Y430186D01* +G01X379644Y432133D01* +G01X400206Y437956D01* +G01X419348Y447459D01* +G01X436418Y460317D01* +G01X450835Y476092D01* +G01X462108Y494248D01* +G01X469853Y514166D01* +G01X473806Y535168D01* +G01X473833Y556538D01* +G01X469933Y577550D01* +G01X462239Y597488D01* +G01X451012Y615673D01* +G01X463442Y615673D01* +G01X496686Y582428D01* +G01X496686Y466000D01* +G01X498439Y454933D01* +G01X503526Y444949D01* +G01X511449Y437026D01* +G01X521433Y431939D01* +G01X532500Y430186D01* +G01X692500Y430186D01* +G01X703567Y431939D01* +G01X713551Y437026D01* +G01X721474Y444949D01* +G01X726561Y454933D01* +G01X728314Y466000D01* +G01X728314Y489866D01* +G01X881348Y489866D01* +G01X998181Y373034D01* +G01X1009806Y364113D01* +G01X1023345Y358505D01* +G01X1037873Y356593D01* +G01X2066727Y356593D01* +G01X2081255Y358505D01* +G01X2094794Y364113D01* +G01X2106419Y373034D01* +G01X2163572Y430186D01* +G01X2280000Y430186D01* +G01X2291067Y431939D01* +G01X2301051Y437026D01* +G01X2308974Y444949D01* +G01X2314061Y454933D01* +G01X2315814Y466000D01* +G01X2315814Y626000D01* +G01X2314061Y637067D01* +G01X2308974Y647051D01* +G01X2301051Y654974D01* +G01X2291067Y660061D01* +G01X2280000Y661814D01* +G01X2141199Y661814D01* +G01X2168062Y688677D01* +G01X2188014Y684808D01* +G01X2208334Y684486D01* +G01X2228398Y687722D01* +G01X2247587Y694414D01* +G01X2265311Y704358D01* +G01X2281024Y717248D01* +G01X2294242Y732685D01* +G01X2304558Y750195D01* +G01X2311654Y769239D01* +G01X2315312Y789230D01* +G01X2315419Y809553D01* +G01X2311972Y829581D01* +G01X2305077Y848699D01* +G01X2294947Y866317D01* +G01X2281893Y881893D01* +G01X2266317Y894947D01* +G01X2248699Y905077D01* +G01X2229581Y911972D01* +G01X2209553Y915419D01* +G01X2189230Y915312D01* +G01X2169239Y911654D01* +G01X2150195Y904558D01* +G01X2132685Y894242D01* +G01X2117248Y881024D01* +G01X2104358Y865311D01* +G01X2094414Y847587D01* +G01X2087722Y828398D01* +G01X2084486Y808334D01* +G01X2084808Y788014D01* +G01X2088677Y768062D01* +G01X2049748Y729134D01* +G01X2037602Y729134D01* +G01X2037602Y729134D01* +G01X2047976Y745103D01* +G01X2055594Y762556D01* +G01X2060248Y781021D01* +G01X2061814Y800000D01* +G01X2060248Y818978D01* +G01X2055594Y837444D01* +G01X2047976Y854897D01* +G01X2037602Y870866D01* +G01X2073000Y870866D01* +G01X2087528Y872779D01* +G01X2101067Y878386D01* +G01X2112693Y887307D01* +G01X2168062Y942677D01* +G01X2188014Y938808D01* +G01X2208334Y938486D01* +G01X2228398Y941722D01* +G01X2247587Y948414D01* +G01X2265311Y958358D01* +G01X2281024Y971248D01* +G01X2294242Y986685D01* +G01X2304558Y1004195D01* +G01X2311654Y1023239D01* +G01X2315312Y1043230D01* +G01X2315419Y1063553D01* +G01X2311972Y1083581D01* +G01X2305077Y1102699D01* +G01X2294947Y1120317D01* +G01X2281893Y1135893D01* +G01X2266317Y1148947D01* +G01X2248699Y1159077D01* +G01X2229581Y1165972D01* +G01X2209553Y1169419D01* +G01X2189230Y1169312D01* +G01X2169239Y1165654D01* +G01X2150195Y1158558D01* +G01X2132685Y1148242D01* +G01X2117248Y1135024D01* +G01X2104358Y1119311D01* +G01X2094414Y1101587D01* +G01X2087722Y1082398D01* +G01X2084486Y1062334D01* +G01X2084808Y1042014D01* +G01X2088677Y1022062D01* +G01X2049748Y983134D01* +G01X2037602Y983134D01* +G01X2037602Y983134D01* +G01X2047976Y999103D01* +G01X2055594Y1016556D01* +G01X2060248Y1035021D01* +G01X2061814Y1054000D01* +G01X2060248Y1072978D01* +G01X2055594Y1091444D01* +G01X2047976Y1108897D01* +G01X2037602Y1124866D01* +G01X2073000Y1124866D01* +G01X2087528Y1126779D01* +G01X2101067Y1132386D01* +G01X2112693Y1141307D01* +G01X2168062Y1196677D01* +G01X2188014Y1192808D01* +G01X2208334Y1192486D01* +G01X2228398Y1195722D01* +G01X2247587Y1202414D01* +G01X2265311Y1212358D01* +G01X2281024Y1225248D01* +G01X2294242Y1240685D01* +G01X2304558Y1258195D01* +G01X2311654Y1277239D01* +G01X2315312Y1297230D01* +G01X2315419Y1317553D01* +G01X2311972Y1337581D01* +G01X2305077Y1356699D01* +G01X2294947Y1374317D01* +G01X2281893Y1389893D01* +G01X2266317Y1402947D01* +G01X2248699Y1413077D01* +G01X2229581Y1419972D01* +G01X2209553Y1423419D01* +G01X2189230Y1423312D01* +G01X2169239Y1419654D01* +G01X2150195Y1412558D01* +G01X2132685Y1402242D01* +G01X2117248Y1389024D01* +G01X2104358Y1373311D01* +G01X2094414Y1355587D01* +G01X2087722Y1336398D01* +G01X2084486Y1316334D01* +G01X2084808Y1296014D01* +G01X2088677Y1276062D01* +G01X2049748Y1237134D01* +G01X2037602Y1237134D01* +G01X2037602Y1237134D01* +G01X2047976Y1253103D01* +G01X2055594Y1270556D01* +G01X2060248Y1289021D01* +G01X2061814Y1308000D01* +G01X2060248Y1326978D01* +G01X2055594Y1345444D01* +G01X2047976Y1362897D01* +G01X2037602Y1378866D01* +G01X2073000Y1378866D01* +G01X2087528Y1380779D01* +G01X2101067Y1386386D01* +G01X2112693Y1395307D01* +G01X2168062Y1450677D01* +G01X2188014Y1446808D01* +G01X2208334Y1446486D01* +G01X2228398Y1449722D01* +G01X2247587Y1456414D01* +G01X2265311Y1466358D01* +G01X2281024Y1479248D01* +G01X2294242Y1494685D01* +G01X2304558Y1512195D01* +G01X2311654Y1531239D01* +G01X2315312Y1551230D01* +G01X2315419Y1571553D01* +G01X2311972Y1591581D01* +G01X2305077Y1610699D01* +G01X2294947Y1628317D01* +G01X2281893Y1643893D01* +G01X2266317Y1656947D01* +G01X2248699Y1667077D01* +G01X2229581Y1673972D01* +G01X2209553Y1677419D01* +G01X2189230Y1677312D01* +G01X2169239Y1673654D01* +G01X2150195Y1666558D01* +G01X2132685Y1656242D01* +G01X2117248Y1643024D01* +G01X2104358Y1627311D01* +G01X2094414Y1609587D01* +G01X2087722Y1590398D01* +G01X2084486Y1570334D01* +G01X2084808Y1550014D01* +G01X2088677Y1530062D01* +G01X2049748Y1491134D01* +G01X2037602Y1491134D01* +G01X2037602Y1491134D01* +G01X2047976Y1507103D01* +G01X2055594Y1524556D01* +G01X2060248Y1543021D01* +G01X2061814Y1562000D01* +G01X2060248Y1580978D01* +G01X2055594Y1599444D01* +G01X2047976Y1616897D01* +G01X2037602Y1632866D01* +G01X2073000Y1632866D01* +G01X2087528Y1634779D01* +G01X2101067Y1640386D01* +G01X2112693Y1649307D01* +G01X2168062Y1704677D01* +G01X2188014Y1700808D01* +G01X2208334Y1700486D01* +G01X2228398Y1703722D01* +G01X2247587Y1710414D01* +G01X2265311Y1720358D01* +G01X2281024Y1733248D01* +G01X2294242Y1748685D01* +G01X2304558Y1766195D01* +G01X2311654Y1785239D01* +G01X2315312Y1805230D01* +G01X2315419Y1825553D01* +G01X2311972Y1845581D01* +G01X2305077Y1864699D01* +G01X2294947Y1882317D01* +G01X2281893Y1897893D01* +G01X2266317Y1910947D01* +G01X2248699Y1921077D01* +G01X2229581Y1927972D01* +G01X2209553Y1931419D01* +G01X2189230Y1931312D01* +G01X2169239Y1927654D01* +G01X2150195Y1920558D01* +G01X2132685Y1910242D01* +G01X2117248Y1897024D01* +G01X2104358Y1881311D01* +G01X2094414Y1863587D01* +G01X2087722Y1844398D01* +G01X2084486Y1824334D01* +G01X2084808Y1804014D01* +G01X2088677Y1784062D01* +G01X2049748Y1745134D01* +G01X2037602Y1745134D01* +G01X2037602Y1745134D01* +G01X2047976Y1761103D01* +G01X2055594Y1778556D01* +G01X2060248Y1797021D01* +G01X2061814Y1816000D01* +G01X2060248Y1834978D01* +G01X2055594Y1853444D01* +G01X2047976Y1870897D01* +G01X2037602Y1886866D01* +G01X2073000Y1886866D01* +G01X2087528Y1888779D01* +G01X2101067Y1894386D01* +G01X2112693Y1903307D01* +G01X2168062Y1958677D01* +G01X2188014Y1954808D01* +G01X2208334Y1954486D01* +G01X2228398Y1957722D01* +G01X2247587Y1964414D01* +G01X2265311Y1974358D01* +G01X2281024Y1987248D01* +G01X2294242Y2002685D01* +G01X2304558Y2020195D01* +G01X2311654Y2039239D01* +G01X2315312Y2059230D01* +G01X2315419Y2079553D01* +G01X2311972Y2099581D01* +G01X2305077Y2118699D01* +G01X2294947Y2136317D01* +G01X2281893Y2151893D01* +G01X2266317Y2164947D01* +G01X2248699Y2175077D01* +G01X2229581Y2181972D01* +G01X2209553Y2185419D01* +G01X2189230Y2185312D01* +G01X2169239Y2181654D01* +G01X2150195Y2174558D01* +G01X2132685Y2164242D01* +G01X2117248Y2151024D01* +G01X2104358Y2135311D01* +G01X2094414Y2117587D01* +G01X2087722Y2098398D01* +G01X2084486Y2078334D01* +G01X2084808Y2058014D01* +G01X2088677Y2038062D01* +G01X2049748Y1999134D01* +G01X2037602Y1999134D01* +G01X2037602Y1999134D01* +G01X2047976Y2015103D01* +G01X2055594Y2032556D01* +G01X2060248Y2051021D01* +G01X2061814Y2070000D01* +G01X2060248Y2088978D01* +G01X2055594Y2107444D01* +G01X2047976Y2124897D01* +G01X2037602Y2140866D01* +G01X2073000Y2140866D01* +G01X2087528Y2142779D01* +G01X2101067Y2148386D01* +G01X2112693Y2157307D01* +G01X2168062Y2212677D01* +G01X2188014Y2208808D01* +G01X2208334Y2208486D01* +G01X2228398Y2211722D01* +G01X2247587Y2218414D01* +G01X2265311Y2228358D01* +G01X2281024Y2241248D01* +G01X2294242Y2256685D01* +G01X2304558Y2274195D01* +G01X2311654Y2293239D01* +G01X2315312Y2313230D01* +G01X2315419Y2333553D01* +G01X2311972Y2353581D01* +G01X2305077Y2372699D01* +G01X2294947Y2390317D01* +G01X2281893Y2405893D01* +G01X2266317Y2418947D01* +G01X2248699Y2429077D01* +G01X2229581Y2435972D01* +G01X2209553Y2439419D01* +G01X2189230Y2439312D01* +G01X2169239Y2435654D01* +G01X2150195Y2428558D01* +G01X2132685Y2418242D01* +G01X2117248Y2405024D01* +G01X2104358Y2389311D01* +G01X2094414Y2371587D01* +G01X2087722Y2352398D01* +G01X2084486Y2332334D01* +G01X2084808Y2312014D01* +G01X2088677Y2292062D01* +G01X2049748Y2253134D01* +G01X2037602Y2253134D01* +G01X2037602Y2253134D01* +G01X2047976Y2269103D01* +G01X2055594Y2286556D01* +G01X2060248Y2305021D01* +G01X2061814Y2324000D01* +G01X2060248Y2342978D01* +G01X2055594Y2361444D01* +G01X2047976Y2378897D01* +G01X2037602Y2394866D01* +G01X2073000Y2394866D01* +G01X2087528Y2396779D01* +G01X2101067Y2402386D01* +G01X2112693Y2411307D01* +G01X2168062Y2466677D01* +G01X2188014Y2462808D01* +G01X2208334Y2462486D01* +G01X2228398Y2465722D01* +G01X2247587Y2472414D01* +G01X2265311Y2482358D01* +G01X2281024Y2495248D01* +G01X2294242Y2510685D01* +G01X2304558Y2528195D01* +G01X2311654Y2547239D01* +G01X2315312Y2567230D01* +G01X2315419Y2587553D01* +G01X2311972Y2607581D01* +G01X2305077Y2626699D01* +G01X2294947Y2644317D01* +G01X2281893Y2659893D01* +G01X2266317Y2672947D01* +G01X2248699Y2683077D01* +G01X2229581Y2689972D01* +G01X2209553Y2693419D01* +G01X2189230Y2693312D01* +G01X2169239Y2689654D01* +G01X2150195Y2682558D01* +G01X2132685Y2672242D01* +G01X2117248Y2659024D01* +G01X2104358Y2643311D01* +G01X2094414Y2625587D01* +G01X2087722Y2606398D01* +G01X2084486Y2586334D01* +G01X2084808Y2566014D01* +G01X2088677Y2546062D01* +G01X2049748Y2507134D01* +G01X2037602Y2507134D01* +G01X2037602Y2507134D01* +G01X2048968Y2524987D01* +G01X2056896Y2544611D01* +G01X2061121Y2565350D01* +G01X2061501Y2586511D01* +G01X2058023Y2607388D01* +G01X2050805Y2627283D01* +G01X2040086Y2645533D01* +G01X2026225Y2661527D01* +G01X2009685Y2674732D01* +G01X2009685Y2674732D01* +G01X1991018Y2684706D01* +G01X1970848Y2691117D01* +G01X1949847Y2693750D01* +G01X1928719Y2692517D01* +G01X1908167Y2687460D01* +G01X1888879Y2678747D01* +G01X1871499Y2666670D01* +G01X1856606Y2651632D01* +G01X1844699Y2634134D01* +G01X1588251Y2634134D01* +G01X1477693Y2744693D01* +G01X1466067Y2753613D01* +G01X1452528Y2759221D01* +G01X1438000Y2761134D01* +G01X690877Y2761134D01* +G01X702968Y2777407D01* +G01X711729Y2795689D01* +G01X716837Y2815308D01* +G01X718105Y2835541D01* +G01X715484Y2855644D01* +G01X709073Y2874877D01* +G01X699107Y2892531D01* +G01X685953Y2907957D01* +G01X670095Y2920587D01* +G01X652116Y2929956D01* +G01X632680Y2935719D01* +G01X612500Y2937664D01* +G01X592320Y2935719D01* +G01X572884Y2929956D01* +G01X554905Y2920587D01* +G01X539047Y2907957D01* +G01X525893Y2892531D01* +G01X515926Y2874877D01* +G01X509515Y2855644D01* +G01X506895Y2835541D01* +G01X508163Y2815308D01* +G01X513271Y2795689D01* +G01X522032Y2777407D01* +G01X534123Y2761134D01* +G01X485500Y2761134D01* +G01X470971Y2759221D01* +G01X457433Y2753613D01* +G01X445807Y2744693D01* +G01X390438Y2689323D01* +G01X370486Y2693192D01* +G01X350166Y2693514D01* +G01X330102Y2690278D01* +G01X310913Y2683585D01* +G01X293189Y2673641D01* +G01X277476Y2660752D01* +G01X264258Y2645315D01* +G01X253942Y2627805D01* +G01X246846Y2608761D01* +G01X243188Y2588770D01* +G01X243081Y2568447D01* +G01X246528Y2548419D01* +G01X253422Y2529301D01* +G01X263553Y2511683D01* +G01X276607Y2496107D01* +G01X292183Y2483053D01* +G01X309801Y2472922D01* +G01X328919Y2466028D01* +G01X348947Y2462581D01* +G01X369270Y2462688D01* +G01X389261Y2466346D01* +G01X408305Y2473442D01* +G01X425815Y2483758D01* +G01X441252Y2496976D01* +G01X454141Y2512689D01* +G01X464085Y2530413D01* +G01X470778Y2549602D01* +G01X474014Y2569666D01* +G01X473692Y2589986D01* +G01X469823Y2609938D01* +G01X508751Y2648866D01* +G01X520898Y2648866D01* +G01X520898Y2648866D01* +G01X510524Y2632897D01* +G01X502906Y2615444D01* +G01X498252Y2596978D01* +G01X496686Y2578000D01* +G01X498252Y2559021D01* +G01X502906Y2540556D01* +G01X510524Y2523103D01* +G01X520898Y2507134D01* +G01X485500Y2507134D01* +G01X470971Y2505221D01* +G01X457433Y2499613D01* +G01X445807Y2490693D01* +G01X390438Y2435323D01* +G01X370486Y2439192D01* +G01X350166Y2439514D01* +G01X330102Y2436278D01* +G01X310913Y2429585D01* +G01X293189Y2419641D01* +G01X277476Y2406752D01* +G01X264258Y2391315D01* +G01X253942Y2373805D01* +G01X246846Y2354761D01* +G01X243188Y2334770D01* +G01X243081Y2314447D01* +G01X246528Y2294419D01* +G01X253422Y2275301D01* +G01X263553Y2257683D01* +G01X276607Y2242107D01* +G01X292183Y2229053D01* +G01X309801Y2218922D01* +G01X328919Y2212028D01* +G01X348947Y2208581D01* +G01X369270Y2208688D01* +G01X389261Y2212346D01* +G01X408305Y2219442D01* +G01X425815Y2229758D01* +G01X441252Y2242976D01* +G01X454141Y2258689D01* +G01X464085Y2276413D01* +G01X470778Y2295602D01* +G01X474014Y2315666D01* +G01X473692Y2335986D01* +G01X469823Y2355938D01* +G01X508751Y2394866D01* +G01X520898Y2394866D01* +G01X520898Y2394866D01* +G01X510524Y2378897D01* +G01X502906Y2361444D01* +G01X498252Y2342978D01* +G01X496686Y2324000D01* +G01X498252Y2305021D01* +G01X502906Y2286556D01* +G01X510524Y2269103D01* +G01X520898Y2253134D01* +G01X485500Y2253134D01* +G01X470971Y2251221D01* +G01X457433Y2245613D01* +G01X445807Y2236693D01* +G01X390438Y2181323D01* +G01X370486Y2185192D01* +G01X350166Y2185514D01* +G01X330102Y2182278D01* +G01X310913Y2175585D01* +G01X293189Y2165641D01* +G01X277476Y2152752D01* +G01X264258Y2137315D01* +G01X253942Y2119805D01* +G01X246846Y2100761D01* +G01X243188Y2080770D01* +G01X243081Y2060447D01* +G01X246528Y2040419D01* +G01X253422Y2021301D01* +G01X263553Y2003683D01* +G01X276607Y1988107D01* +G01X292183Y1975053D01* +G01X309801Y1964922D01* +G01X328919Y1958028D01* +G01X348947Y1954581D01* +G01X369270Y1954688D01* +G01X389261Y1958346D01* +G01X408305Y1965442D01* +G01X425815Y1975758D01* +G01X441252Y1988976D01* +G01X454141Y2004689D01* +G01X464085Y2022413D01* +G01X470778Y2041602D01* +G01X474014Y2061666D01* +G01X473692Y2081986D01* +G01X469823Y2101938D01* +G01X508751Y2140866D01* +G01X520898Y2140866D01* +G01X520898Y2140866D01* +G01X510524Y2124897D01* +G01X502906Y2107444D01* +G01X498252Y2088978D01* +G01X496686Y2070000D01* +G01X498252Y2051021D01* +G01X502906Y2032556D01* +G01X510524Y2015103D01* +G01X520898Y1999134D01* +G01X485500Y1999134D01* +G01X470971Y1997221D01* +G01X457433Y1991613D01* +G01X445807Y1982693D01* +G01X390438Y1927323D01* +G01X370486Y1931192D01* +G01X350166Y1931514D01* +G01X330102Y1928278D01* +G01X310913Y1921585D01* +G01X293189Y1911641D01* +G01X277476Y1898752D01* +G01X264258Y1883315D01* +G01X253942Y1865805D01* +G01X246846Y1846761D01* +G01X243188Y1826770D01* +G01X243081Y1806447D01* +G01X246528Y1786419D01* +G01X253422Y1767301D01* +G01X263553Y1749683D01* +G01X276607Y1734107D01* +G01X292183Y1721053D01* +G01X309801Y1710922D01* +G01X328919Y1704028D01* +G01X348947Y1700581D01* +G01X369270Y1700688D01* +G01X389261Y1704346D01* +G01X408305Y1711442D01* +G01X425815Y1721758D01* +G01X441252Y1734976D01* +G01X454141Y1750689D01* +G01X464085Y1768413D01* +G01X470778Y1787602D01* +G01X474014Y1807666D01* +G01X473692Y1827986D01* +G01X469823Y1847938D01* +G01X508751Y1886866D01* +G01X520898Y1886866D01* +G01X520898Y1886866D01* +G01X510524Y1870897D01* +G01X502906Y1853444D01* +G01X498252Y1834978D01* +G01X496686Y1816000D01* +G01X498252Y1797021D01* +G01X502906Y1778556D01* +G01X510524Y1761103D01* +G01X520898Y1745134D01* +G01X485500Y1745134D01* +G01X470971Y1743221D01* +G01X457433Y1737613D01* +G01X445807Y1728693D01* +G01X390438Y1673323D01* +G01X370486Y1677192D01* +G01X350166Y1677514D01* +G01X330102Y1674278D01* +G01X310913Y1667585D01* +G01X293189Y1657641D01* +G01X277476Y1644752D01* +G01X264258Y1629315D01* +G01X253942Y1611805D01* +G01X246846Y1592761D01* +G01X243188Y1572770D01* +G01X243081Y1552447D01* +G01X246528Y1532419D01* +G01X253422Y1513301D01* +G01X263553Y1495683D01* +G01X276607Y1480107D01* +G01X292183Y1467053D01* +G01X309801Y1456922D01* +G01X328919Y1450028D01* +G01X348947Y1446581D01* +G01X369270Y1446688D01* +G01X389261Y1450346D01* +G01X408305Y1457442D01* +G01X425815Y1467758D01* +G01X441252Y1480976D01* +G01X454141Y1496689D01* +G01X464085Y1514413D01* +G01X470778Y1533602D01* +G01X474014Y1553666D01* +G01X473692Y1573986D01* +G01X469823Y1593938D01* +G01X508751Y1632866D01* +G01X520898Y1632866D01* +G01X520898Y1632866D01* +G01X510524Y1616897D01* +G01X502906Y1599444D01* +G01X498252Y1580978D01* +G01X496686Y1562000D01* +G01X498252Y1543021D01* +G01X502906Y1524556D01* +G01X510524Y1507103D01* +G01X520898Y1491134D01* +G01X485500Y1491134D01* +G01X470971Y1489221D01* +G01X457433Y1483613D01* +G01X445807Y1474693D01* +G01X390438Y1419323D01* +G01X370486Y1423192D01* +G01X350166Y1423514D01* +G01X330102Y1420278D01* +G01X310913Y1413585D01* +G01X293189Y1403641D01* +G01X277476Y1390752D01* +G01X264258Y1375315D01* +G01X253942Y1357805D01* +G01X246846Y1338761D01* +G01X243188Y1318770D01* +G01X243081Y1298447D01* +G01X246528Y1278419D01* +G01X253422Y1259301D01* +G01X263553Y1241683D01* +G01X276607Y1226107D01* +G01X292183Y1213053D01* +G01X309801Y1202922D01* +G01X328919Y1196028D01* +G01X348947Y1192581D01* +G01X369270Y1192688D01* +G01X389261Y1196346D01* +G01X408305Y1203442D01* +G01X425815Y1213758D01* +G01X441252Y1226976D01* +G01X454141Y1242689D01* +G01X464085Y1260413D01* +G01X470778Y1279602D01* +G01X474014Y1299666D01* +G01X473692Y1319986D01* +G01X469823Y1339938D01* +G01X508751Y1378866D01* +G01X520898Y1378866D01* +G01X520898Y1378866D01* +G01X510524Y1362897D01* +G01X502906Y1345444D01* +G01X498252Y1326978D01* +G01X496686Y1308000D01* +G01X498252Y1289021D01* +G01X502906Y1270556D01* +G01X510524Y1253103D01* +G01X520898Y1237134D01* +G01X485500Y1237134D01* +G01X470971Y1235221D01* +G01X457433Y1229613D01* +G01X445807Y1220693D01* +G01X390438Y1165323D01* +G01X370486Y1169192D01* +G01X350166Y1169514D01* +G01X330102Y1166278D01* +G01X310913Y1159585D01* +G01X293189Y1149641D01* +G01X277476Y1136752D01* +G01X264258Y1121315D01* +G01X253942Y1103805D01* +G01X246846Y1084761D01* +G01X243188Y1064770D01* +G01X243081Y1044447D01* +G01X246528Y1024419D01* +G01X253422Y1005301D01* +G01X263553Y987683D01* +G01X276607Y972107D01* +G01X292183Y959053D01* +G01X309801Y948922D01* +G01X328919Y942028D01* +G01X348947Y938581D01* +G01X369270Y938688D01* +G01X389261Y942346D01* +G01X408305Y949442D01* +G01X425815Y959758D01* +G01X441252Y972976D01* +G01X454141Y988689D01* +G01X464085Y1006413D01* +G01X470778Y1025602D01* +G01X474014Y1045666D01* +G01X473692Y1065986D01* +G01X469823Y1085938D01* +G01X508751Y1124866D01* +G01X520898Y1124866D01* +G01X520898Y1124866D01* +G01X510524Y1108897D01* +G01X502906Y1091444D01* +G01X498252Y1072978D01* +G01X496686Y1054000D01* +G01X498252Y1035021D01* +G01X502906Y1016556D01* +G01X510524Y999103D01* +G01X520898Y983134D01* +G01X485500Y983134D01* +G01X470971Y981221D01* +G01X457433Y975613D01* +G01X445807Y966693D01* +G01X390438Y911323D01* +G01X369294Y915310D01* +G01X347778Y915316D01* +G01X326632Y911343D01* +G01X306586Y903527D01* +G01X288332Y892137D01* +G01X272499Y877567D01* +G01X259635Y860321D01* +G01X250183Y840992D01* +G01X244470Y820248D01* +G01X242692Y798806D01* +G01X244912Y777404D01* +G01X106426Y915890D01* +G01X106426Y2842686D01* +G01X243180Y2842686D01* +G01X243180Y2821314D01* +G01X247107Y2800306D01* +G01X254828Y2780377D01* +G01X266078Y2762206D01* +G01X280477Y2746412D01* +G01X297532Y2733533D01* +G01X316663Y2724007D01* +G01X337219Y2718158D01* +G01X358500Y2716186D01* +G01X358500Y2716186D01* +G01X379781Y2718158D01* +G01X400337Y2724007D01* +G01X419468Y2733533D01* +G01X436523Y2746412D01* +G01X450921Y2762206D01* +G01X462172Y2780377D01* +G01X469893Y2800306D01* +G01X473820Y2821314D01* +G01X473820Y2842686D01* +G01X469893Y2863694D01* +G01X462172Y2883623D01* +G01X450921Y2901793D01* +G01X436523Y2917587D01* +G01X419468Y2930467D01* +G01X400337Y2939993D01* +G01X379781Y2945842D01* +G01X358500Y2947814D01* +G01X337219Y2945842D01* +G01X316663Y2939993D01* +G01X297532Y2930467D01* +G01X280477Y2917587D01* +G01X266078Y2901793D01* +G01X254828Y2883623D01* +G01X247107Y2863694D01* +G01X243180Y2842686D01* +G01X106426Y2842686D01* +G01X106426Y3096686D01* +G01X243180Y3096686D01* +G01X243180Y3075314D01* +G01X247107Y3054306D01* +G01X254828Y3034377D01* +G01X266078Y3016206D01* +G01X280477Y3000412D01* +G01X297532Y2987533D01* +G01X316663Y2978007D01* +G01X337219Y2972158D01* +G01X358500Y2970186D01* +G01X358500Y2970186D01* +G01X379781Y2972158D01* +G01X400337Y2978007D01* +G01X419468Y2987533D01* +G01X436523Y3000412D01* +G01X450921Y3016206D01* +G01X462172Y3034377D01* +G01X469893Y3054306D01* +G01X473820Y3075314D01* +G01X473820Y3095749D01* +G01X507287Y3095749D01* +G01X507287Y3076250D01* +G01X510870Y3057084D01* +G01X517913Y3038901D01* +G01X528178Y3022323D01* +G01X541315Y3007913D01* +G01X556875Y2996163D01* +G01X574330Y2987471D01* +G01X593084Y2982135D01* +G01X612500Y2980336D01* +G01X612500Y2980336D01* +G01X631916Y2982135D01* +G01X650670Y2987471D01* +G01X668125Y2996163D01* +G01X683685Y3007913D01* +G01X696822Y3022323D01* +G01X707086Y3038901D01* +G01X714130Y3057084D01* +G01X717713Y3076250D01* +G01X717713Y3095749D01* +G01X714130Y3114916D01* +G01X707086Y3133098D01* +G01X696822Y3149677D01* +G01X683685Y3164087D01* +G01X668125Y3175837D01* +G01X650670Y3184529D01* +G01X631916Y3189865D01* +G01X612500Y3191664D01* +G01X593084Y3189865D01* +G01X574330Y3184529D01* +G01X556875Y3175837D01* +G01X541315Y3164087D01* +G01X528178Y3149677D01* +G01X517913Y3133098D01* +G01X510870Y3114916D01* +G01X507287Y3095749D01* +G01X473820Y3095749D01* +G01X473820Y3096686D01* +G01X469893Y3117694D01* +G01X462172Y3137623D01* +G01X450921Y3155793D01* +G01X436523Y3171587D01* +G01X419468Y3184467D01* +G01X400337Y3193993D01* +G01X379781Y3199842D01* +G01X358500Y3201814D01* +G01X337219Y3199842D01* +G01X316663Y3193993D01* +G01X297532Y3184467D01* +G01X280477Y3171587D01* +G01X266078Y3155793D01* +G01X254828Y3137623D01* +G01X247107Y3117694D01* +G01X243180Y3096686D01* +G01X106426Y3096686D01* +G01X106426Y3350686D01* +G01X243180Y3350686D01* +G01X243180Y3329314D01* +G01X247107Y3308306D01* +G01X254828Y3288377D01* +G01X266078Y3270206D01* +G01X280477Y3254412D01* +G01X297532Y3241533D01* +G01X316663Y3232007D01* +G01X337219Y3226158D01* +G01X358500Y3224186D01* +G01X358500Y3224186D01* +G01X379781Y3226158D01* +G01X400337Y3232007D01* +G01X419468Y3241533D01* +G01X436523Y3254412D01* +G01X450921Y3270206D01* +G01X462172Y3288377D01* +G01X469893Y3308306D01* +G01X473820Y3329314D01* +G01X473820Y3350686D01* +G01X469893Y3371694D01* +G01X462172Y3391623D01* +G01X450921Y3409793D01* +G01X436523Y3425587D01* +G01X419468Y3438467D01* +G01X400337Y3447993D01* +G01X379781Y3453842D01* +G01X358500Y3455814D01* +G01X337219Y3453842D01* +G01X316663Y3447993D01* +G01X297532Y3438467D01* +G01X280477Y3425587D01* +G01X266078Y3409793D01* +G01X254828Y3391623D01* +G01X247107Y3371694D01* +G01X243180Y3350686D01* +G01X106426Y3350686D01* +G01X106426Y3604686D01* +G01X243180Y3604686D01* +G01X243180Y3583314D01* +G01X247107Y3562306D01* +G01X254828Y3542377D01* +G01X266078Y3524206D01* +G01X280477Y3508412D01* +G01X297532Y3495533D01* +G01X316663Y3486007D01* +G01X337219Y3480158D01* +G01X358500Y3478186D01* +G01X358500Y3478186D01* +G01X379781Y3480158D01* +G01X400337Y3486007D01* +G01X419468Y3495533D01* +G01X436523Y3508412D01* +G01X450921Y3524206D01* +G01X462172Y3542377D01* +G01X469893Y3562306D01* +G01X473820Y3583314D01* +G01X473820Y3604686D01* +G01X469893Y3625694D01* +G01X462172Y3645623D01* +G01X450921Y3663793D01* +G01X436523Y3679587D01* +G01X419468Y3692467D01* +G01X400337Y3701993D01* +G01X379781Y3707842D01* +G01X358500Y3709814D01* +G01X337219Y3707842D01* +G01X316663Y3701993D01* +G01X297532Y3692467D01* +G01X280477Y3679587D01* +G01X266078Y3663793D01* +G01X254828Y3645623D01* +G01X247107Y3625694D01* +G01X243180Y3604686D01* +G01X106426Y3604686D01* +G01X106426Y4033719D01* +G01X206031Y3934114D01* +G01X217657Y3925193D01* +G01X231195Y3919585D01* +G01X245724Y3917673D01* +G01X265987Y3917673D01* +G01X254766Y3899498D01* +G01X247073Y3879573D01* +G01X243170Y3858573D01* +G01X243189Y3837214D01* +G01X247131Y3816221D01* +G01X254861Y3796310D01* +G01X266116Y3778156D01* +G01X280514Y3762378D01* +G01X297564Y3749513D01* +G01X316687Y3739998D01* +G01X337232Y3734156D01* +G01X358500Y3732186D01* +G01X358500Y3732186D01* +G01X379768Y3734156D01* +G01X400313Y3739998D01* +G01X419436Y3749513D01* +G01X436486Y3762378D01* +G01X450883Y3778156D01* +G01X462138Y3796310D01* +G01X469868Y3816221D01* +G01X473810Y3837214D01* +G01X473830Y3858573D01* +G01X469927Y3879573D01* +G01X462234Y3899498D01* +G01X451012Y3917673D01* +G01X463442Y3917673D01* +G01X501177Y3879938D01* +G01X501177Y3879938D01* +G01X497201Y3858913D01* +G01X497162Y3837516D01* +G01X501059Y3816477D01* +G01X508760Y3796513D01* +G01X520002Y3778308D01* +G01X534402Y3762481D01* +G01X551467Y3749573D01* +G01X570616Y3740025D01* +G01X591194Y3734163D01* +G01X612500Y3732186D01* +G01X612500Y3732186D01* +G01X633806Y3734163D01* +G01X654384Y3740025D01* +G01X673533Y3749573D01* +G01X690598Y3762481D01* +G01X704998Y3778308D01* +G01X716240Y3796513D01* +G01X723941Y3816477D01* +G01X727838Y3837516D01* +G01X727798Y3858913D01* +G01X723823Y3879938D01* +G01X762751Y3918866D01* +G01X1078336Y3918866D01* +G01X1078336Y3777134D01* +G01X739500Y3777134D01* +G01X724971Y3775221D01* +G01X711433Y3769613D01* +G01X699807Y3760693D01* +G01X644438Y3705323D01* +G01X624486Y3709192D01* +G01X604166Y3709514D01* +G01X584102Y3706278D01* +G01X564913Y3699585D01* +G01X547189Y3689641D01* +G01X531476Y3676752D01* +G01X518258Y3661315D01* +G01X507942Y3643805D01* +G01X500846Y3624761D01* +G01X497188Y3604770D01* +G01X497081Y3584447D01* +G01X500528Y3564419D01* +G01X507422Y3545301D01* +G01X517553Y3527683D01* +G01X530607Y3512107D01* +G01X546183Y3499053D01* +G01X563801Y3488922D01* +G01X582919Y3482028D01* +G01X602947Y3478581D01* +G01X623270Y3478688D01* +G01X643261Y3482346D01* +G01X662305Y3489442D01* +G01X679815Y3499758D01* +G01X695252Y3512976D01* +G01X708141Y3528689D01* +G01X718085Y3546413D01* +G01X724778Y3565602D01* +G01X728014Y3585666D01* +G01X727692Y3605986D01* +G01X723823Y3625938D01* +G01X762751Y3664866D01* +G01X1101895Y3664866D01* +G01X1101895Y3664866D01* +G01X1090561Y3646388D01* +G01X1082787Y3626152D01* +G01X1078833Y3604839D01* +G01X1078833Y3583161D01* +G01X1082787Y3561848D01* +G01X1090561Y3541612D01* +G01X1101895Y3523134D01* +G01X739500Y3523134D01* +G01X724971Y3521221D01* +G01X711433Y3515613D01* +G01X699807Y3506693D01* +G01X644438Y3451323D01* +G01X624486Y3455192D01* +G01X604166Y3455514D01* +G01X584102Y3452278D01* +G01X564913Y3445585D01* +G01X547189Y3435641D01* +G01X531476Y3422752D01* +G01X518258Y3407315D01* +G01X507942Y3389805D01* +G01X500846Y3370761D01* +G01X497188Y3350770D01* +G01X497081Y3330447D01* +G01X500528Y3310419D01* +G01X507422Y3291301D01* +G01X517553Y3273683D01* +G01X530607Y3258107D01* +G01X546183Y3245053D01* +G01X563801Y3234922D01* +G01X582919Y3228028D01* +G01X602947Y3224581D01* +G01X623270Y3224688D01* +G01X643261Y3228346D01* +G01X662305Y3235442D01* +G01X679815Y3245758D01* +G01X695252Y3258976D01* +G01X708141Y3274689D01* +G01X718085Y3292413D01* +G01X724778Y3311602D01* +G01X728014Y3331666D01* +G01X727692Y3351986D01* +G01X723823Y3371938D01* +G01X762751Y3410866D01* +G01X1473673Y3410866D01* +G01X1462885Y3391547D01* +G01X1455648Y3370636D01* +G01X1452186Y3348781D01* +G01X1452606Y3326657D01* +G01X1456897Y3304950D01* +G01X1464923Y3284329D01* +G01X1476438Y3265434D01* +G01X1491086Y3248848D01* +G01X1491086Y3200300D01* +G01X1492750Y3183402D01* +G01X1497679Y3167154D01* +G01X1505683Y3152180D01* +G01X1516455Y3139055D01* +G01X1830391Y2825118D01* +G01X1830391Y2825118D01* +G01X1833400Y2804907D01* +G01X1839914Y2785538D01* +G01X1849731Y2767617D01* +G01X1862546Y2751699D01* +G01X1877958Y2738282D01* +G01X1895488Y2727782D01* +G01X1914592Y2720526D01* +G01X1934672Y2716741D01* +G01X1955106Y2716545D01* +G01X1975256Y2719942D01* +G01X1994495Y2726828D01* +G01X2012225Y2736989D01* +G01X2027893Y2750107D01* +G01X2027893Y2750107D01* +G01X2041011Y2765775D01* +G01X2051171Y2783504D01* +G01X2058058Y2802744D01* +G01X2061455Y2822894D01* +G01X2061265Y2842686D01* +G01X2084680Y2842686D01* +G01X2084680Y2821314D01* +G01X2088607Y2800306D01* +G01X2096328Y2780377D01* +G01X2107578Y2762206D01* +G01X2121977Y2746412D01* +G01X2139032Y2733533D01* +G01X2158163Y2724007D01* +G01X2178719Y2718158D01* +G01X2200000Y2716186D01* +G01X2200000Y2716186D01* +G01X2221281Y2718158D01* +G01X2241837Y2724007D01* +G01X2260968Y2733533D01* +G01X2278023Y2746412D01* +G01X2292421Y2762206D01* +G01X2303672Y2780377D01* +G01X2311393Y2800306D01* +G01X2315320Y2821314D01* +G01X2315320Y2842686D01* +G01X2311393Y2863694D01* +G01X2303672Y2883623D01* +G01X2292421Y2901793D01* +G01X2278023Y2917587D01* +G01X2260968Y2930467D01* +G01X2241837Y2939993D01* +G01X2221281Y2945842D01* +G01X2200000Y2947814D01* +G01X2178719Y2945842D01* +G01X2158163Y2939993D01* +G01X2139032Y2930467D01* +G01X2121977Y2917587D01* +G01X2107578Y2901793D01* +G01X2096328Y2883623D01* +G01X2088607Y2863694D01* +G01X2084680Y2842686D01* +G01X2061265Y2842686D01* +G01X2061258Y2843327D01* +G01X2057474Y2863408D01* +G01X2050218Y2882511D01* +G01X2039718Y2900042D01* +G01X2026301Y2915454D01* +G01X2010383Y2928268D01* +G01X1992461Y2938086D01* +G01X1973093Y2944600D01* +G01X1952881Y2947609D01* +G01X1929059Y2971432D01* +G01X1949703Y2970245D01* +G01X1970229Y2972749D01* +G01X1989983Y2978863D01* +G01X2008334Y2988392D01* +G01X2024699Y3001033D01* +G01X2038555Y3016383D01* +G01X2049460Y3033952D01* +G01X2057066Y3053181D01* +G01X2061132Y3073455D01* +G01X2061528Y3094130D01* +G01X2061116Y3096686D01* +G01X2084680Y3096686D01* +G01X2084680Y3075314D01* +G01X2088607Y3054306D01* +G01X2096328Y3034377D01* +G01X2107578Y3016206D01* +G01X2121977Y3000412D01* +G01X2139032Y2987533D01* +G01X2158163Y2978007D01* +G01X2178719Y2972158D01* +G01X2200000Y2970186D01* +G01X2200000Y2970186D01* +G01X2221281Y2972158D01* +G01X2241837Y2978007D01* +G01X2260968Y2987533D01* +G01X2278023Y3000412D01* +G01X2292421Y3016206D01* +G01X2303672Y3034377D01* +G01X2311393Y3054306D01* +G01X2315320Y3075314D01* +G01X2315320Y3096686D01* +G01X2311393Y3117694D01* +G01X2303672Y3137623D01* +G01X2292421Y3155793D01* +G01X2278023Y3171587D01* +G01X2260968Y3184467D01* +G01X2241837Y3193993D01* +G01X2221281Y3199842D01* +G01X2200000Y3201814D01* +G01X2178719Y3199842D01* +G01X2158163Y3193993D01* +G01X2139032Y3184467D01* +G01X2121977Y3171587D01* +G01X2107578Y3155793D01* +G01X2096328Y3137623D01* +G01X2088607Y3117694D01* +G01X2084680Y3096686D01* +G01X2061116Y3096686D01* +G01X2058241Y3114545D01* +G01X2051375Y3134050D01* +G01X2041151Y3152024D01* +G01X2027893Y3167893D01* +G01X2012024Y3181151D01* +G01X1994050Y3191375D01* +G01X1974545Y3198241D01* +G01X1954130Y3201528D01* +G01X1933455Y3201132D01* +G01X1913181Y3197066D01* +G01X1893952Y3189460D01* +G01X1876383Y3178555D01* +G01X1861033Y3164699D01* +G01X1848392Y3148334D01* +G01X1838863Y3129983D01* +G01X1832749Y3110229D01* +G01X1830245Y3089703D01* +G01X1831432Y3069059D01* +G01X1664314Y3236177D01* +G01X1664314Y3248848D01* +G01X1664314Y3248848D01* +G01X1678961Y3265434D01* +G01X1690477Y3284329D01* +G01X1698503Y3304950D01* +G01X1702793Y3326657D01* +G01X1703214Y3348781D01* +G01X1699752Y3370636D01* +G01X1692515Y3391547D01* +G01X1681726Y3410866D01* +G01X1854398Y3410866D01* +G01X1854398Y3410866D01* +G01X1842885Y3392727D01* +G01X1834920Y3372774D01* +G01X1830778Y3351694D01* +G01X1830601Y3330210D01* +G01X1834394Y3309064D01* +G01X1842029Y3288982D01* +G01X1853241Y3270656D01* +G01X1867645Y3254716D01* +G01X1884745Y3241711D01* +G01X1903953Y3232088D01* +G01X1924609Y3226179D01* +G01X1946000Y3224186D01* +G01X1946000Y3224186D01* +G01X1967391Y3226179D01* +G01X1988046Y3232088D01* +G01X2007255Y3241711D01* +G01X2024355Y3254716D01* +G01X2038759Y3270656D01* +G01X2049971Y3288982D01* +G01X2057606Y3309064D01* +G01X2061399Y3330210D01* +G01X2061222Y3351694D01* +G01X2057080Y3372774D01* +G01X2049115Y3392727D01* +G01X2037602Y3410866D01* +G01X2049748Y3410866D01* +G01X2088677Y3371938D01* +G01X2088677Y3371938D01* +G01X2084808Y3351986D01* +G01X2084486Y3331666D01* +G01X2087722Y3311602D01* +G01X2094414Y3292413D01* +G01X2104358Y3274689D01* +G01X2117248Y3258976D01* +G01X2132685Y3245758D01* +G01X2150195Y3235442D01* +G01X2169239Y3228346D01* +G01X2189230Y3224688D01* +G01X2209553Y3224581D01* +G01X2229581Y3228028D01* +G01X2248699Y3234922D01* +G01X2266317Y3245053D01* +G01X2281893Y3258107D01* +G01X2294947Y3273683D01* +G01X2305077Y3291301D01* +G01X2311972Y3310419D01* +G01X2315419Y3330447D01* +G01X2315312Y3350770D01* +G01X2311654Y3370761D01* +G01X2304558Y3389805D01* +G01X2294242Y3407315D01* +G01X2281024Y3422752D01* +G01X2265311Y3435641D01* +G01X2247587Y3445585D01* +G01X2228398Y3452278D01* +G01X2208334Y3455514D01* +G01X2188014Y3455192D01* +G01X2168062Y3451323D01* +G01X2112693Y3506693D01* +G01X2101067Y3515613D01* +G01X2087528Y3521221D01* +G01X2073000Y3523134D01* +G01X2037602Y3523134D01* +G01X2047976Y3539103D01* +G01X2055594Y3556556D01* +G01X2060248Y3575021D01* +G01X2061814Y3594000D01* +G01X2060248Y3612978D01* +G01X2055594Y3631444D01* +G01X2047976Y3648897D01* +G01X2037602Y3664866D01* +G01X2049748Y3664866D01* +G01X2088677Y3625938D01* +G01X2088677Y3625938D01* +G01X2084808Y3605986D01* +G01X2084486Y3585666D01* +G01X2087722Y3565602D01* +G01X2094414Y3546413D01* +G01X2104358Y3528689D01* +G01X2117248Y3512976D01* +G01X2132685Y3499758D01* +G01X2150195Y3489442D01* +G01X2169239Y3482346D01* +G01X2189230Y3478688D01* +G01X2209553Y3478581D01* +G01X2229581Y3482028D01* +G01X2248699Y3488922D01* +G01X2266317Y3499053D01* +G01X2281893Y3512107D01* +G01X2294947Y3527683D01* +G01X2305077Y3545301D01* +G01X2311972Y3564419D01* +G01X2315419Y3584447D01* +G01X2315312Y3604770D01* +G01X2311654Y3624761D01* +G01X2304558Y3643805D01* +G01X2294242Y3661315D01* +G01X2281024Y3676752D01* +G01X2265311Y3689641D01* +G01X2247587Y3699585D01* +G01X2228398Y3706278D01* +G01X2208334Y3709514D01* +G01X2188014Y3709192D01* +G01X2168062Y3705323D01* +G01X2112693Y3760693D01* +G01X2101067Y3769613D01* +G01X2087528Y3775221D01* +G01X2073000Y3777134D01* +G01X2037602Y3777134D01* +G01X2037602Y3777134D01* +G01X2047976Y3793103D01* +G01X2055594Y3810556D01* +G01X2060248Y3829021D01* +G01X2061814Y3848000D01* +G01X2060248Y3866978D01* +G01X2055594Y3885444D01* +G01X2047976Y3902897D01* +G01X2037602Y3918866D01* +G01X2049748Y3918866D01* +G01X2088677Y3879938D01* +G01X2088677Y3879938D01* +G01X2084808Y3859986D01* +G01X2084486Y3839666D01* +G01X2087722Y3819602D01* +G01X2094414Y3800413D01* +G01X2104358Y3782689D01* +G01X2117248Y3766976D01* +G01X2132685Y3753758D01* +G01X2150195Y3743442D01* +G01X2169239Y3736346D01* +G01X2189230Y3732688D01* +G01X2209553Y3732581D01* +G01X2229581Y3736028D01* +G01X2248699Y3742922D01* +G01X2266317Y3753053D01* +G01X2281893Y3766107D01* +G01X2294947Y3781683D01* +G01X2305077Y3799301D01* +G01X2311972Y3818419D01* +G01X2315419Y3838447D01* +G01X2315312Y3858770D01* +G01X2311654Y3878761D01* +G01X2304558Y3897805D01* +G01X2294242Y3915315D01* +G01X2281024Y3930752D01* +G01X2265311Y3943641D01* +G01X2247587Y3953585D01* +G01X2228398Y3960278D01* +G01X2208334Y3963514D01* +G01X2188014Y3963192D01* +G01X2168062Y3959323D01* +G01X2112693Y4014693D01* +G01X2101067Y4023613D01* +G01X2087528Y4029221D01* +G01X2073000Y4031134D01* +G01X2037602Y4031134D01* +G01X2037602Y4031134D01* +G01X2049115Y4049272D01* +G01X2057080Y4069225D01* +G01X2061222Y4090306D01* +G01X2061399Y4111789D01* +G01X2061238Y4112686D01* +G01X2084680Y4112686D01* +G01X2084680Y4091314D01* +G01X2088607Y4070306D01* +G01X2096328Y4050377D01* +G01X2107578Y4032206D01* +G01X2121977Y4016412D01* +G01X2139032Y4003533D01* +G01X2158163Y3994007D01* +G01X2178719Y3988158D01* +G01X2200000Y3986186D01* +G01X2200000Y3986186D01* +G01X2221281Y3988158D01* +G01X2241837Y3994007D01* +G01X2260968Y4003533D01* +G01X2278023Y4016412D01* +G01X2292421Y4032206D01* +G01X2303672Y4050377D01* +G01X2311393Y4070306D01* +G01X2315320Y4091314D01* +G01X2315320Y4112686D01* +G01X2311393Y4133694D01* +G01X2303672Y4153623D01* +G01X2292421Y4171793D01* +G01X2278023Y4187587D01* +G01X2260968Y4200467D01* +G01X2241837Y4209993D01* +G01X2221281Y4215842D01* +G01X2200000Y4217814D01* +G01X2178719Y4215842D01* +G01X2158163Y4209993D01* +G01X2139032Y4200467D01* +G01X2121977Y4187587D01* +G01X2107578Y4171793D01* +G01X2096328Y4153623D01* +G01X2088607Y4133694D01* +G01X2084680Y4112686D01* +G01X2061238Y4112686D01* +G01X2057606Y4132936D01* +G01X2049971Y4153017D01* +G01X2038759Y4171344D01* +G01X2024355Y4187284D01* +G01X2007255Y4200289D01* +G01X1988046Y4209912D01* +G01X1967391Y4215821D01* +G01X1946000Y4217814D01* +G01X1946000Y4217814D01* +G01X1924609Y4215821D01* +G01X1903953Y4209912D01* +G01X1884745Y4200289D01* +G01X1867645Y4187284D01* +G01X1853241Y4171344D01* +G01X1842029Y4153017D01* +G01X1834394Y4132936D01* +G01X1830601Y4111789D01* +G01X1830778Y4090306D01* +G01X1834920Y4069225D01* +G01X1842885Y4049272D01* +G01X1854398Y4031134D01* +G01X739500Y4031134D01* +G01X724971Y4029221D01* +G01X711433Y4023613D01* +G01X699807Y4014693D01* +G01X644438Y3959323D01* +G01X623270Y3963312D01* +G01X601730Y3963312D01* +G01X580562Y3959323D01* +G01X526386Y4013499D01* +G01X514760Y4022420D01* +G01X501222Y4028028D01* +G01X486693Y4029941D01* +G01X449166Y4029941D01* +G01X449166Y4029941D01* +G01X460861Y4047824D01* +G01X469072Y4067552D01* +G01X473519Y4088452D01* +G01X474050Y4109813D01* +G01X473587Y4112686D01* +G01X497180Y4112686D01* +G01X497180Y4091314D01* +G01X501107Y4070306D01* +G01X508828Y4050377D01* +G01X520078Y4032206D01* +G01X534477Y4016412D01* +G01X551532Y4003533D01* +G01X570663Y3994007D01* +G01X591219Y3988158D01* +G01X612500Y3986186D01* +G01X612500Y3986186D01* +G01X633781Y3988158D01* +G01X654337Y3994007D01* +G01X673468Y4003533D01* +G01X690523Y4016412D01* +G01X704921Y4032206D01* +G01X716172Y4050377D01* +G01X723893Y4070306D01* +G01X727820Y4091314D01* +G01X727820Y4112686D01* +G01X723893Y4133694D01* +G01X716172Y4153623D01* +G01X704921Y4171793D01* +G01X690523Y4187587D01* +G01X673468Y4200467D01* +G01X654337Y4209993D01* +G01X653953Y4210102D01* +G01X1451886Y4210102D01* +G01X1453797Y4188255D01* +G01X1459474Y4167071D01* +G01X1468742Y4147195D01* +G01X1481321Y4129231D01* +G01X1496828Y4113723D01* +G01X1514793Y4101144D01* +G01X1534669Y4091876D01* +G01X1555853Y4086200D01* +G01X1577700Y4084289D01* +G01X1599547Y4086200D01* +G01X1620731Y4091876D01* +G01X1640607Y4101144D01* +G01X1658571Y4113723D01* +G01X1674079Y4129231D01* +G01X1686658Y4147195D01* +G01X1695926Y4167071D01* +G01X1701602Y4188255D01* +G01X1703514Y4210102D01* +G01X1701602Y4231950D01* +G01X1695926Y4253133D01* +G01X1686658Y4273009D01* +G01X1674079Y4290974D01* +G01X1658571Y4306481D01* +G01X1640607Y4319060D01* +G01X1620731Y4328329D01* +G01X1599547Y4334005D01* +G01X1577700Y4335916D01* +G01X1577700Y4335916D01* +G01X1555853Y4334005D01* +G01X1534669Y4328329D01* +G01X1514793Y4319060D01* +G01X1496828Y4306481D01* +G01X1481321Y4290974D01* +G01X1468742Y4273009D01* +G01X1459474Y4253133D01* +G01X1453797Y4231950D01* +G01X1451886Y4210102D01* +G01X653953Y4210102D01* +G01X633781Y4215842D01* +G01X612500Y4217814D01* +G01X591219Y4215842D01* +G01X570663Y4209993D01* +G01X551532Y4200467D01* +G01X534477Y4187587D01* +G01X520078Y4171793D01* +G01X508828Y4153623D01* +G01X501107Y4133694D01* +G01X497180Y4112686D01* +G01X473587Y4112686D01* +G01X470648Y4130909D01* +G01X463428Y4151020D01* +G01X452636Y4169463D01* +G01X438640Y4185609D01* +G01X421915Y4198909D01* +G01X403032Y4208910D01* +G01X382633Y4215271D01* +G01X361412Y4217777D01* +G01X340092Y4216342D01* +G01X319399Y4211014D01* +G01X300037Y4201975D01* +G01X282665Y4189532D01* +G01X267875Y4174110D01* +G01X256169Y4156234D01* +G01X247947Y4136511D01* +G01X243489Y4115613D01* +G01X242946Y4094252D01* +G01X246336Y4073154D01* +G01X253544Y4053039D01* +G01X264326Y4034590D01* +G01X192638Y4106278D01* +G01X192638Y4366686D01* +G01X243180Y4366686D01* +G01X243180Y4345314D01* +G01X247107Y4324306D01* +G01X254828Y4304377D01* +G01X266078Y4286206D01* +G01X280477Y4270412D01* +G01X297532Y4257533D01* +G01X316663Y4248007D01* +G01X337219Y4242158D01* +G01X358500Y4240186D01* +G01X358500Y4240186D01* +G01X379781Y4242158D01* +G01X400337Y4248007D01* +G01X419468Y4257533D01* +G01X436523Y4270412D01* +G01X450921Y4286206D01* +G01X462172Y4304377D01* +G01X469893Y4324306D01* +G01X473820Y4345314D01* +G01X473820Y4366686D01* +G01X497180Y4366686D01* +G01X497180Y4345314D01* +G01X501107Y4324306D01* +G01X508828Y4304377D01* +G01X520078Y4286206D01* +G01X534477Y4270412D01* +G01X551532Y4257533D01* +G01X570663Y4248007D01* +G01X591219Y4242158D01* +G01X612500Y4240186D01* +G01X612500Y4240186D01* +G01X633781Y4242158D01* +G01X654337Y4248007D01* +G01X673468Y4257533D01* +G01X690523Y4270412D01* +G01X704921Y4286206D01* +G01X716172Y4304377D01* +G01X723893Y4324306D01* +G01X727820Y4345314D01* +G01X727820Y4366686D01* +G01X723893Y4387694D01* +G01X716172Y4407623D01* +G01X704921Y4425793D01* +G01X690523Y4441587D01* +G01X673468Y4454467D01* +G01X654337Y4463993D01* +G01X633781Y4469842D01* +G01X612500Y4471814D01* +G01X591219Y4469842D01* +G01X570663Y4463993D01* +G01X551532Y4454467D01* +G01X534477Y4441587D01* +G01X520078Y4425793D01* +G01X508828Y4407623D01* +G01X501107Y4387694D01* +G01X497180Y4366686D01* +G01X473820Y4366686D01* +G01X469893Y4387694D01* +G01X462172Y4407623D01* +G01X450921Y4425793D01* +G01X436523Y4441587D01* +G01X419468Y4454467D01* +G01X400337Y4463993D01* +G01X379781Y4469842D01* +G01X358500Y4471814D01* +G01X337219Y4469842D01* +G01X316663Y4463993D01* +G01X297532Y4454467D01* +G01X280477Y4441587D01* +G01X266078Y4425793D01* +G01X254828Y4407623D01* +G01X247107Y4387694D01* +G01X243180Y4366686D01* +G01X192638Y4366686D01* +G01X192638Y4773007D01* +G01X274611Y4691034D01* +G01X275196Y4690457D01* +G01X275196Y4690457D01* +G01X262582Y4674904D01* +G01X252835Y4657411D01* +G01X246248Y4638500D01* +G01X243016Y4618738D01* +G01X243237Y4598714D01* +G01X246905Y4579027D01* +G01X253908Y4560266D01* +G01X264039Y4542993D01* +G01X276994Y4527722D01* +G01X292386Y4514912D01* +G01X309754Y4504944D01* +G01X328580Y4498118D01* +G01X348300Y4494636D01* +G01X348300Y4494636D01* +G01X368325Y4494604D01* +G01X388057Y4498021D01* +G01X406905Y4504787D01* +G01X424305Y4514698D01* +G01X439738Y4527458D01* +G01X452743Y4542686D01* +G01X462930Y4559927D01* +G01X469994Y4578665D01* +G01X473725Y4598339D01* +G01X474011Y4618363D01* +G01X470844Y4638136D01* +G01X464318Y4657068D01* +G01X454628Y4674593D01* +G01X468522Y4674593D01* +G01X501177Y4641938D01* +G01X497233Y4621240D01* +G01X497104Y4600169D01* +G01X500795Y4579425D01* +G01X508183Y4559692D01* +G01X519024Y4541625D01* +G01X532960Y4525820D01* +G01X549528Y4512803D01* +G01X568180Y4503002D01* +G01X588299Y4496743D01* +G01X609220Y4494233D01* +G01X630249Y4495554D01* +G01X650690Y4500664D01* +G01X669867Y4509393D01* +G01X687146Y4521452D01* +G01X701954Y4536441D01* +G01X713801Y4553866D01* +G01X1109948Y4553866D01* +G01X1220507Y4443307D01* +G01X1232133Y4434386D01* +G01X1245671Y4428779D01* +G01X1260200Y4426866D01* +G01X1854398Y4426866D01* +G01X1842885Y4408727D01* +G01X1834920Y4388774D01* +G01X1830778Y4367694D01* +G01X1830601Y4346210D01* +G01X1834394Y4325064D01* +G01X1842029Y4304982D01* +G01X1853241Y4286656D01* +G01X1867645Y4270716D01* +G01X1884745Y4257711D01* +G01X1903953Y4248088D01* +G01X1924609Y4242179D01* +G01X1946000Y4240186D01* +G01X1967391Y4242179D01* +G01X1988046Y4248088D01* +G01X2007255Y4257711D01* +G01X2024355Y4270716D01* +G01X2038759Y4286656D01* +G01X2049971Y4304982D01* +G01X2057606Y4325064D01* +G01X2061399Y4346210D01* +G01X2061230Y4366686D01* +G01X2084680Y4366686D01* +G01X2084680Y4345314D01* +G01X2088607Y4324306D01* +G01X2096328Y4304377D01* +G01X2107578Y4286206D01* +G01X2121977Y4270412D01* +G01X2139032Y4257533D01* +G01X2158163Y4248007D01* +G01X2178719Y4242158D01* +G01X2200000Y4240186D01* +G01X2200000Y4240186D01* +G01X2221281Y4242158D01* +G01X2241837Y4248007D01* +G01X2260968Y4257533D01* +G01X2278023Y4270412D01* +G01X2292421Y4286206D01* +G01X2303672Y4304377D01* +G01X2311393Y4324306D01* +G01X2315320Y4345314D01* +G01X2315320Y4366686D01* +G01X2311393Y4387694D01* +G01X2303672Y4407623D01* +G01X2292421Y4425793D01* +G01X2278023Y4441587D01* +G01X2260968Y4454467D01* +G01X2241837Y4463993D01* +G01X2221281Y4469842D01* +G01X2200000Y4471814D01* +G01X2178719Y4469842D01* +G01X2158163Y4463993D01* +G01X2139032Y4454467D01* +G01X2121977Y4441587D01* +G01X2107578Y4425793D01* +G01X2096328Y4407623D01* +G01X2088607Y4387694D01* +G01X2084680Y4366686D01* +G01X2061230Y4366686D01* +G01X2061222Y4367694D01* +G01X2057080Y4388774D01* +G01X2049115Y4408727D01* +G01X2037602Y4426866D01* +G01X2073000Y4426866D01* +G01X2087528Y4428779D01* +G01X2101067Y4434386D01* +G01X2112693Y4443307D01* +G01X2168062Y4498677D01* +G01X2188014Y4494808D01* +G01X2208334Y4494486D01* +G01X2228398Y4497722D01* +G01X2247587Y4504414D01* +G01X2265311Y4514358D01* +G01X2281024Y4527248D01* +G01X2294242Y4542685D01* +G01X2304558Y4560195D01* +G01X2311654Y4579239D01* +G01X2315312Y4599230D01* +G01X2315419Y4619553D01* +G01X2311972Y4639581D01* +G01X2305077Y4658699D01* +G01X2294947Y4676317D01* +G01X2281893Y4691893D01* +G01X2266317Y4704947D01* +G01X2248699Y4715077D01* +G01X2229581Y4721972D01* +G01X2209553Y4725419D01* +G01X2189230Y4725312D01* +G01X2169239Y4721654D01* +G01X2150195Y4714558D01* +G01X2132685Y4704242D01* +G01X2117248Y4691024D01* +G01X2104358Y4675311D01* +G01X2094414Y4657587D01* +G01X2087722Y4638398D01* +G01X2084486Y4618334D01* +G01X2084808Y4598014D01* +G01X2088677Y4578062D01* +G01X2049748Y4539134D01* +G01X2037602Y4539134D01* +G01X2037602Y4539134D01* +G01X2047976Y4555103D01* +G01X2055594Y4572556D01* +G01X2060248Y4591021D01* +G01X2061814Y4610000D01* +G01X2060248Y4628978D01* +G01X2055594Y4647444D01* +G01X2047976Y4664897D01* +G01X2037602Y4680866D01* +G01X2073000Y4680866D01* +G01X2087528Y4682779D01* +G01X2101067Y4688386D01* +G01X2112693Y4697307D01* +G01X2168062Y4752677D01* +G01X2188216Y4748787D01* +G01X2208740Y4748516D01* +G01X2228990Y4751873D01* +G01X2248329Y4758752D01* +G01X2266150Y4768936D01* +G01X2281893Y4782107D01* +G01X2295063Y4797850D01* +G01X2305248Y4815671D01* +G01X2312127Y4835010D01* +G01X2315483Y4855260D01* +G01X2315213Y4875784D01* +G01X2311323Y4895938D01* +G01X2411397Y4996011D01* +G01X2418186Y5004232D01* +G01X2418186Y150000D01* +G01X2416451Y130172D01* +G01X2411300Y110946D01* +G01X2402888Y92907D01* +G01X2391471Y76603D01* +G01X2377397Y62528D01* +G01X2361093Y51112D01* +G01X2343054Y42700D01* +G01X2323828Y37549D01* +G01X2304000Y35814D01* +G01X150000Y35814D01* +G01X130172Y37549D01* +G01X110946Y42700D01* +G01X92907Y51112D01* +G01X76603Y62528D01* +G01X62528Y76603D01* +G01X51112Y92907D01* +G01X42700Y110946D01* +G01X37549Y130172D01* +G01X35814Y150000D01* +G37* +G36* +G01X944293Y585693D02* +G01X932667Y594613D01* +G01X919128Y600221D01* +G01X904600Y602134D01* +G01X728314Y602134D01* +G01X728314Y626000D01* +G01X726561Y637067D01* +G01X721474Y647051D01* +G01X713551Y654974D01* +G01X703567Y660061D01* +G01X692500Y661814D01* +G01X576072Y661814D01* +G01X526386Y711499D01* +G01X514760Y720420D01* +G01X501222Y726028D01* +G01X486693Y727941D01* +G01X449166Y727941D01* +G01X449166Y727941D01* +G01X459402Y743153D01* +G01X467110Y759791D01* +G01X472094Y777436D01* +G01X474232Y795647D01* +G01X473468Y813968D01* +G01X469823Y831938D01* +G01X508751Y870866D01* +G01X520898Y870866D01* +G01X520898Y870866D01* +G01X509532Y853013D01* +G01X501604Y833389D01* +G01X497379Y812650D01* +G01X496999Y791489D01* +G01X500477Y770612D01* +G01X507695Y750717D01* +G01X518414Y732467D01* +G01X532275Y716473D01* +G01X548815Y703268D01* +G01X548815Y703268D01* +G01X567482Y693294D01* +G01X587652Y686883D01* +G01X608653Y684250D01* +G01X629781Y685483D01* +G01X650333Y690540D01* +G01X669621Y699252D01* +G01X687001Y711330D01* +G01X701894Y726368D01* +G01X713801Y743866D01* +G01X932148Y743866D01* +G01X1042707Y633307D01* +G01X1054333Y624386D01* +G01X1067871Y618779D01* +G01X1082400Y616866D01* +G01X1854398Y616866D01* +G01X1854398Y616866D01* +G01X1843544Y599997D01* +G01X1835764Y581508D01* +G01X1831290Y561953D01* +G01X1830258Y541920D01* +G01X1832698Y522010D01* +G01X1838537Y502819D01* +G01X1847600Y484924D01* +G01X1859615Y468861D01* +G01X1061125Y468861D01* +G01X944293Y585693D01* +G37* +G36* +G01X1854398Y3523134D02* +G01X1291505Y3523134D01* +G01X1291505Y3523134D01* +G01X1302839Y3541612D01* +G01X1310613Y3561848D01* +G01X1314567Y3583161D01* +G01X1314567Y3604839D01* +G01X1310613Y3626152D01* +G01X1302839Y3646388D01* +G01X1291505Y3664866D01* +G01X1854398Y3664866D01* +G01X1844024Y3648897D01* +G01X1836406Y3631444D01* +G01X1831752Y3612978D01* +G01X1830186Y3594000D01* +G01X1831752Y3575021D01* +G01X1836406Y3556556D01* +G01X1844024Y3539103D01* +G01X1854398Y3523134D01* +G37* +G36* +G01X2037602Y616866D02* +G01X2073000Y616866D01* +G01X2084186Y617992D01* +G01X2084186Y509572D01* +G01X2043475Y468861D01* +G01X2032385Y468861D01* +G01X2032385Y468861D01* +G01X2044400Y484924D01* +G01X2053463Y502819D01* +G01X2059302Y522010D01* +G01X2061742Y541920D01* +G01X2060710Y561953D01* +G01X2056236Y581508D01* +G01X2048456Y599997D01* +G01X2037602Y616866D01* +G37* +G54D10* +G01X-5842Y6762187D02* +G01X-5842Y6681814D01* +G01X-2422300Y6681814D01* +G02X-2536486Y6796000I0J114186D01* +G01X-2536486Y10796000D01* +G02X-2422300Y10910186I114186J0D01* +G01X0Y10910186D01* +G03X35814Y10946000I0J35814D01* +G01X35814Y13350000D01* +G02X150000Y13464186I114186J0D01* +G01X2750004Y13464183D01* +G02X2864190Y13349997I0J-114186D01* +G01X2864188Y12580525D01* +G03X2758800Y12678564I-105389J-7625D01* +G01X2708000Y12678564D01* +G03X2708000Y12467236I0J-105664D01* +G01X2758800Y12467236D01* +G03X2864188Y12565274I0J105664D01* +G01X2864188Y12326532D01* +G03X2758800Y12424564I-105388J-7632D01* +G01X2708000Y12424564D01* +G03X2708000Y12213236I0J-105664D01* +G01X2758800Y12213236D01* +G03X2864188Y12311268I0J105664D01* +G01X2864187Y12072538D01* +G03X2758800Y12170564I-105388J-7638D01* +G01X2708000Y12170564D01* +G03X2708000Y11959236I0J-105664D01* +G01X2758800Y11959236D01* +G03X2864187Y12057261I0J105664D01* +G01X2864187Y11818545D01* +G03X2758800Y11916564I-105387J-7645D01* +G01X2708000Y11916564D01* +G03X2708000Y11705236I0J-105664D01* +G01X2758800Y11705236D01* +G03X2864187Y11803255I0J105664D01* +G01X2864187Y11564551D01* +G03X2758800Y11662564I-105387J-7651D01* +G01X2708000Y11662564D01* +G03X2708000Y11451236I0J-105664D01* +G01X2758800Y11451236D01* +G03X2864187Y11549248I0J105664D01* +G01X2864186Y11310558D01* +G03X2758800Y11408564I-105386J-7658D01* +G01X2708000Y11408564D01* +G03X2708000Y11197236I0J-105664D01* +G01X2758800Y11197236D01* +G03X2864304Y11297093I0J105664D01* +G03X2900000Y11264186I35696J2907D01* +G01X4750000Y11264186D01* +G02X4864186Y11150000I0J-114186D01* +G01X4891892Y5650013D01* +G02X4777706Y5535830I-114186J2D01* +G01X2454000Y5535830D01* +G03X2427838Y5524474I0J-35814D01* +G01X2427838Y6800827D01* +G03X2411397Y6840519I-56134J0D01* +G01X955977Y8295939D01* +G03X916284Y8312381I-39693J-39693D01* +G01X842024Y8312381D01* +G01X842024Y8325097D01* +G03X806210Y8360911I-35814J0D01* +G01X692957Y8360911D01* +G03X657143Y8325097I0J-35814D01* +G01X657143Y8187396D01* +G03X692957Y8151582I35814J0D01* +G01X806210Y8151582D01* +G03X842024Y8187396I0J35814D01* +G01X842024Y8200113D01* +G01X893032Y8200113D01* +G01X2315570Y6777575D01* +G01X2315570Y5379511D01* +G03X2180161Y5486102I-115570J-7511D01* +G03X2088677Y5340062I19838J-114102D01* +G01X2049748Y5301134D01* +G01X2037602Y5301134D01* +G03X1946000Y5487814I-91602J70866D01* +G03X1854398Y5301134I0J-115814D01* +G01X1385051Y5301134D01* +G01X1274493Y5411693D01* +G03X1234800Y5428134I-39693J-39693D01* +G01X713801Y5428134D01* +G03X548815Y5468732I-101301J-56134D01* +G03X520898Y5301134I63685J-96732D01* +G01X485500Y5301134D01* +G03X445807Y5284693I0J-56134D01* +G01X390438Y5229323D01* +G03X281538Y5204543I-31938J-111323D01* +G01X281538Y5285457D01* +G03X474314Y5372000I76962J86543D01* +G03X281538Y5458543I-115814J0D01* +G01X281538Y6802975D01* +G01X430197Y6951634D01* +G03X446638Y6991327I-39693J39693D01* +G01X446638Y7803796D01* +G03X430197Y7843489I-56134J0D01* +G01X315462Y7958223D01* +G03X218800Y8106564I-96662J42677D01* +G01X168000Y8106564D01* +G03X168000Y7895236I0J-105664D01* +G01X218800Y7895236D01* +G01X219675Y7895240D01* +G01X289383Y7825532D01* +G03X218800Y7852564I-70583J-78632D01* +G01X168000Y7852564D01* +G03X168000Y7641236I0J-105664D01* +G01X218800Y7641236D01* +G03X297432Y7817483I0J105664D01* +G01X334370Y7780544D01* +G01X334370Y7014578D01* +G01X185711Y6865919D01* +G03X180954Y6860508I39693J-39693D01* +G03X176197Y6865919I-44450J-34282D01* +G01X53934Y6988182D01* +G01X53934Y8289871D01* +G01X88057Y8323994D01* +G03X168000Y8149236I79943J-69094D01* +G01X218800Y8149236D01* +G03X308320Y8198766I0J105664D01* +G01X457143Y8198766D01* +G01X457143Y8187396D01* +G03X492957Y8151582I35814J0D01* +G01X606211Y8151582D01* +G03X642025Y8187396I0J35814D01* +G01X642025Y8325097D01* +G03X606211Y8360911I-35814J0D01* +G01X492957Y8360911D01* +G03X457143Y8325097I0J-35814D01* +G01X457143Y8311034D01* +G01X308320Y8311034D01* +G03X218800Y8360564I-89520J-56134D01* +G01X168000Y8360564D01* +G03X98905Y8334843I0J-105664D01* +G01X167301Y8403238D01* +G01X168000Y8403236D01* +G01X218800Y8403236D01* +G03X218800Y8614564I0J105664D01* +G01X168000Y8614564D01* +G03X98905Y8588843I0J-105664D01* +G01X167301Y8657238D01* +G01X168000Y8657236D01* +G01X218800Y8657236D01* +G03X218800Y8868564I0J105664D01* +G01X168000Y8868564D01* +G03X71392Y8720100I0J-105664D01* +G01X-131789Y8516919D01* +G03X-148230Y8477227I39693J-39693D01* +G01X-148230Y6927827D01* +G03X-131789Y6888134I56134J0D01* +G01X-5842Y6762187D01* +G01X-2308500Y8136536D02* +G03X-2308500Y8373264I0J118364D01* +G03X-2308500Y8136536I0J-118364D01* +G01X-2308500Y8390536D02* +G03X-2308500Y8627264I0J118364D01* +G03X-2308500Y8390536I0J-118364D01* +G01X-2308500Y8644536D02* +G03X-2308500Y8881264I0J118364D01* +G03X-2308500Y8644536I0J-118364D01* +G01X-2308500Y7628536D02* +G03X-2308500Y7865264I0J118364D01* +G03X-2308500Y7628536I0J-118364D01* +G01X-2308500Y7882536D02* +G03X-2308500Y8119264I0J118364D01* +G03X-2308500Y7882536I0J-118364D01* +G01X-2308500Y8898536D02* +G03X-2308500Y9135264I0J118364D01* +G03X-2308500Y8898536I0J-118364D01* +G01X-2190136Y10743221D02* +G01X-2190136Y10864750D01* +G03X-2225950Y10900564I-35814J0D01* +G01X-2391050Y10900564D01* +G03X-2426864Y10864750I0J-35814D01* +G01X-2426864Y10699650D01* +G03X-2391050Y10663836I35814J0D01* +G01X-2269522Y10663836D01* +G01X-582893Y8977207D01* +G03X-543200Y8960766I39693J39693D01* +G01X-380707Y8960766D01* +G03X-158136Y9016900I104207J56134D01* +G03X-380707Y9073034I-118364J0D01* +G01X-519949Y9073034D01* +G01X-2190136Y10743221D01* +G01X-185896Y9194737D02* +G03X-319925Y9381010I-90605J76163D01* +G01X-1687122Y10748207D01* +G03X-1755204Y10891554I-113378J33992D01* +G03X-1904707Y10838334I-45296J-109354D01* +G01X-1950294Y10838334D01* +G03X-2172864Y10782200I-104207J-56134D01* +G03X-1950294Y10726066I118364J0D01* +G01X-1904707Y10726066D01* +G03X-1766508Y10668822I104207J56134D01* +G01X-392436Y9294751D01* +G03X-185896Y9194737I115936J-23851D01* +G01X-185896Y9448737D02* +G03X-319925Y9635010I-90605J76163D01* +G01X-1433122Y10748207D01* +G03X-1630196Y10865896I-113378J33992D01* +G03X-1512508Y10668822I83696J-83696D01* +G01X-392436Y9548751D01* +G03X-185896Y9448737I115936J-23851D01* +G01X1170361Y9538693D02* +G03X1210053Y9555134I0J56134D01* +G01X1295549Y9640630D01* +G03X1427279Y9687244I33992J113378D01* +G03X1422794Y9826906I-97737J66764D01* +G01X1490290Y9826906D01* +G03X1583542Y9635644I93252J-72898D01* +G03X1676794Y9826906I0J118364D01* +G01X1744290Y9826906D01* +G03X1837542Y9635644I93252J-72898D01* +G03X1930794Y9826906I0J118364D01* +G01X1939258Y9826906D01* +G01X1978164Y9788000D01* +G03X2175238Y9670312I113378J-33992D01* +G03X2057549Y9867386I-83696J83696D01* +G01X2002203Y9922733D01* +G03X1962510Y9939174I-39693J-39693D01* +G01X1933833Y9939174D01* +G03X1837542Y10126372I-96291J68834D01* +G03X1741251Y9939174I0J-118364D01* +G01X1679833Y9939174D01* +G03X1583542Y10126372I-96291J68834D01* +G03X1487251Y9939174I0J-118364D01* +G01X1425833Y9939174D01* +G03X1329542Y10126372I-96291J68834D01* +G03X1233251Y9939174I0J-118364D01* +G01X1171833Y9939174D01* +G03X1088147Y10125699I-96291J68834D01* +G03X966858Y9961128I-12605J-117691D01* +G01X855393Y10072593D01* +G03X815700Y10089034I-39693J-39693D01* +G01X308320Y10089034D01* +G03X218800Y10138564I-89520J-56134D01* +G01X168000Y10138564D01* +G03X98905Y10112843I0J-105664D01* +G01X167301Y10181238D01* +G01X168000Y10181236D01* +G01X218800Y10181236D01* +G03X218800Y10392564I0J105664D01* +G01X168000Y10392564D01* +G03X71392Y10244100I0J-105664D01* +G01X-68289Y10104419D01* +G03X-84730Y10064727I39693J-39693D01* +G01X-84730Y8780055D01* +G01X-242508Y8622278D01* +G03X-360196Y8425204I-33992J-113378D01* +G03X-163122Y8542892I83696J83696D01* +G01X11097Y8717111D01* +G03X27538Y8756804I-39693J39693D01* +G01X27538Y10041475D01* +G01X88057Y10101994D01* +G03X168000Y9927236I79943J-69094D01* +G01X218800Y9927236D01* +G03X308320Y9976766I0J105664D01* +G01X792448Y9976766D01* +G01X925867Y9843347D01* +G03X957178Y9827535I39693J39693D01* +G01X957178Y9671458D01* +G03X963624Y9650961I35814J0D01* +G01X782055Y9650961D01* +G01X750109Y9682906D01* +G03X773444Y9716476I-12479J33570D01* +G01X773444Y9854177D01* +G03X737630Y9889991I-35814J0D01* +G01X624377Y9889991D01* +G03X588563Y9854177I0J-35814D01* +G01X588563Y9716476D01* +G03X624377Y9680662I35814J0D01* +G01X624870Y9680662D01* +G01X624870Y9672627D01* +G03X641311Y9632934I56134J0D01* +G01X719111Y9555134D01* +G03X758804Y9538693I39693J39693D01* +G01X1170361Y9538693D01* +G01X-276500Y7628536D02* +G03X-276500Y7865264I0J118364D01* +G03X-276500Y7628536I0J-118364D01* +G01X-276500Y7882536D02* +G03X-276500Y8119264I0J118364D01* +G03X-276500Y7882536I0J-118364D01* +G01X-276500Y8136536D02* +G03X-276500Y8373264I0J118364D01* +G03X-276500Y8136536I0J-118364D01* +G01X-276500Y8644536D02* +G03X-276500Y8881264I0J118364D01* +G03X-276500Y8644536I0J-118364D01* +G01X-276500Y7374536D02* +G03X-276500Y7611264I0J118364D01* +G03X-276500Y7374536I0J-118364D01* +G01X218800Y12170564D02* +G01X168000Y12170564D01* +G03X168000Y11959236I0J-105664D01* +G01X218800Y11959236D01* +G03X218800Y12170564I0J105664D01* +G01X218800Y12424564D02* +G01X168000Y12424564D01* +G03X168000Y12213236I0J-105664D01* +G01X218800Y12213236D01* +G03X218800Y12424564I0J105664D01* +G01X288650Y12467236D02* +G03X324464Y12503050I0J35814D01* +G01X324464Y12642750D01* +G03X288650Y12678564I-35814J0D01* +G01X98150Y12678564D01* +G03X62336Y12642750I0J-35814D01* +G01X62336Y12503050D01* +G03X98150Y12467236I35814J0D01* +G01X288650Y12467236D01* +G01X218800Y11408564D02* +G01X168000Y11408564D01* +G03X168000Y11197236I0J-105664D01* +G01X218800Y11197236D01* +G03X218800Y11408564I0J105664D01* +G01X218800Y11662564D02* +G01X168000Y11662564D01* +G03X168000Y11451236I0J-105664D01* +G01X218800Y11451236D01* +G03X218800Y11662564I0J105664D01* +G01X218800Y11916564D02* +G01X168000Y11916564D01* +G03X168000Y11705236I0J-105664D01* +G01X218800Y11705236D01* +G03X218800Y11916564I0J105664D01* +G01X218800Y11154564D02* +G01X168000Y11154564D01* +G03X168000Y10943236I0J-105664D01* +G01X218800Y10943236D01* +G03X218800Y11154564I0J105664D01* +G01X218800Y10646564D02* +G01X168000Y10646564D01* +G03X168000Y10435236I0J-105664D01* +G01X218800Y10435236D01* +G03X218800Y10646564I0J105664D01* +G01X218800Y10900564D02* +G01X168000Y10900564D01* +G03X168000Y10689236I0J-105664D01* +G01X218800Y10689236D01* +G03X218800Y10900564I0J105664D01* +G01X218800Y7598564D02* +G01X168000Y7598564D01* +G03X168000Y7387236I0J-105664D01* +G01X218800Y7387236D01* +G03X218800Y7598564I0J105664D01* +G01X388563Y9729193D02* +G01X388563Y9716476D01* +G03X424377Y9680662I35814J0D01* +G01X537631Y9680662D01* +G03X573445Y9716476I0J35814D01* +G01X573445Y9854177D01* +G03X537631Y9889991I-35814J0D01* +G01X424377Y9889991D01* +G03X388563Y9854177I0J-35814D01* +G01X388563Y9841461D01* +G01X303953Y9841461D01* +G03X218800Y9884564I-85153J-62561D01* +G01X168000Y9884564D01* +G03X168000Y9673236I0J-105664D01* +G01X218800Y9673236D01* +G03X312042Y9729193I0J105664D01* +G01X388563Y9729193D01* +G01X218800Y9122564D02* +G01X168000Y9122564D01* +G03X168000Y8911236I0J-105664D01* +G01X218800Y8911236D01* +G03X218800Y9122564I0J105664D01* +G01X218800Y9376564D02* +G01X168000Y9376564D01* +G03X168000Y9165236I0J-105664D01* +G01X218800Y9165236D01* +G03X218800Y9376564I0J105664D01* +G01X218800Y9630564D02* +G01X168000Y9630564D01* +G03X168000Y9419236I0J-105664D01* +G01X218800Y9419236D01* +G03X218800Y9630564I0J105664D01* +G01X218800Y7344564D02* +G01X168000Y7344564D01* +G03X168000Y7133236I0J-105664D01* +G01X218800Y7133236D01* +G03X218800Y7344564I0J105664D01* +G01X1973178Y10008008D02* +G03X2209906Y10008008I118364J0D01* +G03X1973178Y10008008I-118364J0D01* +G01X2758800Y10392564D02* +G01X2708000Y10392564D01* +G03X2708000Y10181236I0J-105664D01* +G01X2758800Y10181236D01* +G03X2758800Y10392564I0J105664D01* +G01X2758800Y10138564D02* +G01X2708000Y10138564D01* +G03X2708000Y9927236I0J-105664D01* +G01X2758800Y9927236D01* +G03X2758800Y10138564I0J105664D01* +G01X2758800Y9884564D02* +G01X2708000Y9884564D01* +G03X2708000Y9673236I0J-105664D01* +G01X2758800Y9673236D01* +G03X2758800Y9884564I0J105664D01* +G01X2758800Y9122564D02* +G01X2708000Y9122564D01* +G03X2708000Y8911236I0J-105664D01* +G01X2758800Y8911236D01* +G03X2758800Y9122564I0J105664D01* +G01X2758800Y9376564D02* +G01X2708000Y9376564D01* +G03X2708000Y9165236I0J-105664D01* +G01X2758800Y9165236D01* +G03X2758800Y9376564I0J105664D01* +G01X2758800Y9630564D02* +G01X2708000Y9630564D01* +G03X2708000Y9419236I0J-105664D01* +G01X2758800Y9419236D01* +G03X2758800Y9630564I0J105664D01* +G01X2758800Y11154564D02* +G01X2708000Y11154564D01* +G03X2708000Y10943236I0J-105664D01* +G01X2758800Y10943236D01* +G03X2758800Y11154564I0J105664D01* +G01X2758800Y10646564D02* +G01X2708000Y10646564D01* +G03X2708000Y10435236I0J-105664D01* +G01X2758800Y10435236D01* +G03X2758800Y10646564I0J105664D01* +G01X2758800Y10900564D02* +G01X2708000Y10900564D01* +G03X2708000Y10689236I0J-105664D01* +G01X2758800Y10689236D01* +G03X2758800Y10900564I0J105664D01* +G01X2758800Y7598564D02* +G01X2708000Y7598564D01* +G03X2708000Y7387236I0J-105664D01* +G01X2758800Y7387236D01* +G03X2758800Y7598564I0J105664D01* +G01X2758800Y7344564D02* +G01X2708000Y7344564D01* +G03X2708000Y7133236I0J-105664D01* +G01X2758800Y7133236D01* +G03X2758800Y7344564I0J105664D01* +G01X2758800Y8868564D02* +G01X2708000Y8868564D01* +G03X2708000Y8657236I0J-105664D01* +G01X2758800Y8657236D01* +G03X2758800Y8868564I0J105664D01* +G01X2758800Y8614564D02* +G01X2708000Y8614564D01* +G03X2708000Y8403236I0J-105664D01* +G01X2758800Y8403236D01* +G03X2758800Y8614564I0J105664D01* +G01X2758800Y8360564D02* +G01X2708000Y8360564D01* +G03X2708000Y8149236I0J-105664D01* +G01X2758800Y8149236D01* +G03X2758800Y8360564I0J105664D01* +G01X2758800Y8106564D02* +G01X2708000Y8106564D01* +G03X2708000Y7895236I0J-105664D01* +G01X2758800Y7895236D01* +G03X2758800Y8106564I0J105664D01* +G01X2758800Y7852564D02* +G01X2708000Y7852564D01* +G03X2708000Y7641236I0J-105664D01* +G01X2758800Y7641236D01* +G03X2758800Y7852564I0J105664D01* +G01X3026770Y6318227D02* +G03X3043211Y6278534I56134J0D01* +G01X3353422Y5968323D01* +G03X3393115Y5951882I39693J39693D01* +G01X3471203Y5951882D01* +G03X3636610Y5906701I104207J56134D01* +G03X3673586Y6074133I-61200J101315D01* +G01X3683908Y6074133D01* +G01X3716032Y6042008D01* +G03X3913106Y5924320I113378J-33992D01* +G03X3795417Y6121394I-83696J83696D01* +G01X3746852Y6169959D01* +G03X3707159Y6186401I-39693J-39693D01* +G01X3666472Y6186401D01* +G03X3674121Y6327332I-91062J75615D01* +G03X3541417Y6375394I-98711J-65316D01* +G01X3443838Y6472973D01* +G01X3443838Y9078652D01* +G01X3782997Y9417811D01* +G03X3799438Y9457504I-39693J39693D01* +G01X3799438Y10187696D01* +G03X3782997Y10227389I-56134J0D01* +G01X3658235Y10352150D01* +G03X3632777Y10456466I-108235J28850D01* +G01X3682949Y10456466D01* +G01X3852270Y10287145D01* +G01X3852270Y9429955D01* +G01X3671647Y9249332D01* +G03X3655206Y9209640I39693J-39693D01* +G01X3655206Y8412380D01* +G01X3492860Y8412380D01* +G03X3457046Y8376566I0J-35814D01* +G01X3457046Y8211466D01* +G03X3492860Y8175652I35814J0D01* +G01X3655206Y8175652D01* +G01X3655206Y8127438D01* +G03X3457046Y8040016I-79796J-87422D01* +G03X3655206Y7952594I118364J0D01* +G01X3655206Y7904086D01* +G03X3671647Y7864393I56134J0D01* +G01X3716032Y7820008D01* +G03X3913106Y7702320I113378J-33992D01* +G03X3795417Y7899394I-83696J83696D01* +G01X3767474Y7927338D01* +G01X3767474Y7939150D01* +G03X3947774Y8040016I61936J100866D01* +G03X3767474Y8140882I-118364J0D01* +G01X3767474Y8193150D01* +G03X3931987Y8234957I61936J100866D01* +G03X3885544Y8398223I-102577J59059D01* +G01X3885544Y9073481D01* +G01X4125897Y9313834D01* +G03X4142338Y9353527I-39693J39693D01* +G01X4142338Y10147952D01* +G01X4267150Y10272765D01* +G03X4375206Y10460206I28850J108235D01* +G03X4187765Y10352150I-79206J-79206D01* +G01X4046511Y10210897D01* +G03X4030070Y10171204I39693J-39693D01* +G01X4030070Y9376778D01* +G01X3789717Y9136425D01* +G03X3773276Y9096733I39693J-39693D01* +G01X3773276Y8398223D01* +G03X3767474Y8394882I56134J-104207D01* +G01X3767474Y9186388D01* +G01X3948097Y9367011D01* +G03X3964538Y9406704I-39693J39693D01* +G01X3964538Y10310396D01* +G03X3948097Y10350089I-56134J0D01* +G01X3745893Y10552293D01* +G03X3706200Y10568734I-39693J-39693D01* +G01X3640310Y10568734D01* +G03X3550000Y10747014I-90310J66266D01* +G03X3459690Y10568734I0J-112014D01* +G01X3427600Y10568734D01* +G03X3387907Y10552293I0J-56134D01* +G01X3324850Y10489235D01* +G03X3216794Y10301794I-28850J-108235D01* +G03X3404235Y10409850I79206J79206D01* +G01X3450851Y10456466D01* +G01X3467223Y10456466D01* +G03X3454273Y10322831I82777J-75466D01* +G03X3578850Y10272765I95727J58168D01* +G01X3687170Y10164444D01* +G01X3687170Y9480755D01* +G01X3348011Y9141597D01* +G03X3331570Y9101904I39693J-39693D01* +G01X3331570Y6449722D01* +G03X3348011Y6410029I56134J0D01* +G01X3462032Y6296008D01* +G03X3484348Y6186401I113378J-33992D01* +G01X3459215Y6186401D01* +G01X3291438Y6354178D01* +G01X3291438Y9507079D01* +G03X3396560Y9569656I4562J111921D01* +G03X3381731Y9691093I-100560J49343D01* +G01X3424227Y9691093D01* +G03X3437986Y9692805I0J56134D01* +G01X3437986Y9542800D01* +G03X3473800Y9506986I35814J0D01* +G01X3626200Y9506986D01* +G03X3662014Y9542800I0J35814D01* +G01X3662014Y9695200D01* +G03X3626200Y9731014I-35814J0D01* +G01X3487399Y9731014D01* +G01X3521150Y9764765D01* +G03X3629206Y9952206I28850J108235D01* +G03X3441765Y9844150I-79206J-79206D01* +G01X3400975Y9803361D01* +G01X3383735Y9803361D01* +G03X3295292Y9985012I-87735J69639D01* +G03X3209152Y9802257I708J-112012D01* +G03X3180534Y9786919I11075J-55031D01* +G01X3043211Y9649597D01* +G03X3026770Y9609904I39693J-39693D01* +G01X3026770Y6318227D01* +G01X3296000Y10522986D02* +G03X3296000Y10747014I0J112014D01* +G03X3296000Y10522986I0J-112014D01* +G01X3296000Y10014986D02* +G03X3296000Y10239014I0J112014D01* +G03X3296000Y10014986I0J-112014D01* +G01X3550000Y10014986D02* +G03X3550000Y10239014I0J112014D01* +G03X3550000Y10014986I0J-112014D01* +G01X3575410Y6634380D02* +G03X3575410Y6397652I0J-118364D01* +G03X3575410Y6634380I0J118364D01* +G01X3575410Y7904380D02* +G03X3575410Y7667652I0J-118364D01* +G03X3575410Y7904380I0J118364D01* +G01X4239866Y7767857D02* +G01X3863402Y7391394D01* +G03X3745714Y7194320I-33992J-113378D01* +G03X3942788Y7312008I83696J83696D01* +G01X4335693Y7704913D01* +G03X4352134Y7744606I-39693J39693D01* +G01X4352134Y9522066D01* +G03X4360270Y9527258I-56134J96934D01* +G01X4360270Y7634261D01* +G01X3863402Y7137394D01* +G03X3731870Y7091068I-33992J-113378D01* +G03X3735729Y6951670I97540J-67052D01* +G01X3727141Y6951670D01* +G01X3688788Y6990023D01* +G03X3491714Y7107712I-113378J33992D01* +G03X3609402Y6910638I83696J-83696D01* +G01X3664197Y6855843D01* +G03X3703890Y6839402I39693J39693D01* +G01X3733516Y6839402D01* +G03X3732525Y6702021I95894J-69386D01* +G01X3722791Y6702021D01* +G01X3688788Y6736023D01* +G03X3491714Y6853712I-113378J33992D01* +G03X3609402Y6656638I83696J-83696D01* +G01X3659847Y6606194D01* +G03X3699539Y6589753I39693J39693D01* +G01X3736820Y6589753D01* +G03X3829410Y6397652I92590J-73737D01* +G03X3922000Y6589753I0J118364D01* +G01X3956664Y6589753D01* +G03X3996357Y6606194I0J56134D01* +G01X4786297Y7396134D01* +G03X4802738Y7435827I-39693J39693D01* +G01X4802738Y9930396D01* +G03X4786297Y9970089I-56134J0D01* +G01X4658235Y10098150D01* +G03X4470794Y10206206I-108235J28850D01* +G03X4578850Y10018765I79206J-79206D01* +G01X4690470Y9907144D01* +G01X4690470Y7459078D01* +G01X3933412Y6702021D01* +G01X3926295Y6702021D01* +G03X3925304Y6839402I-96885J67995D01* +G01X3952313Y6839402D01* +G03X3992006Y6855843I0J56134D01* +G01X4589693Y7453530D01* +G03X4606134Y7493223I-39693J39693D01* +G01X4606134Y9506986D01* +G01X4626200Y9506986D01* +G03X4662014Y9542800I0J35814D01* +G01X4662014Y9695200D01* +G03X4626200Y9731014I-35814J0D01* +G01X4487399Y9731014D01* +G01X4521150Y9764765D01* +G03X4629206Y9952206I28850J108235D01* +G03X4441765Y9844150I-79206J-79206D01* +G01X4376711Y9779097D01* +G03X4360270Y9739404I39693J-39693D01* +G01X4360270Y9710741D01* +G03X4201575Y9679258I-64270J-91742D01* +G03X4239866Y9522066I94425J-60258D01* +G01X4239866Y7767857D01* +G01X3575410Y7650380D02* +G03X3575410Y7413652I0J-118364D01* +G03X3575410Y7650380I0J118364D01* +G01X3575410Y7396380D02* +G03X3575410Y7159652I0J-118364D01* +G03X3575410Y7396380I0J118364D01* +G01X3829410Y6380380D02* +G03X3829410Y6143652I0J-118364D01* +G03X3829410Y6380380I0J118364D01* +G01X3829410Y7650380D02* +G03X3829410Y7413652I0J-118364D01* +G03X3829410Y7650380I0J118364D01* +G01X4296000Y9760986D02* +G03X4296000Y9985014I0J112014D01* +G03X4296000Y9760986I0J-112014D01* +G01X4296000Y10014986D02* +G03X4296000Y10239014I0J112014D01* +G03X4296000Y10014986I0J-112014D01* +G01X4296000Y10522986D02* +G03X4296000Y10747014I0J112014D01* +G03X4296000Y10522986I0J-112014D01* +G01X4550000Y10522986D02* +G03X4550000Y10747014I0J112014D01* +G03X4550000Y10522986I0J-112014D01* +G01X4550000Y10268986D02* +G03X4550000Y10493014I0J112014D01* +G03X4550000Y10268986I0J-112014D01* +G01X35814Y150000D02* +G01X35814Y827731D01* +G01X231431Y632114D01* +G03X266154Y615893I39693J39693D01* +G03X358362Y430186I92346J-69893D01* +G03X451012Y615673I138J115814D01* +G01X463442Y615673D01* +G01X496686Y582428D01* +G01X496686Y466000D01* +G03X532500Y430186I35814J0D01* +G01X692500Y430186D01* +G03X728314Y466000I0J35814D01* +G01X728314Y489866D01* +G01X881348Y489866D01* +G01X998181Y373034D01* +G03X1037873Y356593I39693J39693D01* +G01X2066727Y356593D01* +G03X2106419Y373034I0J56134D01* +G01X2163572Y430186D01* +G01X2280000Y430186D01* +G03X2315814Y466000I0J35814D01* +G01X2315814Y626000D01* +G03X2280000Y661814I-35814J0D01* +G01X2141199Y661814D01* +G01X2168062Y688677D01* +G03X2281893Y881893I31938J111323D01* +G03X2088677Y768062I-81893J-81893D01* +G01X2049748Y729134D01* +G01X2037602Y729134D01* +G03X2037602Y870866I-91602J70866D01* +G01X2073000Y870866D01* +G03X2112693Y887307I0J56134D01* +G01X2168062Y942677D01* +G03X2281893Y1135893I31938J111323D01* +G03X2088677Y1022062I-81893J-81893D01* +G01X2049748Y983134D01* +G01X2037602Y983134D01* +G03X2037602Y1124866I-91602J70866D01* +G01X2073000Y1124866D01* +G03X2112693Y1141307I0J56134D01* +G01X2168062Y1196677D01* +G03X2281893Y1389893I31938J111323D01* +G03X2088677Y1276062I-81893J-81893D01* +G01X2049748Y1237134D01* +G01X2037602Y1237134D01* +G03X2037602Y1378866I-91602J70866D01* +G01X2073000Y1378866D01* +G03X2112693Y1395307I0J56134D01* +G01X2168062Y1450677D01* +G03X2281893Y1643893I31938J111323D01* +G03X2088677Y1530062I-81893J-81893D01* +G01X2049748Y1491134D01* +G01X2037602Y1491134D01* +G03X2037602Y1632866I-91602J70866D01* +G01X2073000Y1632866D01* +G03X2112693Y1649307I0J56134D01* +G01X2168062Y1704677D01* +G03X2281893Y1897893I31938J111323D01* +G03X2088677Y1784062I-81893J-81893D01* +G01X2049748Y1745134D01* +G01X2037602Y1745134D01* +G03X2037602Y1886866I-91602J70866D01* +G01X2073000Y1886866D01* +G03X2112693Y1903307I0J56134D01* +G01X2168062Y1958677D01* +G03X2281893Y2151893I31938J111323D01* +G03X2088677Y2038062I-81893J-81893D01* +G01X2049748Y1999134D01* +G01X2037602Y1999134D01* +G03X2037602Y2140866I-91602J70866D01* +G01X2073000Y2140866D01* +G03X2112693Y2157307I0J56134D01* +G01X2168062Y2212677D01* +G03X2281893Y2405893I31938J111323D01* +G03X2088677Y2292062I-81893J-81893D01* +G01X2049748Y2253134D01* +G01X2037602Y2253134D01* +G03X2037602Y2394866I-91602J70866D01* +G01X2073000Y2394866D01* +G03X2112693Y2411307I0J56134D01* +G01X2168062Y2466677D01* +G03X2281893Y2659893I31938J111323D01* +G03X2088677Y2546062I-81893J-81893D01* +G01X2049748Y2507134D01* +G01X2037602Y2507134D01* +G03X2009685Y2674732I-91602J70866D01* +G03X1844699Y2634134I-63685J-96732D01* +G01X1588251Y2634134D01* +G01X1477693Y2744693D01* +G03X1438000Y2761134I-39693J-39693D01* +G01X690877Y2761134D01* +G03X612500Y2937664I-78377J70866D01* +G03X534123Y2761134I0J-105664D01* +G01X485500Y2761134D01* +G03X445807Y2744693I0J-56134D01* +G01X390438Y2689323D01* +G03X276607Y2496107I-31938J-111323D01* +G03X469823Y2609938I81893J81893D01* +G01X508751Y2648866D01* +G01X520898Y2648866D01* +G03X520898Y2507134I91602J-70866D01* +G01X485500Y2507134D01* +G03X445807Y2490693I0J-56134D01* +G01X390438Y2435323D01* +G03X276607Y2242107I-31938J-111323D01* +G03X469823Y2355938I81893J81893D01* +G01X508751Y2394866D01* +G01X520898Y2394866D01* +G03X520898Y2253134I91602J-70866D01* +G01X485500Y2253134D01* +G03X445807Y2236693I0J-56134D01* +G01X390438Y2181323D01* +G03X276607Y1988107I-31938J-111323D01* +G03X469823Y2101938I81893J81893D01* +G01X508751Y2140866D01* +G01X520898Y2140866D01* +G03X520898Y1999134I91602J-70866D01* +G01X485500Y1999134D01* +G03X445807Y1982693I0J-56134D01* +G01X390438Y1927323D01* +G03X276607Y1734107I-31938J-111323D01* +G03X469823Y1847938I81893J81893D01* +G01X508751Y1886866D01* +G01X520898Y1886866D01* +G03X520898Y1745134I91602J-70866D01* +G01X485500Y1745134D01* +G03X445807Y1728693I0J-56134D01* +G01X390438Y1673323D01* +G03X276607Y1480107I-31938J-111323D01* +G03X469823Y1593938I81893J81893D01* +G01X508751Y1632866D01* +G01X520898Y1632866D01* +G03X520898Y1491134I91602J-70866D01* +G01X485500Y1491134D01* +G03X445807Y1474693I0J-56134D01* +G01X390438Y1419323D01* +G03X276607Y1226107I-31938J-111323D01* +G03X469823Y1339938I81893J81893D01* +G01X508751Y1378866D01* +G01X520898Y1378866D01* +G03X520898Y1237134I91602J-70866D01* +G01X485500Y1237134D01* +G03X445807Y1220693I0J-56134D01* +G01X390438Y1165323D01* +G03X276607Y972107I-31938J-111323D01* +G03X469823Y1085938I81893J81893D01* +G01X508751Y1124866D01* +G01X520898Y1124866D01* +G03X520898Y983134I91602J-70866D01* +G01X485500Y983134D01* +G03X445807Y966693I0J-56134D01* +G01X390438Y911323D01* +G03X244912Y777404I-31938J-111323D01* +G01X106426Y915890D01* +G01X106426Y4033719D01* +G01X206031Y3934114D01* +G03X245724Y3917673I39693J39693D01* +G01X265987Y3917673D01* +G03X358500Y3732186I92513J-69673D01* +G03X451012Y3917673I0J115814D01* +G01X463442Y3917673D01* +G01X501177Y3879938D01* +G03X612500Y3732186I111323J-31938D01* +G03X723823Y3879938I0J115814D01* +G01X762751Y3918866D01* +G01X1078336Y3918866D01* +G01X1078336Y3777134D01* +G01X739500Y3777134D01* +G03X699807Y3760693I0J-56134D01* +G01X644438Y3705323D01* +G03X530607Y3512107I-31938J-111323D01* +G03X723823Y3625938I81893J81893D01* +G01X762751Y3664866D01* +G01X1101895Y3664866D01* +G03X1101895Y3523134I94805J-70866D01* +G01X739500Y3523134D01* +G03X699807Y3506693I0J-56134D01* +G01X644438Y3451323D01* +G03X530607Y3258107I-31938J-111323D01* +G03X723823Y3371938I81893J81893D01* +G01X762751Y3410866D01* +G01X1473673Y3410866D01* +G03X1491086Y3248848I104027J-70764D01* +G01X1491086Y3200300D01* +G03X1516455Y3139055I86614J0D01* +G01X1830391Y2825118D01* +G03X2027893Y2750107I115609J6881D01* +G03X1952881Y2947609I-81893J81893D01* +G01X1929059Y2971432D01* +G03X2027893Y3167893I16941J114568D01* +G03X1831432Y3069059I-81893J-81893D01* +G01X1664314Y3236177D01* +G01X1664314Y3248848D01* +G03X1681726Y3410866I-86614J91253D01* +G01X1854398Y3410866D01* +G03X1946000Y3224186I91602J-70866D01* +G03X2037602Y3410866I0J115814D01* +G01X2049748Y3410866D01* +G01X2088677Y3371938D01* +G03X2281893Y3258107I111323J-31938D01* +G03X2168062Y3451323I-81893J81893D01* +G01X2112693Y3506693D01* +G03X2073000Y3523134I-39693J-39693D01* +G01X2037602Y3523134D01* +G03X2037602Y3664866I-91602J70866D01* +G01X2049748Y3664866D01* +G01X2088677Y3625938D01* +G03X2281893Y3512107I111323J-31938D01* +G03X2168062Y3705323I-81893J81893D01* +G01X2112693Y3760693D01* +G03X2073000Y3777134I-39693J-39693D01* +G01X2037602Y3777134D01* +G03X2037602Y3918866I-91602J70866D01* +G01X2049748Y3918866D01* +G01X2088677Y3879938D01* +G03X2281893Y3766107I111323J-31938D01* +G03X2168062Y3959323I-81893J81893D01* +G01X2112693Y4014693D01* +G03X2073000Y4031134I-39693J-39693D01* +G01X2037602Y4031134D01* +G03X1946000Y4217814I-91602J70866D01* +G03X1854398Y4031134I0J-115814D01* +G01X739500Y4031134D01* +G03X699807Y4014693I0J-56134D01* +G01X644438Y3959323D01* +G03X580562Y3959323I-31938J-111323D01* +G01X526386Y4013499D01* +G03X486693Y4029941I-39693J-39693D01* +G01X449166Y4029941D01* +G03X361412Y4217777I-90666J72059D01* +G03X264326Y4034590I-2912J-115777D01* +G01X192638Y4106278D01* +G01X192638Y4773007D01* +G01X274611Y4691034D01* +G01X275196Y4690457D01* +G03X348300Y4494636I83304J-80457D01* +G03X454628Y4674593I10200J115364D01* +G01X468522Y4674593D01* +G01X501177Y4641938D01* +G03X568180Y4503002I111323J-31938D01* +G03X713801Y4553866I44320J106998D01* +G01X1109948Y4553866D01* +G01X1220507Y4443307D01* +G03X1260200Y4426866I39693J39693D01* +G01X1854398Y4426866D01* +G03X1946000Y4240186I91602J-70866D01* +G03X2037602Y4426866I0J115814D01* +G01X2073000Y4426866D01* +G03X2112693Y4443307I0J56134D01* +G01X2168062Y4498677D01* +G03X2281893Y4691893I31938J111323D01* +G03X2088677Y4578062I-81893J-81893D01* +G01X2049748Y4539134D01* +G01X2037602Y4539134D01* +G03X2037602Y4680866I-91602J70866D01* +G01X2073000Y4680866D01* +G03X2112693Y4697307I0J56134D01* +G01X2168062Y4752677D01* +G03X2311323Y4895938I31938J111323D01* +G01X2411397Y4996011D01* +G03X2418186Y5004232I-39693J39693D01* +G01X2418186Y150000D01* +G02X2304000Y35814I-114186J0D01* +G01X150000Y35814D01* +G02X35814Y150000I0J114186D01* +G01X358500Y3478186D02* +G03X358500Y3709814I0J115814D01* +G03X358500Y3478186I0J-115814D01* +G01X358500Y4240186D02* +G03X358500Y4471814I0J115814D01* +G03X358500Y4240186I0J-115814D01* +G01X358500Y3224186D02* +G03X358500Y3455814I0J115814D01* +G03X358500Y3224186I0J-115814D01* +G01X358500Y2970186D02* +G03X358500Y3201814I0J115814D01* +G03X358500Y2970186I0J-115814D01* +G01X358500Y2716186D02* +G03X358500Y2947814I0J115814D01* +G03X358500Y2716186I0J-115814D01* +G01X612500Y3986186D02* +G03X612500Y4217814I0J115814D01* +G03X612500Y3986186I0J-115814D01* +G01X612500Y4240186D02* +G03X612500Y4471814I0J115814D01* +G03X612500Y4240186I0J-115814D01* +G01X612500Y2980336D02* +G03X612500Y3191664I0J105664D01* +G03X612500Y2980336I0J-105664D01* +G01X1577700Y4335916D02* +G03X1577700Y4084289I0J-125814D01* +G03X1577700Y4335916I0J125814D01* +G01X2200000Y4240186D02* +G03X2200000Y4471814I0J115814D01* +G03X2200000Y4240186I0J-115814D01* +G01X2200000Y3986186D02* +G03X2200000Y4217814I0J115814D01* +G03X2200000Y3986186I0J-115814D01* +G01X2200000Y2716186D02* +G03X2200000Y2947814I0J115814D01* +G03X2200000Y2716186I0J-115814D01* +G01X2200000Y2970186D02* +G03X2200000Y3201814I0J115814D01* +G03X2200000Y2970186I0J-115814D01* +G01X944293Y585693D02* +G03X904600Y602134I-39693J-39693D01* +G01X728314Y602134D01* +G01X728314Y626000D01* +G03X692500Y661814I-35814J0D01* +G01X576072Y661814D01* +G01X526386Y711499D01* +G03X486693Y727941I-39693J-39693D01* +G01X449166Y727941D01* +G03X469823Y831938I-90666J72059D01* +G01X508751Y870866D01* +G01X520898Y870866D01* +G03X548815Y703268I91602J-70866D01* +G03X713801Y743866I63685J96732D01* +G01X932148Y743866D01* +G01X1042707Y633307D01* +G03X1082400Y616866I39693J39693D01* +G01X1854398Y616866D01* +G03X1859615Y468861I91602J-70866D01* +G01X1061125Y468861D01* +G01X944293Y585693D01* +G01X1854398Y3523134D02* +G01X1291505Y3523134D01* +G03X1291505Y3664866I-94805J70866D01* +G01X1854398Y3664866D01* +G03X1854398Y3523134I91602J-70866D01* +G01X2037602Y616866D02* +G01X2073000Y616866D01* +G03X2084186Y617992I0J56134D01* +G01X2084186Y509572D01* +G01X2043475Y468861D01* +G01X2032385Y468861D01* +G03X2037602Y616866I-86385J77139D01* +G54D11* +G01X612500Y2832000D02* +G01X612500Y2927504D01* +G01X612500Y2832000D02* +G01X516996Y2832000D01* +G01X612500Y2832000D02* +G01X708004Y2832000D01* +G01X358500Y3086000D02* +G01X358500Y2980346D01* +G01X358500Y3086000D02* +G01X358500Y3191654D01* +G01X358500Y3086000D02* +G01X252846Y3086000D01* +G01X358500Y3086000D02* +G01X464154Y3086000D01* +G01X358500Y3340000D02* +G01X358500Y3234346D01* +G01X358500Y3340000D02* +G01X358500Y3445654D01* +G01X358500Y3340000D02* +G01X252846Y3340000D01* +G01X358500Y3340000D02* +G01X464154Y3340000D01* +G01X358500Y3594000D02* +G01X358500Y3488346D01* +G01X358500Y3594000D02* +G01X358500Y3699654D01* +G01X358500Y3594000D02* +G01X252846Y3594000D01* +G01X358500Y3594000D02* +G01X464154Y3594000D01* +G01X358500Y4102000D02* +G01X358500Y4207654D01* +G01X358500Y4102000D02* +G01X252846Y4102000D01* +G01X358500Y4102000D02* +G01X464154Y4102000D01* +G01X1946000Y546000D02* +G01X1840346Y546000D01* +G01X1946000Y546000D02* +G01X2051654Y546000D01* +G01X1946000Y3086000D02* +G01X1946000Y2980346D01* +G01X1946000Y3086000D02* +G01X1946000Y3191654D01* +G01X1946000Y3086000D02* +G01X1840346Y3086000D01* +G01X1946000Y3086000D02* +G01X2051654Y3086000D01* +G01X1946000Y5372000D02* +G01X1946000Y5477654D01* +G01X1946000Y5372000D02* +G01X1840346Y5372000D01* +G01X1946000Y5372000D02* +G01X2051654Y5372000D01* +G01X1946000Y4102000D02* +G01X1946000Y4207654D01* +G01X1946000Y4102000D02* +G01X1840346Y4102000D01* +G01X1946000Y4102000D02* +G01X2051654Y4102000D01* +G01X1946000Y3594000D02* +G01X1840346Y3594000D01* +G01X1946000Y3594000D02* +G01X2051654Y3594000D01* +G01X1946000Y3340000D02* +G01X1946000Y3234346D01* +G01X1946000Y3340000D02* +G01X1840346Y3340000D01* +G01X1946000Y3340000D02* +G01X2051654Y3340000D01* +G01X2200000Y2832000D02* +G01X2200000Y2726346D01* +G01X2200000Y2832000D02* +G01X2200000Y2937654D01* +G01X2200000Y2832000D02* +G01X2094346Y2832000D01* +G01X2200000Y2832000D02* +G01X2305654Y2832000D01* +G01X358500Y5372000D02* +G01X358500Y5266346D01* +G01X358500Y5372000D02* +G01X358500Y5477654D01* +G01X358500Y5372000D02* +G01X464154Y5372000D01* +G01X3575410Y6516016D02* +G01X3575410Y6624220D01* +G01X3575410Y6516016D02* +G01X3575410Y6407812D01* +G01X3575410Y6516016D02* +G01X3683614Y6516016D01* +G01X3575410Y6516016D02* +G01X3467206Y6516016D01* +G01X2733400Y7238900D02* +G01X2612496Y7238900D01* +G01X2733400Y7238900D02* +G01X2854304Y7238900D01* +G01X2733400Y7238900D02* +G01X2733400Y7334404D01* +G01X2733400Y7238900D02* +G01X2733400Y7143396D01* +G01X-276500Y8000900D02* +G01X-276500Y7892696D01* +G01X-276500Y8000900D02* +G01X-276500Y8109104D01* +G01X-276500Y8000900D02* +G01X-384704Y8000900D01* +G01X-276500Y8000900D02* +G01X-168296Y8000900D01* +G01X2091542Y10008008D02* +G01X1983338Y10008008D01* +G01X2091542Y10008008D02* +G01X2199746Y10008008D01* +G01X2091542Y10008008D02* +G01X2091542Y10116212D01* +G01X2091542Y10008008D02* +G01X2091542Y9899804D01* +G01X1075542Y10008008D02* +G01X967338Y10008008D01* +G01X1075542Y10008008D02* +G01X1183746Y10008008D01* +G01X1075542Y10008008D02* +G01X1075542Y10116212D01* +G01X3296000Y10127000D02* +G01X3296000Y10025146D01* +G01X3296000Y10127000D02* +G01X3296000Y10228854D01* +G01X3296000Y10127000D02* +G01X3194146Y10127000D01* +G01X3296000Y10127000D02* +G01X3397854Y10127000D01* +G01X2733400Y7492900D02* +G01X2612496Y7492900D01* +G01X2733400Y7492900D02* +G01X2854304Y7492900D01* +G01X2733400Y7492900D02* +G01X2733400Y7588404D01* +G01X2733400Y7492900D02* +G01X2733400Y7397396D01* +G01X4296000Y10127000D02* +G01X4296000Y10025146D01* +G01X4296000Y10127000D02* +G01X4296000Y10228854D01* +G01X4296000Y10127000D02* +G01X4194146Y10127000D01* +G01X4296000Y10127000D02* +G01X4397854Y10127000D01* +G01X2733400Y12572900D02* +G01X2612496Y12572900D01* +G01X2733400Y12572900D02* +G01X2733400Y12668404D01* +G01X2733400Y12572900D02* +G01X2733400Y12477396D01* +G01X193400Y7238900D02* +G01X72496Y7238900D01* +G01X193400Y7238900D02* +G01X314304Y7238900D01* +G01X193400Y7238900D02* +G01X193400Y7334404D01* +G01X193400Y7238900D02* +G01X193400Y7143396D01* +G04 Copper End* + +G04 Pad Start* +G54D12* +G01X1196700Y3594000D03* +G54D13* +G01X1196700Y3848000D03* +G54D14* +G01X481004Y9785327D03* +G01X681004Y9785327D03* +G01X749584Y8256247D03* +G01X549584Y8256247D03* +G54D15* +G01X2733400Y12572900D03* +G01X2733400Y12318900D03* +G01X2733400Y12064900D03* +G01X2733400Y11810900D03* +G01X2733400Y11556900D03* +G01X2733400Y11302900D03* +G01X2733400Y11048900D03* +G01X2733400Y10794900D03* +G01X2733400Y10540900D03* +G01X2733400Y10286900D03* +G01X2733400Y10032900D03* +G01X2733400Y9778900D03* +G01X2733400Y9524900D03* +G01X2733400Y9270900D03* +G01X2733400Y9016900D03* +G01X2733400Y8762900D03* +G01X2733400Y8508900D03* +G01X2733400Y8254900D03* +G01X2733400Y8000900D03* +G01X2733400Y7746900D03* +G01X2733400Y7492900D03* +G01X2733400Y7238900D03* +G01X193400Y7238900D03* +G01X193400Y7492900D03* +G01X193400Y7746900D03* +G01X193400Y8000900D03* +G01X193400Y8254900D03* +G01X193400Y8508900D03* +G01X193400Y8762900D03* +G01X193400Y9016900D03* +G01X193400Y9270900D03* +G01X193400Y9524900D03* +G01X193400Y9778900D03* +G01X193400Y10032900D03* +G01X193400Y10286900D03* +G01X193400Y10540900D03* +G01X193400Y10794900D03* +G01X193400Y11048900D03* +G01X193400Y11302900D03* +G01X193400Y11556900D03* +G01X193400Y11810900D03* +G01X193400Y12064900D03* +G01X193400Y12318900D03* +G54D17* +G01X193400Y12572900D03* +G54D12* +G01X-276500Y7492900D03* +G01X-276500Y7746900D03* +G01X-276500Y8000900D03* +G01X-276500Y8254900D03* +G01X-276500Y8508900D03* +G01X-276500Y8762900D03* +G01X-276500Y9016900D03* +G01X-276500Y9270900D03* +G01X-276500Y9524900D03* +G01X-2308500Y9016900D03* +G01X-2308500Y8762900D03* +G01X-2308500Y8508900D03* +G01X-2308500Y8254900D03* +G01X-2308500Y8000900D03* +G01X-2308500Y7746900D03* +G54D18* +G01X1946000Y5372000D03* +G01X2200000Y5372000D03* +G01X1946000Y5118000D03* +G01X2200000Y5118000D03* +G01X1946000Y4864000D03* +G01X2200000Y4864000D03* +G01X1946000Y4610000D03* +G01X2200000Y4610000D03* +G01X1946000Y4356000D03* +G01X2200000Y4356000D03* +G01X1946000Y4102000D03* +G01X2200000Y4102000D03* +G01X1946000Y3848000D03* +G01X2200000Y3848000D03* +G01X1946000Y3594000D03* +G01X2200000Y3594000D03* +G01X1946000Y3340000D03* +G01X2200000Y3340000D03* +G01X1946000Y3086000D03* +G01X2200000Y3086000D03* +G01X1946000Y2832000D03* +G01X2200000Y2832000D03* +G01X1946000Y2578000D03* +G01X2200000Y2578000D03* +G01X1946000Y2324000D03* +G01X2200000Y2324000D03* +G01X1946000Y2070000D03* +G01X2200000Y2070000D03* +G01X1946000Y1816000D03* +G01X2200000Y1816000D03* +G01X1946000Y1562000D03* +G01X2200000Y1562000D03* +G01X1946000Y1308000D03* +G01X2200000Y1308000D03* +G01X1946000Y1054000D03* +G01X2200000Y1054000D03* +G01X1946000Y800000D03* +G01X2200000Y800000D03* +G01X1946000Y546000D03* +G54D19* +G01X2200000Y546000D03* +G01X612500Y546000D03* +G54D18* +G01X358500Y546000D03* +G01X612500Y800000D03* +G01X358500Y800000D03* +G01X612500Y1054000D03* +G01X358500Y1054000D03* +G01X612500Y1308000D03* +G01X358500Y1308000D03* +G01X612500Y1562000D03* +G01X358500Y1562000D03* +G01X612500Y1816000D03* +G01X358500Y1816000D03* +G01X612500Y2070000D03* +G01X358500Y2070000D03* +G01X612500Y2324000D03* +G01X358500Y2324000D03* +G01X612500Y2578000D03* +G01X358500Y2578000D03* +G54D20* +G01X612500Y2832000D03* +G54D18* +G01X358500Y2832000D03* +G54D20* +G01X612500Y3086000D03* +G54D18* +G01X358500Y3086000D03* +G01X612500Y3340000D03* +G01X358500Y3340000D03* +G01X612500Y3594000D03* +G01X358500Y3594000D03* +G01X612500Y3848000D03* +G01X358500Y3848000D03* +G01X612500Y4102000D03* +G01X358500Y4102000D03* +G01X612500Y4356000D03* +G01X358500Y4356000D03* +G01X612500Y4610000D03* +G01X358500Y4610000D03* +G01X612500Y4864000D03* +G01X358500Y4864000D03* +G01X612500Y5118000D03* +G01X358500Y5118000D03* +G01X612500Y5372000D03* +G01X358500Y5372000D03* +G54D12* +G01X3829410Y6008016D03* +G01X3575410Y6008016D03* +G01X3829410Y6262016D03* +G01X3575410Y6262016D03* +G01X3829410Y6516016D03* +G01X3575410Y6516016D03* +G01X3829410Y6770016D03* +G01X3575410Y6770016D03* +G01X3829410Y7024016D03* +G01X3575410Y7024016D03* +G01X3829410Y7278016D03* +G01X3575410Y7278016D03* +G01X3829410Y7532016D03* +G01X3575410Y7532016D03* +G01X3829410Y7786016D03* +G01X3575410Y7786016D03* +G01X3829410Y8040016D03* +G01X3575410Y8040016D03* +G01X3829410Y8294016D03* +G54D13* +G01X3575410Y8294016D03* +G54D21* +G01X3550000Y9619000D03* +G54D22* +G01X3296000Y9619000D03* +G01X3550000Y9873000D03* +G01X3296000Y9873000D03* +G01X3550000Y10127000D03* +G01X3296000Y10127000D03* +G01X3550000Y10381000D03* +G01X3296000Y10381000D03* +G01X3550000Y10635000D03* +G01X3296000Y10635000D03* +G54D12* +G01X2091542Y10008008D03* +G01X2091542Y9754008D03* +G01X1837542Y10008008D03* +G01X1837542Y9754008D03* +G01X1583542Y10008008D03* +G01X1583542Y9754008D03* +G01X1329542Y10008008D03* +G01X1329542Y9754008D03* +G01X1075542Y10008008D03* +G54D13* +G01X1075542Y9754008D03* +G54D21* +G01X4550000Y9619000D03* +G54D22* +G01X4296000Y9619000D03* +G01X4550000Y9873000D03* +G01X4296000Y9873000D03* +G01X4550000Y10127000D03* +G01X4296000Y10127000D03* +G01X4550000Y10381000D03* +G01X4296000Y10381000D03* +G01X4550000Y10635000D03* +G01X4296000Y10635000D03* +G54D13* +G01X-2308500Y10782200D03* +G54D12* +G01X-2054500Y10782200D03* +G01X-1800500Y10782200D03* +G01X-1546500Y10782200D03* +G54D23* +G01X1577700Y4210102D03* +G01X1577700Y3340102D03* +G04 Pad End* + +G04 Track Start* +G54D24* +G01X2091542Y9754008D02* +G01X1962510Y9883040D01* +G01X965560Y9883040D01* +G01X612500Y5372000D02* +G01X1234800Y5372000D01* +G01X1361800Y5245000D01* +G01X2073000Y5245000D01* +G01X2200000Y5372000D01* +G01X612500Y5118000D02* +G01X1184000Y5118000D01* +G01X1311000Y4991000D01* +G01X2073000Y4991000D01* +G01X2200000Y5118000D01* +G01X358500Y5118000D02* +G01X485500Y5245000D01* +G01X1209400Y5245000D01* +G01X1336400Y5118000D01* +G01X1946000Y5118000D01* +G01X358500Y4864000D02* +G01X485500Y4991000D01* +G01X1158600Y4991000D02* +G01X1285600Y4864000D01* +G01X1946000Y4864000D01* +G01X485500Y4991000D02* +G01X1158600Y4991000D01* +G01X612500Y4864000D02* +G01X1133200Y4864000D01* +G01X2073000Y4737000D02* +G01X2200000Y4864000D01* +G01X1133200Y4864000D02* +G01X1260200Y4737000D01* +G01X2073000Y4737000D01* +G01X612500Y4610000D02* +G01X1133200Y4610000D01* +G01X1260200Y4483000D01* +G01X2073000Y4483000D01* +G01X2200000Y4610000D01* +G01X612500Y3848000D02* +G01X739500Y3975000D01* +G01X2073000Y3975000D02* +G01X2200000Y3848000D01* +G01X739500Y3975000D02* +G01X2073000Y3975000D01* +G01X612500Y3594000D02* +G01X739500Y3721000D01* +G01X2073000Y3721000D02* +G01X2200000Y3594000D01* +G01X739500Y3721000D02* +G01X2073000Y3721000D01* +G01X612500Y3340000D02* +G01X739500Y3467000D01* +G01X2073000Y3467000D02* +G01X2200000Y3340000D01* +G01X739500Y3467000D02* +G01X2073000Y3467000D01* +G01X358500Y2578000D02* +G01X485500Y2705000D01* +G01X2073000Y2451000D02* +G01X2200000Y2578000D01* +G01X358500Y2324000D02* +G01X485500Y2451000D01* +G01X2073000Y2197000D02* +G01X2200000Y2324000D01* +G01X358500Y2070000D02* +G01X485500Y2197000D01* +G01X2073000Y1943000D02* +G01X2200000Y2070000D01* +G01X358500Y1816000D02* +G01X485500Y1943000D01* +G01X2073000Y1689000D02* +G01X2200000Y1816000D01* +G01X358500Y1562000D02* +G01X485500Y1689000D01* +G01X2073000Y1435000D02* +G01X2200000Y1562000D01* +G01X358500Y1308000D02* +G01X485500Y1435000D01* +G01X1933300Y1295300D02* +G01X1946000Y1308000D01* +G01X358500Y1054000D02* +G01X485500Y1181000D01* +G01X2073000Y1181000D02* +G01X2200000Y1308000D01* +G01X2073000Y927000D02* +G01X2200000Y1054000D01* +G01X358500Y800000D02* +G01X485500Y927000D01* +G01X2073000Y673000D02* +G01X2200000Y800000D01* +G01X485500Y1943000D02* +G01X1272900Y1943000D01* +G01X1399900Y1816000D01* +G01X1946000Y1816000D01* +G01X612500Y2070000D02* +G01X1298300Y2070000D01* +G01X1425300Y1943000D01* +G01X2073000Y1943000D01* +G01X485500Y2197000D02* +G01X1336400Y2197000D01* +G01X1463400Y2070000D01* +G01X1946000Y2070000D01* +G01X612500Y2324000D02* +G01X1361800Y2324000D01* +G01X1488800Y2197000D01* +G01X2073000Y2197000D01* +G01X485500Y2451000D02* +G01X1387200Y2451000D01* +G01X1514200Y2324000D01* +G01X1946000Y2324000D01* +G01X612500Y2578000D02* +G01X1412600Y2578000D01* +G01X1539600Y2451000D01* +G01X2073000Y2451000D01* +G01X485500Y2705000D02* +G01X1438000Y2705000D01* +G01X1565000Y2578000D01* +G01X1946000Y2578000D01* +G01X612500Y1816000D02* +G01X1234800Y1816000D01* +G01X1361800Y1689000D01* +G01X2073000Y1689000D01* +G01X485500Y1689000D02* +G01X1196700Y1689000D01* +G01X1323700Y1562000D01* +G01X1946000Y1562000D01* +G01X612500Y1562000D02* +G01X1158600Y1562000D01* +G01X1285600Y1435000D01* +G01X2073000Y1435000D01* +G01X485500Y1435000D02* +G01X1133200Y1435000D01* +G01X1272900Y1295300D01* +G01X1933300Y1295300D01* +G01X612500Y1308000D02* +G01X1107800Y1308000D01* +G01X1234800Y1181000D01* +G01X2073000Y1181000D01* +G01X485500Y1181000D02* +G01X1069700Y1181000D01* +G01X1196700Y1054000D01* +G01X1946000Y1054000D01* +G01X612500Y1054000D02* +G01X1031600Y1054000D01* +G01X1158600Y927000D01* +G01X2073000Y927000D01* +G01X485500Y927000D02* +G01X993500Y927000D01* +G01X1120500Y800000D01* +G01X1946000Y800000D01* +G01X612500Y800000D02* +G01X955400Y800000D01* +G01X1082400Y673000D01* +G01X2073000Y673000D01* +G54D25* +G01X1946000Y2832000D02* +G01X1577700Y3200300D01* +G01X1577700Y3340102D01* +G54D24* +G01X612500Y546000D02* +G01X904600Y546000D01* +G01X4416404Y7611010D02* +G01X3829410Y7024016D01* +G01X3575410Y7024016D02* +G01X3703890Y6895536D01* +G01X3952313Y6895536D01* +G01X3711340Y7904086D02* +G01X3829410Y7786016D01* +G01X3956664Y6645887D02* +G01X3699539Y6645887D01* +G01X3575410Y6770016D01* +G01X3435964Y6130267D02* +G01X3707159Y6130267D01* +G01X3829410Y6008016D01* +G01X3575410Y6008016D02* +G01X3393115Y6008016D01* +G01X486693Y3973807D02* +G01X612500Y3848000D01* +G01X245724Y3973807D02* +G01X486693Y3973807D01* +G01X491773Y4730727D02* +G01X612500Y4610000D01* +G01X193400Y8254900D02* +G01X548237Y8254900D01* +G01X549584Y8256247D01* +G01X136504Y6826227D02* +G01X136504Y4083027D01* +G01X245724Y3973807D01* +G01X225404Y4819627D02* +G01X314304Y4730727D01* +G01X491773Y4730727D01* +G01X486693Y671807D02* +G01X612500Y546000D01* +G01X50292Y6785438D02* +G01X50292Y892638D01* +G01X271124Y671807D01* +G01X486693Y671807D01* +G01X904600Y546000D02* +G01X1037873Y412727D01* +G01X2066727Y412727D01* +G01X2200000Y546000D01* +G01X2371704Y5035704D02* +G01X2200000Y4864000D01* +G01X749584Y8256247D02* +G01X916284Y8256247D01* +G01X2371704Y6800827D01* +G01X2371704Y5035704D01* +G01X3235304Y6330927D02* +G01X3435964Y6130267D01* +G01X3575410Y6262016D02* +G01X3387704Y6449722D01* +G01X3393115Y6008016D02* +G01X3082904Y6318227D01* +G01X4086204Y9353527D02* +G01X3829410Y9096733D01* +G01X3829410Y8294016D01* +G01X193400Y8000900D02* +G01X390504Y7803796D01* +G01X193400Y8762723D02* +G01X-92096Y8477227D01* +G01X-92096Y6927827D01* +G01X50292Y6785438D01* +G01X390504Y7803796D02* +G01X390504Y6991327D01* +G01X225404Y6826227D01* +G01X225404Y4819627D01* +G01X-276500Y8508900D02* +G01X-28596Y8756804D01* +G01X-28596Y10064727D01* +G01X193400Y10286723D01* +G01X965560Y9883040D02* +G01X815700Y10032900D01* +G01X193400Y10032900D01* +G01X193400Y9778900D02* +G01X199827Y9785327D01* +G01X481004Y9785327D01* +G01X681004Y9785327D02* +G01X681004Y9672627D01* +G01X758804Y9594827D01* +G01X1170361Y9594827D01* +G01X1329542Y9754008D01* +G01X4746604Y7435827D02* +G01X3956664Y6645887D01* +G01X3952313Y6895536D02* +G01X4550000Y7493223D01* +G01X4550000Y9619000D01* +G01X4296000Y9619000D02* +G01X4296000Y7744606D01* +G01X3829410Y7278016D01* +G01X4550000Y9873000D02* +G01X4416404Y9739404D01* +G01X4416404Y7611010D01* +G01X4550000Y10127000D02* +G01X4746604Y9930396D01* +G01X4746604Y7435827D01* +G01X4296000Y10381000D02* +G01X4086204Y10171204D01* +G01X4086204Y9353527D01* +G01X3296000Y9619000D02* +G01X3235304Y9558304D01* +G01X3235304Y6330927D01* +G01X3743304Y10187696D02* +G01X3550000Y10381000D01* +G01X3296000Y10381000D02* +G01X3427600Y10512600D01* +G01X3706200Y10512600D01* +G01X3908404Y10310396D01* +G01X3908404Y9406704D01* +G01X3711340Y9209640D01* +G01X3711340Y7904086D01* +G01X3424227Y9747227D02* +G01X3550000Y9873000D01* +G01X3082904Y6318227D02* +G01X3082904Y9609904D01* +G01X3220227Y9747227D01* +G01X3424227Y9747227D01* +G01X3387704Y6449722D02* +G01X3387704Y9101904D01* +G01X3743304Y9457504D01* +G01X3743304Y10187696D01* +G01X193400Y8508723D02* +G01X-2200Y8313123D01* +G01X-2200Y6964930D01* +G01X136504Y6826227D01* +G01X-276500Y9016900D02* +G01X-543200Y9016900D01* +G01X-2308500Y10782200D01* +G01X-2067200Y10782200D02* +G01X-1800500Y10782200D01* +G01X-276500Y9270900D02* +G01X-289200Y9270900D01* +G01X-1800500Y10782200D01* +G01X-276500Y9524900D02* +G01X-289200Y9524900D01* +G01X-1546500Y10782200D01* +G04 Track End* + +M02* + diff --git a/hardware/gerber/Gerber_BottomPasteMaskLayer.GBP b/hardware/gerber/Gerber_BottomPasteMaskLayer.GBP new file mode 100644 index 0000000..15d628f --- /dev/null +++ b/hardware/gerber/Gerber_BottomPasteMaskLayer.GBP @@ -0,0 +1,85 @@ +G04 Layer: BottomPasteMaskLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%ADD10C,0.254*% +%ADD11C,0.8675*% +G75* + + +G04 PolygonModel Start* +G36* +G01X751006Y9721326D02* +G01X746005Y9716325D01* +G01X631004Y9716325D01* +G01X626005Y9721326D01* +G01X626503Y9763323D01* +G01X670503Y9763323D01* +G01X670503Y9808321D01* +G01X625502Y9808321D01* +G01X626005Y9849324D01* +G01X631004Y9854326D01* +G01X746005Y9854326D01* +G01X751006Y9849324D01* +G01X751006Y9721326D01* +G37* +G36* +G01X536005Y9721326D02* +G01X531004Y9716325D01* +G01X416006Y9716325D01* +G01X411004Y9721326D01* +G01X411004Y9849324D01* +G01X416006Y9854326D01* +G01X531004Y9854326D01* +G01X536005Y9849324D01* +G01X535502Y9808321D01* +G01X491504Y9808321D01* +G01X491504Y9763323D01* +G01X536003Y9763323D01* +G01X536005Y9721326D01* +G37* +G36* +G01X479582Y8320247D02* +G01X484583Y8325248D01* +G01X599584Y8325248D01* +G01X604583Y8320247D01* +G01X604085Y8278251D01* +G01X560084Y8278251D01* +G01X560084Y8233252D01* +G01X605086Y8233252D01* +G01X604583Y8192249D01* +G01X599584Y8187247D01* +G01X484583Y8187247D01* +G01X479582Y8192249D01* +G01X479582Y8320247D01* +G37* +G36* +G01X694583Y8320247D02* +G01X699584Y8325248D01* +G01X814582Y8325248D01* +G01X819584Y8320247D01* +G01X819584Y8192249D01* +G01X814582Y8187247D01* +G01X699584Y8187247D01* +G01X694583Y8192249D01* +G01X695085Y8233252D01* +G01X739083Y8233252D01* +G01X739083Y8278251D01* +G01X694585Y8278251D01* +G01X694583Y8320247D01* +G37* + +G04 Pad Start* +G04 Pad End* +G54D10* + +M02* + diff --git a/hardware/gerber/Gerber_BottomSilkscreenLayer.GBO b/hardware/gerber/Gerber_BottomSilkscreenLayer.GBO new file mode 100644 index 0000000..aac9c43 --- /dev/null +++ b/hardware/gerber/Gerber_BottomSilkscreenLayer.GBO @@ -0,0 +1,184 @@ +G04 Layer: BottomSilkscreenLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%ADD10C,0.1524*% +%ADD11C,0.254*% +%ADD12C,0.6821*% +G75* + + +G04 Text Start* +G54D10* +G01X616945Y9961095D02* +G01X616945Y9911311D01* +G01X616945Y9961095D02* +G01X595609Y9961095D01* +G01X588243Y9958809D01* +G01X585957Y9956523D01* +G01X583671Y9951697D01* +G01X583671Y9946871D01* +G01X585957Y9942045D01* +G01X588243Y9939759D01* +G01X595609Y9937473D01* +G01X616945Y9937473D01* +G01X600181Y9937473D02* +G01X583671Y9911311D01* +G01X557001Y9951697D02* +G01X552175Y9953983D01* +G01X545063Y9961095D01* +G01X545063Y9911311D01* +G01X650600Y9649437D02* +G01X645774Y9651723D01* +G01X638662Y9658835D01* +G01X638662Y9609051D01* +G01X611992Y9658835D02* +G01X611992Y9609051D01* +G01X588116Y9642325D02* +G01X611992Y9618449D01* +G01X602340Y9628101D02* +G01X585830Y9609051D01* +G01X559160Y9609051D02* +G01X542396Y9609051D01* +G01X547222Y9616163D01* +G01X552048Y9623275D01* +G01X554334Y9630387D01* +G01X554334Y9637499D01* +G01X552048Y9644611D01* +G01X549508Y9649437D01* +G01X544936Y9654263D01* +G01X540110Y9656549D01* +G01X530458Y9656549D01* +G01X525886Y9654263D01* +G01X521060Y9649437D01* +G01X518774Y9644611D01* +G01X516234Y9637499D01* +G01X516234Y9630387D01* +G01X518774Y9623275D01* +G01X523346Y9616163D01* +G01X528172Y9609051D01* +G01X511408Y9609051D01* +G01X691113Y8442175D02* +G01X691113Y8392391D01* +G01X691113Y8442175D02* +G01X669777Y8442175D01* +G01X662411Y8439889D01* +G01X660125Y8437603D01* +G01X657839Y8432777D01* +G01X657839Y8427951D01* +G01X660125Y8423125D01* +G01X662411Y8420839D01* +G01X669777Y8418553D01* +G01X691113Y8418553D01* +G01X674349Y8418553D02* +G01X657839Y8392391D01* +G01X628883Y8430491D02* +G01X628883Y8432777D01* +G01X626343Y8437603D01* +G01X624057Y8439889D01* +G01X619231Y8442175D01* +G01X609833Y8442175D01* +G01X605007Y8439889D01* +G01X602467Y8437603D01* +G01X600181Y8432777D01* +G01X600181Y8427951D01* +G01X602467Y8423125D01* +G01X607293Y8416013D01* +G01X631169Y8392391D01* +G01X597895Y8392391D01* +G01X714100Y8115277D02* +G01X709274Y8117563D01* +G01X702162Y8124675D01* +G01X702162Y8074891D01* +G01X675492Y8124675D02* +G01X675492Y8074891D01* +G01X651616Y8108165D02* +G01X675492Y8084289D01* +G01X665840Y8093941D02* +G01X649330Y8074891D01* +G01X622660Y8074891D02* +G01X605896Y8074891D01* +G01X610722Y8082003D01* +G01X615548Y8089115D01* +G01X617834Y8096227D01* +G01X617834Y8103339D01* +G01X615548Y8110451D01* +G01X613008Y8115277D01* +G01X608436Y8120103D01* +G01X603610Y8122389D01* +G01X593958Y8122389D01* +G01X589386Y8120103D01* +G01X584560Y8115277D01* +G01X582274Y8110451D01* +G01X579734Y8103339D01* +G01X579734Y8096227D01* +G01X582274Y8089115D01* +G01X586846Y8082003D01* +G01X591672Y8074891D01* +G01X574908Y8074891D01* +G04 Text End* + +G04 PolygonModel Start* +G01X533384Y9693617D02* +G01X404890Y9693617D01* +G01X404890Y9693617D02* +G01X404890Y9877036D01* +G01X404890Y9877036D02* +G01X533384Y9877036D01* +G01X628624Y9693617D02* +G01X757117Y9693617D01* +G01X757117Y9693617D02* +G01X757117Y9877036D01* +G01X757117Y9877036D02* +G01X628624Y9877036D01* +G01X697204Y8347956D02* +G01X825697Y8347956D01* +G01X825697Y8347956D02* +G01X825697Y8164537D01* +G01X825697Y8164537D02* +G01X697204Y8164537D01* +G01X601964Y8347956D02* +G01X473470Y8347956D01* +G01X473470Y8347956D02* +G01X473470Y8164537D01* +G01X473470Y8164537D02* +G01X601964Y8164537D01* +G54D11* +G01X2327000Y406300D02* +G01X2327000Y5511700D01* +G01X1819000Y406300D02* +G01X1819000Y5511700D01* +G01X1819000Y5511700D02* +G01X2327000Y5511700D01* +G01X1819000Y406300D02* +G01X2327000Y406300D01* +G01X3702410Y8433716D02* +G01X3702410Y8167016D01* +G01X3702410Y8167016D02* +G01X3461110Y8167016D01* +G01X3952397Y8441006D02* +G01X3952397Y5861001D01* +G01X3452398Y5861001D01* +G01X3452398Y8441006D01* +G01X3952397Y8441006D01* +G01X923142Y10135008D02* +G01X2243942Y10135008D01* +G01X2243942Y9627008D01* +G01X923142Y9627008D01* +G01X923142Y10135008D01* +G01X923142Y9881008D02* +G01X1202542Y9881008D01* +G01X1202542Y9627008D01* +G01X923142Y9627008D01* +G01X923142Y9881008D01* + +M02* + diff --git a/hardware/gerber/Gerber_BottomSolderMaskLayer.GBS b/hardware/gerber/Gerber_BottomSolderMaskLayer.GBS new file mode 100644 index 0000000..a73c345 --- /dev/null +++ b/hardware/gerber/Gerber_BottomSolderMaskLayer.GBS @@ -0,0 +1,260 @@ +G04 Layer: BottomSolderMaskLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%AMRoundRect*1,1,$1,$2,$3*1,1,$1,$4,$5*1,1,$1,0-$2,0-$3*1,1,$1,0-$4,0-$5*20,1,$1,$2,$3,$4,$5,0*20,1,$1,$4,$5,0-$2,0-$3,0*20,1,$1,0-$2,0-$3,0-$4,0-$5,0*20,1,$1,0-$4,0-$5,$2,$3,0*4,1,4,$2,$3,$4,$5,0-$2,0-$3,0-$4,0-$5,$2,$3,0*% +%ADD10C,1.7526*% +%ADD11RoundRect,0.1016X-0.8255X-0.8255X-0.8255X0.8255*% +%ADD12RoundRect,0.1016X-0.56627X0.68851X0.56627X0.68851*% +%ADD13O,2.0066X1.4986*% +%ADD14RoundRect,0.1016X-0.9525X0.6985X0.9525X0.6985*% +%ADD15C,1.8585*% +%ADD16C,1.8542*% +%ADD17C,1.7016*% +%ADD18RoundRect,0.1016X-0.8X-0.8X-0.8X0.8*% +%ADD19C,1.4986*% +%ADD20RoundRect,0.1016X-0.762X-0.762X-0.762X0.762*% +%ADD21C,1.6256*% +%ADD22RoundRect,0.1016X-0.8255X0.8255X0.8255X0.8255*% +%ADD23C,1.9016*% +G75* + + +G04 Pad Start* +G54D10* +G01X1196700Y3594000D03* +G54D11* +G01X1196700Y3848000D03* +G54D12* +G01X481004Y9785327D03* +G01X681004Y9785327D03* +G01X749584Y8256247D03* +G01X549584Y8256247D03* +G54D13* +G01X2733400Y12572900D03* +G01X2733400Y12318900D03* +G01X2733400Y12064900D03* +G01X2733400Y11810900D03* +G01X2733400Y11556900D03* +G01X2733400Y11302900D03* +G01X2733400Y11048900D03* +G01X2733400Y10794900D03* +G01X2733400Y10540900D03* +G01X2733400Y10286900D03* +G01X2733400Y10032900D03* +G01X2733400Y9778900D03* +G01X2733400Y9524900D03* +G01X2733400Y9270900D03* +G01X2733400Y9016900D03* +G01X2733400Y8762900D03* +G01X2733400Y8508900D03* +G01X2733400Y8254900D03* +G01X2733400Y8000900D03* +G01X2733400Y7746900D03* +G01X2733400Y7492900D03* +G01X2733400Y7238900D03* +G01X193400Y7238900D03* +G01X193400Y7492900D03* +G01X193400Y7746900D03* +G01X193400Y8000900D03* +G01X193400Y8254900D03* +G01X193400Y8508900D03* +G01X193400Y8762900D03* +G01X193400Y9016900D03* +G01X193400Y9270900D03* +G01X193400Y9524900D03* +G01X193400Y9778900D03* +G01X193400Y10032900D03* +G01X193400Y10286900D03* +G01X193400Y10540900D03* +G01X193400Y10794900D03* +G01X193400Y11048900D03* +G01X193400Y11302900D03* +G01X193400Y11556900D03* +G01X193400Y11810900D03* +G01X193400Y12064900D03* +G01X193400Y12318900D03* +G54D14* +G01X193400Y12572900D03* +G54D16* +G01X-276500Y7492900D03* +G01X-276500Y7746900D03* +G01X-276500Y8000900D03* +G01X-276500Y8254900D03* +G01X-276500Y8508900D03* +G01X-276500Y8762900D03* +G01X-276500Y9016900D03* +G01X-276500Y9270900D03* +G01X-276500Y9524900D03* +G01X-2308500Y9016900D03* +G01X-2308500Y8762900D03* +G01X-2308500Y8508900D03* +G01X-2308500Y8254900D03* +G01X-2308500Y8000900D03* +G01X-2308500Y7746900D03* +G54D17* +G01X1946000Y5372000D03* +G01X2200000Y5372000D03* +G01X1946000Y5118000D03* +G01X2200000Y5118000D03* +G01X1946000Y4864000D03* +G01X2200000Y4864000D03* +G01X1946000Y4610000D03* +G01X2200000Y4610000D03* +G01X1946000Y4356000D03* +G01X2200000Y4356000D03* +G01X1946000Y4102000D03* +G01X2200000Y4102000D03* +G01X1946000Y3848000D03* +G01X2200000Y3848000D03* +G01X1946000Y3594000D03* +G01X2200000Y3594000D03* +G01X1946000Y3340000D03* +G01X2200000Y3340000D03* +G01X1946000Y3086000D03* +G01X2200000Y3086000D03* +G01X1946000Y2832000D03* +G01X2200000Y2832000D03* +G01X1946000Y2578000D03* +G01X2200000Y2578000D03* +G01X1946000Y2324000D03* +G01X2200000Y2324000D03* +G01X1946000Y2070000D03* +G01X2200000Y2070000D03* +G01X1946000Y1816000D03* +G01X2200000Y1816000D03* +G01X1946000Y1562000D03* +G01X2200000Y1562000D03* +G01X1946000Y1308000D03* +G01X2200000Y1308000D03* +G01X1946000Y1054000D03* +G01X2200000Y1054000D03* +G01X1946000Y800000D03* +G01X2200000Y800000D03* +G01X1946000Y546000D03* +G54D18* +G01X2200000Y546000D03* +G01X612500Y546000D03* +G54D17* +G01X358500Y546000D03* +G01X612500Y800000D03* +G01X358500Y800000D03* +G01X612500Y1054000D03* +G01X358500Y1054000D03* +G01X612500Y1308000D03* +G01X358500Y1308000D03* +G01X612500Y1562000D03* +G01X358500Y1562000D03* +G01X612500Y1816000D03* +G01X358500Y1816000D03* +G01X612500Y2070000D03* +G01X358500Y2070000D03* +G01X612500Y2324000D03* +G01X358500Y2324000D03* +G01X612500Y2578000D03* +G01X358500Y2578000D03* +G54D19* +G01X612500Y2832000D03* +G54D17* +G01X358500Y2832000D03* +G54D19* +G01X612500Y3086000D03* +G54D17* +G01X358500Y3086000D03* +G01X612500Y3340000D03* +G01X358500Y3340000D03* +G01X612500Y3594000D03* +G01X358500Y3594000D03* +G01X612500Y3848000D03* +G01X358500Y3848000D03* +G01X612500Y4102000D03* +G01X358500Y4102000D03* +G01X612500Y4356000D03* +G01X358500Y4356000D03* +G01X612500Y4610000D03* +G01X358500Y4610000D03* +G01X612500Y4864000D03* +G01X358500Y4864000D03* +G01X612500Y5118000D03* +G01X358500Y5118000D03* +G01X612500Y5372000D03* +G01X358500Y5372000D03* +G54D10* +G01X3829410Y6008016D03* +G01X3575410Y6008016D03* +G01X3829410Y6262016D03* +G01X3575410Y6262016D03* +G01X3829410Y6516016D03* +G01X3575410Y6516016D03* +G01X3829410Y6770016D03* +G01X3575410Y6770016D03* +G01X3829410Y7024016D03* +G01X3575410Y7024016D03* +G01X3829410Y7278016D03* +G01X3575410Y7278016D03* +G01X3829410Y7532016D03* +G01X3575410Y7532016D03* +G01X3829410Y7786016D03* +G01X3575410Y7786016D03* +G01X3829410Y8040016D03* +G01X3575410Y8040016D03* +G01X3829410Y8294016D03* +G54D11* +G01X3575410Y8294016D03* +G54D20* +G01X3550000Y9619000D03* +G54D21* +G01X3296000Y9619000D03* +G01X3550000Y9873000D03* +G01X3296000Y9873000D03* +G01X3550000Y10127000D03* +G01X3296000Y10127000D03* +G01X3550000Y10381000D03* +G01X3296000Y10381000D03* +G01X3550000Y10635000D03* +G01X3296000Y10635000D03* +G54D10* +G01X2091542Y10008008D03* +G01X2091542Y9754008D03* +G01X1837542Y10008008D03* +G01X1837542Y9754008D03* +G01X1583542Y10008008D03* +G01X1583542Y9754008D03* +G01X1329542Y10008008D03* +G01X1329542Y9754008D03* +G01X1075542Y10008008D03* +G54D22* +G01X1075542Y9754008D03* +G54D20* +G01X4550000Y9619000D03* +G54D21* +G01X4296000Y9619000D03* +G01X4550000Y9873000D03* +G01X4296000Y9873000D03* +G01X4550000Y10127000D03* +G01X4296000Y10127000D03* +G01X4550000Y10381000D03* +G01X4296000Y10381000D03* +G01X4550000Y10635000D03* +G01X4296000Y10635000D03* +G54D22* +G01X-2308500Y10782200D03* +G54D10* +G01X-2054500Y10782200D03* +G01X-1800500Y10782200D03* +G01X-1546500Y10782200D03* +G54D23* +G01X1577700Y4210102D03* +G01X1577700Y3340102D03* +G04 Pad End* + +M02* + diff --git a/hardware/gerber/Gerber_DocumentLayer.GDL b/hardware/gerber/Gerber_DocumentLayer.GDL new file mode 100644 index 0000000..2c76353 --- /dev/null +++ b/hardware/gerber/Gerber_DocumentLayer.GDL @@ -0,0 +1,99 @@ +G04 Layer: DocumentLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%ADD10C,0.254*% +%ADD11C,0.2978*% +G75* + + +G04 PolygonModel Start* +G36* +G01X904600Y2705000D02* +G01X739500Y2705000D01* +G01X739500Y3213000D01* +G01X904600Y3213000D01* +G01X904600Y2705000D01* +G37* +G36* +G01X3715100Y9911100D02* +G01X3715100Y10368300D01* +G01X3867500Y10368300D01* +G01X3867500Y9911100D01* +G01X3715100Y9911100D01* +G37* +G36* +G01X4715100Y9911100D02* +G01X4715100Y10368300D01* +G01X4867500Y10368300D01* +G01X4867500Y9911100D01* +G01X4715100Y9911100D01* +G37* +G36* +G01X2130399Y6247599D02* +G01X2130399Y6223601D01* +G01X2034400Y6223601D01* +G01X2034400Y6247599D01* +G01X2130399Y6247599D01* +G37* +G36* +G01X1558401Y6247599D02* +G01X1654400Y6247599D01* +G01X1654400Y6223601D01* +G01X1558401Y6223601D01* +G01X1558401Y6247599D01* +G37* +G36* +G01X1594400Y6315600D02* +G01X1618401Y6315600D01* +G01X1618401Y6155600D01* +G01X1594400Y6155600D01* +G01X1594400Y6315600D01* +G37* +G36* +G01X1534401Y6395600D02* +G01X1582399Y6395600D01* +G01X1582399Y6315600D01* +G01X1534401Y6315600D01* +G01X1534401Y6395600D01* +G37* +G36* +G01X1534401Y6075600D02* +G01X1534401Y6155600D01* +G01X1582399Y6155600D01* +G01X1582399Y6075600D01* +G01X1534401Y6075600D01* +G37* +G36* +G01X1753620Y3433614D02* +G01X1753620Y3255814D01* +G01X1702820Y3255814D01* +G01X1702820Y3433614D01* +G01X1753620Y3433614D01* +G37* +G36* +G01X1636968Y3370584D02* +G01X1814768Y3370584D01* +G01X1814768Y3319784D01* +G01X1636968Y3319784D01* +G01X1636968Y3370584D01* +G37* +G36* +G01X1722828Y4285332D02* +G01X1722828Y4107532D01* +G01X1672028Y4107532D01* +G01X1672028Y4285332D01* +G01X1722828Y4285332D01* +G37* +G54D10* + +M02* + diff --git a/hardware/gerber/Gerber_DrillDrawingLayer.GDD b/hardware/gerber/Gerber_DrillDrawingLayer.GDD new file mode 100644 index 0000000..99e59ec --- /dev/null +++ b/hardware/gerber/Gerber_DrillDrawingLayer.GDD @@ -0,0 +1,3388 @@ +G04 Layer: DrillDrawingLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%AMIconRect*4,1,4,0.28,-0.28,-0.28,-0.28,-0.28,0.28,0.28,0.28,0.28,-0.28,0*4,0,4,0.233333,-0.233333,0.233333,0.233333,-0.233333,0.233333,-0.233333,-0.233333,0.233333,-0.233333,0*% +%AMIconTriangle*4,1,3,-0.339593,0.240473,0.339593,0.240473,0,-0.37884,-0.339593,0.240473,0*4,0,3,-0.265673,0.19404,0,-0.27342,0.266233,0.19404,-0.265673,0.19404,0*% +%ADD10IconRect*% +%ADD11C,0.616X0.522667*% +%ADD12IconTriangle*% +%ADD13C,0.2032*% +%ADD14C,0.254*% +G75* + + +G04 Drill Drawing Start* +G54D10* +G01X1196700Y3594000D03* +G01X1196700Y3848000D03* +G54D11* +G01X1577700Y4210107D03* +G01X1577700Y3340096D03* +G01X1946000Y4864000D03* +G01X1946000Y5118000D03* +G01X1946000Y5372000D03* +G01X1946000Y800000D03* +G01X1946000Y1054000D03* +G01X1946000Y1308000D03* +G01X1946000Y1562000D03* +G01X1946000Y1816000D03* +G01X1946000Y2070000D03* +G01X1946000Y2324000D03* +G01X1946000Y2578000D03* +G01X1946000Y2832000D03* +G01X1946000Y3086000D03* +G01X1946000Y3340000D03* +G01X1946000Y3848000D03* +G01X1946000Y4102000D03* +G01X1946000Y4356000D03* +G01X1946000Y4610000D03* +G01X1946000Y546000D03* +G01X1946000Y3594000D03* +G01X2200000Y4864000D03* +G01X2200000Y5118000D03* +G01X2200000Y5372000D03* +G01X2200000Y1054000D03* +G01X2200000Y1308000D03* +G01X2200000Y1562000D03* +G01X2200000Y1816000D03* +G01X2200000Y2070000D03* +G01X2200000Y2324000D03* +G01X2200000Y2578000D03* +G01X2200000Y2832000D03* +G01X2200000Y3086000D03* +G01X2200000Y3340000D03* +G01X2200000Y3594000D03* +G01X2200000Y3848000D03* +G01X2200000Y4102000D03* +G01X2200000Y4356000D03* +G01X2200000Y4610000D03* +G01X2200000Y546000D03* +G01X2200000Y800000D03* +G54D12* +G01X-2308500Y7746900D03* +G01X-2308500Y8000900D03* +G01X-2308500Y8254900D03* +G01X-2308500Y8508900D03* +G01X-2308500Y8762900D03* +G01X-2308500Y9016900D03* +G01X-2308500Y10782200D03* +G01X-2054500Y10782200D03* +G01X-1800500Y10782200D03* +G01X-1546500Y10782200D03* +G01X-276500Y7746900D03* +G01X-276500Y8000900D03* +G01X-276500Y8254900D03* +G01X-276500Y8508900D03* +G01X-276500Y8762900D03* +G01X-276500Y9016900D03* +G01X-276500Y9270900D03* +G01X-276500Y9524900D03* +G01X-276500Y7492900D03* +G01X193402Y7492895D03* +G01X193402Y7746895D03* +G01X193402Y8000895D03* +G01X193402Y8254895D03* +G01X193402Y8508895D03* +G01X193402Y8762895D03* +G01X193402Y9016895D03* +G01X193402Y9270895D03* +G01X193402Y9524895D03* +G01X193402Y9778895D03* +G01X193402Y10032895D03* +G01X193402Y10286895D03* +G01X193402Y10540895D03* +G01X193402Y10794895D03* +G01X193402Y11048895D03* +G01X193402Y11302895D03* +G01X193402Y11556895D03* +G01X193402Y11810895D03* +G01X193402Y12064895D03* +G01X193402Y12318895D03* +G01X193402Y12572895D03* +G01X193402Y7238895D03* +G01X358500Y546000D03* +G01X358500Y800000D03* +G01X358500Y1054000D03* +G01X358500Y1308000D03* +G01X358500Y1562000D03* +G01X358500Y1816000D03* +G01X358500Y2070000D03* +G01X358500Y2324000D03* +G01X358500Y3340000D03* +G01X358500Y3594000D03* +G01X358500Y3848000D03* +G01X358500Y4102000D03* +G01X358500Y4356000D03* +G01X358500Y4610000D03* +G01X358500Y4864000D03* +G01X358500Y5118000D03* +G01X358500Y5372000D03* +G01X358500Y2578000D03* +G01X358500Y2832000D03* +G01X358500Y3086000D03* +G01X612500Y546000D03* +G01X612500Y800000D03* +G01X612500Y1054000D03* +G01X612500Y1308000D03* +G01X612500Y1562000D03* +G01X612500Y1816000D03* +G01X612500Y2070000D03* +G01X612500Y2324000D03* +G01X612500Y2578000D03* +G01X612500Y3594000D03* +G01X612500Y3848000D03* +G01X612500Y4102000D03* +G01X612500Y4356000D03* +G01X612500Y4610000D03* +G01X612500Y4864000D03* +G01X612500Y5118000D03* +G01X612500Y5372000D03* +G01X612500Y2832000D03* +G01X612500Y3086000D03* +G01X612500Y3340000D03* +G01X1075542Y9754008D03* +G01X1075542Y10008008D03* +G01X1329542Y9754008D03* +G01X1329542Y10008008D03* +G01X1583542Y9754008D03* +G01X1583542Y10008008D03* +G01X1837542Y9754008D03* +G01X1837542Y10008008D03* +G01X2091542Y9754008D03* +G01X2091542Y10008008D03* +G01X2733397Y9016895D03* +G01X2733397Y9270895D03* +G01X2733397Y9524895D03* +G01X2733397Y9778895D03* +G01X2733397Y10032895D03* +G01X2733397Y10286895D03* +G01X2733397Y11556895D03* +G01X2733397Y11810895D03* +G01X2733397Y12064895D03* +G01X2733397Y12318895D03* +G01X2733397Y7238895D03* +G01X2733397Y7492895D03* +G01X2733397Y7746895D03* +G01X2733397Y8000895D03* +G01X2733397Y8254895D03* +G01X2733397Y8508895D03* +G01X2733397Y8762895D03* +G01X2733397Y10540895D03* +G01X2733397Y10794895D03* +G01X2733397Y11048895D03* +G01X2733397Y11302895D03* +G01X2733397Y12572895D03* +G01X3296000Y9619000D03* +G01X3296000Y9873000D03* +G01X3296000Y10380997D03* +G01X3296000Y10634997D03* +G01X3296000Y10127000D03* +G01X3550000Y9619000D03* +G01X3550000Y9873000D03* +G01X3550000Y10127000D03* +G01X3550000Y10380997D03* +G01X3550000Y10634997D03* +G01X3575410Y6008016D03* +G01X3575410Y6262016D03* +G01X3575410Y6516016D03* +G01X3575410Y7786016D03* +G01X3575410Y6770016D03* +G01X3575410Y7024016D03* +G01X3575410Y7532016D03* +G01X3575410Y8294016D03* +G01X3575410Y7278016D03* +G01X3575410Y8040016D03* +G01X3829410Y6008016D03* +G01X3829410Y6262016D03* +G01X3829410Y6770016D03* +G01X3829410Y7278016D03* +G01X3829410Y8040016D03* +G01X3829410Y7024016D03* +G01X3829410Y7532016D03* +G01X3829410Y6516016D03* +G01X3829410Y7786016D03* +G01X3829410Y8294016D03* +G01X4296000Y9619000D03* +G01X4296000Y9873000D03* +G01X4296000Y10127000D03* +G01X4296000Y10380997D03* +G01X4296000Y10634997D03* +G01X4550000Y9619000D03* +G01X4550000Y9873000D03* +G01X4550000Y10127000D03* +G01X4550000Y10380997D03* +G01X4550000Y10634997D03* +G04 Drill Drawing End* + +G04 Text Start* +G54D13* +G01X7228152Y13278294D02* +G01X7228152Y13158152D01* +G01X7228152Y13278294D02* +G01X7273872Y13158152D01* +G01X7319592Y13278294D02* +G01X7273872Y13158152D01* +G01X7319592Y13278294D02* +G01X7319592Y13158152D01* +G01X7435924Y13238162D02* +G01X7435924Y13158152D01* +G01X7435924Y13221144D02* +G01X7424494Y13232574D01* +G01X7413064Y13238162D01* +G01X7396046Y13238162D01* +G01X7384616Y13232574D01* +G01X7373186Y13221144D01* +G01X7367344Y13203872D01* +G01X7367344Y13192442D01* +G01X7373186Y13175424D01* +G01X7384616Y13163994D01* +G01X7396046Y13158152D01* +G01X7413064Y13158152D01* +G01X7424494Y13163994D01* +G01X7435924Y13175424D01* +G01X7483676Y13238162D02* +G01X7483676Y13158152D01* +G01X7483676Y13203872D02* +G01X7489518Y13221144D01* +G01X7500948Y13232574D01* +G01X7512378Y13238162D01* +G01X7529396Y13238162D01* +G01X7577148Y13278294D02* +G01X7577148Y13158152D01* +G01X7634298Y13238162D02* +G01X7577148Y13181012D01* +G01X7600008Y13203872D02* +G01X7640140Y13158152D01* +G01X8765432Y13249592D02* +G01X8759590Y13261022D01* +G01X8748160Y13272452D01* +G01X8736730Y13278294D01* +G01X8713870Y13278294D01* +G01X8702440Y13272452D01* +G01X8691010Y13261022D01* +G01X8685422Y13249592D01* +G01X8679580Y13232574D01* +G01X8679580Y13203872D01* +G01X8685422Y13186854D01* +G01X8691010Y13175424D01* +G01X8702440Y13163994D01* +G01X8713870Y13158152D01* +G01X8736730Y13158152D01* +G01X8748160Y13163994D01* +G01X8759590Y13175424D01* +G01X8765432Y13186854D01* +G01X8841886Y13238162D02* +G01X8830456Y13232574D01* +G01X8819026Y13221144D01* +G01X8813184Y13203872D01* +G01X8813184Y13192442D01* +G01X8819026Y13175424D01* +G01X8830456Y13163994D01* +G01X8841886Y13158152D01* +G01X8858904Y13158152D01* +G01X8870334Y13163994D01* +G01X8881764Y13175424D01* +G01X8887606Y13192442D01* +G01X8887606Y13203872D01* +G01X8881764Y13221144D01* +G01X8870334Y13232574D01* +G01X8858904Y13238162D01* +G01X8841886Y13238162D01* +G01X8935358Y13238162D02* +G01X8935358Y13181012D01* +G01X8941200Y13163994D01* +G01X8952630Y13158152D01* +G01X8969648Y13158152D01* +G01X8981078Y13163994D01* +G01X8998350Y13181012D01* +G01X8998350Y13238162D02* +G01X8998350Y13158152D01* +G01X9046102Y13238162D02* +G01X9046102Y13158152D01* +G01X9046102Y13215302D02* +G01X9063374Y13232574D01* +G01X9074804Y13238162D01* +G01X9091822Y13238162D01* +G01X9103252Y13232574D01* +G01X9109094Y13215302D01* +G01X9109094Y13158152D01* +G01X9174118Y13278294D02* +G01X9174118Y13181012D01* +G01X9179706Y13163994D01* +G01X9191136Y13158152D01* +G01X9202566Y13158152D01* +G01X9156846Y13238162D02* +G01X9196978Y13238162D01* +G01X10173753Y13261022D02* +G01X10162323Y13272452D01* +G01X10145305Y13278294D01* +G01X10122445Y13278294D01* +G01X10105173Y13272452D01* +G01X10093743Y13261022D01* +G01X10093743Y13249592D01* +G01X10099585Y13238162D01* +G01X10105173Y13232574D01* +G01X10116603Y13226732D01* +G01X10150893Y13215302D01* +G01X10162323Y13209714D01* +G01X10168165Y13203872D01* +G01X10173753Y13192442D01* +G01X10173753Y13175424D01* +G01X10162323Y13163994D01* +G01X10145305Y13158152D01* +G01X10122445Y13158152D01* +G01X10105173Y13163994D01* +G01X10093743Y13175424D01* +G01X10221505Y13278294D02* +G01X10227347Y13272452D01* +G01X10232935Y13278294D01* +G01X10227347Y13283882D01* +G01X10221505Y13278294D01* +G01X10227347Y13238162D02* +G01X10227347Y13158152D01* +G01X10343679Y13238162D02* +G01X10280687Y13158152D01* +G01X10280687Y13238162D02* +G01X10343679Y13238162D01* +G01X10280687Y13158152D02* +G01X10343679Y13158152D01* +G01X10391431Y13203872D02* +G01X10460011Y13203872D01* +G01X10460011Y13215302D01* +G01X10454423Y13226732D01* +G01X10448581Y13232574D01* +G01X10437151Y13238162D01* +G01X10420133Y13238162D01* +G01X10408703Y13232574D01* +G01X10397273Y13221144D01* +G01X10391431Y13203872D01* +G01X10391431Y13192442D01* +G01X10397273Y13175424D01* +G01X10408703Y13163994D01* +G01X10420133Y13158152D01* +G01X10437151Y13158152D01* +G01X10448581Y13163994D01* +G01X10460011Y13175424D01* +G01X13964848Y13278294D02* +G01X13964848Y13158152D01* +G01X13964848Y13278294D02* +G01X14016410Y13278294D01* +G01X14033428Y13272452D01* +G01X14039270Y13266864D01* +G01X14044858Y13255434D01* +G01X14044858Y13238162D01* +G01X14039270Y13226732D01* +G01X14033428Y13221144D01* +G01X14016410Y13215302D01* +G01X13964848Y13215302D01* +G01X14092610Y13278294D02* +G01X14092610Y13158152D01* +G01X14208942Y13238162D02* +G01X14208942Y13158152D01* +G01X14208942Y13221144D02* +G01X14197512Y13232574D01* +G01X14186082Y13238162D01* +G01X14169064Y13238162D01* +G01X14157634Y13232574D01* +G01X14146204Y13221144D01* +G01X14140362Y13203872D01* +G01X14140362Y13192442D01* +G01X14146204Y13175424D01* +G01X14157634Y13163994D01* +G01X14169064Y13158152D01* +G01X14186082Y13158152D01* +G01X14197512Y13163994D01* +G01X14208942Y13175424D01* +G01X14273966Y13278294D02* +G01X14273966Y13181012D01* +G01X14279554Y13163994D01* +G01X14290984Y13158152D01* +G01X14302414Y13158152D01* +G01X14256694Y13238162D02* +G01X14296826Y13238162D01* +G01X14350166Y13203872D02* +G01X14418746Y13203872D01* +G01X14418746Y13215302D01* +G01X14413158Y13226732D01* +G01X14407316Y13232574D01* +G01X14395886Y13238162D01* +G01X14378868Y13238162D01* +G01X14367438Y13232574D01* +G01X14356008Y13221144D01* +G01X14350166Y13203872D01* +G01X14350166Y13192442D01* +G01X14356008Y13175424D01* +G01X14367438Y13163994D01* +G01X14378868Y13158152D01* +G01X14395886Y13158152D01* +G01X14407316Y13163994D01* +G01X14418746Y13175424D01* +G01X14535078Y13278294D02* +G01X14535078Y13158152D01* +G01X14535078Y13221144D02* +G01X14523648Y13232574D01* +G01X14512218Y13238162D01* +G01X14495200Y13238162D01* +G01X14483770Y13232574D01* +G01X14472340Y13221144D01* +G01X14466498Y13203872D01* +G01X14466498Y13192442D01* +G01X14472340Y13175424D01* +G01X14483770Y13163994D01* +G01X14495200Y13158152D01* +G01X14512218Y13158152D01* +G01X14523648Y13163994D01* +G01X14535078Y13175424D01* +G01X15506266Y13261022D02* +G01X15494836Y13272452D01* +G01X15477818Y13278294D01* +G01X15454958Y13278294D01* +G01X15437686Y13272452D01* +G01X15426256Y13261022D01* +G01X15426256Y13249592D01* +G01X15432098Y13238162D01* +G01X15437686Y13232574D01* +G01X15449116Y13226732D01* +G01X15483406Y13215302D01* +G01X15494836Y13209714D01* +G01X15500678Y13203872D01* +G01X15506266Y13192442D01* +G01X15506266Y13175424D01* +G01X15494836Y13163994D01* +G01X15477818Y13158152D01* +G01X15454958Y13158152D01* +G01X15437686Y13163994D01* +G01X15426256Y13175424D01* +G01X15554018Y13278294D02* +G01X15554018Y13158152D01* +G01X15554018Y13215302D02* +G01X15571290Y13232574D01* +G01X15582720Y13238162D01* +G01X15599738Y13238162D01* +G01X15611168Y13232574D01* +G01X15617010Y13215302D01* +G01X15617010Y13158152D01* +G01X15733342Y13238162D02* +G01X15733342Y13158152D01* +G01X15733342Y13221144D02* +G01X15721912Y13232574D01* +G01X15710482Y13238162D01* +G01X15693464Y13238162D01* +G01X15682034Y13232574D01* +G01X15670604Y13221144D01* +G01X15664762Y13203872D01* +G01X15664762Y13192442D01* +G01X15670604Y13175424D01* +G01X15682034Y13163994D01* +G01X15693464Y13158152D01* +G01X15710482Y13158152D01* +G01X15721912Y13163994D01* +G01X15733342Y13175424D01* +G01X15781094Y13238162D02* +G01X15781094Y13118274D01* +G01X15781094Y13221144D02* +G01X15792524Y13232574D01* +G01X15803954Y13238162D01* +G01X15821226Y13238162D01* +G01X15832656Y13232574D01* +G01X15844086Y13221144D01* +G01X15849674Y13203872D01* +G01X15849674Y13192442D01* +G01X15844086Y13175424D01* +G01X15832656Y13163994D01* +G01X15821226Y13158152D01* +G01X15803954Y13158152D01* +G01X15792524Y13163994D01* +G01X15781094Y13175424D01* +G01X15897426Y13203872D02* +G01X15966006Y13203872D01* +G01X15966006Y13215302D01* +G01X15960418Y13226732D01* +G01X15954576Y13232574D01* +G01X15943146Y13238162D01* +G01X15926128Y13238162D01* +G01X15914698Y13232574D01* +G01X15903268Y13221144D01* +G01X15897426Y13203872D01* +G01X15897426Y13192442D01* +G01X15903268Y13175424D01* +G01X15914698Y13163994D01* +G01X15926128Y13158152D01* +G01X15943146Y13158152D01* +G01X15954576Y13163994D01* +G01X15966006Y13175424D01* +G01X16857437Y13278294D02* +G01X16903157Y13158152D01* +G01X16948877Y13278294D02* +G01X16903157Y13158152D01* +G01X16996629Y13278294D02* +G01X17002471Y13272452D01* +G01X17008059Y13278294D01* +G01X17002471Y13283882D01* +G01X16996629Y13278294D01* +G01X17002471Y13238162D02* +G01X17002471Y13158152D01* +G01X17124391Y13238162D02* +G01X17124391Y13158152D01* +G01X17124391Y13221144D02* +G01X17112961Y13232574D01* +G01X17101531Y13238162D01* +G01X17084513Y13238162D01* +G01X17073083Y13232574D01* +G01X17061653Y13221144D01* +G01X17055811Y13203872D01* +G01X17055811Y13192442D01* +G01X17061653Y13175424D01* +G01X17073083Y13163994D01* +G01X17084513Y13158152D01* +G01X17101531Y13158152D01* +G01X17112961Y13163994D01* +G01X17124391Y13175424D01* +G01X17275013Y13301154D02* +G01X17172143Y13118274D01* +G01X17322765Y13278294D02* +G01X17322765Y13158152D01* +G01X17322765Y13278294D02* +G01X17374327Y13278294D01* +G01X17391345Y13272452D01* +G01X17397187Y13266864D01* +G01X17402775Y13255434D01* +G01X17402775Y13238162D01* +G01X17397187Y13226732D01* +G01X17391345Y13221144D01* +G01X17374327Y13215302D01* +G01X17322765Y13215302D01* +G01X17519107Y13238162D02* +G01X17519107Y13158152D01* +G01X17519107Y13221144D02* +G01X17507677Y13232574D01* +G01X17496247Y13238162D01* +G01X17479229Y13238162D01* +G01X17467799Y13232574D01* +G01X17456369Y13221144D01* +G01X17450527Y13203872D01* +G01X17450527Y13192442D01* +G01X17456369Y13175424D01* +G01X17467799Y13163994D01* +G01X17479229Y13158152D01* +G01X17496247Y13158152D01* +G01X17507677Y13163994D01* +G01X17519107Y13175424D01* +G01X17635439Y13278294D02* +G01X17635439Y13158152D01* +G01X17635439Y13221144D02* +G01X17624009Y13232574D01* +G01X17612579Y13238162D01* +G01X17595561Y13238162D01* +G01X17584131Y13232574D01* +G01X17572701Y13221144D01* +G01X17566859Y13203872D01* +G01X17566859Y13192442D01* +G01X17572701Y13175424D01* +G01X17584131Y13163994D01* +G01X17595561Y13158152D01* +G01X17612579Y13158152D01* +G01X17624009Y13163994D01* +G01X17635439Y13175424D01* +G01X18526616Y13278294D02* +G01X18526616Y13158152D01* +G01X18526616Y13278294D02* +G01X18578178Y13278294D01* +G01X18595196Y13272452D01* +G01X18601038Y13266864D01* +G01X18606626Y13255434D01* +G01X18606626Y13238162D01* +G01X18601038Y13226732D01* +G01X18595196Y13221144D01* +G01X18578178Y13215302D01* +G01X18526616Y13215302D01* +G01X18722958Y13238162D02* +G01X18722958Y13158152D01* +G01X18722958Y13221144D02* +G01X18711528Y13232574D01* +G01X18700098Y13238162D01* +G01X18683080Y13238162D01* +G01X18671650Y13232574D01* +G01X18660220Y13221144D01* +G01X18654378Y13203872D01* +G01X18654378Y13192442D01* +G01X18660220Y13175424D01* +G01X18671650Y13163994D01* +G01X18683080Y13158152D01* +G01X18700098Y13158152D01* +G01X18711528Y13163994D01* +G01X18722958Y13175424D01* +G01X18839290Y13278294D02* +G01X18839290Y13158152D01* +G01X18839290Y13221144D02* +G01X18827860Y13232574D01* +G01X18816430Y13238162D01* +G01X18799412Y13238162D01* +G01X18787982Y13232574D01* +G01X18776552Y13221144D01* +G01X18770710Y13203872D01* +G01X18770710Y13192442D01* +G01X18776552Y13175424D01* +G01X18787982Y13163994D01* +G01X18799412Y13158152D01* +G01X18816430Y13158152D01* +G01X18827860Y13163994D01* +G01X18839290Y13175424D01* +G01X19095068Y13261022D02* +G01X19083638Y13272452D01* +G01X19066620Y13278294D01* +G01X19043760Y13278294D01* +G01X19026488Y13272452D01* +G01X19015058Y13261022D01* +G01X19015058Y13249592D01* +G01X19020900Y13238162D01* +G01X19026488Y13232574D01* +G01X19037918Y13226732D01* +G01X19072208Y13215302D01* +G01X19083638Y13209714D01* +G01X19089480Y13203872D01* +G01X19095068Y13192442D01* +G01X19095068Y13175424D01* +G01X19083638Y13163994D01* +G01X19066620Y13158152D01* +G01X19043760Y13158152D01* +G01X19026488Y13163994D01* +G01X19015058Y13175424D01* +G01X19142820Y13278294D02* +G01X19142820Y13158152D01* +G01X19142820Y13215302D02* +G01X19160092Y13232574D01* +G01X19171522Y13238162D01* +G01X19188540Y13238162D01* +G01X19199970Y13232574D01* +G01X19205812Y13215302D01* +G01X19205812Y13158152D01* +G01X19322144Y13238162D02* +G01X19322144Y13158152D01* +G01X19322144Y13221144D02* +G01X19310714Y13232574D01* +G01X19299284Y13238162D01* +G01X19282266Y13238162D01* +G01X19270836Y13232574D01* +G01X19259406Y13221144D01* +G01X19253564Y13203872D01* +G01X19253564Y13192442D01* +G01X19259406Y13175424D01* +G01X19270836Y13163994D01* +G01X19282266Y13158152D01* +G01X19299284Y13158152D01* +G01X19310714Y13163994D01* +G01X19322144Y13175424D01* +G01X19369896Y13238162D02* +G01X19369896Y13118274D01* +G01X19369896Y13221144D02* +G01X19381326Y13232574D01* +G01X19392756Y13238162D01* +G01X19410028Y13238162D01* +G01X19421458Y13232574D01* +G01X19432888Y13221144D01* +G01X19438476Y13203872D01* +G01X19438476Y13192442D01* +G01X19432888Y13175424D01* +G01X19421458Y13163994D01* +G01X19410028Y13158152D01* +G01X19392756Y13158152D01* +G01X19381326Y13163994D01* +G01X19369896Y13175424D01* +G01X19486228Y13203872D02* +G01X19554808Y13203872D01* +G01X19554808Y13215302D01* +G01X19549220Y13226732D01* +G01X19543378Y13232574D01* +G01X19531948Y13238162D01* +G01X19514930Y13238162D01* +G01X19503500Y13232574D01* +G01X19492070Y13221144D01* +G01X19486228Y13203872D01* +G01X19486228Y13192442D01* +G01X19492070Y13175424D01* +G01X19503500Y13163994D01* +G01X19514930Y13158152D01* +G01X19531948Y13158152D01* +G01X19543378Y13163994D01* +G01X19554808Y13175424D01* +G01X20445985Y13278294D02* +G01X20445985Y13158152D01* +G01X20445985Y13158152D02* +G01X20514565Y13158152D01* +G01X20630897Y13238162D02* +G01X20630897Y13158152D01* +G01X20630897Y13221144D02* +G01X20619467Y13232574D01* +G01X20608037Y13238162D01* +G01X20591019Y13238162D01* +G01X20579589Y13232574D01* +G01X20568159Y13221144D01* +G01X20562317Y13203872D01* +G01X20562317Y13192442D01* +G01X20568159Y13175424D01* +G01X20579589Y13163994D01* +G01X20591019Y13158152D01* +G01X20608037Y13158152D01* +G01X20619467Y13163994D01* +G01X20630897Y13175424D01* +G01X20684491Y13238162D02* +G01X20718781Y13158152D01* +G01X20753071Y13238162D02* +G01X20718781Y13158152D01* +G01X20707351Y13135292D01* +G01X20695921Y13123862D01* +G01X20684491Y13118274D01* +G01X20678649Y13118274D01* +G01X20800823Y13203872D02* +G01X20869403Y13203872D01* +G01X20869403Y13215302D01* +G01X20863815Y13226732D01* +G01X20857973Y13232574D01* +G01X20846543Y13238162D01* +G01X20829525Y13238162D01* +G01X20818095Y13232574D01* +G01X20806665Y13221144D01* +G01X20800823Y13203872D01* +G01X20800823Y13192442D01* +G01X20806665Y13175424D01* +G01X20818095Y13163994D01* +G01X20829525Y13158152D01* +G01X20846543Y13158152D01* +G01X20857973Y13163994D01* +G01X20869403Y13175424D01* +G01X20917155Y13238162D02* +G01X20917155Y13158152D01* +G01X20917155Y13203872D02* +G01X20922997Y13221144D01* +G01X20934427Y13232574D01* +G01X20945857Y13238162D01* +G01X20962875Y13238162D01* +G01X21138643Y13278294D02* +G01X21138643Y13158152D01* +G01X21138643Y13278294D02* +G01X21190205Y13278294D01* +G01X21207223Y13272452D01* +G01X21213065Y13266864D01* +G01X21218653Y13255434D01* +G01X21218653Y13238162D01* +G01X21213065Y13226732D01* +G01X21207223Y13221144D01* +G01X21190205Y13215302D01* +G01X21138643Y13215302D01* +G01X21334985Y13238162D02* +G01X21334985Y13158152D01* +G01X21334985Y13221144D02* +G01X21323555Y13232574D01* +G01X21312125Y13238162D01* +G01X21295107Y13238162D01* +G01X21283677Y13232574D01* +G01X21272247Y13221144D01* +G01X21266405Y13203872D01* +G01X21266405Y13192442D01* +G01X21272247Y13175424D01* +G01X21283677Y13163994D01* +G01X21295107Y13158152D01* +G01X21312125Y13158152D01* +G01X21323555Y13163994D01* +G01X21334985Y13175424D01* +G01X21382737Y13278294D02* +G01X21388579Y13272452D01* +G01X21394167Y13278294D01* +G01X21388579Y13283882D01* +G01X21382737Y13278294D01* +G01X21388579Y13238162D02* +G01X21388579Y13158152D01* +G01X21441919Y13238162D02* +G01X21441919Y13158152D01* +G01X21441919Y13203872D02* +G01X21447761Y13221144D01* +G01X21459191Y13232574D01* +G01X21470621Y13238162D01* +G01X21487639Y13238162D01* +G01X8685422Y12669021D02* +G01X8685422Y12674863D01* +G01X8691010Y12686293D01* +G01X8696852Y12691881D01* +G01X8708282Y12697723D01* +G01X8731142Y12697723D01* +G01X8742572Y12691881D01* +G01X8748160Y12686293D01* +G01X8754002Y12674863D01* +G01X8754002Y12663433D01* +G01X8748160Y12652003D01* +G01X8736730Y12634731D01* +G01X8679580Y12577581D01* +G01X8759590Y12577581D01* +G01X10105173Y12697723D02* +G01X10168165Y12697723D01* +G01X10133875Y12652003D01* +G01X10150893Y12652003D01* +G01X10162323Y12646161D01* +G01X10168165Y12640573D01* +G01X10173753Y12623301D01* +G01X10173753Y12611871D01* +G01X10168165Y12594853D01* +G01X10156735Y12583423D01* +G01X10139463Y12577581D01* +G01X10122445Y12577581D01* +G01X10105173Y12583423D01* +G01X10099585Y12589011D01* +G01X10093743Y12600441D01* +G01X10250207Y12697723D02* +G01X10232935Y12691881D01* +G01X10227347Y12680451D01* +G01X10227347Y12669021D01* +G01X10232935Y12657591D01* +G01X10244365Y12652003D01* +G01X10267225Y12646161D01* +G01X10284497Y12640573D01* +G01X10295927Y12629143D01* +G01X10301515Y12617713D01* +G01X10301515Y12600441D01* +G01X10295927Y12589011D01* +G01X10290085Y12583423D01* +G01X10273067Y12577581D01* +G01X10250207Y12577581D01* +G01X10232935Y12583423D01* +G01X10227347Y12589011D01* +G01X10221505Y12600441D01* +G01X10221505Y12617713D01* +G01X10227347Y12629143D01* +G01X10238777Y12640573D01* +G01X10255795Y12646161D01* +G01X10278655Y12652003D01* +G01X10290085Y12657591D01* +G01X10295927Y12669021D01* +G01X10295927Y12680451D01* +G01X10290085Y12691881D01* +G01X10273067Y12697723D01* +G01X10250207Y12697723D01* +G01X10355109Y12606283D02* +G01X10349267Y12600441D01* +G01X10355109Y12594853D01* +G01X10360697Y12600441D01* +G01X10355109Y12606283D01* +G01X10442739Y12697723D02* +G01X10425721Y12691881D01* +G01X10414291Y12674863D01* +G01X10408449Y12646161D01* +G01X10408449Y12629143D01* +G01X10414291Y12600441D01* +G01X10425721Y12583423D01* +G01X10442739Y12577581D01* +G01X10454169Y12577581D01* +G01X10471441Y12583423D01* +G01X10482871Y12600441D01* +G01X10488459Y12629143D01* +G01X10488459Y12646161D01* +G01X10482871Y12674863D01* +G01X10471441Y12691881D01* +G01X10454169Y12697723D01* +G01X10442739Y12697723D01* +G01X10536211Y12657591D02* +G01X10599203Y12577581D01* +G01X10599203Y12657591D02* +G01X10536211Y12577581D01* +G01X10658385Y12697723D02* +G01X10721377Y12697723D01* +G01X10687087Y12652003D01* +G01X10704105Y12652003D01* +G01X10715535Y12646161D01* +G01X10721377Y12640573D01* +G01X10726965Y12623301D01* +G01X10726965Y12611871D01* +G01X10721377Y12594853D01* +G01X10709947Y12583423D01* +G01X10692675Y12577581D01* +G01X10675657Y12577581D01* +G01X10658385Y12583423D01* +G01X10652797Y12589011D01* +G01X10646955Y12600441D01* +G01X10803419Y12697723D02* +G01X10786147Y12691881D01* +G01X10780559Y12680451D01* +G01X10780559Y12669021D01* +G01X10786147Y12657591D01* +G01X10797577Y12652003D01* +G01X10820437Y12646161D01* +G01X10837709Y12640573D01* +G01X10849139Y12629143D01* +G01X10854727Y12617713D01* +G01X10854727Y12600441D01* +G01X10849139Y12589011D01* +G01X10843297Y12583423D01* +G01X10826279Y12577581D01* +G01X10803419Y12577581D01* +G01X10786147Y12583423D01* +G01X10780559Y12589011D01* +G01X10774717Y12600441D01* +G01X10774717Y12617713D01* +G01X10780559Y12629143D01* +G01X10791989Y12640573D01* +G01X10809007Y12646161D01* +G01X10831867Y12652003D01* +G01X10843297Y12657591D01* +G01X10849139Y12669021D01* +G01X10849139Y12680451D01* +G01X10843297Y12691881D01* +G01X10826279Y12697723D01* +G01X10803419Y12697723D01* +G01X10908321Y12606283D02* +G01X10902479Y12600441D01* +G01X10908321Y12594853D01* +G01X10913909Y12600441D01* +G01X10908321Y12606283D01* +G01X10995951Y12697723D02* +G01X10978933Y12691881D01* +G01X10967503Y12674863D01* +G01X10961661Y12646161D01* +G01X10961661Y12629143D01* +G01X10967503Y12600441D01* +G01X10978933Y12583423D01* +G01X10995951Y12577581D01* +G01X11007381Y12577581D01* +G01X11024653Y12583423D01* +G01X11036083Y12600441D01* +G01X11041671Y12629143D01* +G01X11041671Y12646161D01* +G01X11036083Y12674863D01* +G01X11024653Y12691881D01* +G01X11007381Y12697723D01* +G01X10995951Y12697723D01* +G01X11089423Y12657591D02* +G01X11089423Y12577581D01* +G01X11089423Y12634731D02* +G01X11106695Y12652003D01* +G01X11118125Y12657591D01* +G01X11135143Y12657591D01* +G01X11146573Y12652003D01* +G01X11152415Y12634731D01* +G01X11152415Y12577581D01* +G01X11152415Y12634731D02* +G01X11169433Y12652003D01* +G01X11180863Y12657591D01* +G01X11198135Y12657591D01* +G01X11209565Y12652003D01* +G01X11215153Y12634731D01* +G01X11215153Y12577581D01* +G01X11262905Y12697723D02* +G01X11268747Y12691881D01* +G01X11274335Y12697723D01* +G01X11268747Y12703311D01* +G01X11262905Y12697723D01* +G01X11268747Y12657591D02* +G01X11268747Y12577581D01* +G01X11322087Y12697723D02* +G01X11322087Y12577581D01* +G01X11409971Y12720583D02* +G01X11398541Y12709153D01* +G01X11387111Y12691881D01* +G01X11375681Y12669021D01* +G01X11369839Y12640573D01* +G01X11369839Y12617713D01* +G01X11375681Y12589011D01* +G01X11387111Y12566151D01* +G01X11398541Y12549133D01* +G01X11409971Y12537703D01* +G01X11492013Y12697723D02* +G01X11474995Y12691881D01* +G01X11463565Y12674863D01* +G01X11457723Y12646161D01* +G01X11457723Y12629143D01* +G01X11463565Y12600441D01* +G01X11474995Y12583423D01* +G01X11492013Y12577581D01* +G01X11503443Y12577581D01* +G01X11520715Y12583423D01* +G01X11532145Y12600441D01* +G01X11537733Y12629143D01* +G01X11537733Y12646161D01* +G01X11532145Y12674863D01* +G01X11520715Y12691881D01* +G01X11503443Y12697723D01* +G01X11492013Y12697723D01* +G01X11591327Y12606283D02* +G01X11585485Y12600441D01* +G01X11591327Y12594853D01* +G01X11596915Y12600441D01* +G01X11591327Y12606283D01* +G01X11719089Y12657591D02* +G01X11713247Y12640573D01* +G01X11701817Y12629143D01* +G01X11684799Y12623301D01* +G01X11678957Y12623301D01* +G01X11661939Y12629143D01* +G01X11650509Y12640573D01* +G01X11644667Y12657591D01* +G01X11644667Y12663433D01* +G01X11650509Y12680451D01* +G01X11661939Y12691881D01* +G01X11678957Y12697723D01* +G01X11684799Y12697723D01* +G01X11701817Y12691881D01* +G01X11713247Y12680451D01* +G01X11719089Y12657591D01* +G01X11719089Y12629143D01* +G01X11713247Y12600441D01* +G01X11701817Y12583423D01* +G01X11684799Y12577581D01* +G01X11673369Y12577581D01* +G01X11656097Y12583423D01* +G01X11650509Y12594853D01* +G01X11835421Y12680451D02* +G01X11829833Y12691881D01* +G01X11812561Y12697723D01* +G01X11801131Y12697723D01* +G01X11784113Y12691881D01* +G01X11772683Y12674863D01* +G01X11766841Y12646161D01* +G01X11766841Y12617713D01* +G01X11772683Y12594853D01* +G01X11784113Y12583423D01* +G01X11801131Y12577581D01* +G01X11806973Y12577581D01* +G01X11823991Y12583423D01* +G01X11835421Y12594853D01* +G01X11841263Y12611871D01* +G01X11841263Y12617713D01* +G01X11835421Y12634731D01* +G01X11823991Y12646161D01* +G01X11806973Y12652003D01* +G01X11801131Y12652003D01* +G01X11784113Y12646161D01* +G01X11772683Y12634731D01* +G01X11766841Y12617713D01* +G01X11957595Y12697723D02* +G01X11900445Y12697723D01* +G01X11894857Y12646161D01* +G01X11900445Y12652003D01* +G01X11917717Y12657591D01* +G01X11934735Y12657591D01* +G01X11952007Y12652003D01* +G01X11963437Y12640573D01* +G01X11969025Y12623301D01* +G01X11969025Y12611871D01* +G01X11963437Y12594853D01* +G01X11952007Y12583423D01* +G01X11934735Y12577581D01* +G01X11917717Y12577581D01* +G01X11900445Y12583423D01* +G01X11894857Y12589011D01* +G01X11889015Y12600441D01* +G01X12016777Y12657591D02* +G01X12079769Y12577581D01* +G01X12079769Y12657591D02* +G01X12016777Y12577581D01* +G01X12161811Y12697723D02* +G01X12144793Y12691881D01* +G01X12133363Y12674863D01* +G01X12127521Y12646161D01* +G01X12127521Y12629143D01* +G01X12133363Y12600441D01* +G01X12144793Y12583423D01* +G01X12161811Y12577581D01* +G01X12173241Y12577581D01* +G01X12190513Y12583423D01* +G01X12201943Y12600441D01* +G01X12207531Y12629143D01* +G01X12207531Y12646161D01* +G01X12201943Y12674863D01* +G01X12190513Y12691881D01* +G01X12173241Y12697723D01* +G01X12161811Y12697723D01* +G01X12261125Y12606283D02* +G01X12255283Y12600441D01* +G01X12261125Y12594853D01* +G01X12266713Y12600441D01* +G01X12261125Y12606283D01* +G01X12388887Y12657591D02* +G01X12383045Y12640573D01* +G01X12371615Y12629143D01* +G01X12354597Y12623301D01* +G01X12348755Y12623301D01* +G01X12331737Y12629143D01* +G01X12320307Y12640573D01* +G01X12314465Y12657591D01* +G01X12314465Y12663433D01* +G01X12320307Y12680451D01* +G01X12331737Y12691881D01* +G01X12348755Y12697723D01* +G01X12354597Y12697723D01* +G01X12371615Y12691881D01* +G01X12383045Y12680451D01* +G01X12388887Y12657591D01* +G01X12388887Y12629143D01* +G01X12383045Y12600441D01* +G01X12371615Y12583423D01* +G01X12354597Y12577581D01* +G01X12343167Y12577581D01* +G01X12325895Y12583423D01* +G01X12320307Y12594853D01* +G01X12505219Y12680451D02* +G01X12499631Y12691881D01* +G01X12482359Y12697723D01* +G01X12470929Y12697723D01* +G01X12453911Y12691881D01* +G01X12442481Y12674863D01* +G01X12436639Y12646161D01* +G01X12436639Y12617713D01* +G01X12442481Y12594853D01* +G01X12453911Y12583423D01* +G01X12470929Y12577581D01* +G01X12476771Y12577581D01* +G01X12493789Y12583423D01* +G01X12505219Y12594853D01* +G01X12511061Y12611871D01* +G01X12511061Y12617713D01* +G01X12505219Y12634731D01* +G01X12493789Y12646161D01* +G01X12476771Y12652003D01* +G01X12470929Y12652003D01* +G01X12453911Y12646161D01* +G01X12442481Y12634731D01* +G01X12436639Y12617713D01* +G01X12627393Y12697723D02* +G01X12570243Y12697723D01* +G01X12564655Y12646161D01* +G01X12570243Y12652003D01* +G01X12587515Y12657591D01* +G01X12604533Y12657591D01* +G01X12621805Y12652003D01* +G01X12633235Y12640573D01* +G01X12638823Y12623301D01* +G01X12638823Y12611871D01* +G01X12633235Y12594853D01* +G01X12621805Y12583423D01* +G01X12604533Y12577581D01* +G01X12587515Y12577581D01* +G01X12570243Y12583423D01* +G01X12564655Y12589011D01* +G01X12558813Y12600441D01* +G01X12686575Y12657591D02* +G01X12686575Y12577581D01* +G01X12686575Y12634731D02* +G01X12703847Y12652003D01* +G01X12715277Y12657591D01* +G01X12732295Y12657591D01* +G01X12743725Y12652003D01* +G01X12749567Y12634731D01* +G01X12749567Y12577581D01* +G01X12749567Y12634731D02* +G01X12766585Y12652003D01* +G01X12778015Y12657591D01* +G01X12795287Y12657591D01* +G01X12806717Y12652003D01* +G01X12812305Y12634731D01* +G01X12812305Y12577581D01* +G01X12860057Y12657591D02* +G01X12860057Y12577581D01* +G01X12860057Y12634731D02* +G01X12877329Y12652003D01* +G01X12888759Y12657591D01* +G01X12905777Y12657591D01* +G01X12917207Y12652003D01* +G01X12923049Y12634731D01* +G01X12923049Y12577581D01* +G01X12923049Y12634731D02* +G01X12940067Y12652003D01* +G01X12951497Y12657591D01* +G01X12968769Y12657591D01* +G01X12980199Y12652003D01* +G01X12985787Y12634731D01* +G01X12985787Y12577581D01* +G01X13033539Y12720583D02* +G01X13044969Y12709153D01* +G01X13056399Y12691881D01* +G01X13067829Y12669021D01* +G01X13073671Y12640573D01* +G01X13073671Y12617713D01* +G01X13067829Y12589011D01* +G01X13056399Y12566151D01* +G01X13044969Y12549133D01* +G01X13033539Y12537703D01* +G01X13964848Y12697723D02* +G01X13964848Y12577581D01* +G01X13964848Y12697723D02* +G01X14016410Y12697723D01* +G01X14033428Y12691881D01* +G01X14039270Y12686293D01* +G01X14044858Y12674863D01* +G01X14044858Y12657591D01* +G01X14039270Y12646161D01* +G01X14033428Y12640573D01* +G01X14016410Y12634731D01* +G01X13964848Y12634731D01* +G01X14132742Y12697723D02* +G01X14132742Y12577581D01* +G01X14092610Y12697723D02* +G01X14172620Y12697723D01* +G01X14220372Y12697723D02* +G01X14220372Y12577581D01* +G01X14300382Y12697723D02* +G01X14300382Y12577581D01* +G01X14220372Y12640573D02* +G01X14300382Y12640573D01* +G01X15426256Y12697723D02* +G01X15426256Y12577581D01* +G01X15426256Y12697723D02* +G01X15477818Y12697723D01* +G01X15494836Y12691881D01* +G01X15500678Y12686293D01* +G01X15506266Y12674863D01* +G01X15506266Y12663433D01* +G01X15500678Y12652003D01* +G01X15494836Y12646161D01* +G01X15477818Y12640573D01* +G01X15426256Y12640573D01* +G01X15466388Y12640573D02* +G01X15506266Y12577581D01* +G01X15582720Y12657591D02* +G01X15571290Y12652003D01* +G01X15559860Y12640573D01* +G01X15554018Y12623301D01* +G01X15554018Y12611871D01* +G01X15559860Y12594853D01* +G01X15571290Y12583423D01* +G01X15582720Y12577581D01* +G01X15599738Y12577581D01* +G01X15611168Y12583423D01* +G01X15622598Y12594853D01* +G01X15628440Y12611871D01* +G01X15628440Y12623301D01* +G01X15622598Y12640573D01* +G01X15611168Y12652003D01* +G01X15599738Y12657591D01* +G01X15582720Y12657591D01* +G01X15676192Y12657591D02* +G01X15676192Y12600441D01* +G01X15682034Y12583423D01* +G01X15693464Y12577581D01* +G01X15710482Y12577581D01* +G01X15721912Y12583423D01* +G01X15739184Y12600441D01* +G01X15739184Y12657591D02* +G01X15739184Y12577581D01* +G01X15786936Y12657591D02* +G01X15786936Y12577581D01* +G01X15786936Y12634731D02* +G01X15804208Y12652003D01* +G01X15815638Y12657591D01* +G01X15832656Y12657591D01* +G01X15844086Y12652003D01* +G01X15849928Y12634731D01* +G01X15849928Y12577581D01* +G01X15966260Y12697723D02* +G01X15966260Y12577581D01* +G01X15966260Y12640573D02* +G01X15954830Y12652003D01* +G01X15943400Y12657591D01* +G01X15926382Y12657591D01* +G01X15914952Y12652003D01* +G01X15903522Y12640573D01* +G01X15897680Y12623301D01* +G01X15897680Y12611871D01* +G01X15903522Y12594853D01* +G01X15914952Y12583423D01* +G01X15926382Y12577581D01* +G01X15943400Y12577581D01* +G01X15954830Y12583423D01* +G01X15966260Y12594853D01* +G01X16857437Y12697723D02* +G01X16857437Y12577581D01* +G01X16857437Y12697723D02* +G01X16908999Y12697723D01* +G01X16926017Y12691881D01* +G01X16931859Y12686293D01* +G01X16937447Y12674863D01* +G01X16937447Y12657591D01* +G01X16931859Y12646161D01* +G01X16926017Y12640573D01* +G01X16908999Y12634731D01* +G01X16857437Y12634731D01* +G01X17053779Y12657591D02* +G01X17053779Y12577581D01* +G01X17053779Y12640573D02* +G01X17042349Y12652003D01* +G01X17030919Y12657591D01* +G01X17013901Y12657591D01* +G01X17002471Y12652003D01* +G01X16991041Y12640573D01* +G01X16985199Y12623301D01* +G01X16985199Y12611871D01* +G01X16991041Y12594853D01* +G01X17002471Y12583423D01* +G01X17013901Y12577581D01* +G01X17030919Y12577581D01* +G01X17042349Y12583423D01* +G01X17053779Y12594853D01* +G01X17170111Y12697723D02* +G01X17170111Y12577581D01* +G01X17170111Y12640573D02* +G01X17158681Y12652003D01* +G01X17147251Y12657591D01* +G01X17130233Y12657591D01* +G01X17118803Y12652003D01* +G01X17107373Y12640573D01* +G01X17101531Y12623301D01* +G01X17101531Y12611871D01* +G01X17107373Y12594853D01* +G01X17118803Y12583423D01* +G01X17130233Y12577581D01* +G01X17147251Y12577581D01* +G01X17158681Y12583423D01* +G01X17170111Y12594853D01* +G01X18566748Y12720583D02* +G01X18555318Y12709153D01* +G01X18543888Y12691881D01* +G01X18532458Y12669021D01* +G01X18526616Y12640573D01* +G01X18526616Y12617713D01* +G01X18532458Y12589011D01* +G01X18543888Y12566151D01* +G01X18555318Y12549133D01* +G01X18566748Y12537703D01* +G01X18614500Y12697723D02* +G01X18614500Y12577581D01* +G01X18614500Y12697723D02* +G01X18660220Y12577581D01* +G01X18705940Y12697723D02* +G01X18660220Y12577581D01* +G01X18705940Y12697723D02* +G01X18705940Y12577581D01* +G01X18753692Y12697723D02* +G01X18759534Y12691881D01* +G01X18765122Y12697723D01* +G01X18759534Y12703311D01* +G01X18753692Y12697723D01* +G01X18759534Y12657591D02* +G01X18759534Y12577581D01* +G01X18812874Y12657591D02* +G01X18875866Y12577581D01* +G01X18875866Y12657591D02* +G01X18812874Y12577581D01* +G01X18923618Y12623301D02* +G01X18992198Y12623301D01* +G01X18992198Y12634731D01* +G01X18986610Y12646161D01* +G01X18980768Y12652003D01* +G01X18969338Y12657591D01* +G01X18952320Y12657591D01* +G01X18940890Y12652003D01* +G01X18929460Y12640573D01* +G01X18923618Y12623301D01* +G01X18923618Y12611871D01* +G01X18929460Y12594853D01* +G01X18940890Y12583423D01* +G01X18952320Y12577581D01* +G01X18969338Y12577581D01* +G01X18980768Y12583423D01* +G01X18992198Y12594853D01* +G01X19108530Y12697723D02* +G01X19108530Y12577581D01* +G01X19108530Y12640573D02* +G01X19097100Y12652003D01* +G01X19085670Y12657591D01* +G01X19068652Y12657591D01* +G01X19057222Y12652003D01* +G01X19045792Y12640573D01* +G01X19039950Y12623301D01* +G01X19039950Y12611871D01* +G01X19045792Y12594853D01* +G01X19057222Y12583423D01* +G01X19068652Y12577581D01* +G01X19085670Y12577581D01* +G01X19097100Y12583423D01* +G01X19108530Y12594853D01* +G01X19156282Y12720583D02* +G01X19167712Y12709153D01* +G01X19179142Y12691881D01* +G01X19190572Y12669021D01* +G01X19196414Y12640573D01* +G01X19196414Y12617713D01* +G01X19190572Y12589011D01* +G01X19179142Y12566151D01* +G01X19167712Y12549133D01* +G01X19156282Y12537703D01* +G01X20486117Y12697723D02* +G01X20486117Y12577581D01* +G01X20445985Y12697723D02* +G01X20525995Y12697723D01* +G01X20602449Y12657591D02* +G01X20591019Y12652003D01* +G01X20579589Y12640573D01* +G01X20573747Y12623301D01* +G01X20573747Y12611871D01* +G01X20579589Y12594853D01* +G01X20591019Y12583423D01* +G01X20602449Y12577581D01* +G01X20619467Y12577581D01* +G01X20630897Y12583423D01* +G01X20642327Y12594853D01* +G01X20648169Y12611871D01* +G01X20648169Y12623301D01* +G01X20642327Y12640573D01* +G01X20630897Y12652003D01* +G01X20619467Y12657591D01* +G01X20602449Y12657591D01* +G01X20695921Y12657591D02* +G01X20695921Y12537703D01* +G01X20695921Y12640573D02* +G01X20707351Y12652003D01* +G01X20718781Y12657591D01* +G01X20736053Y12657591D01* +G01X20747483Y12652003D01* +G01X20758913Y12640573D01* +G01X20764501Y12623301D01* +G01X20764501Y12611871D01* +G01X20758913Y12594853D01* +G01X20747483Y12583423D01* +G01X20736053Y12577581D01* +G01X20718781Y12577581D01* +G01X20707351Y12583423D01* +G01X20695921Y12594853D01* +G01X20940269Y12697723D02* +G01X20940269Y12577581D01* +G01X20940269Y12577581D02* +G01X21008849Y12577581D01* +G01X21125181Y12657591D02* +G01X21125181Y12577581D01* +G01X21125181Y12640573D02* +G01X21113751Y12652003D01* +G01X21102321Y12657591D01* +G01X21085303Y12657591D01* +G01X21073873Y12652003D01* +G01X21062443Y12640573D01* +G01X21056601Y12623301D01* +G01X21056601Y12611871D01* +G01X21062443Y12594853D01* +G01X21073873Y12583423D01* +G01X21085303Y12577581D01* +G01X21102321Y12577581D01* +G01X21113751Y12583423D01* +G01X21125181Y12594853D01* +G01X21178775Y12657591D02* +G01X21213065Y12577581D01* +G01X21247355Y12657591D02* +G01X21213065Y12577581D01* +G01X21201635Y12554721D01* +G01X21190205Y12543291D01* +G01X21178775Y12537703D01* +G01X21172933Y12537703D01* +G01X21295107Y12623301D02* +G01X21363687Y12623301D01* +G01X21363687Y12634731D01* +G01X21358099Y12646161D01* +G01X21352257Y12652003D01* +G01X21340827Y12657591D01* +G01X21323809Y12657591D01* +G01X21312379Y12652003D01* +G01X21300949Y12640573D01* +G01X21295107Y12623301D01* +G01X21295107Y12611871D01* +G01X21300949Y12594853D01* +G01X21312379Y12583423D01* +G01X21323809Y12577581D01* +G01X21340827Y12577581D01* +G01X21352257Y12583423D01* +G01X21363687Y12594853D01* +G01X21411439Y12657591D02* +G01X21411439Y12577581D01* +G01X21411439Y12623301D02* +G01X21417281Y12640573D01* +G01X21428711Y12652003D01* +G01X21440141Y12657591D01* +G01X21457159Y12657591D01* +G01X21504911Y12629143D02* +G01X21607781Y12629143D01* +G01X21655533Y12697723D02* +G01X21655533Y12577581D01* +G01X21655533Y12697723D02* +G01X21707095Y12697723D01* +G01X21724113Y12691881D01* +G01X21729955Y12686293D01* +G01X21735543Y12674863D01* +G01X21735543Y12663433D01* +G01X21729955Y12652003D01* +G01X21724113Y12646161D01* +G01X21707095Y12640573D01* +G01X21655533Y12640573D02* +G01X21707095Y12640573D01* +G01X21724113Y12634731D01* +G01X21729955Y12629143D01* +G01X21735543Y12617713D01* +G01X21735543Y12600441D01* +G01X21729955Y12589011D01* +G01X21724113Y12583423D01* +G01X21707095Y12577581D01* +G01X21655533Y12577581D01* +G01X21811997Y12657591D02* +G01X21800567Y12652003D01* +G01X21789137Y12640573D01* +G01X21783295Y12623301D01* +G01X21783295Y12611871D01* +G01X21789137Y12594853D01* +G01X21800567Y12583423D01* +G01X21811997Y12577581D01* +G01X21829015Y12577581D01* +G01X21840445Y12583423D01* +G01X21851875Y12594853D01* +G01X21857717Y12611871D01* +G01X21857717Y12623301D01* +G01X21851875Y12640573D01* +G01X21840445Y12652003D01* +G01X21829015Y12657591D01* +G01X21811997Y12657591D01* +G01X21922741Y12697723D02* +G01X21922741Y12600441D01* +G01X21928329Y12583423D01* +G01X21939759Y12577581D01* +G01X21951189Y12577581D01* +G01X21905469Y12657591D02* +G01X21945601Y12657591D01* +G01X22016213Y12697723D02* +G01X22016213Y12600441D01* +G01X22021801Y12583423D01* +G01X22033231Y12577581D01* +G01X22044661Y12577581D01* +G01X21998941Y12657591D02* +G01X22039073Y12657591D01* +G01X22121115Y12657591D02* +G01X22109685Y12652003D01* +G01X22098255Y12640573D01* +G01X22092413Y12623301D01* +G01X22092413Y12611871D01* +G01X22098255Y12594853D01* +G01X22109685Y12583423D01* +G01X22121115Y12577581D01* +G01X22138133Y12577581D01* +G01X22149563Y12583423D01* +G01X22160993Y12594853D01* +G01X22166835Y12611871D01* +G01X22166835Y12623301D01* +G01X22160993Y12640573D01* +G01X22149563Y12652003D01* +G01X22138133Y12657591D01* +G01X22121115Y12657591D01* +G01X22214587Y12657591D02* +G01X22214587Y12577581D01* +G01X22214587Y12634731D02* +G01X22231859Y12652003D01* +G01X22243289Y12657591D01* +G01X22260307Y12657591D01* +G01X22271737Y12652003D01* +G01X22277579Y12634731D01* +G01X22277579Y12577581D01* +G01X22277579Y12634731D02* +G01X22294597Y12652003D01* +G01X22306027Y12657591D01* +G01X22323299Y12657591D01* +G01X22334729Y12652003D01* +G01X22340317Y12634731D01* +G01X22340317Y12577581D01* +G01X22516085Y12697723D02* +G01X22516085Y12577581D01* +G01X22516085Y12577581D02* +G01X22584665Y12577581D01* +G01X22700997Y12657591D02* +G01X22700997Y12577581D01* +G01X22700997Y12640573D02* +G01X22689567Y12652003D01* +G01X22678137Y12657591D01* +G01X22661119Y12657591D01* +G01X22649689Y12652003D01* +G01X22638259Y12640573D01* +G01X22632417Y12623301D01* +G01X22632417Y12611871D01* +G01X22638259Y12594853D01* +G01X22649689Y12583423D01* +G01X22661119Y12577581D01* +G01X22678137Y12577581D01* +G01X22689567Y12583423D01* +G01X22700997Y12594853D01* +G01X22754591Y12657591D02* +G01X22788881Y12577581D01* +G01X22823171Y12657591D02* +G01X22788881Y12577581D01* +G01X22777451Y12554721D01* +G01X22766021Y12543291D01* +G01X22754591Y12537703D01* +G01X22748749Y12537703D01* +G01X22870923Y12623301D02* +G01X22939503Y12623301D01* +G01X22939503Y12634731D01* +G01X22933915Y12646161D01* +G01X22928073Y12652003D01* +G01X22916643Y12657591D01* +G01X22899625Y12657591D01* +G01X22888195Y12652003D01* +G01X22876765Y12640573D01* +G01X22870923Y12623301D01* +G01X22870923Y12611871D01* +G01X22876765Y12594853D01* +G01X22888195Y12583423D01* +G01X22899625Y12577581D01* +G01X22916643Y12577581D01* +G01X22928073Y12583423D01* +G01X22939503Y12594853D01* +G01X22987255Y12657591D02* +G01X22987255Y12577581D01* +G01X22987255Y12623301D02* +G01X22993097Y12640573D01* +G01X23004527Y12652003D01* +G01X23015957Y12657591D01* +G01X23032975Y12657591D01* +G01X8736730Y12117151D02* +G01X8679580Y12037141D01* +G01X8765432Y12037141D01* +G01X8736730Y12117151D02* +G01X8736730Y11997009D01* +G01X8819026Y12088449D02* +G01X8819026Y12094291D01* +G01X8824614Y12105721D01* +G01X8830456Y12111309D01* +G01X8841886Y12117151D01* +G01X8864746Y12117151D01* +G01X8876176Y12111309D01* +G01X8881764Y12105721D01* +G01X8887606Y12094291D01* +G01X8887606Y12082861D01* +G01X8881764Y12071431D01* +G01X8870334Y12054159D01* +G01X8813184Y11997009D01* +G01X8893194Y11997009D01* +G01X10105173Y12117151D02* +G01X10168165Y12117151D01* +G01X10133875Y12071431D01* +G01X10150893Y12071431D01* +G01X10162323Y12065589D01* +G01X10168165Y12060001D01* +G01X10173753Y12042729D01* +G01X10173753Y12031299D01* +G01X10168165Y12014281D01* +G01X10156735Y12002851D01* +G01X10139463Y11997009D01* +G01X10122445Y11997009D01* +G01X10105173Y12002851D01* +G01X10099585Y12008439D01* +G01X10093743Y12019869D01* +G01X10295927Y12077019D02* +G01X10290085Y12060001D01* +G01X10278655Y12048571D01* +G01X10261637Y12042729D01* +G01X10255795Y12042729D01* +G01X10238777Y12048571D01* +G01X10227347Y12060001D01* +G01X10221505Y12077019D01* +G01X10221505Y12082861D01* +G01X10227347Y12099879D01* +G01X10238777Y12111309D01* +G01X10255795Y12117151D01* +G01X10261637Y12117151D01* +G01X10278655Y12111309D01* +G01X10290085Y12099879D01* +G01X10295927Y12077019D01* +G01X10295927Y12048571D01* +G01X10290085Y12019869D01* +G01X10278655Y12002851D01* +G01X10261637Y11997009D01* +G01X10250207Y11997009D01* +G01X10232935Y12002851D01* +G01X10227347Y12014281D01* +G01X10349521Y12025711D02* +G01X10343679Y12019869D01* +G01X10349521Y12014281D01* +G01X10355109Y12019869D01* +G01X10349521Y12025711D01* +G01X10460011Y12117151D02* +G01X10402861Y12037141D01* +G01X10488713Y12037141D01* +G01X10460011Y12117151D02* +G01X10460011Y11997009D01* +G01X10536465Y12077019D02* +G01X10599457Y11997009D01* +G01X10599457Y12077019D02* +G01X10536465Y11997009D01* +G01X10658639Y12117151D02* +G01X10721631Y12117151D01* +G01X10687341Y12071431D01* +G01X10704359Y12071431D01* +G01X10715789Y12065589D01* +G01X10721631Y12060001D01* +G01X10727219Y12042729D01* +G01X10727219Y12031299D01* +G01X10721631Y12014281D01* +G01X10710201Y12002851D01* +G01X10692929Y11997009D01* +G01X10675911Y11997009D01* +G01X10658639Y12002851D01* +G01X10653051Y12008439D01* +G01X10647209Y12019869D01* +G01X10849393Y12077019D02* +G01X10843551Y12060001D01* +G01X10832121Y12048571D01* +G01X10815103Y12042729D01* +G01X10809261Y12042729D01* +G01X10792243Y12048571D01* +G01X10780813Y12060001D01* +G01X10774971Y12077019D01* +G01X10774971Y12082861D01* +G01X10780813Y12099879D01* +G01X10792243Y12111309D01* +G01X10809261Y12117151D01* +G01X10815103Y12117151D01* +G01X10832121Y12111309D01* +G01X10843551Y12099879D01* +G01X10849393Y12077019D01* +G01X10849393Y12048571D01* +G01X10843551Y12019869D01* +G01X10832121Y12002851D01* +G01X10815103Y11997009D01* +G01X10803673Y11997009D01* +G01X10786401Y12002851D01* +G01X10780813Y12014281D01* +G01X10902987Y12025711D02* +G01X10897145Y12019869D01* +G01X10902987Y12014281D01* +G01X10908575Y12019869D01* +G01X10902987Y12025711D01* +G01X11013477Y12117151D02* +G01X10956327Y12037141D01* +G01X11042179Y12037141D01* +G01X11013477Y12117151D02* +G01X11013477Y11997009D01* +G01X11089931Y12077019D02* +G01X11089931Y11997009D01* +G01X11089931Y12054159D02* +G01X11107203Y12071431D01* +G01X11118633Y12077019D01* +G01X11135651Y12077019D01* +G01X11147081Y12071431D01* +G01X11152923Y12054159D01* +G01X11152923Y11997009D01* +G01X11152923Y12054159D02* +G01X11169941Y12071431D01* +G01X11181371Y12077019D01* +G01X11198643Y12077019D01* +G01X11210073Y12071431D01* +G01X11215661Y12054159D01* +G01X11215661Y11997009D01* +G01X11263413Y12117151D02* +G01X11269255Y12111309D01* +G01X11274843Y12117151D01* +G01X11269255Y12122739D01* +G01X11263413Y12117151D01* +G01X11269255Y12077019D02* +G01X11269255Y11997009D01* +G01X11322595Y12117151D02* +G01X11322595Y11997009D01* +G01X11410479Y12140011D02* +G01X11399049Y12128581D01* +G01X11387619Y12111309D01* +G01X11376189Y12088449D01* +G01X11370347Y12060001D01* +G01X11370347Y12037141D01* +G01X11376189Y12008439D01* +G01X11387619Y11985579D01* +G01X11399049Y11968561D01* +G01X11410479Y11957131D01* +G01X11458231Y12094291D02* +G01X11469661Y12099879D01* +G01X11486933Y12117151D01* +G01X11486933Y11997009D01* +G01X11540527Y12025711D02* +G01X11534685Y12019869D01* +G01X11540527Y12014281D01* +G01X11546115Y12019869D01* +G01X11540527Y12025711D01* +G01X11628157Y12117151D02* +G01X11611139Y12111309D01* +G01X11599709Y12094291D01* +G01X11593867Y12065589D01* +G01X11593867Y12048571D01* +G01X11599709Y12019869D01* +G01X11611139Y12002851D01* +G01X11628157Y11997009D01* +G01X11639587Y11997009D01* +G01X11656859Y12002851D01* +G01X11668289Y12019869D01* +G01X11673877Y12048571D01* +G01X11673877Y12065589D01* +G01X11668289Y12094291D01* +G01X11656859Y12111309D01* +G01X11639587Y12117151D01* +G01X11628157Y12117151D01* +G01X11755919Y12117151D02* +G01X11738901Y12111309D01* +G01X11727471Y12094291D01* +G01X11721629Y12065589D01* +G01X11721629Y12048571D01* +G01X11727471Y12019869D01* +G01X11738901Y12002851D01* +G01X11755919Y11997009D01* +G01X11767349Y11997009D01* +G01X11784621Y12002851D01* +G01X11796051Y12019869D01* +G01X11801639Y12048571D01* +G01X11801639Y12065589D01* +G01X11796051Y12094291D01* +G01X11784621Y12111309D01* +G01X11767349Y12117151D01* +G01X11755919Y12117151D01* +G01X11883681Y12117151D02* +G01X11866663Y12111309D01* +G01X11855233Y12094291D01* +G01X11849391Y12065589D01* +G01X11849391Y12048571D01* +G01X11855233Y12019869D01* +G01X11866663Y12002851D01* +G01X11883681Y11997009D01* +G01X11895111Y11997009D01* +G01X11912383Y12002851D01* +G01X11923813Y12019869D01* +G01X11929401Y12048571D01* +G01X11929401Y12065589D01* +G01X11923813Y12094291D01* +G01X11912383Y12111309D01* +G01X11895111Y12117151D01* +G01X11883681Y12117151D01* +G01X11977153Y12077019D02* +G01X12040145Y11997009D01* +G01X12040145Y12077019D02* +G01X11977153Y11997009D01* +G01X12087897Y12094291D02* +G01X12099327Y12099879D01* +G01X12116599Y12117151D01* +G01X12116599Y11997009D01* +G01X12170193Y12025711D02* +G01X12164351Y12019869D01* +G01X12170193Y12014281D01* +G01X12175781Y12019869D01* +G01X12170193Y12025711D01* +G01X12257823Y12117151D02* +G01X12240805Y12111309D01* +G01X12229375Y12094291D01* +G01X12223533Y12065589D01* +G01X12223533Y12048571D01* +G01X12229375Y12019869D01* +G01X12240805Y12002851D01* +G01X12257823Y11997009D01* +G01X12269253Y11997009D01* +G01X12286525Y12002851D01* +G01X12297955Y12019869D01* +G01X12303543Y12048571D01* +G01X12303543Y12065589D01* +G01X12297955Y12094291D01* +G01X12286525Y12111309D01* +G01X12269253Y12117151D01* +G01X12257823Y12117151D01* +G01X12385585Y12117151D02* +G01X12368567Y12111309D01* +G01X12357137Y12094291D01* +G01X12351295Y12065589D01* +G01X12351295Y12048571D01* +G01X12357137Y12019869D01* +G01X12368567Y12002851D01* +G01X12385585Y11997009D01* +G01X12397015Y11997009D01* +G01X12414287Y12002851D01* +G01X12425717Y12019869D01* +G01X12431305Y12048571D01* +G01X12431305Y12065589D01* +G01X12425717Y12094291D01* +G01X12414287Y12111309D01* +G01X12397015Y12117151D01* +G01X12385585Y12117151D01* +G01X12513347Y12117151D02* +G01X12496329Y12111309D01* +G01X12484899Y12094291D01* +G01X12479057Y12065589D01* +G01X12479057Y12048571D01* +G01X12484899Y12019869D01* +G01X12496329Y12002851D01* +G01X12513347Y11997009D01* +G01X12524777Y11997009D01* +G01X12542049Y12002851D01* +G01X12553479Y12019869D01* +G01X12559067Y12048571D01* +G01X12559067Y12065589D01* +G01X12553479Y12094291D01* +G01X12542049Y12111309D01* +G01X12524777Y12117151D01* +G01X12513347Y12117151D01* +G01X12606819Y12077019D02* +G01X12606819Y11997009D01* +G01X12606819Y12054159D02* +G01X12624091Y12071431D01* +G01X12635521Y12077019D01* +G01X12652539Y12077019D01* +G01X12663969Y12071431D01* +G01X12669811Y12054159D01* +G01X12669811Y11997009D01* +G01X12669811Y12054159D02* +G01X12686829Y12071431D01* +G01X12698259Y12077019D01* +G01X12715531Y12077019D01* +G01X12726961Y12071431D01* +G01X12732549Y12054159D01* +G01X12732549Y11997009D01* +G01X12780301Y12077019D02* +G01X12780301Y11997009D01* +G01X12780301Y12054159D02* +G01X12797573Y12071431D01* +G01X12809003Y12077019D01* +G01X12826021Y12077019D01* +G01X12837451Y12071431D01* +G01X12843293Y12054159D01* +G01X12843293Y11997009D01* +G01X12843293Y12054159D02* +G01X12860311Y12071431D01* +G01X12871741Y12077019D01* +G01X12889013Y12077019D01* +G01X12900443Y12071431D01* +G01X12906031Y12054159D01* +G01X12906031Y11997009D01* +G01X12953783Y12140011D02* +G01X12965213Y12128581D01* +G01X12976643Y12111309D01* +G01X12988073Y12088449D01* +G01X12993915Y12060001D01* +G01X12993915Y12037141D01* +G01X12988073Y12008439D01* +G01X12976643Y11985579D01* +G01X12965213Y11968561D01* +G01X12953783Y11957131D01* +G01X13964848Y12117151D02* +G01X13964848Y11997009D01* +G01X13964848Y12117151D02* +G01X14016410Y12117151D01* +G01X14033428Y12111309D01* +G01X14039270Y12105721D01* +G01X14044858Y12094291D01* +G01X14044858Y12077019D01* +G01X14039270Y12065589D01* +G01X14033428Y12060001D01* +G01X14016410Y12054159D01* +G01X13964848Y12054159D01* +G01X14132742Y12117151D02* +G01X14132742Y11997009D01* +G01X14092610Y12117151D02* +G01X14172620Y12117151D01* +G01X14220372Y12117151D02* +G01X14220372Y11997009D01* +G01X14300382Y12117151D02* +G01X14300382Y11997009D01* +G01X14220372Y12060001D02* +G01X14300382Y12060001D01* +G01X15426256Y12117151D02* +G01X15426256Y11997009D01* +G01X15426256Y12117151D02* +G01X15477818Y12117151D01* +G01X15494836Y12111309D01* +G01X15500678Y12105721D01* +G01X15506266Y12094291D01* +G01X15506266Y12082861D01* +G01X15500678Y12071431D01* +G01X15494836Y12065589D01* +G01X15477818Y12060001D01* +G01X15426256Y12060001D01* +G01X15466388Y12060001D02* +G01X15506266Y11997009D01* +G01X15582720Y12077019D02* +G01X15571290Y12071431D01* +G01X15559860Y12060001D01* +G01X15554018Y12042729D01* +G01X15554018Y12031299D01* +G01X15559860Y12014281D01* +G01X15571290Y12002851D01* +G01X15582720Y11997009D01* +G01X15599738Y11997009D01* +G01X15611168Y12002851D01* +G01X15622598Y12014281D01* +G01X15628440Y12031299D01* +G01X15628440Y12042729D01* +G01X15622598Y12060001D01* +G01X15611168Y12071431D01* +G01X15599738Y12077019D01* +G01X15582720Y12077019D01* +G01X15676192Y12077019D02* +G01X15676192Y12019869D01* +G01X15682034Y12002851D01* +G01X15693464Y11997009D01* +G01X15710482Y11997009D01* +G01X15721912Y12002851D01* +G01X15739184Y12019869D01* +G01X15739184Y12077019D02* +G01X15739184Y11997009D01* +G01X15786936Y12077019D02* +G01X15786936Y11997009D01* +G01X15786936Y12054159D02* +G01X15804208Y12071431D01* +G01X15815638Y12077019D01* +G01X15832656Y12077019D01* +G01X15844086Y12071431D01* +G01X15849928Y12054159D01* +G01X15849928Y11997009D01* +G01X15966260Y12117151D02* +G01X15966260Y11997009D01* +G01X15966260Y12060001D02* +G01X15954830Y12071431D01* +G01X15943400Y12077019D01* +G01X15926382Y12077019D01* +G01X15914952Y12071431D01* +G01X15903522Y12060001D01* +G01X15897680Y12042729D01* +G01X15897680Y12031299D01* +G01X15903522Y12014281D01* +G01X15914952Y12002851D01* +G01X15926382Y11997009D01* +G01X15943400Y11997009D01* +G01X15954830Y12002851D01* +G01X15966260Y12014281D01* +G01X16857437Y12117151D02* +G01X16857437Y11997009D01* +G01X16857437Y12117151D02* +G01X16908999Y12117151D01* +G01X16926017Y12111309D01* +G01X16931859Y12105721D01* +G01X16937447Y12094291D01* +G01X16937447Y12077019D01* +G01X16931859Y12065589D01* +G01X16926017Y12060001D01* +G01X16908999Y12054159D01* +G01X16857437Y12054159D01* +G01X17053779Y12077019D02* +G01X17053779Y11997009D01* +G01X17053779Y12060001D02* +G01X17042349Y12071431D01* +G01X17030919Y12077019D01* +G01X17013901Y12077019D01* +G01X17002471Y12071431D01* +G01X16991041Y12060001D01* +G01X16985199Y12042729D01* +G01X16985199Y12031299D01* +G01X16991041Y12014281D01* +G01X17002471Y12002851D01* +G01X17013901Y11997009D01* +G01X17030919Y11997009D01* +G01X17042349Y12002851D01* +G01X17053779Y12014281D01* +G01X17170111Y12117151D02* +G01X17170111Y11997009D01* +G01X17170111Y12060001D02* +G01X17158681Y12071431D01* +G01X17147251Y12077019D01* +G01X17130233Y12077019D01* +G01X17118803Y12071431D01* +G01X17107373Y12060001D01* +G01X17101531Y12042729D01* +G01X17101531Y12031299D01* +G01X17107373Y12014281D01* +G01X17118803Y12002851D01* +G01X17130233Y11997009D01* +G01X17147251Y11997009D01* +G01X17158681Y12002851D01* +G01X17170111Y12014281D01* +G01X18566748Y12140011D02* +G01X18555318Y12128581D01* +G01X18543888Y12111309D01* +G01X18532458Y12088449D01* +G01X18526616Y12060001D01* +G01X18526616Y12037141D01* +G01X18532458Y12008439D01* +G01X18543888Y11985579D01* +G01X18555318Y11968561D01* +G01X18566748Y11957131D01* +G01X18614500Y12117151D02* +G01X18614500Y11997009D01* +G01X18614500Y12117151D02* +G01X18660220Y11997009D01* +G01X18705940Y12117151D02* +G01X18660220Y11997009D01* +G01X18705940Y12117151D02* +G01X18705940Y11997009D01* +G01X18753692Y12117151D02* +G01X18759534Y12111309D01* +G01X18765122Y12117151D01* +G01X18759534Y12122739D01* +G01X18753692Y12117151D01* +G01X18759534Y12077019D02* +G01X18759534Y11997009D01* +G01X18812874Y12077019D02* +G01X18875866Y11997009D01* +G01X18875866Y12077019D02* +G01X18812874Y11997009D01* +G01X18923618Y12042729D02* +G01X18992198Y12042729D01* +G01X18992198Y12054159D01* +G01X18986610Y12065589D01* +G01X18980768Y12071431D01* +G01X18969338Y12077019D01* +G01X18952320Y12077019D01* +G01X18940890Y12071431D01* +G01X18929460Y12060001D01* +G01X18923618Y12042729D01* +G01X18923618Y12031299D01* +G01X18929460Y12014281D01* +G01X18940890Y12002851D01* +G01X18952320Y11997009D01* +G01X18969338Y11997009D01* +G01X18980768Y12002851D01* +G01X18992198Y12014281D01* +G01X19108530Y12117151D02* +G01X19108530Y11997009D01* +G01X19108530Y12060001D02* +G01X19097100Y12071431D01* +G01X19085670Y12077019D01* +G01X19068652Y12077019D01* +G01X19057222Y12071431D01* +G01X19045792Y12060001D01* +G01X19039950Y12042729D01* +G01X19039950Y12031299D01* +G01X19045792Y12014281D01* +G01X19057222Y12002851D01* +G01X19068652Y11997009D01* +G01X19085670Y11997009D01* +G01X19097100Y12002851D01* +G01X19108530Y12014281D01* +G01X19156282Y12140011D02* +G01X19167712Y12128581D01* +G01X19179142Y12111309D01* +G01X19190572Y12088449D01* +G01X19196414Y12060001D01* +G01X19196414Y12037141D01* +G01X19190572Y12008439D01* +G01X19179142Y11985579D01* +G01X19167712Y11968561D01* +G01X19156282Y11957131D01* +G01X20486117Y12117151D02* +G01X20486117Y11997009D01* +G01X20445985Y12117151D02* +G01X20525995Y12117151D01* +G01X20602449Y12077019D02* +G01X20591019Y12071431D01* +G01X20579589Y12060001D01* +G01X20573747Y12042729D01* +G01X20573747Y12031299D01* +G01X20579589Y12014281D01* +G01X20591019Y12002851D01* +G01X20602449Y11997009D01* +G01X20619467Y11997009D01* +G01X20630897Y12002851D01* +G01X20642327Y12014281D01* +G01X20648169Y12031299D01* +G01X20648169Y12042729D01* +G01X20642327Y12060001D01* +G01X20630897Y12071431D01* +G01X20619467Y12077019D01* +G01X20602449Y12077019D01* +G01X20695921Y12077019D02* +G01X20695921Y11957131D01* +G01X20695921Y12060001D02* +G01X20707351Y12071431D01* +G01X20718781Y12077019D01* +G01X20736053Y12077019D01* +G01X20747483Y12071431D01* +G01X20758913Y12060001D01* +G01X20764501Y12042729D01* +G01X20764501Y12031299D01* +G01X20758913Y12014281D01* +G01X20747483Y12002851D01* +G01X20736053Y11997009D01* +G01X20718781Y11997009D01* +G01X20707351Y12002851D01* +G01X20695921Y12014281D01* +G01X20940269Y12117151D02* +G01X20940269Y11997009D01* +G01X20940269Y11997009D02* +G01X21008849Y11997009D01* +G01X21125181Y12077019D02* +G01X21125181Y11997009D01* +G01X21125181Y12060001D02* +G01X21113751Y12071431D01* +G01X21102321Y12077019D01* +G01X21085303Y12077019D01* +G01X21073873Y12071431D01* +G01X21062443Y12060001D01* +G01X21056601Y12042729D01* +G01X21056601Y12031299D01* +G01X21062443Y12014281D01* +G01X21073873Y12002851D01* +G01X21085303Y11997009D01* +G01X21102321Y11997009D01* +G01X21113751Y12002851D01* +G01X21125181Y12014281D01* +G01X21178775Y12077019D02* +G01X21213065Y11997009D01* +G01X21247355Y12077019D02* +G01X21213065Y11997009D01* +G01X21201635Y11974149D01* +G01X21190205Y11962719D01* +G01X21178775Y11957131D01* +G01X21172933Y11957131D01* +G01X21295107Y12042729D02* +G01X21363687Y12042729D01* +G01X21363687Y12054159D01* +G01X21358099Y12065589D01* +G01X21352257Y12071431D01* +G01X21340827Y12077019D01* +G01X21323809Y12077019D01* +G01X21312379Y12071431D01* +G01X21300949Y12060001D01* +G01X21295107Y12042729D01* +G01X21295107Y12031299D01* +G01X21300949Y12014281D01* +G01X21312379Y12002851D01* +G01X21323809Y11997009D01* +G01X21340827Y11997009D01* +G01X21352257Y12002851D01* +G01X21363687Y12014281D01* +G01X21411439Y12077019D02* +G01X21411439Y11997009D01* +G01X21411439Y12042729D02* +G01X21417281Y12060001D01* +G01X21428711Y12071431D01* +G01X21440141Y12077019D01* +G01X21457159Y12077019D01* +G01X21504911Y12048571D02* +G01X21607781Y12048571D01* +G01X21655533Y12117151D02* +G01X21655533Y11997009D01* +G01X21655533Y12117151D02* +G01X21707095Y12117151D01* +G01X21724113Y12111309D01* +G01X21729955Y12105721D01* +G01X21735543Y12094291D01* +G01X21735543Y12082861D01* +G01X21729955Y12071431D01* +G01X21724113Y12065589D01* +G01X21707095Y12060001D01* +G01X21655533Y12060001D02* +G01X21707095Y12060001D01* +G01X21724113Y12054159D01* +G01X21729955Y12048571D01* +G01X21735543Y12037141D01* +G01X21735543Y12019869D01* +G01X21729955Y12008439D01* +G01X21724113Y12002851D01* +G01X21707095Y11997009D01* +G01X21655533Y11997009D01* +G01X21811997Y12077019D02* +G01X21800567Y12071431D01* +G01X21789137Y12060001D01* +G01X21783295Y12042729D01* +G01X21783295Y12031299D01* +G01X21789137Y12014281D01* +G01X21800567Y12002851D01* +G01X21811997Y11997009D01* +G01X21829015Y11997009D01* +G01X21840445Y12002851D01* +G01X21851875Y12014281D01* +G01X21857717Y12031299D01* +G01X21857717Y12042729D01* +G01X21851875Y12060001D01* +G01X21840445Y12071431D01* +G01X21829015Y12077019D01* +G01X21811997Y12077019D01* +G01X21922741Y12117151D02* +G01X21922741Y12019869D01* +G01X21928329Y12002851D01* +G01X21939759Y11997009D01* +G01X21951189Y11997009D01* +G01X21905469Y12077019D02* +G01X21945601Y12077019D01* +G01X22016213Y12117151D02* +G01X22016213Y12019869D01* +G01X22021801Y12002851D01* +G01X22033231Y11997009D01* +G01X22044661Y11997009D01* +G01X21998941Y12077019D02* +G01X22039073Y12077019D01* +G01X22121115Y12077019D02* +G01X22109685Y12071431D01* +G01X22098255Y12060001D01* +G01X22092413Y12042729D01* +G01X22092413Y12031299D01* +G01X22098255Y12014281D01* +G01X22109685Y12002851D01* +G01X22121115Y11997009D01* +G01X22138133Y11997009D01* +G01X22149563Y12002851D01* +G01X22160993Y12014281D01* +G01X22166835Y12031299D01* +G01X22166835Y12042729D01* +G01X22160993Y12060001D01* +G01X22149563Y12071431D01* +G01X22138133Y12077019D01* +G01X22121115Y12077019D01* +G01X22214587Y12077019D02* +G01X22214587Y11997009D01* +G01X22214587Y12054159D02* +G01X22231859Y12071431D01* +G01X22243289Y12077019D01* +G01X22260307Y12077019D01* +G01X22271737Y12071431D01* +G01X22277579Y12054159D01* +G01X22277579Y11997009D01* +G01X22277579Y12054159D02* +G01X22294597Y12071431D01* +G01X22306027Y12077019D01* +G01X22323299Y12077019D01* +G01X22334729Y12071431D01* +G01X22340317Y12054159D01* +G01X22340317Y11997009D01* +G01X22516085Y12117151D02* +G01X22516085Y11997009D01* +G01X22516085Y11997009D02* +G01X22584665Y11997009D01* +G01X22700997Y12077019D02* +G01X22700997Y11997009D01* +G01X22700997Y12060001D02* +G01X22689567Y12071431D01* +G01X22678137Y12077019D01* +G01X22661119Y12077019D01* +G01X22649689Y12071431D01* +G01X22638259Y12060001D01* +G01X22632417Y12042729D01* +G01X22632417Y12031299D01* +G01X22638259Y12014281D01* +G01X22649689Y12002851D01* +G01X22661119Y11997009D01* +G01X22678137Y11997009D01* +G01X22689567Y12002851D01* +G01X22700997Y12014281D01* +G01X22754591Y12077019D02* +G01X22788881Y11997009D01* +G01X22823171Y12077019D02* +G01X22788881Y11997009D01* +G01X22777451Y11974149D01* +G01X22766021Y11962719D01* +G01X22754591Y11957131D01* +G01X22748749Y11957131D01* +G01X22870923Y12042729D02* +G01X22939503Y12042729D01* +G01X22939503Y12054159D01* +G01X22933915Y12065589D01* +G01X22928073Y12071431D01* +G01X22916643Y12077019D01* +G01X22899625Y12077019D01* +G01X22888195Y12071431D01* +G01X22876765Y12060001D01* +G01X22870923Y12042729D01* +G01X22870923Y12031299D01* +G01X22876765Y12014281D01* +G01X22888195Y12002851D01* +G01X22899625Y11997009D01* +G01X22916643Y11997009D01* +G01X22928073Y12002851D01* +G01X22939503Y12014281D01* +G01X22987255Y12077019D02* +G01X22987255Y11997009D01* +G01X22987255Y12042729D02* +G01X22993097Y12060001D01* +G01X23004527Y12071431D01* +G01X23015957Y12077019D01* +G01X23032975Y12077019D01* +G01X8679580Y11513720D02* +G01X8691010Y11519308D01* +G01X8708282Y11536580D01* +G01X8708282Y11416438D01* +G01X8824614Y11536580D02* +G01X8767464Y11536580D01* +G01X8761876Y11485018D01* +G01X8767464Y11490860D01* +G01X8784736Y11496448D01* +G01X8801754Y11496448D01* +G01X8819026Y11490860D01* +G01X8830456Y11479430D01* +G01X8836044Y11462158D01* +G01X8836044Y11450728D01* +G01X8830456Y11433710D01* +G01X8819026Y11422280D01* +G01X8801754Y11416438D01* +G01X8784736Y11416438D01* +G01X8767464Y11422280D01* +G01X8761876Y11427868D01* +G01X8756034Y11439298D01* +G01X8895226Y11536580D02* +G01X8958218Y11536580D01* +G01X8923928Y11490860D01* +G01X8940946Y11490860D01* +G01X8952376Y11485018D01* +G01X8958218Y11479430D01* +G01X8963806Y11462158D01* +G01X8963806Y11450728D01* +G01X8958218Y11433710D01* +G01X8946788Y11422280D01* +G01X8929516Y11416438D01* +G01X8912498Y11416438D01* +G01X8895226Y11422280D01* +G01X8889638Y11427868D01* +G01X8883796Y11439298D01* +G01X10105173Y11536580D02* +G01X10168165Y11536580D01* +G01X10133875Y11490860D01* +G01X10150893Y11490860D01* +G01X10162323Y11485018D01* +G01X10168165Y11479430D01* +G01X10173753Y11462158D01* +G01X10173753Y11450728D01* +G01X10168165Y11433710D01* +G01X10156735Y11422280D01* +G01X10139463Y11416438D01* +G01X10122445Y11416438D01* +G01X10105173Y11422280D01* +G01X10099585Y11427868D01* +G01X10093743Y11439298D01* +G01X10290085Y11519308D02* +G01X10284497Y11530738D01* +G01X10267225Y11536580D01* +G01X10255795Y11536580D01* +G01X10238777Y11530738D01* +G01X10227347Y11513720D01* +G01X10221505Y11485018D01* +G01X10221505Y11456570D01* +G01X10227347Y11433710D01* +G01X10238777Y11422280D01* +G01X10255795Y11416438D01* +G01X10261637Y11416438D01* +G01X10278655Y11422280D01* +G01X10290085Y11433710D01* +G01X10295927Y11450728D01* +G01X10295927Y11456570D01* +G01X10290085Y11473588D01* +G01X10278655Y11485018D01* +G01X10261637Y11490860D01* +G01X10255795Y11490860D01* +G01X10238777Y11485018D01* +G01X10227347Y11473588D01* +G01X10221505Y11456570D01* +G01X10349521Y11445140D02* +G01X10343679Y11439298D01* +G01X10349521Y11433710D01* +G01X10355109Y11439298D01* +G01X10349521Y11445140D01* +G01X10437151Y11536580D02* +G01X10420133Y11530738D01* +G01X10408703Y11513720D01* +G01X10402861Y11485018D01* +G01X10402861Y11468000D01* +G01X10408703Y11439298D01* +G01X10420133Y11422280D01* +G01X10437151Y11416438D01* +G01X10448581Y11416438D01* +G01X10465853Y11422280D01* +G01X10477283Y11439298D01* +G01X10482871Y11468000D01* +G01X10482871Y11485018D01* +G01X10477283Y11513720D01* +G01X10465853Y11530738D01* +G01X10448581Y11536580D01* +G01X10437151Y11536580D01* +G01X10530623Y11496448D02* +G01X10593615Y11416438D01* +G01X10593615Y11496448D02* +G01X10530623Y11416438D01* +G01X10652797Y11536580D02* +G01X10715789Y11536580D01* +G01X10681499Y11490860D01* +G01X10698517Y11490860D01* +G01X10709947Y11485018D01* +G01X10715789Y11479430D01* +G01X10721377Y11462158D01* +G01X10721377Y11450728D01* +G01X10715789Y11433710D01* +G01X10704359Y11422280D01* +G01X10687087Y11416438D01* +G01X10670069Y11416438D01* +G01X10652797Y11422280D01* +G01X10647209Y11427868D01* +G01X10641367Y11439298D01* +G01X10837709Y11519308D02* +G01X10832121Y11530738D01* +G01X10814849Y11536580D01* +G01X10803419Y11536580D01* +G01X10786401Y11530738D01* +G01X10774971Y11513720D01* +G01X10769129Y11485018D01* +G01X10769129Y11456570D01* +G01X10774971Y11433710D01* +G01X10786401Y11422280D01* +G01X10803419Y11416438D01* +G01X10809261Y11416438D01* +G01X10826279Y11422280D01* +G01X10837709Y11433710D01* +G01X10843551Y11450728D01* +G01X10843551Y11456570D01* +G01X10837709Y11473588D01* +G01X10826279Y11485018D01* +G01X10809261Y11490860D01* +G01X10803419Y11490860D01* +G01X10786401Y11485018D01* +G01X10774971Y11473588D01* +G01X10769129Y11456570D01* +G01X10897145Y11445140D02* +G01X10891303Y11439298D01* +G01X10897145Y11433710D01* +G01X10902733Y11439298D01* +G01X10897145Y11445140D01* +G01X10984775Y11536580D02* +G01X10967757Y11530738D01* +G01X10956327Y11513720D01* +G01X10950485Y11485018D01* +G01X10950485Y11468000D01* +G01X10956327Y11439298D01* +G01X10967757Y11422280D01* +G01X10984775Y11416438D01* +G01X10996205Y11416438D01* +G01X11013477Y11422280D01* +G01X11024907Y11439298D01* +G01X11030495Y11468000D01* +G01X11030495Y11485018D01* +G01X11024907Y11513720D01* +G01X11013477Y11530738D01* +G01X10996205Y11536580D01* +G01X10984775Y11536580D01* +G01X11078247Y11496448D02* +G01X11078247Y11416438D01* +G01X11078247Y11473588D02* +G01X11095519Y11490860D01* +G01X11106949Y11496448D01* +G01X11123967Y11496448D01* +G01X11135397Y11490860D01* +G01X11141239Y11473588D01* +G01X11141239Y11416438D01* +G01X11141239Y11473588D02* +G01X11158257Y11490860D01* +G01X11169687Y11496448D01* +G01X11186959Y11496448D01* +G01X11198389Y11490860D01* +G01X11203977Y11473588D01* +G01X11203977Y11416438D01* +G01X11251729Y11536580D02* +G01X11257571Y11530738D01* +G01X11263159Y11536580D01* +G01X11257571Y11542168D01* +G01X11251729Y11536580D01* +G01X11257571Y11496448D02* +G01X11257571Y11416438D01* +G01X11310911Y11536580D02* +G01X11310911Y11416438D01* +G01X11398795Y11559440D02* +G01X11387365Y11548010D01* +G01X11375935Y11530738D01* +G01X11364505Y11507878D01* +G01X11358663Y11479430D01* +G01X11358663Y11456570D01* +G01X11364505Y11427868D01* +G01X11375935Y11405008D01* +G01X11387365Y11387990D01* +G01X11398795Y11376560D01* +G01X11480837Y11536580D02* +G01X11463819Y11530738D01* +G01X11452389Y11513720D01* +G01X11446547Y11485018D01* +G01X11446547Y11468000D01* +G01X11452389Y11439298D01* +G01X11463819Y11422280D01* +G01X11480837Y11416438D01* +G01X11492267Y11416438D01* +G01X11509539Y11422280D01* +G01X11520969Y11439298D01* +G01X11526557Y11468000D01* +G01X11526557Y11485018D01* +G01X11520969Y11513720D01* +G01X11509539Y11530738D01* +G01X11492267Y11536580D01* +G01X11480837Y11536580D01* +G01X11580151Y11445140D02* +G01X11574309Y11439298D01* +G01X11580151Y11433710D01* +G01X11585739Y11439298D01* +G01X11580151Y11445140D01* +G01X11707913Y11496448D02* +G01X11702071Y11479430D01* +G01X11690641Y11468000D01* +G01X11673623Y11462158D01* +G01X11667781Y11462158D01* +G01X11650763Y11468000D01* +G01X11639333Y11479430D01* +G01X11633491Y11496448D01* +G01X11633491Y11502290D01* +G01X11639333Y11519308D01* +G01X11650763Y11530738D01* +G01X11667781Y11536580D01* +G01X11673623Y11536580D01* +G01X11690641Y11530738D01* +G01X11702071Y11519308D01* +G01X11707913Y11496448D01* +G01X11707913Y11468000D01* +G01X11702071Y11439298D01* +G01X11690641Y11422280D01* +G01X11673623Y11416438D01* +G01X11662193Y11416438D01* +G01X11644921Y11422280D01* +G01X11639333Y11433710D01* +G01X11755665Y11513720D02* +G01X11767095Y11519308D01* +G01X11784367Y11536580D01* +G01X11784367Y11416438D01* +G01X11889269Y11536580D02* +G01X11832119Y11456570D01* +G01X11917971Y11456570D01* +G01X11889269Y11536580D02* +G01X11889269Y11416438D01* +G01X11965723Y11496448D02* +G01X12028715Y11416438D01* +G01X12028715Y11496448D02* +G01X11965723Y11416438D01* +G01X12110757Y11536580D02* +G01X12093739Y11530738D01* +G01X12082309Y11513720D01* +G01X12076467Y11485018D01* +G01X12076467Y11468000D01* +G01X12082309Y11439298D01* +G01X12093739Y11422280D01* +G01X12110757Y11416438D01* +G01X12122187Y11416438D01* +G01X12139459Y11422280D01* +G01X12150889Y11439298D01* +G01X12156477Y11468000D01* +G01X12156477Y11485018D01* +G01X12150889Y11513720D01* +G01X12139459Y11530738D01* +G01X12122187Y11536580D01* +G01X12110757Y11536580D01* +G01X12210071Y11445140D02* +G01X12204229Y11439298D01* +G01X12210071Y11433710D01* +G01X12215659Y11439298D01* +G01X12210071Y11445140D01* +G01X12337833Y11496448D02* +G01X12331991Y11479430D01* +G01X12320561Y11468000D01* +G01X12303543Y11462158D01* +G01X12297701Y11462158D01* +G01X12280683Y11468000D01* +G01X12269253Y11479430D01* +G01X12263411Y11496448D01* +G01X12263411Y11502290D01* +G01X12269253Y11519308D01* +G01X12280683Y11530738D01* +G01X12297701Y11536580D01* +G01X12303543Y11536580D01* +G01X12320561Y11530738D01* +G01X12331991Y11519308D01* +G01X12337833Y11496448D01* +G01X12337833Y11468000D01* +G01X12331991Y11439298D01* +G01X12320561Y11422280D01* +G01X12303543Y11416438D01* +G01X12292113Y11416438D01* +G01X12274841Y11422280D01* +G01X12269253Y11433710D01* +G01X12385585Y11513720D02* +G01X12397015Y11519308D01* +G01X12414287Y11536580D01* +G01X12414287Y11416438D01* +G01X12519189Y11536580D02* +G01X12462039Y11456570D01* +G01X12547891Y11456570D01* +G01X12519189Y11536580D02* +G01X12519189Y11416438D01* +G01X12595643Y11496448D02* +G01X12595643Y11416438D01* +G01X12595643Y11473588D02* +G01X12612915Y11490860D01* +G01X12624345Y11496448D01* +G01X12641363Y11496448D01* +G01X12652793Y11490860D01* +G01X12658635Y11473588D01* +G01X12658635Y11416438D01* +G01X12658635Y11473588D02* +G01X12675653Y11490860D01* +G01X12687083Y11496448D01* +G01X12704355Y11496448D01* +G01X12715785Y11490860D01* +G01X12721373Y11473588D01* +G01X12721373Y11416438D01* +G01X12769125Y11496448D02* +G01X12769125Y11416438D01* +G01X12769125Y11473588D02* +G01X12786397Y11490860D01* +G01X12797827Y11496448D01* +G01X12814845Y11496448D01* +G01X12826275Y11490860D01* +G01X12832117Y11473588D01* +G01X12832117Y11416438D01* +G01X12832117Y11473588D02* +G01X12849135Y11490860D01* +G01X12860565Y11496448D01* +G01X12877837Y11496448D01* +G01X12889267Y11490860D01* +G01X12894855Y11473588D01* +G01X12894855Y11416438D01* +G01X12942607Y11559440D02* +G01X12954037Y11548010D01* +G01X12965467Y11530738D01* +G01X12976897Y11507878D01* +G01X12982739Y11479430D01* +G01X12982739Y11456570D01* +G01X12976897Y11427868D01* +G01X12965467Y11405008D01* +G01X12954037Y11387990D01* +G01X12942607Y11376560D01* +G01X13964848Y11536580D02* +G01X13964848Y11416438D01* +G01X13964848Y11536580D02* +G01X14016410Y11536580D01* +G01X14033428Y11530738D01* +G01X14039270Y11525150D01* +G01X14044858Y11513720D01* +G01X14044858Y11496448D01* +G01X14039270Y11485018D01* +G01X14033428Y11479430D01* +G01X14016410Y11473588D01* +G01X13964848Y11473588D01* +G01X14132742Y11536580D02* +G01X14132742Y11416438D01* +G01X14092610Y11536580D02* +G01X14172620Y11536580D01* +G01X14220372Y11536580D02* +G01X14220372Y11416438D01* +G01X14300382Y11536580D02* +G01X14300382Y11416438D01* +G01X14220372Y11479430D02* +G01X14300382Y11479430D01* +G01X15426256Y11536580D02* +G01X15426256Y11416438D01* +G01X15426256Y11536580D02* +G01X15477818Y11536580D01* +G01X15494836Y11530738D01* +G01X15500678Y11525150D01* +G01X15506266Y11513720D01* +G01X15506266Y11502290D01* +G01X15500678Y11490860D01* +G01X15494836Y11485018D01* +G01X15477818Y11479430D01* +G01X15426256Y11479430D01* +G01X15466388Y11479430D02* +G01X15506266Y11416438D01* +G01X15582720Y11496448D02* +G01X15571290Y11490860D01* +G01X15559860Y11479430D01* +G01X15554018Y11462158D01* +G01X15554018Y11450728D01* +G01X15559860Y11433710D01* +G01X15571290Y11422280D01* +G01X15582720Y11416438D01* +G01X15599738Y11416438D01* +G01X15611168Y11422280D01* +G01X15622598Y11433710D01* +G01X15628440Y11450728D01* +G01X15628440Y11462158D01* +G01X15622598Y11479430D01* +G01X15611168Y11490860D01* +G01X15599738Y11496448D01* +G01X15582720Y11496448D01* +G01X15676192Y11496448D02* +G01X15676192Y11439298D01* +G01X15682034Y11422280D01* +G01X15693464Y11416438D01* +G01X15710482Y11416438D01* +G01X15721912Y11422280D01* +G01X15739184Y11439298D01* +G01X15739184Y11496448D02* +G01X15739184Y11416438D01* +G01X15786936Y11496448D02* +G01X15786936Y11416438D01* +G01X15786936Y11473588D02* +G01X15804208Y11490860D01* +G01X15815638Y11496448D01* +G01X15832656Y11496448D01* +G01X15844086Y11490860D01* +G01X15849928Y11473588D01* +G01X15849928Y11416438D01* +G01X15966260Y11536580D02* +G01X15966260Y11416438D01* +G01X15966260Y11479430D02* +G01X15954830Y11490860D01* +G01X15943400Y11496448D01* +G01X15926382Y11496448D01* +G01X15914952Y11490860D01* +G01X15903522Y11479430D01* +G01X15897680Y11462158D01* +G01X15897680Y11450728D01* +G01X15903522Y11433710D01* +G01X15914952Y11422280D01* +G01X15926382Y11416438D01* +G01X15943400Y11416438D01* +G01X15954830Y11422280D01* +G01X15966260Y11433710D01* +G01X16857437Y11536580D02* +G01X16857437Y11416438D01* +G01X16857437Y11536580D02* +G01X16908999Y11536580D01* +G01X16926017Y11530738D01* +G01X16931859Y11525150D01* +G01X16937447Y11513720D01* +G01X16937447Y11496448D01* +G01X16931859Y11485018D01* +G01X16926017Y11479430D01* +G01X16908999Y11473588D01* +G01X16857437Y11473588D01* +G01X17053779Y11496448D02* +G01X17053779Y11416438D01* +G01X17053779Y11479430D02* +G01X17042349Y11490860D01* +G01X17030919Y11496448D01* +G01X17013901Y11496448D01* +G01X17002471Y11490860D01* +G01X16991041Y11479430D01* +G01X16985199Y11462158D01* +G01X16985199Y11450728D01* +G01X16991041Y11433710D01* +G01X17002471Y11422280D01* +G01X17013901Y11416438D01* +G01X17030919Y11416438D01* +G01X17042349Y11422280D01* +G01X17053779Y11433710D01* +G01X17170111Y11536580D02* +G01X17170111Y11416438D01* +G01X17170111Y11479430D02* +G01X17158681Y11490860D01* +G01X17147251Y11496448D01* +G01X17130233Y11496448D01* +G01X17118803Y11490860D01* +G01X17107373Y11479430D01* +G01X17101531Y11462158D01* +G01X17101531Y11450728D01* +G01X17107373Y11433710D01* +G01X17118803Y11422280D01* +G01X17130233Y11416438D01* +G01X17147251Y11416438D01* +G01X17158681Y11422280D01* +G01X17170111Y11433710D01* +G01X18566748Y11559440D02* +G01X18555318Y11548010D01* +G01X18543888Y11530738D01* +G01X18532458Y11507878D01* +G01X18526616Y11479430D01* +G01X18526616Y11456570D01* +G01X18532458Y11427868D01* +G01X18543888Y11405008D01* +G01X18555318Y11387990D01* +G01X18566748Y11376560D01* +G01X18614500Y11536580D02* +G01X18614500Y11416438D01* +G01X18614500Y11536580D02* +G01X18660220Y11416438D01* +G01X18705940Y11536580D02* +G01X18660220Y11416438D01* +G01X18705940Y11536580D02* +G01X18705940Y11416438D01* +G01X18753692Y11536580D02* +G01X18759534Y11530738D01* +G01X18765122Y11536580D01* +G01X18759534Y11542168D01* +G01X18753692Y11536580D01* +G01X18759534Y11496448D02* +G01X18759534Y11416438D01* +G01X18812874Y11496448D02* +G01X18875866Y11416438D01* +G01X18875866Y11496448D02* +G01X18812874Y11416438D01* +G01X18923618Y11462158D02* +G01X18992198Y11462158D01* +G01X18992198Y11473588D01* +G01X18986610Y11485018D01* +G01X18980768Y11490860D01* +G01X18969338Y11496448D01* +G01X18952320Y11496448D01* +G01X18940890Y11490860D01* +G01X18929460Y11479430D01* +G01X18923618Y11462158D01* +G01X18923618Y11450728D01* +G01X18929460Y11433710D01* +G01X18940890Y11422280D01* +G01X18952320Y11416438D01* +G01X18969338Y11416438D01* +G01X18980768Y11422280D01* +G01X18992198Y11433710D01* +G01X19108530Y11536580D02* +G01X19108530Y11416438D01* +G01X19108530Y11479430D02* +G01X19097100Y11490860D01* +G01X19085670Y11496448D01* +G01X19068652Y11496448D01* +G01X19057222Y11490860D01* +G01X19045792Y11479430D01* +G01X19039950Y11462158D01* +G01X19039950Y11450728D01* +G01X19045792Y11433710D01* +G01X19057222Y11422280D01* +G01X19068652Y11416438D01* +G01X19085670Y11416438D01* +G01X19097100Y11422280D01* +G01X19108530Y11433710D01* +G01X19156282Y11559440D02* +G01X19167712Y11548010D01* +G01X19179142Y11530738D01* +G01X19190572Y11507878D01* +G01X19196414Y11479430D01* +G01X19196414Y11456570D01* +G01X19190572Y11427868D01* +G01X19179142Y11405008D01* +G01X19167712Y11387990D01* +G01X19156282Y11376560D01* +G01X20486117Y11536580D02* +G01X20486117Y11416438D01* +G01X20445985Y11536580D02* +G01X20525995Y11536580D01* +G01X20602449Y11496448D02* +G01X20591019Y11490860D01* +G01X20579589Y11479430D01* +G01X20573747Y11462158D01* +G01X20573747Y11450728D01* +G01X20579589Y11433710D01* +G01X20591019Y11422280D01* +G01X20602449Y11416438D01* +G01X20619467Y11416438D01* +G01X20630897Y11422280D01* +G01X20642327Y11433710D01* +G01X20648169Y11450728D01* +G01X20648169Y11462158D01* +G01X20642327Y11479430D01* +G01X20630897Y11490860D01* +G01X20619467Y11496448D01* +G01X20602449Y11496448D01* +G01X20695921Y11496448D02* +G01X20695921Y11376560D01* +G01X20695921Y11479430D02* +G01X20707351Y11490860D01* +G01X20718781Y11496448D01* +G01X20736053Y11496448D01* +G01X20747483Y11490860D01* +G01X20758913Y11479430D01* +G01X20764501Y11462158D01* +G01X20764501Y11450728D01* +G01X20758913Y11433710D01* +G01X20747483Y11422280D01* +G01X20736053Y11416438D01* +G01X20718781Y11416438D01* +G01X20707351Y11422280D01* +G01X20695921Y11433710D01* +G01X20940269Y11536580D02* +G01X20940269Y11416438D01* +G01X20940269Y11416438D02* +G01X21008849Y11416438D01* +G01X21125181Y11496448D02* +G01X21125181Y11416438D01* +G01X21125181Y11479430D02* +G01X21113751Y11490860D01* +G01X21102321Y11496448D01* +G01X21085303Y11496448D01* +G01X21073873Y11490860D01* +G01X21062443Y11479430D01* +G01X21056601Y11462158D01* +G01X21056601Y11450728D01* +G01X21062443Y11433710D01* +G01X21073873Y11422280D01* +G01X21085303Y11416438D01* +G01X21102321Y11416438D01* +G01X21113751Y11422280D01* +G01X21125181Y11433710D01* +G01X21178775Y11496448D02* +G01X21213065Y11416438D01* +G01X21247355Y11496448D02* +G01X21213065Y11416438D01* +G01X21201635Y11393578D01* +G01X21190205Y11382148D01* +G01X21178775Y11376560D01* +G01X21172933Y11376560D01* +G01X21295107Y11462158D02* +G01X21363687Y11462158D01* +G01X21363687Y11473588D01* +G01X21358099Y11485018D01* +G01X21352257Y11490860D01* +G01X21340827Y11496448D01* +G01X21323809Y11496448D01* +G01X21312379Y11490860D01* +G01X21300949Y11479430D01* +G01X21295107Y11462158D01* +G01X21295107Y11450728D01* +G01X21300949Y11433710D01* +G01X21312379Y11422280D01* +G01X21323809Y11416438D01* +G01X21340827Y11416438D01* +G01X21352257Y11422280D01* +G01X21363687Y11433710D01* +G01X21411439Y11496448D02* +G01X21411439Y11416438D01* +G01X21411439Y11462158D02* +G01X21417281Y11479430D01* +G01X21428711Y11490860D01* +G01X21440141Y11496448D01* +G01X21457159Y11496448D01* +G01X21504911Y11468000D02* +G01X21607781Y11468000D01* +G01X21655533Y11536580D02* +G01X21655533Y11416438D01* +G01X21655533Y11536580D02* +G01X21707095Y11536580D01* +G01X21724113Y11530738D01* +G01X21729955Y11525150D01* +G01X21735543Y11513720D01* +G01X21735543Y11502290D01* +G01X21729955Y11490860D01* +G01X21724113Y11485018D01* +G01X21707095Y11479430D01* +G01X21655533Y11479430D02* +G01X21707095Y11479430D01* +G01X21724113Y11473588D01* +G01X21729955Y11468000D01* +G01X21735543Y11456570D01* +G01X21735543Y11439298D01* +G01X21729955Y11427868D01* +G01X21724113Y11422280D01* +G01X21707095Y11416438D01* +G01X21655533Y11416438D01* +G01X21811997Y11496448D02* +G01X21800567Y11490860D01* +G01X21789137Y11479430D01* +G01X21783295Y11462158D01* +G01X21783295Y11450728D01* +G01X21789137Y11433710D01* +G01X21800567Y11422280D01* +G01X21811997Y11416438D01* +G01X21829015Y11416438D01* +G01X21840445Y11422280D01* +G01X21851875Y11433710D01* +G01X21857717Y11450728D01* +G01X21857717Y11462158D01* +G01X21851875Y11479430D01* +G01X21840445Y11490860D01* +G01X21829015Y11496448D01* +G01X21811997Y11496448D01* +G01X21922741Y11536580D02* +G01X21922741Y11439298D01* +G01X21928329Y11422280D01* +G01X21939759Y11416438D01* +G01X21951189Y11416438D01* +G01X21905469Y11496448D02* +G01X21945601Y11496448D01* +G01X22016213Y11536580D02* +G01X22016213Y11439298D01* +G01X22021801Y11422280D01* +G01X22033231Y11416438D01* +G01X22044661Y11416438D01* +G01X21998941Y11496448D02* +G01X22039073Y11496448D01* +G01X22121115Y11496448D02* +G01X22109685Y11490860D01* +G01X22098255Y11479430D01* +G01X22092413Y11462158D01* +G01X22092413Y11450728D01* +G01X22098255Y11433710D01* +G01X22109685Y11422280D01* +G01X22121115Y11416438D01* +G01X22138133Y11416438D01* +G01X22149563Y11422280D01* +G01X22160993Y11433710D01* +G01X22166835Y11450728D01* +G01X22166835Y11462158D01* +G01X22160993Y11479430D01* +G01X22149563Y11490860D01* +G01X22138133Y11496448D01* +G01X22121115Y11496448D01* +G01X22214587Y11496448D02* +G01X22214587Y11416438D01* +G01X22214587Y11473588D02* +G01X22231859Y11490860D01* +G01X22243289Y11496448D01* +G01X22260307Y11496448D01* +G01X22271737Y11490860D01* +G01X22277579Y11473588D01* +G01X22277579Y11416438D01* +G01X22277579Y11473588D02* +G01X22294597Y11490860D01* +G01X22306027Y11496448D01* +G01X22323299Y11496448D01* +G01X22334729Y11490860D01* +G01X22340317Y11473588D01* +G01X22340317Y11416438D01* +G01X22516085Y11536580D02* +G01X22516085Y11416438D01* +G01X22516085Y11416438D02* +G01X22584665Y11416438D01* +G01X22700997Y11496448D02* +G01X22700997Y11416438D01* +G01X22700997Y11479430D02* +G01X22689567Y11490860D01* +G01X22678137Y11496448D01* +G01X22661119Y11496448D01* +G01X22649689Y11490860D01* +G01X22638259Y11479430D01* +G01X22632417Y11462158D01* +G01X22632417Y11450728D01* +G01X22638259Y11433710D01* +G01X22649689Y11422280D01* +G01X22661119Y11416438D01* +G01X22678137Y11416438D01* +G01X22689567Y11422280D01* +G01X22700997Y11433710D01* +G01X22754591Y11496448D02* +G01X22788881Y11416438D01* +G01X22823171Y11496448D02* +G01X22788881Y11416438D01* +G01X22777451Y11393578D01* +G01X22766021Y11382148D01* +G01X22754591Y11376560D01* +G01X22748749Y11376560D01* +G01X22870923Y11462158D02* +G01X22939503Y11462158D01* +G01X22939503Y11473588D01* +G01X22933915Y11485018D01* +G01X22928073Y11490860D01* +G01X22916643Y11496448D01* +G01X22899625Y11496448D01* +G01X22888195Y11490860D01* +G01X22876765Y11479430D01* +G01X22870923Y11462158D01* +G01X22870923Y11450728D01* +G01X22876765Y11433710D01* +G01X22888195Y11422280D01* +G01X22899625Y11416438D01* +G01X22916643Y11416438D01* +G01X22928073Y11422280D01* +G01X22939503Y11433710D01* +G01X22987255Y11496448D02* +G01X22987255Y11416438D01* +G01X22987255Y11462158D02* +G01X22993097Y11479430D01* +G01X23004527Y11490860D01* +G01X23015957Y11496448D01* +G01X23032975Y11496448D01* + +G04 Image Start* +G36* +G01X7385975Y11889701D02* +G01X7378235Y11889112D01* +G01X7370392Y11888914D01* +G01X7362548Y11889112D01* +G01X7354808Y11889701D01* +G01X7347181Y11890670D01* +G01X7339676Y11892010D01* +G01X7325070Y11895765D01* +G01X7311067Y11900889D01* +G01X7297745Y11907307D01* +G01X7285180Y11914940D01* +G01X7273448Y11923713D01* +G01X7262626Y11933548D01* +G01X7252790Y11944371D01* +G01X7244017Y11956103D01* +G01X7236384Y11968668D01* +G01X7229967Y11981990D01* +G01X7224843Y11995992D01* +G01X7221087Y12010598D01* +G01X7219747Y12018103D01* +G01X7218778Y12025731D01* +G01X7218190Y12033471D01* +G01X7217992Y12041314D01* +G01X7243392Y12041314D01* +G01X7244048Y12028348D01* +G01X7245976Y12015751D01* +G01X7249111Y12003590D01* +G01X7253388Y11991927D01* +G01X7258742Y11980828D01* +G01X7265111Y11970357D01* +G01X7272428Y11960577D01* +G01X7280631Y11951554D01* +G01X7289654Y11943351D01* +G01X7299434Y11936033D01* +G01X7309906Y11929665D01* +G01X7321005Y11924310D01* +G01X7332667Y11920033D01* +G01X7344829Y11916899D01* +G01X7344829Y11916899D01* +G01X7357425Y11914971D01* +G01X7370392Y11914314D01* +G01X7383358Y11914971D01* +G01X7395954Y11916899D01* +G01X7408116Y11920033D01* +G01X7419778Y11924310D01* +G01X7430878Y11929665D01* +G01X7441349Y11936033D01* +G01X7451129Y11943351D01* +G01X7460152Y11951554D01* +G01X7468355Y11960577D01* +G01X7475672Y11970357D01* +G01X7482041Y11980828D01* +G01X7487395Y11991927D01* +G01X7491672Y12003590D01* +G01X7494807Y12015751D01* +G01X7496735Y12028348D01* +G01X7497392Y12041314D01* +G01X7496735Y12054281D01* +G01X7494807Y12066877D01* +G01X7491672Y12079038D01* +G01X7487395Y12090701D01* +G01X7482041Y12101800D01* +G01X7475672Y12112272D01* +G01X7468355Y12122051D01* +G01X7460152Y12131075D01* +G01X7451129Y12139277D01* +G01X7441349Y12146595D01* +G01X7430878Y12152963D01* +G01X7419778Y12158318D01* +G01X7408116Y12162595D01* +G01X7395954Y12165729D01* +G01X7383358Y12167657D01* +G01X7370392Y12168314D01* +G01X7357425Y12167657D01* +G01X7344829Y12165729D01* +G01X7332667Y12162595D01* +G01X7321005Y12158318D01* +G01X7309906Y12152963D01* +G01X7299434Y12146595D01* +G01X7289654Y12139277D01* +G01X7280631Y12131075D01* +G01X7272428Y12122051D01* +G01X7265111Y12112272D01* +G01X7258742Y12101800D01* +G01X7253388Y12090701D01* +G01X7249111Y12079038D01* +G01X7245976Y12066877D01* +G01X7244048Y12054281D01* +G01X7243392Y12041314D01* +G01X7217992Y12041314D01* +G01X7218190Y12049157D01* +G01X7218778Y12056897D01* +G01X7219747Y12064525D01* +G01X7221087Y12072030D01* +G01X7224843Y12086636D01* +G01X7229967Y12100638D01* +G01X7236384Y12113960D01* +G01X7244017Y12126526D01* +G01X7252790Y12138258D01* +G01X7262626Y12149080D01* +G01X7273448Y12158916D01* +G01X7285180Y12167689D01* +G01X7297745Y12175322D01* +G01X7311067Y12181739D01* +G01X7325070Y12186863D01* +G01X7339676Y12190618D01* +G01X7347181Y12191958D01* +G01X7354808Y12192927D01* +G01X7362548Y12193516D01* +G01X7370392Y12193714D01* +G01X7378235Y12193516D01* +G01X7385975Y12192927D01* +G01X7393602Y12191958D01* +G01X7401108Y12190618D01* +G01X7415713Y12186863D01* +G01X7429716Y12181739D01* +G01X7443038Y12175322D01* +G01X7455603Y12167689D01* +G01X7467335Y12158916D01* +G01X7478157Y12149080D01* +G01X7487993Y12138258D01* +G01X7496766Y12126526D01* +G01X7504399Y12113960D01* +G01X7510816Y12100638D01* +G01X7515941Y12086636D01* +G01X7519696Y12072030D01* +G01X7521036Y12064525D01* +G01X7522005Y12056897D01* +G01X7522593Y12049157D01* +G01X7522792Y12041314D01* +G01X7522593Y12033471D01* +G01X7522005Y12025731D01* +G01X7521036Y12018103D01* +G01X7519696Y12010598D01* +G01X7515941Y11995992D01* +G01X7510816Y11981990D01* +G01X7504399Y11968668D01* +G01X7496766Y11956103D01* +G01X7487993Y11944371D01* +G01X7478157Y11933548D01* +G01X7467335Y11923713D01* +G01X7455603Y11914940D01* +G01X7443038Y11907307D01* +G01X7429716Y11900889D01* +G01X7415713Y11895765D01* +G01X7401108Y11892010D01* +G01X7393602Y11890670D01* +G01X7385975Y11889701D01* +G37* +G36* +G01X7217992Y11613143D02* +G01X7522792Y11613143D01* +G01X7370392Y11349186D01* +G01X7232657Y11587743D01* +G01X7261984Y11587743D01* +G01X7370392Y11399986D01* +G01X7478799Y11587743D01* +G01X7478799Y11587743D01* +G01X7261984Y11587743D01* +G01X7232657Y11587743D01* +G01X7217992Y11613143D01* +G37* +G36* +G01X7217992Y12774286D02* +G01X7497392Y12774286D01* +G01X7497392Y12494886D01* +G01X7217992Y12494886D01* +G01X7217992Y12748886D01* +G01X7243392Y12748886D01* +G01X7243392Y12520286D01* +G01X7471992Y12520286D01* +G01X7471992Y12748886D01* +G01X7471992Y12748886D01* +G01X7243392Y12748886D01* +G01X7217992Y12748886D01* +G01X7217992Y12774286D01* +G37* + +G04 PolygonModel Start* +G54D14* +G01X6927706Y11177714D02* +G01X23623706Y11177714D01* +G01X6927706Y11758286D02* +G01X23623706Y11758286D01* +G01X6927706Y12338857D02* +G01X23623706Y12338857D01* +G01X6927706Y12919428D02* +G01X23623706Y12919428D01* +G01X6927706Y13500000D02* +G01X23623706Y13500000D01* +G01X6927706Y13500000D02* +G01X6927706Y11203114D01* +G01X8379134Y13500000D02* +G01X8379134Y11203114D01* +G01X9793298Y13500000D02* +G01X9793298Y11203114D01* +G01X13664403Y13500000D02* +G01X13664403Y11203114D01* +G01X15125810Y13500000D02* +G01X15125810Y11203114D01* +G01X16556991Y13500000D02* +G01X16556991Y11203114D01* +G01X18226170Y13500000D02* +G01X18226170Y11203114D01* +G01X20145539Y13500000D02* +G01X20145539Y11203114D01* +G01X23623706Y13500000D02* +G01X23623706Y11203114D01* + +M02* + diff --git a/hardware/gerber/Gerber_TopLayer.GTL b/hardware/gerber/Gerber_TopLayer.GTL new file mode 100644 index 0000000..c3aa21d --- /dev/null +++ b/hardware/gerber/Gerber_TopLayer.GTL @@ -0,0 +1,8895 @@ +G04 Layer: TopLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 92* +%FSLAX45Y45*% +%MOMM*% +%ADD10C,0.2032*% +%ADD11C,0.254*% +%ADD12C,1.651*% +%ADD13R,1.651X1.651*% +%ADD14O,1.905X1.397*% +%ADD15R,1.9112X1.397*% +%ADD16R,1.905X1.397*% +%ADD17C,1.6*% +%ADD18R,1.6X1.6*% +%ADD19C,1.397*% +%ADD20R,1.524X1.524*% +%ADD21C,1.524*% +%ADD22R,1.9X2.37599*% +%ADD23C,1.8*% +%ADD24C,1.016*% +%ADD25C,0.762*% +%ADD26C,0.4064*% +G75* + + +G04 Copper Start* +G36* +G01X2864188Y12311268D02* +G01X2864187Y12072538D01* +G01X2860922Y12092029D01* +G01X2854084Y12110571D01* +G01X2843913Y12127515D01* +G01X2830764Y12142269D01* +G01X2815099Y12154317D01* +G01X2797464Y12163236D01* +G01X2778476Y12168716D01* +G01X2758800Y12170564D01* +G01X2708000Y12170564D01* +G01X2688584Y12168765D01* +G01X2669830Y12163429D01* +G01X2652375Y12154737D01* +G01X2636815Y12142987D01* +G01X2623678Y12128577D01* +G01X2613413Y12111998D01* +G01X2606370Y12093816D01* +G01X2602787Y12074649D01* +G01X2602787Y12055150D01* +G01X2606370Y12035984D01* +G01X2613413Y12017801D01* +G01X2623678Y12001223D01* +G01X2636815Y11986813D01* +G01X2652375Y11975063D01* +G01X2669830Y11966371D01* +G01X2688584Y11961035D01* +G01X2708000Y11959236D01* +G01X2758800Y11959236D01* +G01X2778476Y11961084D01* +G01X2797463Y11966564D01* +G01X2815099Y11975483D01* +G01X2830764Y11987531D01* +G01X2843913Y12002285D01* +G01X2854084Y12019229D01* +G01X2860922Y12037771D01* +G01X2864187Y12057261D01* +G01X2864187Y11818545D01* +G01X2864187Y11818545D01* +G01X2860920Y11838035D01* +G01X2854082Y11856575D01* +G01X2843910Y11873518D01* +G01X2830762Y11888271D01* +G01X2815097Y11900318D01* +G01X2797462Y11909237D01* +G01X2778475Y11914716D01* +G01X2758800Y11916564D01* +G01X2708000Y11916564D01* +G01X2688584Y11914765D01* +G01X2669830Y11909429D01* +G01X2652375Y11900737D01* +G01X2636815Y11888987D01* +G01X2623678Y11874577D01* +G01X2613413Y11857998D01* +G01X2606370Y11839816D01* +G01X2602787Y11820649D01* +G01X2602787Y11801150D01* +G01X2606370Y11781984D01* +G01X2613413Y11763801D01* +G01X2623678Y11747223D01* +G01X2636815Y11732813D01* +G01X2652375Y11721063D01* +G01X2669830Y11712371D01* +G01X2688584Y11707035D01* +G01X2708000Y11705236D01* +G01X2758800Y11705236D01* +G01X2778475Y11707084D01* +G01X2797462Y11712563D01* +G01X2815097Y11721482D01* +G01X2830762Y11733528D01* +G01X2843910Y11748281D01* +G01X2854082Y11765224D01* +G01X2860920Y11783765D01* +G01X2864187Y11803255D01* +G01X2864187Y11564551D01* +G01X2864187Y11564551D01* +G01X2860919Y11584040D01* +G01X2854080Y11602580D01* +G01X2843908Y11619522D01* +G01X2830760Y11634274D01* +G01X2815095Y11646319D01* +G01X2797460Y11655237D01* +G01X2778474Y11660716D01* +G01X2758800Y11662564D01* +G01X2708000Y11662564D01* +G01X2688584Y11660765D01* +G01X2669830Y11655429D01* +G01X2652375Y11646737D01* +G01X2636815Y11634987D01* +G01X2623678Y11620577D01* +G01X2613413Y11603998D01* +G01X2606370Y11585816D01* +G01X2602787Y11566649D01* +G01X2602787Y11547150D01* +G01X2606370Y11527984D01* +G01X2613413Y11509801D01* +G01X2623678Y11493223D01* +G01X2636815Y11478813D01* +G01X2652375Y11467063D01* +G01X2669830Y11458371D01* +G01X2688584Y11453035D01* +G01X2708000Y11451236D01* +G01X2758800Y11451236D01* +G01X2778474Y11453084D01* +G01X2797460Y11458563D01* +G01X2815094Y11467481D01* +G01X2830760Y11479526D01* +G01X2843908Y11494278D01* +G01X2854080Y11511220D01* +G01X2860919Y11529759D01* +G01X2864187Y11549248D01* +G01X2864186Y11310558D01* +G01X2864186Y11310558D01* +G01X2860917Y11330046D01* +G01X2854078Y11348584D01* +G01X2843906Y11365525D01* +G01X2830757Y11380276D01* +G01X2815092Y11392320D01* +G01X2797459Y11401238D01* +G01X2778473Y11406716D01* +G01X2758800Y11408564D01* +G01X2708000Y11408564D01* +G01X2688584Y11406765D01* +G01X2669830Y11401429D01* +G01X2652375Y11392737D01* +G01X2636815Y11380987D01* +G01X2623678Y11366577D01* +G01X2613413Y11349998D01* +G01X2606370Y11331816D01* +G01X2602787Y11312649D01* +G01X2602787Y11293150D01* +G01X2606370Y11273984D01* +G01X2613413Y11255801D01* +G01X2623678Y11239223D01* +G01X2636815Y11224813D01* +G01X2652375Y11213063D01* +G01X2669830Y11204371D01* +G01X2688584Y11199035D01* +G01X2708000Y11197236D01* +G01X2758800Y11197236D01* +G01X2778701Y11199127D01* +G01X2797890Y11204733D01* +G01X2815680Y11213852D01* +G01X2831434Y11226159D01* +G01X2844587Y11241212D01* +G01X2854671Y11258474D01* +G01X2861322Y11277326D01* +G01X2864304Y11297093D01* +G01X2866730Y11286744D01* +G01X2872086Y11277562D01* +G01X2879902Y11270357D01* +G01X2889488Y11265764D01* +G01X2900000Y11264186D01* +G01X4750000Y11264186D01* +G01X4769828Y11262451D01* +G01X4789054Y11257300D01* +G01X4807093Y11248888D01* +G01X4823397Y11237472D01* +G01X4837472Y11223397D01* +G01X4848888Y11207093D01* +G01X4857300Y11189054D01* +G01X4862451Y11169828D01* +G01X4864186Y11150000D01* +G01X4891892Y5650013D01* +G01X4891892Y5650013D01* +G01X4890157Y5630186D01* +G01X4885005Y5610960D01* +G01X4876593Y5592922D01* +G01X4865177Y5576618D01* +G01X4851102Y5562544D01* +G01X4834798Y5551128D01* +G01X4816759Y5542716D01* +G01X4797534Y5537565D01* +G01X4777706Y5535830D01* +G01X2454000Y5535830D01* +G01X2442933Y5534077D01* +G01X2432949Y5528990D01* +G01X2425026Y5521067D01* +G01X2419939Y5511083D01* +G01X2418186Y5500016D01* +G01X2418186Y150000D01* +G01X2416451Y130172D01* +G01X2411300Y110946D01* +G01X2402888Y92907D01* +G01X2391471Y76603D01* +G01X2377397Y62528D01* +G01X2361093Y51112D01* +G01X2343054Y42700D01* +G01X2323828Y37549D01* +G01X2304000Y35814D01* +G01X150000Y35814D01* +G01X130172Y37549D01* +G01X110946Y42700D01* +G01X92907Y51112D01* +G01X76603Y62528D01* +G01X62528Y76603D01* +G01X51112Y92907D01* +G01X42700Y110946D01* +G01X37549Y130172D01* +G01X35814Y150000D01* +G01X35814Y556686D01* +G01X243180Y556686D01* +G01X243180Y535314D01* +G01X247107Y514306D01* +G01X254828Y494377D01* +G01X266078Y476206D01* +G01X280477Y460412D01* +G01X297532Y447533D01* +G01X316663Y438007D01* +G01X337219Y432158D01* +G01X358500Y430186D01* +G01X358500Y430186D01* +G01X379781Y432158D01* +G01X400337Y438007D01* +G01X419468Y447533D01* +G01X436523Y460412D01* +G01X441617Y466000D01* +G01X496686Y466000D01* +G01X498439Y454933D01* +G01X503526Y444949D01* +G01X511449Y437026D01* +G01X521433Y431939D01* +G01X532500Y430186D01* +G01X692500Y430186D01* +G01X703567Y431939D01* +G01X713551Y437026D01* +G01X721474Y444949D01* +G01X726561Y454933D01* +G01X728314Y466000D01* +G01X728314Y556686D01* +G01X1830680Y556686D01* +G01X1830680Y535314D01* +G01X1834607Y514306D01* +G01X1842328Y494377D01* +G01X1853578Y476206D01* +G01X1867977Y460412D01* +G01X1885032Y447533D01* +G01X1904163Y438007D01* +G01X1924719Y432158D01* +G01X1946000Y430186D01* +G01X1946000Y430186D01* +G01X1967281Y432158D01* +G01X1987837Y438007D01* +G01X2006968Y447533D01* +G01X2024023Y460412D01* +G01X2038421Y476206D01* +G01X2049672Y494377D01* +G01X2057393Y514306D01* +G01X2061320Y535314D01* +G01X2061320Y556686D01* +G01X2057393Y577694D01* +G01X2049672Y597623D01* +G01X2038421Y615793D01* +G01X2029117Y626000D01* +G01X2084186Y626000D01* +G01X2084186Y466000D01* +G01X2085939Y454933D01* +G01X2091026Y444949D01* +G01X2098949Y437026D01* +G01X2108933Y431939D01* +G01X2120000Y430186D01* +G01X2280000Y430186D01* +G01X2291067Y431939D01* +G01X2301051Y437026D01* +G01X2308974Y444949D01* +G01X2314061Y454933D01* +G01X2315814Y466000D01* +G01X2315814Y626000D01* +G01X2315814Y626000D01* +G01X2314061Y637067D01* +G01X2308974Y647051D01* +G01X2301051Y654974D01* +G01X2291067Y660061D01* +G01X2280000Y661814D01* +G01X2120000Y661814D01* +G01X2108933Y660061D01* +G01X2098949Y654974D01* +G01X2091026Y647051D01* +G01X2085939Y637067D01* +G01X2084186Y626000D01* +G01X2029117Y626000D01* +G01X2024023Y631587D01* +G01X2006968Y644467D01* +G01X1987837Y653993D01* +G01X1967281Y659842D01* +G01X1946000Y661814D01* +G01X1924719Y659842D01* +G01X1904163Y653993D01* +G01X1885032Y644467D01* +G01X1867977Y631587D01* +G01X1853578Y615793D01* +G01X1842328Y597623D01* +G01X1834607Y577694D01* +G01X1830680Y556686D01* +G01X728314Y556686D01* +G01X728314Y626000D01* +G01X728314Y626000D01* +G01X726561Y637067D01* +G01X721474Y647051D01* +G01X713551Y654974D01* +G01X703567Y660061D01* +G01X692500Y661814D01* +G01X532500Y661814D01* +G01X521433Y660061D01* +G01X511449Y654974D01* +G01X503526Y647051D01* +G01X498439Y637067D01* +G01X496686Y626000D01* +G01X496686Y466000D01* +G01X441617Y466000D01* +G01X450921Y476206D01* +G01X462172Y494377D01* +G01X469893Y514306D01* +G01X473820Y535314D01* +G01X473820Y556686D01* +G01X469893Y577694D01* +G01X462172Y597623D01* +G01X450921Y615793D01* +G01X436523Y631587D01* +G01X419468Y644467D01* +G01X400337Y653993D01* +G01X379781Y659842D01* +G01X358500Y661814D01* +G01X337219Y659842D01* +G01X316663Y653993D01* +G01X297532Y644467D01* +G01X280477Y631587D01* +G01X266078Y615793D01* +G01X254828Y597623D01* +G01X247107Y577694D01* +G01X243180Y556686D01* +G01X35814Y556686D01* +G01X35814Y810686D01* +G01X243180Y810686D01* +G01X243180Y789314D01* +G01X247107Y768306D01* +G01X254828Y748377D01* +G01X266078Y730206D01* +G01X280477Y714412D01* +G01X297532Y701533D01* +G01X316663Y692007D01* +G01X337219Y686158D01* +G01X358500Y684186D01* +G01X358500Y684186D01* +G01X379781Y686158D01* +G01X400337Y692007D01* +G01X419468Y701533D01* +G01X436523Y714412D01* +G01X450921Y730206D01* +G01X462172Y748377D01* +G01X469893Y768306D01* +G01X473820Y789314D01* +G01X473820Y810686D01* +G01X473820Y810686D01* +G01X497180Y810686D01* +G01X497180Y789314D01* +G01X501107Y768306D01* +G01X508828Y748377D01* +G01X520078Y730206D01* +G01X534477Y714412D01* +G01X551532Y701533D01* +G01X570663Y692007D01* +G01X591219Y686158D01* +G01X612500Y684186D01* +G01X612500Y684186D01* +G01X633781Y686158D01* +G01X654337Y692007D01* +G01X673468Y701533D01* +G01X690523Y714412D01* +G01X704921Y730206D01* +G01X716172Y748377D01* +G01X723893Y768306D01* +G01X727820Y789314D01* +G01X727820Y810686D01* +G01X727820Y810686D01* +G01X1830680Y810686D01* +G01X1830680Y789314D01* +G01X1834607Y768306D01* +G01X1842328Y748377D01* +G01X1853578Y730206D01* +G01X1867977Y714412D01* +G01X1885032Y701533D01* +G01X1904163Y692007D01* +G01X1924719Y686158D01* +G01X1946000Y684186D01* +G01X1946000Y684186D01* +G01X1967281Y686158D01* +G01X1987837Y692007D01* +G01X2006968Y701533D01* +G01X2024023Y714412D01* +G01X2038421Y730206D01* +G01X2049672Y748377D01* +G01X2057393Y768306D01* +G01X2061320Y789314D01* +G01X2061320Y810686D01* +G01X2061320Y810686D01* +G01X2084680Y810686D01* +G01X2084680Y789314D01* +G01X2088607Y768306D01* +G01X2096328Y748377D01* +G01X2107578Y730206D01* +G01X2121977Y714412D01* +G01X2139032Y701533D01* +G01X2158163Y692007D01* +G01X2178719Y686158D01* +G01X2200000Y684186D01* +G01X2200000Y684186D01* +G01X2221281Y686158D01* +G01X2241837Y692007D01* +G01X2260968Y701533D01* +G01X2278023Y714412D01* +G01X2292421Y730206D01* +G01X2303672Y748377D01* +G01X2311393Y768306D01* +G01X2315320Y789314D01* +G01X2315320Y810686D01* +G01X2311393Y831694D01* +G01X2303672Y851623D01* +G01X2292421Y869793D01* +G01X2278023Y885587D01* +G01X2260968Y898467D01* +G01X2241837Y907993D01* +G01X2221281Y913842D01* +G01X2200000Y915814D01* +G01X2178719Y913842D01* +G01X2158163Y907993D01* +G01X2139032Y898467D01* +G01X2121977Y885587D01* +G01X2107578Y869793D01* +G01X2096328Y851623D01* +G01X2088607Y831694D01* +G01X2084680Y810686D01* +G01X2061320Y810686D01* +G01X2057393Y831694D01* +G01X2049672Y851623D01* +G01X2038421Y869793D01* +G01X2024023Y885587D01* +G01X2006968Y898467D01* +G01X1987837Y907993D01* +G01X1967281Y913842D01* +G01X1946000Y915814D01* +G01X1924719Y913842D01* +G01X1904163Y907993D01* +G01X1885032Y898467D01* +G01X1867977Y885587D01* +G01X1853578Y869793D01* +G01X1842328Y851623D01* +G01X1834607Y831694D01* +G01X1830680Y810686D01* +G01X727820Y810686D01* +G01X723893Y831694D01* +G01X716172Y851623D01* +G01X704921Y869793D01* +G01X690523Y885587D01* +G01X673468Y898467D01* +G01X654337Y907993D01* +G01X633781Y913842D01* +G01X612500Y915814D01* +G01X591219Y913842D01* +G01X570663Y907993D01* +G01X551532Y898467D01* +G01X534477Y885587D01* +G01X520078Y869793D01* +G01X508828Y851623D01* +G01X501107Y831694D01* +G01X497180Y810686D01* +G01X473820Y810686D01* +G01X469893Y831694D01* +G01X462172Y851623D01* +G01X450921Y869793D01* +G01X436523Y885587D01* +G01X419468Y898467D01* +G01X400337Y907993D01* +G01X379781Y913842D01* +G01X358500Y915814D01* +G01X337219Y913842D01* +G01X316663Y907993D01* +G01X297532Y898467D01* +G01X280477Y885587D01* +G01X266078Y869793D01* +G01X254828Y851623D01* +G01X247107Y831694D01* +G01X243180Y810686D01* +G01X35814Y810686D01* +G01X35814Y1064686D01* +G01X243180Y1064686D01* +G01X243180Y1043314D01* +G01X247107Y1022306D01* +G01X254828Y1002377D01* +G01X266078Y984206D01* +G01X280477Y968412D01* +G01X297532Y955533D01* +G01X316663Y946007D01* +G01X337219Y940158D01* +G01X358500Y938186D01* +G01X358500Y938186D01* +G01X379781Y940158D01* +G01X400337Y946007D01* +G01X419468Y955533D01* +G01X436523Y968412D01* +G01X450921Y984206D01* +G01X462172Y1002377D01* +G01X469893Y1022306D01* +G01X473820Y1043314D01* +G01X473820Y1064686D01* +G01X473820Y1064686D01* +G01X497180Y1064686D01* +G01X497180Y1043314D01* +G01X501107Y1022306D01* +G01X508828Y1002377D01* +G01X520078Y984206D01* +G01X534477Y968412D01* +G01X551532Y955533D01* +G01X570663Y946007D01* +G01X591219Y940158D01* +G01X612500Y938186D01* +G01X612500Y938186D01* +G01X633781Y940158D01* +G01X654337Y946007D01* +G01X673468Y955533D01* +G01X690523Y968412D01* +G01X704921Y984206D01* +G01X716172Y1002377D01* +G01X723893Y1022306D01* +G01X727820Y1043314D01* +G01X727820Y1064686D01* +G01X727820Y1064686D01* +G01X1830680Y1064686D01* +G01X1830680Y1043314D01* +G01X1834607Y1022306D01* +G01X1842328Y1002377D01* +G01X1853578Y984206D01* +G01X1867977Y968412D01* +G01X1885032Y955533D01* +G01X1904163Y946007D01* +G01X1924719Y940158D01* +G01X1946000Y938186D01* +G01X1946000Y938186D01* +G01X1967281Y940158D01* +G01X1987837Y946007D01* +G01X2006968Y955533D01* +G01X2024023Y968412D01* +G01X2038421Y984206D01* +G01X2049672Y1002377D01* +G01X2057393Y1022306D01* +G01X2061320Y1043314D01* +G01X2061320Y1064686D01* +G01X2061320Y1064686D01* +G01X2084680Y1064686D01* +G01X2084680Y1043314D01* +G01X2088607Y1022306D01* +G01X2096328Y1002377D01* +G01X2107578Y984206D01* +G01X2121977Y968412D01* +G01X2139032Y955533D01* +G01X2158163Y946007D01* +G01X2178719Y940158D01* +G01X2200000Y938186D01* +G01X2200000Y938186D01* +G01X2221281Y940158D01* +G01X2241837Y946007D01* +G01X2260968Y955533D01* +G01X2278023Y968412D01* +G01X2292421Y984206D01* +G01X2303672Y1002377D01* +G01X2311393Y1022306D01* +G01X2315320Y1043314D01* +G01X2315320Y1064686D01* +G01X2311393Y1085694D01* +G01X2303672Y1105623D01* +G01X2292421Y1123793D01* +G01X2278023Y1139587D01* +G01X2260968Y1152467D01* +G01X2241837Y1161993D01* +G01X2221281Y1167842D01* +G01X2200000Y1169814D01* +G01X2178719Y1167842D01* +G01X2158163Y1161993D01* +G01X2139032Y1152467D01* +G01X2121977Y1139587D01* +G01X2107578Y1123793D01* +G01X2096328Y1105623D01* +G01X2088607Y1085694D01* +G01X2084680Y1064686D01* +G01X2061320Y1064686D01* +G01X2057393Y1085694D01* +G01X2049672Y1105623D01* +G01X2038421Y1123793D01* +G01X2024023Y1139587D01* +G01X2006968Y1152467D01* +G01X1987837Y1161993D01* +G01X1967281Y1167842D01* +G01X1946000Y1169814D01* +G01X1924719Y1167842D01* +G01X1904163Y1161993D01* +G01X1885032Y1152467D01* +G01X1867977Y1139587D01* +G01X1853578Y1123793D01* +G01X1842328Y1105623D01* +G01X1834607Y1085694D01* +G01X1830680Y1064686D01* +G01X727820Y1064686D01* +G01X723893Y1085694D01* +G01X716172Y1105623D01* +G01X704921Y1123793D01* +G01X690523Y1139587D01* +G01X673468Y1152467D01* +G01X654337Y1161993D01* +G01X633781Y1167842D01* +G01X612500Y1169814D01* +G01X591219Y1167842D01* +G01X570663Y1161993D01* +G01X551532Y1152467D01* +G01X534477Y1139587D01* +G01X520078Y1123793D01* +G01X508828Y1105623D01* +G01X501107Y1085694D01* +G01X497180Y1064686D01* +G01X473820Y1064686D01* +G01X469893Y1085694D01* +G01X462172Y1105623D01* +G01X450921Y1123793D01* +G01X436523Y1139587D01* +G01X419468Y1152467D01* +G01X400337Y1161993D01* +G01X379781Y1167842D01* +G01X358500Y1169814D01* +G01X337219Y1167842D01* +G01X316663Y1161993D01* +G01X297532Y1152467D01* +G01X280477Y1139587D01* +G01X266078Y1123793D01* +G01X254828Y1105623D01* +G01X247107Y1085694D01* +G01X243180Y1064686D01* +G01X35814Y1064686D01* +G01X35814Y1318686D01* +G01X243180Y1318686D01* +G01X243180Y1297314D01* +G01X247107Y1276306D01* +G01X254828Y1256377D01* +G01X266078Y1238206D01* +G01X280477Y1222412D01* +G01X297532Y1209533D01* +G01X316663Y1200007D01* +G01X337219Y1194158D01* +G01X358500Y1192186D01* +G01X358500Y1192186D01* +G01X379781Y1194158D01* +G01X400337Y1200007D01* +G01X419468Y1209533D01* +G01X436523Y1222412D01* +G01X450921Y1238206D01* +G01X462172Y1256377D01* +G01X469893Y1276306D01* +G01X473820Y1297314D01* +G01X473820Y1318686D01* +G01X473820Y1318686D01* +G01X497180Y1318686D01* +G01X497180Y1297314D01* +G01X501107Y1276306D01* +G01X508828Y1256377D01* +G01X520078Y1238206D01* +G01X534477Y1222412D01* +G01X551532Y1209533D01* +G01X570663Y1200007D01* +G01X591219Y1194158D01* +G01X612500Y1192186D01* +G01X612500Y1192186D01* +G01X633781Y1194158D01* +G01X654337Y1200007D01* +G01X673468Y1209533D01* +G01X690523Y1222412D01* +G01X704921Y1238206D01* +G01X716172Y1256377D01* +G01X723893Y1276306D01* +G01X727820Y1297314D01* +G01X727820Y1318686D01* +G01X727820Y1318686D01* +G01X1830680Y1318686D01* +G01X1830680Y1297314D01* +G01X1834607Y1276306D01* +G01X1842328Y1256377D01* +G01X1853578Y1238206D01* +G01X1867977Y1222412D01* +G01X1885032Y1209533D01* +G01X1904163Y1200007D01* +G01X1924719Y1194158D01* +G01X1946000Y1192186D01* +G01X1946000Y1192186D01* +G01X1967281Y1194158D01* +G01X1987837Y1200007D01* +G01X2006968Y1209533D01* +G01X2024023Y1222412D01* +G01X2038421Y1238206D01* +G01X2049672Y1256377D01* +G01X2057393Y1276306D01* +G01X2061320Y1297314D01* +G01X2061320Y1318686D01* +G01X2061320Y1318686D01* +G01X2084680Y1318686D01* +G01X2084680Y1297314D01* +G01X2088607Y1276306D01* +G01X2096328Y1256377D01* +G01X2107578Y1238206D01* +G01X2121977Y1222412D01* +G01X2139032Y1209533D01* +G01X2158163Y1200007D01* +G01X2178719Y1194158D01* +G01X2200000Y1192186D01* +G01X2200000Y1192186D01* +G01X2221281Y1194158D01* +G01X2241837Y1200007D01* +G01X2260968Y1209533D01* +G01X2278023Y1222412D01* +G01X2292421Y1238206D01* +G01X2303672Y1256377D01* +G01X2311393Y1276306D01* +G01X2315320Y1297314D01* +G01X2315320Y1318686D01* +G01X2311393Y1339694D01* +G01X2303672Y1359623D01* +G01X2292421Y1377793D01* +G01X2278023Y1393587D01* +G01X2260968Y1406467D01* +G01X2241837Y1415993D01* +G01X2221281Y1421842D01* +G01X2200000Y1423814D01* +G01X2178719Y1421842D01* +G01X2158163Y1415993D01* +G01X2139032Y1406467D01* +G01X2121977Y1393587D01* +G01X2107578Y1377793D01* +G01X2096328Y1359623D01* +G01X2088607Y1339694D01* +G01X2084680Y1318686D01* +G01X2061320Y1318686D01* +G01X2057393Y1339694D01* +G01X2049672Y1359623D01* +G01X2038421Y1377793D01* +G01X2024023Y1393587D01* +G01X2006968Y1406467D01* +G01X1987837Y1415993D01* +G01X1967281Y1421842D01* +G01X1946000Y1423814D01* +G01X1924719Y1421842D01* +G01X1904163Y1415993D01* +G01X1885032Y1406467D01* +G01X1867977Y1393587D01* +G01X1853578Y1377793D01* +G01X1842328Y1359623D01* +G01X1834607Y1339694D01* +G01X1830680Y1318686D01* +G01X727820Y1318686D01* +G01X723893Y1339694D01* +G01X716172Y1359623D01* +G01X704921Y1377793D01* +G01X690523Y1393587D01* +G01X673468Y1406467D01* +G01X654337Y1415993D01* +G01X633781Y1421842D01* +G01X612500Y1423814D01* +G01X591219Y1421842D01* +G01X570663Y1415993D01* +G01X551532Y1406467D01* +G01X534477Y1393587D01* +G01X520078Y1377793D01* +G01X508828Y1359623D01* +G01X501107Y1339694D01* +G01X497180Y1318686D01* +G01X473820Y1318686D01* +G01X469893Y1339694D01* +G01X462172Y1359623D01* +G01X450921Y1377793D01* +G01X436523Y1393587D01* +G01X419468Y1406467D01* +G01X400337Y1415993D01* +G01X379781Y1421842D01* +G01X358500Y1423814D01* +G01X337219Y1421842D01* +G01X316663Y1415993D01* +G01X297532Y1406467D01* +G01X280477Y1393587D01* +G01X266078Y1377793D01* +G01X254828Y1359623D01* +G01X247107Y1339694D01* +G01X243180Y1318686D01* +G01X35814Y1318686D01* +G01X35814Y1572686D01* +G01X243180Y1572686D01* +G01X243180Y1551314D01* +G01X247107Y1530306D01* +G01X254828Y1510377D01* +G01X266078Y1492206D01* +G01X280477Y1476412D01* +G01X297532Y1463533D01* +G01X316663Y1454007D01* +G01X337219Y1448158D01* +G01X358500Y1446186D01* +G01X358500Y1446186D01* +G01X379781Y1448158D01* +G01X400337Y1454007D01* +G01X419468Y1463533D01* +G01X436523Y1476412D01* +G01X450921Y1492206D01* +G01X462172Y1510377D01* +G01X469893Y1530306D01* +G01X473820Y1551314D01* +G01X473820Y1572686D01* +G01X473820Y1572686D01* +G01X497180Y1572686D01* +G01X497180Y1551314D01* +G01X501107Y1530306D01* +G01X508828Y1510377D01* +G01X520078Y1492206D01* +G01X534477Y1476412D01* +G01X551532Y1463533D01* +G01X570663Y1454007D01* +G01X591219Y1448158D01* +G01X612500Y1446186D01* +G01X612500Y1446186D01* +G01X633781Y1448158D01* +G01X654337Y1454007D01* +G01X673468Y1463533D01* +G01X690523Y1476412D01* +G01X704921Y1492206D01* +G01X716172Y1510377D01* +G01X723893Y1530306D01* +G01X727820Y1551314D01* +G01X727820Y1572686D01* +G01X727820Y1572686D01* +G01X1830680Y1572686D01* +G01X1830680Y1551314D01* +G01X1834607Y1530306D01* +G01X1842328Y1510377D01* +G01X1853578Y1492206D01* +G01X1867977Y1476412D01* +G01X1885032Y1463533D01* +G01X1904163Y1454007D01* +G01X1924719Y1448158D01* +G01X1946000Y1446186D01* +G01X1946000Y1446186D01* +G01X1967281Y1448158D01* +G01X1987837Y1454007D01* +G01X2006968Y1463533D01* +G01X2024023Y1476412D01* +G01X2038421Y1492206D01* +G01X2049672Y1510377D01* +G01X2057393Y1530306D01* +G01X2061320Y1551314D01* +G01X2061320Y1572686D01* +G01X2061320Y1572686D01* +G01X2084680Y1572686D01* +G01X2084680Y1551314D01* +G01X2088607Y1530306D01* +G01X2096328Y1510377D01* +G01X2107578Y1492206D01* +G01X2121977Y1476412D01* +G01X2139032Y1463533D01* +G01X2158163Y1454007D01* +G01X2178719Y1448158D01* +G01X2200000Y1446186D01* +G01X2200000Y1446186D01* +G01X2221281Y1448158D01* +G01X2241837Y1454007D01* +G01X2260968Y1463533D01* +G01X2278023Y1476412D01* +G01X2292421Y1492206D01* +G01X2303672Y1510377D01* +G01X2311393Y1530306D01* +G01X2315320Y1551314D01* +G01X2315320Y1572686D01* +G01X2311393Y1593694D01* +G01X2303672Y1613623D01* +G01X2292421Y1631793D01* +G01X2278023Y1647587D01* +G01X2260968Y1660467D01* +G01X2241837Y1669993D01* +G01X2221281Y1675842D01* +G01X2200000Y1677814D01* +G01X2178719Y1675842D01* +G01X2158163Y1669993D01* +G01X2139032Y1660467D01* +G01X2121977Y1647587D01* +G01X2107578Y1631793D01* +G01X2096328Y1613623D01* +G01X2088607Y1593694D01* +G01X2084680Y1572686D01* +G01X2061320Y1572686D01* +G01X2057393Y1593694D01* +G01X2049672Y1613623D01* +G01X2038421Y1631793D01* +G01X2024023Y1647587D01* +G01X2006968Y1660467D01* +G01X1987837Y1669993D01* +G01X1967281Y1675842D01* +G01X1946000Y1677814D01* +G01X1924719Y1675842D01* +G01X1904163Y1669993D01* +G01X1885032Y1660467D01* +G01X1867977Y1647587D01* +G01X1853578Y1631793D01* +G01X1842328Y1613623D01* +G01X1834607Y1593694D01* +G01X1830680Y1572686D01* +G01X727820Y1572686D01* +G01X723893Y1593694D01* +G01X716172Y1613623D01* +G01X704921Y1631793D01* +G01X690523Y1647587D01* +G01X673468Y1660467D01* +G01X654337Y1669993D01* +G01X633781Y1675842D01* +G01X612500Y1677814D01* +G01X591219Y1675842D01* +G01X570663Y1669993D01* +G01X551532Y1660467D01* +G01X534477Y1647587D01* +G01X520078Y1631793D01* +G01X508828Y1613623D01* +G01X501107Y1593694D01* +G01X497180Y1572686D01* +G01X473820Y1572686D01* +G01X469893Y1593694D01* +G01X462172Y1613623D01* +G01X450921Y1631793D01* +G01X436523Y1647587D01* +G01X419468Y1660467D01* +G01X400337Y1669993D01* +G01X379781Y1675842D01* +G01X358500Y1677814D01* +G01X337219Y1675842D01* +G01X316663Y1669993D01* +G01X297532Y1660467D01* +G01X280477Y1647587D01* +G01X266078Y1631793D01* +G01X254828Y1613623D01* +G01X247107Y1593694D01* +G01X243180Y1572686D01* +G01X35814Y1572686D01* +G01X35814Y1826686D01* +G01X243180Y1826686D01* +G01X243180Y1805314D01* +G01X247107Y1784306D01* +G01X254828Y1764377D01* +G01X266078Y1746206D01* +G01X280477Y1730412D01* +G01X297532Y1717533D01* +G01X316663Y1708007D01* +G01X337219Y1702158D01* +G01X358500Y1700186D01* +G01X358500Y1700186D01* +G01X379781Y1702158D01* +G01X400337Y1708007D01* +G01X419468Y1717533D01* +G01X436523Y1730412D01* +G01X450921Y1746206D01* +G01X462172Y1764377D01* +G01X469893Y1784306D01* +G01X473820Y1805314D01* +G01X473820Y1826686D01* +G01X473820Y1826686D01* +G01X497180Y1826686D01* +G01X497180Y1805314D01* +G01X501107Y1784306D01* +G01X508828Y1764377D01* +G01X520078Y1746206D01* +G01X534477Y1730412D01* +G01X551532Y1717533D01* +G01X570663Y1708007D01* +G01X591219Y1702158D01* +G01X612500Y1700186D01* +G01X612500Y1700186D01* +G01X633781Y1702158D01* +G01X654337Y1708007D01* +G01X673468Y1717533D01* +G01X690523Y1730412D01* +G01X704921Y1746206D01* +G01X716172Y1764377D01* +G01X723893Y1784306D01* +G01X727820Y1805314D01* +G01X727820Y1826686D01* +G01X727820Y1826686D01* +G01X1830680Y1826686D01* +G01X1830680Y1805314D01* +G01X1834607Y1784306D01* +G01X1842328Y1764377D01* +G01X1853578Y1746206D01* +G01X1867977Y1730412D01* +G01X1885032Y1717533D01* +G01X1904163Y1708007D01* +G01X1924719Y1702158D01* +G01X1946000Y1700186D01* +G01X1946000Y1700186D01* +G01X1967281Y1702158D01* +G01X1987837Y1708007D01* +G01X2006968Y1717533D01* +G01X2024023Y1730412D01* +G01X2038421Y1746206D01* +G01X2049672Y1764377D01* +G01X2057393Y1784306D01* +G01X2061320Y1805314D01* +G01X2061320Y1826686D01* +G01X2061320Y1826686D01* +G01X2084680Y1826686D01* +G01X2084680Y1805314D01* +G01X2088607Y1784306D01* +G01X2096328Y1764377D01* +G01X2107578Y1746206D01* +G01X2121977Y1730412D01* +G01X2139032Y1717533D01* +G01X2158163Y1708007D01* +G01X2178719Y1702158D01* +G01X2200000Y1700186D01* +G01X2200000Y1700186D01* +G01X2221281Y1702158D01* +G01X2241837Y1708007D01* +G01X2260968Y1717533D01* +G01X2278023Y1730412D01* +G01X2292421Y1746206D01* +G01X2303672Y1764377D01* +G01X2311393Y1784306D01* +G01X2315320Y1805314D01* +G01X2315320Y1826686D01* +G01X2311393Y1847694D01* +G01X2303672Y1867623D01* +G01X2292421Y1885793D01* +G01X2278023Y1901587D01* +G01X2260968Y1914467D01* +G01X2241837Y1923993D01* +G01X2221281Y1929842D01* +G01X2200000Y1931814D01* +G01X2178719Y1929842D01* +G01X2158163Y1923993D01* +G01X2139032Y1914467D01* +G01X2121977Y1901587D01* +G01X2107578Y1885793D01* +G01X2096328Y1867623D01* +G01X2088607Y1847694D01* +G01X2084680Y1826686D01* +G01X2061320Y1826686D01* +G01X2057393Y1847694D01* +G01X2049672Y1867623D01* +G01X2038421Y1885793D01* +G01X2024023Y1901587D01* +G01X2006968Y1914467D01* +G01X1987837Y1923993D01* +G01X1967281Y1929842D01* +G01X1946000Y1931814D01* +G01X1924719Y1929842D01* +G01X1904163Y1923993D01* +G01X1885032Y1914467D01* +G01X1867977Y1901587D01* +G01X1853578Y1885793D01* +G01X1842328Y1867623D01* +G01X1834607Y1847694D01* +G01X1830680Y1826686D01* +G01X727820Y1826686D01* +G01X723893Y1847694D01* +G01X716172Y1867623D01* +G01X704921Y1885793D01* +G01X690523Y1901587D01* +G01X673468Y1914467D01* +G01X654337Y1923993D01* +G01X633781Y1929842D01* +G01X612500Y1931814D01* +G01X591219Y1929842D01* +G01X570663Y1923993D01* +G01X551532Y1914467D01* +G01X534477Y1901587D01* +G01X520078Y1885793D01* +G01X508828Y1867623D01* +G01X501107Y1847694D01* +G01X497180Y1826686D01* +G01X473820Y1826686D01* +G01X469893Y1847694D01* +G01X462172Y1867623D01* +G01X450921Y1885793D01* +G01X436523Y1901587D01* +G01X419468Y1914467D01* +G01X400337Y1923993D01* +G01X379781Y1929842D01* +G01X358500Y1931814D01* +G01X337219Y1929842D01* +G01X316663Y1923993D01* +G01X297532Y1914467D01* +G01X280477Y1901587D01* +G01X266078Y1885793D01* +G01X254828Y1867623D01* +G01X247107Y1847694D01* +G01X243180Y1826686D01* +G01X35814Y1826686D01* +G01X35814Y2080686D01* +G01X243180Y2080686D01* +G01X243180Y2059314D01* +G01X247107Y2038306D01* +G01X254828Y2018377D01* +G01X266078Y2000206D01* +G01X280477Y1984412D01* +G01X297532Y1971533D01* +G01X316663Y1962007D01* +G01X337219Y1956158D01* +G01X358500Y1954186D01* +G01X358500Y1954186D01* +G01X379781Y1956158D01* +G01X400337Y1962007D01* +G01X419468Y1971533D01* +G01X436523Y1984412D01* +G01X450921Y2000206D01* +G01X462172Y2018377D01* +G01X469893Y2038306D01* +G01X473820Y2059314D01* +G01X473820Y2080686D01* +G01X473820Y2080686D01* +G01X497180Y2080686D01* +G01X497180Y2059314D01* +G01X501107Y2038306D01* +G01X508828Y2018377D01* +G01X520078Y2000206D01* +G01X534477Y1984412D01* +G01X551532Y1971533D01* +G01X570663Y1962007D01* +G01X591219Y1956158D01* +G01X612500Y1954186D01* +G01X612500Y1954186D01* +G01X633781Y1956158D01* +G01X654337Y1962007D01* +G01X673468Y1971533D01* +G01X690523Y1984412D01* +G01X704921Y2000206D01* +G01X716172Y2018377D01* +G01X723893Y2038306D01* +G01X727820Y2059314D01* +G01X727820Y2080686D01* +G01X727820Y2080686D01* +G01X1830680Y2080686D01* +G01X1830680Y2059314D01* +G01X1834607Y2038306D01* +G01X1842328Y2018377D01* +G01X1853578Y2000206D01* +G01X1867977Y1984412D01* +G01X1885032Y1971533D01* +G01X1904163Y1962007D01* +G01X1924719Y1956158D01* +G01X1946000Y1954186D01* +G01X1946000Y1954186D01* +G01X1967281Y1956158D01* +G01X1987837Y1962007D01* +G01X2006968Y1971533D01* +G01X2024023Y1984412D01* +G01X2038421Y2000206D01* +G01X2049672Y2018377D01* +G01X2057393Y2038306D01* +G01X2061320Y2059314D01* +G01X2061320Y2080686D01* +G01X2061320Y2080686D01* +G01X2084680Y2080686D01* +G01X2084680Y2059314D01* +G01X2088607Y2038306D01* +G01X2096328Y2018377D01* +G01X2107578Y2000206D01* +G01X2121977Y1984412D01* +G01X2139032Y1971533D01* +G01X2158163Y1962007D01* +G01X2178719Y1956158D01* +G01X2200000Y1954186D01* +G01X2200000Y1954186D01* +G01X2221281Y1956158D01* +G01X2241837Y1962007D01* +G01X2260968Y1971533D01* +G01X2278023Y1984412D01* +G01X2292421Y2000206D01* +G01X2303672Y2018377D01* +G01X2311393Y2038306D01* +G01X2315320Y2059314D01* +G01X2315320Y2080686D01* +G01X2311393Y2101694D01* +G01X2303672Y2121623D01* +G01X2292421Y2139793D01* +G01X2278023Y2155587D01* +G01X2260968Y2168467D01* +G01X2241837Y2177993D01* +G01X2221281Y2183842D01* +G01X2200000Y2185814D01* +G01X2178719Y2183842D01* +G01X2158163Y2177993D01* +G01X2139032Y2168467D01* +G01X2121977Y2155587D01* +G01X2107578Y2139793D01* +G01X2096328Y2121623D01* +G01X2088607Y2101694D01* +G01X2084680Y2080686D01* +G01X2061320Y2080686D01* +G01X2057393Y2101694D01* +G01X2049672Y2121623D01* +G01X2038421Y2139793D01* +G01X2024023Y2155587D01* +G01X2006968Y2168467D01* +G01X1987837Y2177993D01* +G01X1967281Y2183842D01* +G01X1946000Y2185814D01* +G01X1924719Y2183842D01* +G01X1904163Y2177993D01* +G01X1885032Y2168467D01* +G01X1867977Y2155587D01* +G01X1853578Y2139793D01* +G01X1842328Y2121623D01* +G01X1834607Y2101694D01* +G01X1830680Y2080686D01* +G01X727820Y2080686D01* +G01X723893Y2101694D01* +G01X716172Y2121623D01* +G01X704921Y2139793D01* +G01X690523Y2155587D01* +G01X673468Y2168467D01* +G01X654337Y2177993D01* +G01X633781Y2183842D01* +G01X612500Y2185814D01* +G01X591219Y2183842D01* +G01X570663Y2177993D01* +G01X551532Y2168467D01* +G01X534477Y2155587D01* +G01X520078Y2139793D01* +G01X508828Y2121623D01* +G01X501107Y2101694D01* +G01X497180Y2080686D01* +G01X473820Y2080686D01* +G01X469893Y2101694D01* +G01X462172Y2121623D01* +G01X450921Y2139793D01* +G01X436523Y2155587D01* +G01X419468Y2168467D01* +G01X400337Y2177993D01* +G01X379781Y2183842D01* +G01X358500Y2185814D01* +G01X337219Y2183842D01* +G01X316663Y2177993D01* +G01X297532Y2168467D01* +G01X280477Y2155587D01* +G01X266078Y2139793D01* +G01X254828Y2121623D01* +G01X247107Y2101694D01* +G01X243180Y2080686D01* +G01X35814Y2080686D01* +G01X35814Y2334686D01* +G01X243180Y2334686D01* +G01X243180Y2313314D01* +G01X247107Y2292306D01* +G01X254828Y2272377D01* +G01X266078Y2254206D01* +G01X280477Y2238412D01* +G01X297532Y2225533D01* +G01X316663Y2216007D01* +G01X337219Y2210158D01* +G01X358500Y2208186D01* +G01X358500Y2208186D01* +G01X379781Y2210158D01* +G01X400337Y2216007D01* +G01X419468Y2225533D01* +G01X436523Y2238412D01* +G01X450921Y2254206D01* +G01X462172Y2272377D01* +G01X469893Y2292306D01* +G01X473820Y2313314D01* +G01X473820Y2334686D01* +G01X473820Y2334686D01* +G01X497180Y2334686D01* +G01X497180Y2313314D01* +G01X501107Y2292306D01* +G01X508828Y2272377D01* +G01X520078Y2254206D01* +G01X534477Y2238412D01* +G01X551532Y2225533D01* +G01X570663Y2216007D01* +G01X591219Y2210158D01* +G01X612500Y2208186D01* +G01X612500Y2208186D01* +G01X633781Y2210158D01* +G01X654337Y2216007D01* +G01X673468Y2225533D01* +G01X690523Y2238412D01* +G01X704921Y2254206D01* +G01X716172Y2272377D01* +G01X723893Y2292306D01* +G01X727820Y2313314D01* +G01X727820Y2334686D01* +G01X727820Y2334686D01* +G01X1830680Y2334686D01* +G01X1830680Y2313314D01* +G01X1834607Y2292306D01* +G01X1842328Y2272377D01* +G01X1853578Y2254206D01* +G01X1867977Y2238412D01* +G01X1885032Y2225533D01* +G01X1904163Y2216007D01* +G01X1924719Y2210158D01* +G01X1946000Y2208186D01* +G01X1946000Y2208186D01* +G01X1967281Y2210158D01* +G01X1987837Y2216007D01* +G01X2006968Y2225533D01* +G01X2024023Y2238412D01* +G01X2038421Y2254206D01* +G01X2049672Y2272377D01* +G01X2057393Y2292306D01* +G01X2061320Y2313314D01* +G01X2061320Y2334686D01* +G01X2061320Y2334686D01* +G01X2084680Y2334686D01* +G01X2084680Y2313314D01* +G01X2088607Y2292306D01* +G01X2096328Y2272377D01* +G01X2107578Y2254206D01* +G01X2121977Y2238412D01* +G01X2139032Y2225533D01* +G01X2158163Y2216007D01* +G01X2178719Y2210158D01* +G01X2200000Y2208186D01* +G01X2200000Y2208186D01* +G01X2221281Y2210158D01* +G01X2241837Y2216007D01* +G01X2260968Y2225533D01* +G01X2278023Y2238412D01* +G01X2292421Y2254206D01* +G01X2303672Y2272377D01* +G01X2311393Y2292306D01* +G01X2315320Y2313314D01* +G01X2315320Y2334686D01* +G01X2311393Y2355694D01* +G01X2303672Y2375623D01* +G01X2292421Y2393793D01* +G01X2278023Y2409587D01* +G01X2260968Y2422467D01* +G01X2241837Y2431993D01* +G01X2221281Y2437842D01* +G01X2200000Y2439814D01* +G01X2178719Y2437842D01* +G01X2158163Y2431993D01* +G01X2139032Y2422467D01* +G01X2121977Y2409587D01* +G01X2107578Y2393793D01* +G01X2096328Y2375623D01* +G01X2088607Y2355694D01* +G01X2084680Y2334686D01* +G01X2061320Y2334686D01* +G01X2057393Y2355694D01* +G01X2049672Y2375623D01* +G01X2038421Y2393793D01* +G01X2024023Y2409587D01* +G01X2006968Y2422467D01* +G01X1987837Y2431993D01* +G01X1967281Y2437842D01* +G01X1946000Y2439814D01* +G01X1924719Y2437842D01* +G01X1904163Y2431993D01* +G01X1885032Y2422467D01* +G01X1867977Y2409587D01* +G01X1853578Y2393793D01* +G01X1842328Y2375623D01* +G01X1834607Y2355694D01* +G01X1830680Y2334686D01* +G01X727820Y2334686D01* +G01X723893Y2355694D01* +G01X716172Y2375623D01* +G01X704921Y2393793D01* +G01X690523Y2409587D01* +G01X673468Y2422467D01* +G01X654337Y2431993D01* +G01X633781Y2437842D01* +G01X612500Y2439814D01* +G01X591219Y2437842D01* +G01X570663Y2431993D01* +G01X551532Y2422467D01* +G01X534477Y2409587D01* +G01X520078Y2393793D01* +G01X508828Y2375623D01* +G01X501107Y2355694D01* +G01X497180Y2334686D01* +G01X473820Y2334686D01* +G01X469893Y2355694D01* +G01X462172Y2375623D01* +G01X450921Y2393793D01* +G01X436523Y2409587D01* +G01X419468Y2422467D01* +G01X400337Y2431993D01* +G01X379781Y2437842D01* +G01X358500Y2439814D01* +G01X337219Y2437842D01* +G01X316663Y2431993D01* +G01X297532Y2422467D01* +G01X280477Y2409587D01* +G01X266078Y2393793D01* +G01X254828Y2375623D01* +G01X247107Y2355694D01* +G01X243180Y2334686D01* +G01X35814Y2334686D01* +G01X35814Y2588686D01* +G01X243180Y2588686D01* +G01X243180Y2567314D01* +G01X247107Y2546306D01* +G01X254828Y2526377D01* +G01X266078Y2508206D01* +G01X280477Y2492412D01* +G01X297532Y2479533D01* +G01X316663Y2470007D01* +G01X337219Y2464158D01* +G01X358500Y2462186D01* +G01X358500Y2462186D01* +G01X379781Y2464158D01* +G01X400337Y2470007D01* +G01X419468Y2479533D01* +G01X436523Y2492412D01* +G01X450921Y2508206D01* +G01X462172Y2526377D01* +G01X469893Y2546306D01* +G01X473820Y2567314D01* +G01X473820Y2588686D01* +G01X473820Y2588686D01* +G01X497180Y2588686D01* +G01X497180Y2567314D01* +G01X501107Y2546306D01* +G01X508828Y2526377D01* +G01X520078Y2508206D01* +G01X534477Y2492412D01* +G01X551532Y2479533D01* +G01X570663Y2470007D01* +G01X591219Y2464158D01* +G01X612500Y2462186D01* +G01X612500Y2462186D01* +G01X633781Y2464158D01* +G01X654337Y2470007D01* +G01X673468Y2479533D01* +G01X690523Y2492412D01* +G01X704921Y2508206D01* +G01X716172Y2526377D01* +G01X723893Y2546306D01* +G01X727820Y2567314D01* +G01X727820Y2588686D01* +G01X727820Y2588686D01* +G01X1830680Y2588686D01* +G01X1830680Y2567314D01* +G01X1834607Y2546306D01* +G01X1842328Y2526377D01* +G01X1853578Y2508206D01* +G01X1867977Y2492412D01* +G01X1885032Y2479533D01* +G01X1904163Y2470007D01* +G01X1924719Y2464158D01* +G01X1946000Y2462186D01* +G01X1946000Y2462186D01* +G01X1967281Y2464158D01* +G01X1987837Y2470007D01* +G01X2006968Y2479533D01* +G01X2024023Y2492412D01* +G01X2038421Y2508206D01* +G01X2049672Y2526377D01* +G01X2057393Y2546306D01* +G01X2061320Y2567314D01* +G01X2061320Y2588686D01* +G01X2061320Y2588686D01* +G01X2084680Y2588686D01* +G01X2084680Y2567314D01* +G01X2088607Y2546306D01* +G01X2096328Y2526377D01* +G01X2107578Y2508206D01* +G01X2121977Y2492412D01* +G01X2139032Y2479533D01* +G01X2158163Y2470007D01* +G01X2178719Y2464158D01* +G01X2200000Y2462186D01* +G01X2200000Y2462186D01* +G01X2221281Y2464158D01* +G01X2241837Y2470007D01* +G01X2260968Y2479533D01* +G01X2278023Y2492412D01* +G01X2292421Y2508206D01* +G01X2303672Y2526377D01* +G01X2311393Y2546306D01* +G01X2315320Y2567314D01* +G01X2315320Y2588686D01* +G01X2311393Y2609694D01* +G01X2303672Y2629623D01* +G01X2292421Y2647793D01* +G01X2278023Y2663587D01* +G01X2260968Y2676467D01* +G01X2241837Y2685993D01* +G01X2221281Y2691842D01* +G01X2200000Y2693814D01* +G01X2178719Y2691842D01* +G01X2158163Y2685993D01* +G01X2139032Y2676467D01* +G01X2121977Y2663587D01* +G01X2107578Y2647793D01* +G01X2096328Y2629623D01* +G01X2088607Y2609694D01* +G01X2084680Y2588686D01* +G01X2061320Y2588686D01* +G01X2057393Y2609694D01* +G01X2049672Y2629623D01* +G01X2038421Y2647793D01* +G01X2024023Y2663587D01* +G01X2006968Y2676467D01* +G01X1987837Y2685993D01* +G01X1967281Y2691842D01* +G01X1946000Y2693814D01* +G01X1924719Y2691842D01* +G01X1904163Y2685993D01* +G01X1885032Y2676467D01* +G01X1867977Y2663587D01* +G01X1853578Y2647793D01* +G01X1842328Y2629623D01* +G01X1834607Y2609694D01* +G01X1830680Y2588686D01* +G01X727820Y2588686D01* +G01X723893Y2609694D01* +G01X716172Y2629623D01* +G01X704921Y2647793D01* +G01X690523Y2663587D01* +G01X673468Y2676467D01* +G01X654337Y2685993D01* +G01X633781Y2691842D01* +G01X612500Y2693814D01* +G01X591219Y2691842D01* +G01X570663Y2685993D01* +G01X551532Y2676467D01* +G01X534477Y2663587D01* +G01X520078Y2647793D01* +G01X508828Y2629623D01* +G01X501107Y2609694D01* +G01X497180Y2588686D01* +G01X473820Y2588686D01* +G01X469893Y2609694D01* +G01X462172Y2629623D01* +G01X450921Y2647793D01* +G01X436523Y2663587D01* +G01X419468Y2676467D01* +G01X400337Y2685993D01* +G01X379781Y2691842D01* +G01X358500Y2693814D01* +G01X337219Y2691842D01* +G01X316663Y2685993D01* +G01X297532Y2676467D01* +G01X280477Y2663587D01* +G01X266078Y2647793D01* +G01X254828Y2629623D01* +G01X247107Y2609694D01* +G01X243180Y2588686D01* +G01X35814Y2588686D01* +G01X35814Y3078173D01* +G01X242951Y3078173D01* +G01X246413Y3056857D01* +G01X253772Y3036555D01* +G01X264772Y3017971D01* +G01X279031Y3001753D01* +G01X296053Y2988464D01* +G01X315246Y2978566D01* +G01X335943Y2972404D01* +G01X357425Y2970191D01* +G01X378944Y2972005D01* +G01X399752Y2977782D01* +G01X369281Y2947311D01* +G01X349044Y2947427D01* +G01X329097Y2944019D01* +G01X310047Y2937191D01* +G01X292476Y2927151D01* +G01X276921Y2914206D01* +G01X263857Y2898750D01* +G01X253683Y2881257D01* +G01X246709Y2862260D01* +G01X243149Y2842339D01* +G01X243110Y2822102D01* +G01X246594Y2802168D01* +G01X253495Y2783144D01* +G01X263603Y2765612D01* +G01X276607Y2750107D01* +G01X292112Y2737103D01* +G01X309644Y2726995D01* +G01X328668Y2720094D01* +G01X348602Y2716610D01* +G01X368839Y2716649D01* +G01X388760Y2720209D01* +G01X407757Y2727183D01* +G01X425250Y2737357D01* +G01X440706Y2750421D01* +G01X453651Y2765976D01* +G01X463691Y2783547D01* +G01X470519Y2802597D01* +G01X473927Y2822544D01* +G01X473811Y2842781D01* +G01X516156Y2885126D01* +G01X521163Y2885126D01* +G01X512749Y2866851D01* +G01X507951Y2847312D01* +G01X506944Y2827219D01* +G01X509764Y2807299D01* +G01X516308Y2788274D01* +G01X526339Y2770835D01* +G01X539494Y2755613D01* +G01X555296Y2743160D01* +G01X573171Y2733928D01* +G01X592473Y2728251D01* +G01X612500Y2726336D01* +G01X632527Y2728251D01* +G01X651829Y2733928D01* +G01X669704Y2743160D01* +G01X685506Y2755613D01* +G01X698661Y2770835D01* +G01X708692Y2788274D01* +G01X715236Y2807299D01* +G01X718056Y2827219D01* +G01X717280Y2842686D01* +G01X1830680Y2842686D01* +G01X1830680Y2821314D01* +G01X1834607Y2800306D01* +G01X1842328Y2780377D01* +G01X1853578Y2762206D01* +G01X1867977Y2746412D01* +G01X1885032Y2733533D01* +G01X1904163Y2724007D01* +G01X1924719Y2718158D01* +G01X1946000Y2716186D01* +G01X1946000Y2716186D01* +G01X1967281Y2718158D01* +G01X1987837Y2724007D01* +G01X2006968Y2733533D01* +G01X2024023Y2746412D01* +G01X2038421Y2762206D01* +G01X2049672Y2780377D01* +G01X2057393Y2800306D01* +G01X2061320Y2821314D01* +G01X2061320Y2842686D01* +G01X2061320Y2842686D01* +G01X2084680Y2842686D01* +G01X2084680Y2821314D01* +G01X2088607Y2800306D01* +G01X2096328Y2780377D01* +G01X2107578Y2762206D01* +G01X2121977Y2746412D01* +G01X2139032Y2733533D01* +G01X2158163Y2724007D01* +G01X2178719Y2718158D01* +G01X2200000Y2716186D01* +G01X2200000Y2716186D01* +G01X2221281Y2718158D01* +G01X2241837Y2724007D01* +G01X2260968Y2733533D01* +G01X2278023Y2746412D01* +G01X2292421Y2762206D01* +G01X2303672Y2780377D01* +G01X2311393Y2800306D01* +G01X2315320Y2821314D01* +G01X2315320Y2842686D01* +G01X2311393Y2863694D01* +G01X2303672Y2883623D01* +G01X2292421Y2901793D01* +G01X2278023Y2917587D01* +G01X2260968Y2930467D01* +G01X2241837Y2939993D01* +G01X2221281Y2945842D01* +G01X2200000Y2947814D01* +G01X2178719Y2945842D01* +G01X2158163Y2939993D01* +G01X2139032Y2930467D01* +G01X2121977Y2917587D01* +G01X2107578Y2901793D01* +G01X2096328Y2883623D01* +G01X2088607Y2863694D01* +G01X2084680Y2842686D01* +G01X2061320Y2842686D01* +G01X2057393Y2863694D01* +G01X2049672Y2883623D01* +G01X2038421Y2901793D01* +G01X2024023Y2917587D01* +G01X2006968Y2930467D01* +G01X1987837Y2939993D01* +G01X1967281Y2945842D01* +G01X1946000Y2947814D01* +G01X1924719Y2945842D01* +G01X1904163Y2939993D01* +G01X1885032Y2930467D01* +G01X1867977Y2917587D01* +G01X1853578Y2901793D01* +G01X1842328Y2883623D01* +G01X1834607Y2863694D01* +G01X1830680Y2842686D01* +G01X717280Y2842686D01* +G01X717048Y2847312D01* +G01X712251Y2866851D01* +G01X703837Y2885126D01* +G01X739540Y2885126D01* +G01X753960Y2886546D01* +G01X767825Y2890752D01* +G01X780604Y2897583D01* +G01X791805Y2906775D01* +G01X981716Y3096686D01* +G01X1830680Y3096686D01* +G01X1830680Y3075314D01* +G01X1834607Y3054306D01* +G01X1842328Y3034377D01* +G01X1853578Y3016206D01* +G01X1867977Y3000412D01* +G01X1885032Y2987533D01* +G01X1904163Y2978007D01* +G01X1924719Y2972158D01* +G01X1946000Y2970186D01* +G01X1946000Y2970186D01* +G01X1967281Y2972158D01* +G01X1987837Y2978007D01* +G01X2006968Y2987533D01* +G01X2024023Y3000412D01* +G01X2038421Y3016206D01* +G01X2049672Y3034377D01* +G01X2057393Y3054306D01* +G01X2061320Y3075314D01* +G01X2061320Y3096686D01* +G01X2061320Y3096686D01* +G01X2084680Y3096686D01* +G01X2084680Y3075314D01* +G01X2088607Y3054306D01* +G01X2096328Y3034377D01* +G01X2107578Y3016206D01* +G01X2121977Y3000412D01* +G01X2139032Y2987533D01* +G01X2158163Y2978007D01* +G01X2178719Y2972158D01* +G01X2200000Y2970186D01* +G01X2200000Y2970186D01* +G01X2221281Y2972158D01* +G01X2241837Y2978007D01* +G01X2260968Y2987533D01* +G01X2278023Y3000412D01* +G01X2292421Y3016206D01* +G01X2303672Y3034377D01* +G01X2311393Y3054306D01* +G01X2315320Y3075314D01* +G01X2315320Y3096686D01* +G01X2311393Y3117694D01* +G01X2303672Y3137623D01* +G01X2292421Y3155793D01* +G01X2278023Y3171587D01* +G01X2260968Y3184467D01* +G01X2241837Y3193993D01* +G01X2221281Y3199842D01* +G01X2200000Y3201814D01* +G01X2178719Y3199842D01* +G01X2158163Y3193993D01* +G01X2139032Y3184467D01* +G01X2121977Y3171587D01* +G01X2107578Y3155793D01* +G01X2096328Y3137623D01* +G01X2088607Y3117694D01* +G01X2084680Y3096686D01* +G01X2061320Y3096686D01* +G01X2057393Y3117694D01* +G01X2049672Y3137623D01* +G01X2038421Y3155793D01* +G01X2024023Y3171587D01* +G01X2006968Y3184467D01* +G01X1987837Y3193993D01* +G01X1967281Y3199842D01* +G01X1946000Y3201814D01* +G01X1924719Y3199842D01* +G01X1904163Y3193993D01* +G01X1885032Y3184467D01* +G01X1867977Y3171587D01* +G01X1853578Y3155793D01* +G01X1842328Y3137623D01* +G01X1834607Y3117694D01* +G01X1830680Y3096686D01* +G01X981716Y3096686D01* +G01X1225132Y3340102D01* +G01X1451886Y3340102D01* +G01X1453797Y3318254D01* +G01X1459474Y3297071D01* +G01X1468742Y3277195D01* +G01X1481321Y3259230D01* +G01X1496828Y3243723D01* +G01X1514793Y3231144D01* +G01X1534669Y3221875D01* +G01X1555853Y3216199D01* +G01X1577700Y3214288D01* +G01X1599547Y3216199D01* +G01X1620731Y3221875D01* +G01X1640607Y3231144D01* +G01X1658571Y3243723D01* +G01X1674079Y3259230D01* +G01X1686658Y3277195D01* +G01X1695926Y3297071D01* +G01X1701602Y3318254D01* +G01X1703514Y3340102D01* +G01X1702588Y3350686D01* +G01X1830680Y3350686D01* +G01X1830680Y3329314D01* +G01X1834607Y3308306D01* +G01X1842328Y3288377D01* +G01X1853578Y3270206D01* +G01X1867977Y3254412D01* +G01X1885032Y3241533D01* +G01X1904163Y3232007D01* +G01X1924719Y3226158D01* +G01X1946000Y3224186D01* +G01X1946000Y3224186D01* +G01X1967281Y3226158D01* +G01X1987837Y3232007D01* +G01X2006968Y3241533D01* +G01X2024023Y3254412D01* +G01X2038421Y3270206D01* +G01X2049672Y3288377D01* +G01X2057393Y3308306D01* +G01X2061320Y3329314D01* +G01X2061320Y3350686D01* +G01X2084680Y3350686D01* +G01X2084680Y3329314D01* +G01X2088607Y3308306D01* +G01X2096328Y3288377D01* +G01X2107578Y3270206D01* +G01X2121977Y3254412D01* +G01X2139032Y3241533D01* +G01X2158163Y3232007D01* +G01X2178719Y3226158D01* +G01X2200000Y3224186D01* +G01X2200000Y3224186D01* +G01X2221281Y3226158D01* +G01X2241837Y3232007D01* +G01X2260968Y3241533D01* +G01X2278023Y3254412D01* +G01X2292421Y3270206D01* +G01X2303672Y3288377D01* +G01X2311393Y3308306D01* +G01X2315320Y3329314D01* +G01X2315320Y3350686D01* +G01X2311393Y3371694D01* +G01X2303672Y3391623D01* +G01X2292421Y3409793D01* +G01X2278023Y3425587D01* +G01X2260968Y3438467D01* +G01X2241837Y3447993D01* +G01X2221281Y3453842D01* +G01X2200000Y3455814D01* +G01X2178719Y3453842D01* +G01X2158163Y3447993D01* +G01X2139032Y3438467D01* +G01X2121977Y3425587D01* +G01X2107578Y3409793D01* +G01X2096328Y3391623D01* +G01X2088607Y3371694D01* +G01X2084680Y3350686D01* +G01X2061320Y3350686D01* +G01X2057393Y3371694D01* +G01X2049672Y3391623D01* +G01X2038421Y3409793D01* +G01X2024023Y3425587D01* +G01X2006968Y3438467D01* +G01X1987837Y3447993D01* +G01X1967281Y3453842D01* +G01X1946000Y3455814D01* +G01X1924719Y3453842D01* +G01X1904163Y3447993D01* +G01X1885032Y3438467D01* +G01X1867977Y3425587D01* +G01X1853578Y3409793D01* +G01X1842328Y3391623D01* +G01X1834607Y3371694D01* +G01X1830680Y3350686D01* +G01X1702588Y3350686D01* +G01X1701602Y3361949D01* +G01X1695926Y3383132D01* +G01X1686658Y3403008D01* +G01X1674079Y3420973D01* +G01X1658571Y3436481D01* +G01X1640607Y3449059D01* +G01X1620731Y3458328D01* +G01X1599547Y3464004D01* +G01X1577700Y3465915D01* +G01X1577700Y3465915D01* +G01X1555853Y3464004D01* +G01X1534669Y3458328D01* +G01X1514793Y3449059D01* +G01X1496828Y3436481D01* +G01X1481321Y3420973D01* +G01X1468742Y3403008D01* +G01X1459474Y3383132D01* +G01X1453797Y3361949D01* +G01X1451886Y3340102D01* +G01X1225132Y3340102D01* +G01X1248965Y3363935D01* +G01X1258157Y3375136D01* +G01X1264988Y3387914D01* +G01X1269194Y3401780D01* +G01X1270614Y3416200D01* +G01X1270614Y3501551D01* +G01X1285677Y3515941D01* +G01X1297984Y3532749D01* +G01X1307153Y3551454D01* +G01X1312901Y3571477D01* +G01X1315050Y3592198D01* +G01X1314138Y3604686D01* +G01X1830680Y3604686D01* +G01X1830680Y3583314D01* +G01X1834607Y3562306D01* +G01X1842328Y3542377D01* +G01X1853578Y3524206D01* +G01X1867977Y3508412D01* +G01X1885032Y3495533D01* +G01X1904163Y3486007D01* +G01X1924719Y3480158D01* +G01X1946000Y3478186D01* +G01X1946000Y3478186D01* +G01X1967281Y3480158D01* +G01X1987837Y3486007D01* +G01X2006968Y3495533D01* +G01X2024023Y3508412D01* +G01X2038421Y3524206D01* +G01X2049672Y3542377D01* +G01X2057393Y3562306D01* +G01X2061320Y3583314D01* +G01X2061320Y3604686D01* +G01X2084680Y3604686D01* +G01X2084680Y3583314D01* +G01X2088607Y3562306D01* +G01X2096328Y3542377D01* +G01X2107578Y3524206D01* +G01X2121977Y3508412D01* +G01X2139032Y3495533D01* +G01X2158163Y3486007D01* +G01X2178719Y3480158D01* +G01X2200000Y3478186D01* +G01X2200000Y3478186D01* +G01X2221281Y3480158D01* +G01X2241837Y3486007D01* +G01X2260968Y3495533D01* +G01X2278023Y3508412D01* +G01X2292421Y3524206D01* +G01X2303672Y3542377D01* +G01X2311393Y3562306D01* +G01X2315320Y3583314D01* +G01X2315320Y3604686D01* +G01X2311393Y3625694D01* +G01X2303672Y3645623D01* +G01X2292421Y3663793D01* +G01X2278023Y3679587D01* +G01X2260968Y3692467D01* +G01X2241837Y3701993D01* +G01X2221281Y3707842D01* +G01X2200000Y3709814D01* +G01X2178719Y3707842D01* +G01X2158163Y3701993D01* +G01X2139032Y3692467D01* +G01X2121977Y3679587D01* +G01X2107578Y3663793D01* +G01X2096328Y3645623D01* +G01X2088607Y3625694D01* +G01X2084680Y3604686D01* +G01X2061320Y3604686D01* +G01X2061320Y3604686D01* +G01X2057393Y3625694D01* +G01X2049672Y3645623D01* +G01X2038421Y3663793D01* +G01X2024023Y3679587D01* +G01X2006968Y3692467D01* +G01X1987837Y3701993D01* +G01X1967281Y3707842D01* +G01X1946000Y3709814D01* +G01X1924719Y3707842D01* +G01X1904163Y3701993D01* +G01X1885032Y3692467D01* +G01X1867977Y3679587D01* +G01X1853578Y3663793D01* +G01X1842328Y3645623D01* +G01X1834607Y3625694D01* +G01X1830680Y3604686D01* +G01X1314138Y3604686D01* +G01X1313533Y3612974D01* +G01X1308397Y3633163D01* +G01X1299802Y3652138D01* +G01X1288012Y3669313D01* +G01X1273395Y3684155D01* +G01X1256401Y3696204D01* +G01X1237559Y3705088D01* +G01X1217451Y3710531D01* +G01X1196700Y3712364D01* +G01X1175949Y3710531D01* +G01X1155841Y3705088D01* +G01X1136998Y3696204D01* +G01X1120005Y3684155D01* +G01X1105387Y3669313D01* +G01X1093598Y3652138D01* +G01X1085002Y3633163D01* +G01X1079867Y3612974D01* +G01X1078350Y3592198D01* +G01X1080499Y3571477D01* +G01X1086247Y3551454D01* +G01X1095416Y3532749D01* +G01X1107723Y3515941D01* +G01X1122786Y3501551D01* +G01X1122786Y3446816D01* +G01X708924Y3032954D01* +G01X708924Y3032954D01* +G01X703884Y3032954D01* +G01X703884Y3032954D01* +G01X712279Y3051228D01* +G01X717059Y3070762D01* +G01X718053Y3090848D01* +G01X715222Y3110758D01* +G01X708671Y3129772D01* +G01X698636Y3147199D01* +G01X685482Y3162410D01* +G01X669683Y3174854D01* +G01X651813Y3184078D01* +G01X632519Y3189750D01* +G01X612500Y3191664D01* +G01X612500Y3191664D01* +G01X592481Y3189750D01* +G01X573187Y3184078D01* +G01X555317Y3174854D01* +G01X539518Y3162410D01* +G01X526363Y3147199D01* +G01X516329Y3129772D01* +G01X509777Y3110758D01* +G01X506947Y3090848D01* +G01X507940Y3070762D01* +G01X512721Y3051228D01* +G01X521116Y3032954D01* +G01X485540Y3032954D01* +G01X471879Y3031680D01* +G01X458688Y3027904D01* +G01X467732Y3047514D01* +G01X472978Y3068462D01* +G01X474244Y3090020D01* +G01X471485Y3111439D01* +G01X464798Y3131972D01* +G01X454416Y3150908D01* +G01X440698Y3167586D01* +G01X424122Y3181428D01* +G01X405265Y3191952D01* +G01X384782Y3198792D01* +G01X363385Y3201711D01* +G01X341818Y3200606D01* +G01X320831Y3195517D01* +G01X301154Y3186619D01* +G01X283471Y3174224D01* +G01X268396Y3158761D01* +G01X256454Y3140768D01* +G01X248060Y3120871D01* +G01X243507Y3099761D01* +G01X242951Y3078173D01* +G01X35814Y3078173D01* +G01X35814Y3350686D01* +G01X243180Y3350686D01* +G01X243180Y3329314D01* +G01X247107Y3308306D01* +G01X254828Y3288377D01* +G01X266078Y3270206D01* +G01X280477Y3254412D01* +G01X297532Y3241533D01* +G01X316663Y3232007D01* +G01X337219Y3226158D01* +G01X358500Y3224186D01* +G01X358500Y3224186D01* +G01X379781Y3226158D01* +G01X400337Y3232007D01* +G01X419468Y3241533D01* +G01X436523Y3254412D01* +G01X450921Y3270206D01* +G01X462172Y3288377D01* +G01X469893Y3308306D01* +G01X473820Y3329314D01* +G01X473820Y3350686D01* +G01X497180Y3350686D01* +G01X497180Y3329314D01* +G01X501107Y3308306D01* +G01X508828Y3288377D01* +G01X520078Y3270206D01* +G01X534477Y3254412D01* +G01X551532Y3241533D01* +G01X570663Y3232007D01* +G01X591219Y3226158D01* +G01X612500Y3224186D01* +G01X612500Y3224186D01* +G01X633781Y3226158D01* +G01X654337Y3232007D01* +G01X673468Y3241533D01* +G01X690523Y3254412D01* +G01X704921Y3270206D01* +G01X716172Y3288377D01* +G01X723893Y3308306D01* +G01X727820Y3329314D01* +G01X727820Y3350686D01* +G01X723893Y3371694D01* +G01X716172Y3391623D01* +G01X704921Y3409793D01* +G01X690523Y3425587D01* +G01X673468Y3438467D01* +G01X654337Y3447993D01* +G01X633781Y3453842D01* +G01X612500Y3455814D01* +G01X591219Y3453842D01* +G01X570663Y3447993D01* +G01X551532Y3438467D01* +G01X534477Y3425587D01* +G01X520078Y3409793D01* +G01X508828Y3391623D01* +G01X501107Y3371694D01* +G01X497180Y3350686D01* +G01X473820Y3350686D01* +G01X469893Y3371694D01* +G01X462172Y3391623D01* +G01X450921Y3409793D01* +G01X436523Y3425587D01* +G01X419468Y3438467D01* +G01X400337Y3447993D01* +G01X379781Y3453842D01* +G01X358500Y3455814D01* +G01X337219Y3453842D01* +G01X316663Y3447993D01* +G01X297532Y3438467D01* +G01X280477Y3425587D01* +G01X266078Y3409793D01* +G01X254828Y3391623D01* +G01X247107Y3371694D01* +G01X243180Y3350686D01* +G01X35814Y3350686D01* +G01X35814Y3604686D01* +G01X243180Y3604686D01* +G01X243180Y3583314D01* +G01X247107Y3562306D01* +G01X254828Y3542377D01* +G01X266078Y3524206D01* +G01X280477Y3508412D01* +G01X297532Y3495533D01* +G01X316663Y3486007D01* +G01X337219Y3480158D01* +G01X358500Y3478186D01* +G01X358500Y3478186D01* +G01X379781Y3480158D01* +G01X400337Y3486007D01* +G01X419468Y3495533D01* +G01X436523Y3508412D01* +G01X450921Y3524206D01* +G01X462172Y3542377D01* +G01X469893Y3562306D01* +G01X473820Y3583314D01* +G01X473820Y3604686D01* +G01X497180Y3604686D01* +G01X497180Y3583314D01* +G01X501107Y3562306D01* +G01X508828Y3542377D01* +G01X520078Y3524206D01* +G01X534477Y3508412D01* +G01X551532Y3495533D01* +G01X570663Y3486007D01* +G01X591219Y3480158D01* +G01X612500Y3478186D01* +G01X612500Y3478186D01* +G01X633781Y3480158D01* +G01X654337Y3486007D01* +G01X673468Y3495533D01* +G01X690523Y3508412D01* +G01X704921Y3524206D01* +G01X716172Y3542377D01* +G01X723893Y3562306D01* +G01X727820Y3583314D01* +G01X727820Y3604686D01* +G01X723893Y3625694D01* +G01X716172Y3645623D01* +G01X704921Y3663793D01* +G01X690523Y3679587D01* +G01X673468Y3692467D01* +G01X654337Y3701993D01* +G01X633781Y3707842D01* +G01X612500Y3709814D01* +G01X591219Y3707842D01* +G01X570663Y3701993D01* +G01X551532Y3692467D01* +G01X534477Y3679587D01* +G01X520078Y3663793D01* +G01X508828Y3645623D01* +G01X501107Y3625694D01* +G01X497180Y3604686D01* +G01X473820Y3604686D01* +G01X469893Y3625694D01* +G01X462172Y3645623D01* +G01X450921Y3663793D01* +G01X436523Y3679587D01* +G01X419468Y3692467D01* +G01X400337Y3701993D01* +G01X379781Y3707842D01* +G01X358500Y3709814D01* +G01X337219Y3707842D01* +G01X316663Y3701993D01* +G01X297532Y3692467D01* +G01X280477Y3679587D01* +G01X266078Y3663793D01* +G01X254828Y3645623D01* +G01X247107Y3625694D01* +G01X243180Y3604686D01* +G01X35814Y3604686D01* +G01X35814Y3858686D01* +G01X243180Y3858686D01* +G01X243180Y3837314D01* +G01X247107Y3816306D01* +G01X254828Y3796377D01* +G01X266078Y3778206D01* +G01X280477Y3762412D01* +G01X297532Y3749533D01* +G01X316663Y3740007D01* +G01X337219Y3734158D01* +G01X358500Y3732186D01* +G01X358500Y3732186D01* +G01X379781Y3734158D01* +G01X400337Y3740007D01* +G01X419468Y3749533D01* +G01X436523Y3762412D01* +G01X450921Y3778206D01* +G01X462172Y3796377D01* +G01X469893Y3816306D01* +G01X473820Y3837314D01* +G01X473820Y3858686D01* +G01X497180Y3858686D01* +G01X497180Y3837314D01* +G01X501107Y3816306D01* +G01X508828Y3796377D01* +G01X520078Y3778206D01* +G01X534477Y3762412D01* +G01X551532Y3749533D01* +G01X570663Y3740007D01* +G01X591219Y3734158D01* +G01X612500Y3732186D01* +G01X612500Y3732186D01* +G01X633781Y3734158D01* +G01X654337Y3740007D01* +G01X673468Y3749533D01* +G01X690523Y3762412D01* +G01X704921Y3778206D01* +G01X716172Y3796377D01* +G01X723893Y3816306D01* +G01X727820Y3837314D01* +G01X727820Y3858686D01* +G01X723893Y3879694D01* +G01X716172Y3899623D01* +G01X704921Y3917793D01* +G01X690523Y3933587D01* +G01X673468Y3946467D01* +G01X654337Y3955993D01* +G01X633781Y3961842D01* +G01X612500Y3963814D01* +G01X591219Y3961842D01* +G01X570663Y3955993D01* +G01X551532Y3946467D01* +G01X534477Y3933587D01* +G01X520078Y3917793D01* +G01X508828Y3899623D01* +G01X501107Y3879694D01* +G01X497180Y3858686D01* +G01X473820Y3858686D01* +G01X469893Y3879694D01* +G01X462172Y3899623D01* +G01X450921Y3917793D01* +G01X436523Y3933587D01* +G01X419468Y3946467D01* +G01X400337Y3955993D01* +G01X379781Y3961842D01* +G01X358500Y3963814D01* +G01X337219Y3961842D01* +G01X316663Y3955993D01* +G01X297532Y3946467D01* +G01X280477Y3933587D01* +G01X266078Y3917793D01* +G01X254828Y3899623D01* +G01X247107Y3879694D01* +G01X243180Y3858686D01* +G01X35814Y3858686D01* +G01X35814Y4112686D01* +G01X243180Y4112686D01* +G01X243180Y4091314D01* +G01X247107Y4070306D01* +G01X254828Y4050377D01* +G01X266078Y4032206D01* +G01X280477Y4016412D01* +G01X297532Y4003533D01* +G01X316663Y3994007D01* +G01X337219Y3988158D01* +G01X358500Y3986186D01* +G01X358500Y3986186D01* +G01X379781Y3988158D01* +G01X400337Y3994007D01* +G01X419468Y4003533D01* +G01X436523Y4016412D01* +G01X450921Y4032206D01* +G01X462172Y4050377D01* +G01X469893Y4070306D01* +G01X473820Y4091314D01* +G01X473820Y4112686D01* +G01X497180Y4112686D01* +G01X497180Y4091314D01* +G01X501107Y4070306D01* +G01X508828Y4050377D01* +G01X520078Y4032206D01* +G01X534477Y4016412D01* +G01X551532Y4003533D01* +G01X570663Y3994007D01* +G01X591219Y3988158D01* +G01X612500Y3986186D01* +G01X612500Y3986186D01* +G01X633781Y3988158D01* +G01X654337Y3994007D01* +G01X673468Y4003533D01* +G01X690523Y4016412D01* +G01X704921Y4032206D01* +G01X716172Y4050377D01* +G01X723893Y4070306D01* +G01X727820Y4091314D01* +G01X727820Y4112686D01* +G01X723893Y4133694D01* +G01X716172Y4153623D01* +G01X704921Y4171793D01* +G01X690523Y4187587D01* +G01X673468Y4200467D01* +G01X654337Y4209993D01* +G01X633781Y4215842D01* +G01X612500Y4217814D01* +G01X591219Y4215842D01* +G01X570663Y4209993D01* +G01X551532Y4200467D01* +G01X534477Y4187587D01* +G01X520078Y4171793D01* +G01X508828Y4153623D01* +G01X501107Y4133694D01* +G01X497180Y4112686D01* +G01X473820Y4112686D01* +G01X469893Y4133694D01* +G01X462172Y4153623D01* +G01X450921Y4171793D01* +G01X436523Y4187587D01* +G01X419468Y4200467D01* +G01X400337Y4209993D01* +G01X379781Y4215842D01* +G01X358500Y4217814D01* +G01X337219Y4215842D01* +G01X316663Y4209993D01* +G01X297532Y4200467D01* +G01X280477Y4187587D01* +G01X266078Y4171793D01* +G01X254828Y4153623D01* +G01X247107Y4133694D01* +G01X243180Y4112686D01* +G01X35814Y4112686D01* +G01X35814Y4366686D01* +G01X243180Y4366686D01* +G01X243180Y4345314D01* +G01X247107Y4324306D01* +G01X254828Y4304377D01* +G01X266078Y4286206D01* +G01X280477Y4270412D01* +G01X297532Y4257533D01* +G01X316663Y4248007D01* +G01X337219Y4242158D01* +G01X358500Y4240186D01* +G01X358500Y4240186D01* +G01X379781Y4242158D01* +G01X400337Y4248007D01* +G01X419468Y4257533D01* +G01X436523Y4270412D01* +G01X450921Y4286206D01* +G01X462172Y4304377D01* +G01X469893Y4324306D01* +G01X473820Y4345314D01* +G01X473820Y4366686D01* +G01X497180Y4366686D01* +G01X497180Y4345314D01* +G01X501107Y4324306D01* +G01X508828Y4304377D01* +G01X520078Y4286206D01* +G01X534477Y4270412D01* +G01X551532Y4257533D01* +G01X570663Y4248007D01* +G01X591219Y4242158D01* +G01X612500Y4240186D01* +G01X612500Y4240186D01* +G01X633781Y4242158D01* +G01X654337Y4248007D01* +G01X673468Y4257533D01* +G01X690523Y4270412D01* +G01X704921Y4286206D01* +G01X716172Y4304377D01* +G01X723893Y4324306D01* +G01X727820Y4345314D01* +G01X727820Y4366686D01* +G01X723893Y4387694D01* +G01X716172Y4407623D01* +G01X704921Y4425793D01* +G01X690523Y4441587D01* +G01X673468Y4454467D01* +G01X654337Y4463993D01* +G01X633781Y4469842D01* +G01X612500Y4471814D01* +G01X591219Y4469842D01* +G01X570663Y4463993D01* +G01X551532Y4454467D01* +G01X534477Y4441587D01* +G01X520078Y4425793D01* +G01X508828Y4407623D01* +G01X501107Y4387694D01* +G01X497180Y4366686D01* +G01X473820Y4366686D01* +G01X469893Y4387694D01* +G01X462172Y4407623D01* +G01X450921Y4425793D01* +G01X436523Y4441587D01* +G01X419468Y4454467D01* +G01X400337Y4463993D01* +G01X379781Y4469842D01* +G01X358500Y4471814D01* +G01X337219Y4469842D01* +G01X316663Y4463993D01* +G01X297532Y4454467D01* +G01X280477Y4441587D01* +G01X266078Y4425793D01* +G01X254828Y4407623D01* +G01X247107Y4387694D01* +G01X243180Y4366686D01* +G01X35814Y4366686D01* +G01X35814Y4620686D01* +G01X243180Y4620686D01* +G01X243180Y4599314D01* +G01X247107Y4578306D01* +G01X254828Y4558377D01* +G01X266078Y4540206D01* +G01X280477Y4524412D01* +G01X297532Y4511533D01* +G01X316663Y4502007D01* +G01X337219Y4496158D01* +G01X358500Y4494186D01* +G01X358500Y4494186D01* +G01X379781Y4496158D01* +G01X400337Y4502007D01* +G01X419468Y4511533D01* +G01X436523Y4524412D01* +G01X450921Y4540206D01* +G01X462172Y4558377D01* +G01X469893Y4578306D01* +G01X473820Y4599314D01* +G01X473820Y4620686D01* +G01X497180Y4620686D01* +G01X497180Y4599314D01* +G01X501107Y4578306D01* +G01X508828Y4558377D01* +G01X520078Y4540206D01* +G01X534477Y4524412D01* +G01X551532Y4511533D01* +G01X570663Y4502007D01* +G01X591219Y4496158D01* +G01X612500Y4494186D01* +G01X612500Y4494186D01* +G01X633781Y4496158D01* +G01X654337Y4502007D01* +G01X673468Y4511533D01* +G01X690523Y4524412D01* +G01X704921Y4540206D01* +G01X716172Y4558377D01* +G01X723893Y4578306D01* +G01X727820Y4599314D01* +G01X727820Y4620686D01* +G01X723893Y4641694D01* +G01X716172Y4661623D01* +G01X704921Y4679793D01* +G01X690523Y4695587D01* +G01X673468Y4708467D01* +G01X654337Y4717993D01* +G01X633781Y4723842D01* +G01X612500Y4725814D01* +G01X591219Y4723842D01* +G01X570663Y4717993D01* +G01X551532Y4708467D01* +G01X534477Y4695587D01* +G01X520078Y4679793D01* +G01X508828Y4661623D01* +G01X501107Y4641694D01* +G01X497180Y4620686D01* +G01X473820Y4620686D01* +G01X469893Y4641694D01* +G01X462172Y4661623D01* +G01X450921Y4679793D01* +G01X436523Y4695587D01* +G01X419468Y4708467D01* +G01X400337Y4717993D01* +G01X379781Y4723842D01* +G01X358500Y4725814D01* +G01X337219Y4723842D01* +G01X316663Y4717993D01* +G01X297532Y4708467D01* +G01X280477Y4695587D01* +G01X266078Y4679793D01* +G01X254828Y4661623D01* +G01X247107Y4641694D01* +G01X243180Y4620686D01* +G01X35814Y4620686D01* +G01X35814Y4874686D01* +G01X243180Y4874686D01* +G01X243180Y4853314D01* +G01X247107Y4832306D01* +G01X254828Y4812377D01* +G01X266078Y4794206D01* +G01X280477Y4778412D01* +G01X297532Y4765533D01* +G01X316663Y4756007D01* +G01X337219Y4750158D01* +G01X358500Y4748186D01* +G01X358500Y4748186D01* +G01X379781Y4750158D01* +G01X400337Y4756007D01* +G01X419468Y4765533D01* +G01X436523Y4778412D01* +G01X450921Y4794206D01* +G01X462172Y4812377D01* +G01X469893Y4832306D01* +G01X473820Y4853314D01* +G01X473820Y4874686D01* +G01X497180Y4874686D01* +G01X497180Y4853314D01* +G01X501107Y4832306D01* +G01X508828Y4812377D01* +G01X520078Y4794206D01* +G01X534477Y4778412D01* +G01X551532Y4765533D01* +G01X570663Y4756007D01* +G01X591219Y4750158D01* +G01X612500Y4748186D01* +G01X612500Y4748186D01* +G01X633781Y4750158D01* +G01X654337Y4756007D01* +G01X673468Y4765533D01* +G01X690523Y4778412D01* +G01X704921Y4794206D01* +G01X716172Y4812377D01* +G01X723893Y4832306D01* +G01X727820Y4853314D01* +G01X727820Y4874686D01* +G01X723893Y4895694D01* +G01X716172Y4915623D01* +G01X704921Y4933793D01* +G01X690523Y4949587D01* +G01X673468Y4962467D01* +G01X654337Y4971993D01* +G01X633781Y4977842D01* +G01X612500Y4979814D01* +G01X591219Y4977842D01* +G01X570663Y4971993D01* +G01X551532Y4962467D01* +G01X534477Y4949587D01* +G01X520078Y4933793D01* +G01X508828Y4915623D01* +G01X501107Y4895694D01* +G01X497180Y4874686D01* +G01X473820Y4874686D01* +G01X469893Y4895694D01* +G01X462172Y4915623D01* +G01X450921Y4933793D01* +G01X436523Y4949587D01* +G01X419468Y4962467D01* +G01X400337Y4971993D01* +G01X379781Y4977842D01* +G01X358500Y4979814D01* +G01X337219Y4977842D01* +G01X316663Y4971993D01* +G01X297532Y4962467D01* +G01X280477Y4949587D01* +G01X266078Y4933793D01* +G01X254828Y4915623D01* +G01X247107Y4895694D01* +G01X243180Y4874686D01* +G01X35814Y4874686D01* +G01X35814Y5128686D01* +G01X243180Y5128686D01* +G01X243180Y5107314D01* +G01X247107Y5086306D01* +G01X254828Y5066377D01* +G01X266078Y5048206D01* +G01X280477Y5032412D01* +G01X297532Y5019533D01* +G01X316663Y5010007D01* +G01X337219Y5004158D01* +G01X358500Y5002186D01* +G01X358500Y5002186D01* +G01X379781Y5004158D01* +G01X400337Y5010007D01* +G01X419468Y5019533D01* +G01X436523Y5032412D01* +G01X450921Y5048206D01* +G01X462172Y5066377D01* +G01X469893Y5086306D01* +G01X473820Y5107314D01* +G01X473820Y5128686D01* +G01X473820Y5128686D01* +G01X497180Y5128686D01* +G01X497180Y5107314D01* +G01X501107Y5086306D01* +G01X508828Y5066377D01* +G01X520078Y5048206D01* +G01X534477Y5032412D01* +G01X551532Y5019533D01* +G01X570663Y5010007D01* +G01X591219Y5004158D01* +G01X612500Y5002186D01* +G01X612500Y5002186D01* +G01X633781Y5004158D01* +G01X654337Y5010007D01* +G01X673468Y5019533D01* +G01X690523Y5032412D01* +G01X704921Y5048206D01* +G01X716172Y5066377D01* +G01X723893Y5086306D01* +G01X727820Y5107314D01* +G01X727820Y5128686D01* +G01X723893Y5149694D01* +G01X716172Y5169623D01* +G01X704921Y5187793D01* +G01X690523Y5203587D01* +G01X673468Y5216467D01* +G01X654337Y5225993D01* +G01X633781Y5231842D01* +G01X612500Y5233814D01* +G01X591219Y5231842D01* +G01X570663Y5225993D01* +G01X551532Y5216467D01* +G01X534477Y5203587D01* +G01X520078Y5187793D01* +G01X508828Y5169623D01* +G01X501107Y5149694D01* +G01X497180Y5128686D01* +G01X473820Y5128686D01* +G01X469893Y5149694D01* +G01X462172Y5169623D01* +G01X450921Y5187793D01* +G01X436523Y5203587D01* +G01X419468Y5216467D01* +G01X400337Y5225993D01* +G01X379781Y5231842D01* +G01X358500Y5233814D01* +G01X337219Y5231842D01* +G01X316663Y5225993D01* +G01X297532Y5216467D01* +G01X280477Y5203587D01* +G01X266078Y5187793D01* +G01X254828Y5169623D01* +G01X247107Y5149694D01* +G01X243180Y5128686D01* +G01X35814Y5128686D01* +G01X35814Y5382686D01* +G01X243180Y5382686D01* +G01X243180Y5361314D01* +G01X247107Y5340306D01* +G01X254828Y5320377D01* +G01X266078Y5302206D01* +G01X280477Y5286412D01* +G01X297532Y5273533D01* +G01X316663Y5264007D01* +G01X337219Y5258158D01* +G01X358500Y5256186D01* +G01X358500Y5256186D01* +G01X379781Y5258158D01* +G01X400337Y5264007D01* +G01X419468Y5273533D01* +G01X436523Y5286412D01* +G01X450921Y5302206D01* +G01X462172Y5320377D01* +G01X469893Y5340306D01* +G01X473820Y5361314D01* +G01X473820Y5382686D01* +G01X497180Y5382686D01* +G01X497180Y5361314D01* +G01X501107Y5340306D01* +G01X508828Y5320377D01* +G01X520078Y5302206D01* +G01X534477Y5286412D01* +G01X551532Y5273533D01* +G01X570663Y5264007D01* +G01X591219Y5258158D01* +G01X612500Y5256186D01* +G01X612500Y5256186D01* +G01X633781Y5258158D01* +G01X654337Y5264007D01* +G01X673468Y5273533D01* +G01X690523Y5286412D01* +G01X704921Y5302206D01* +G01X716172Y5320377D01* +G01X723893Y5340306D01* +G01X727820Y5361314D01* +G01X727820Y5382686D01* +G01X723893Y5403694D01* +G01X716172Y5423623D01* +G01X704921Y5441793D01* +G01X690523Y5457587D01* +G01X673468Y5470467D01* +G01X654337Y5479993D01* +G01X633781Y5485842D01* +G01X612500Y5487814D01* +G01X591219Y5485842D01* +G01X570663Y5479993D01* +G01X551532Y5470467D01* +G01X534477Y5457587D01* +G01X520078Y5441793D01* +G01X508828Y5423623D01* +G01X501107Y5403694D01* +G01X497180Y5382686D01* +G01X473820Y5382686D01* +G01X469893Y5403694D01* +G01X462172Y5423623D01* +G01X450921Y5441793D01* +G01X436523Y5457587D01* +G01X419468Y5470467D01* +G01X400337Y5479993D01* +G01X379781Y5485842D01* +G01X358500Y5487814D01* +G01X337219Y5485842D01* +G01X316663Y5479993D01* +G01X297532Y5470467D01* +G01X280477Y5457587D01* +G01X266078Y5441793D01* +G01X254828Y5423623D01* +G01X247107Y5403694D01* +G01X243180Y5382686D01* +G01X35814Y5382686D01* +G01X35814Y6646000D01* +G01X34061Y6657067D01* +G01X28974Y6667051D01* +G01X21051Y6674974D01* +G01X11067Y6680061D01* +G01X0Y6681814D01* +G01X-2422300Y6681814D01* +G01X-2442128Y6683549D01* +G01X-2461354Y6688700D01* +G01X-2479393Y6697112D01* +G01X-2495697Y6708528D01* +G01X-2509772Y6722603D01* +G01X-2521188Y6738907D01* +G01X-2529600Y6756946D01* +G01X-2534751Y6776172D01* +G01X-2536486Y6796000D01* +G01X-2536486Y7248649D01* +G01X62787Y7248649D01* +G01X62787Y7229150D01* +G01X66370Y7209984D01* +G01X73413Y7191801D01* +G01X83678Y7175223D01* +G01X96815Y7160813D01* +G01X112375Y7149063D01* +G01X129830Y7140371D01* +G01X148584Y7135035D01* +G01X168000Y7133236D01* +G01X218800Y7133236D01* +G01X238216Y7135035D01* +G01X256970Y7140371D01* +G01X274425Y7149063D01* +G01X289985Y7160813D01* +G01X303122Y7175223D01* +G01X313386Y7191801D01* +G01X320430Y7209984D01* +G01X324013Y7229150D01* +G01X324013Y7248649D01* +G01X320430Y7267816D01* +G01X313386Y7285998D01* +G01X303122Y7302577D01* +G01X289985Y7316987D01* +G01X274425Y7328737D01* +G01X256970Y7337429D01* +G01X238216Y7342765D01* +G01X218800Y7344564D01* +G01X218800Y7344564D01* +G01X168000Y7344564D01* +G01X148584Y7342765D01* +G01X129830Y7337429D01* +G01X112375Y7328737D01* +G01X96815Y7316987D01* +G01X83678Y7302577D01* +G01X73413Y7285998D01* +G01X66370Y7267816D01* +G01X62787Y7248649D01* +G01X-2536486Y7248649D01* +G01X-2536486Y7492900D01* +G01X-394864Y7492900D01* +G01X-392983Y7471882D01* +G01X-387400Y7451533D01* +G01X-378292Y7432498D01* +G01X-365949Y7415383D01* +G01X-350763Y7400731D01* +G01X-333216Y7389009D01* +G01X-313867Y7380589D01* +G01X-293331Y7375739D01* +G01X-272259Y7374612D01* +G01X-251322Y7377245D01* +G01X-231186Y7383553D01* +G01X-212489Y7393337D01* +G01X-195828Y7406286D01* +G01X107478Y7406286D01* +G01X121335Y7398099D01* +G01X136275Y7392111D01* +G01X151951Y7388462D01* +G01X168000Y7387236D01* +G01X218800Y7387236D01* +G01X234848Y7388462D01* +G01X250525Y7392111D01* +G01X265465Y7398099D01* +G01X279322Y7406286D01* +G01X535723Y7406286D01* +G01X1497792Y6444218D01* +G01X1497792Y6390214D01* +G01X1489406Y6390214D01* +G01X1478339Y6388461D01* +G01X1468355Y6383374D01* +G01X1460432Y6375450D01* +G01X1455345Y6365467D01* +G01X1453592Y6354400D01* +G01X1453592Y6116800D01* +G01X1455345Y6105733D01* +G01X1460432Y6095749D01* +G01X1468355Y6087826D01* +G01X1478339Y6082739D01* +G01X1489406Y6080986D01* +G01X1497792Y6080986D01* +G01X1497792Y4307281D01* +G01X1497792Y4307281D01* +G01X1484173Y4294256D01* +G01X1472653Y4279343D01* +G01X1463490Y4262877D01* +G01X1456888Y4245226D01* +G01X1452997Y4226788D01* +G01X1192573Y3966364D01* +G01X1114150Y3966364D01* +G01X1103083Y3964611D01* +G01X1093099Y3959524D01* +G01X1085176Y3951601D01* +G01X1080089Y3941617D01* +G01X1078336Y3930550D01* +G01X1078336Y3765450D01* +G01X1080089Y3754383D01* +G01X1085176Y3744399D01* +G01X1093099Y3736476D01* +G01X1103083Y3731389D01* +G01X1114150Y3729636D01* +G01X1279250Y3729636D01* +G01X1290317Y3731389D01* +G01X1300301Y3736476D01* +G01X1308224Y3744399D01* +G01X1313311Y3754383D01* +G01X1315064Y3765450D01* +G01X1315064Y3843873D01* +G01X1329877Y3858686D01* +G01X1830680Y3858686D01* +G01X1830680Y3837314D01* +G01X1834607Y3816306D01* +G01X1842328Y3796377D01* +G01X1853578Y3778206D01* +G01X1867977Y3762412D01* +G01X1885032Y3749533D01* +G01X1904163Y3740007D01* +G01X1924719Y3734158D01* +G01X1946000Y3732186D01* +G01X1946000Y3732186D01* +G01X1967281Y3734158D01* +G01X1987837Y3740007D01* +G01X2006968Y3749533D01* +G01X2024023Y3762412D01* +G01X2038421Y3778206D01* +G01X2049672Y3796377D01* +G01X2057393Y3816306D01* +G01X2061320Y3837314D01* +G01X2061320Y3858686D01* +G01X2084680Y3858686D01* +G01X2084680Y3837314D01* +G01X2088607Y3816306D01* +G01X2096328Y3796377D01* +G01X2107578Y3778206D01* +G01X2121977Y3762412D01* +G01X2139032Y3749533D01* +G01X2158163Y3740007D01* +G01X2178719Y3734158D01* +G01X2200000Y3732186D01* +G01X2200000Y3732186D01* +G01X2221281Y3734158D01* +G01X2241837Y3740007D01* +G01X2260968Y3749533D01* +G01X2278023Y3762412D01* +G01X2292421Y3778206D01* +G01X2303672Y3796377D01* +G01X2311393Y3816306D01* +G01X2315320Y3837314D01* +G01X2315320Y3858686D01* +G01X2311393Y3879694D01* +G01X2303672Y3899623D01* +G01X2292421Y3917793D01* +G01X2278023Y3933587D01* +G01X2260968Y3946467D01* +G01X2241837Y3955993D01* +G01X2221281Y3961842D01* +G01X2200000Y3963814D01* +G01X2178719Y3961842D01* +G01X2158163Y3955993D01* +G01X2139032Y3946467D01* +G01X2121977Y3933587D01* +G01X2107578Y3917793D01* +G01X2096328Y3899623D01* +G01X2088607Y3879694D01* +G01X2084680Y3858686D01* +G01X2061320Y3858686D01* +G01X2057393Y3879694D01* +G01X2049672Y3899623D01* +G01X2038421Y3917793D01* +G01X2024023Y3933587D01* +G01X2006968Y3946467D01* +G01X1987837Y3955993D01* +G01X1967281Y3961842D01* +G01X1946000Y3963814D01* +G01X1924719Y3961842D01* +G01X1904163Y3955993D01* +G01X1885032Y3946467D01* +G01X1867977Y3933587D01* +G01X1853578Y3917793D01* +G01X1842328Y3899623D01* +G01X1834607Y3879694D01* +G01X1830680Y3858686D01* +G01X1329877Y3858686D01* +G01X1557166Y4085975D01* +G01X1579270Y4084298D01* +G01X1601325Y4086527D01* +G01X1622647Y4092591D01* +G01X1642573Y4102304D01* +G01X1656814Y4112686D01* +G01X1830680Y4112686D01* +G01X1830680Y4091314D01* +G01X1834607Y4070306D01* +G01X1842328Y4050377D01* +G01X1853578Y4032206D01* +G01X1867977Y4016412D01* +G01X1885032Y4003533D01* +G01X1904163Y3994007D01* +G01X1924719Y3988158D01* +G01X1946000Y3986186D01* +G01X1946000Y3986186D01* +G01X1967281Y3988158D01* +G01X1987837Y3994007D01* +G01X2006968Y4003533D01* +G01X2024023Y4016412D01* +G01X2038421Y4032206D01* +G01X2049672Y4050377D01* +G01X2057393Y4070306D01* +G01X2061320Y4091314D01* +G01X2061320Y4112686D01* +G01X2084680Y4112686D01* +G01X2084680Y4091314D01* +G01X2088607Y4070306D01* +G01X2096328Y4050377D01* +G01X2107578Y4032206D01* +G01X2121977Y4016412D01* +G01X2139032Y4003533D01* +G01X2158163Y3994007D01* +G01X2178719Y3988158D01* +G01X2200000Y3986186D01* +G01X2200000Y3986186D01* +G01X2221281Y3988158D01* +G01X2241837Y3994007D01* +G01X2260968Y4003533D01* +G01X2278023Y4016412D01* +G01X2292421Y4032206D01* +G01X2303672Y4050377D01* +G01X2311393Y4070306D01* +G01X2315320Y4091314D01* +G01X2315320Y4112686D01* +G01X2311393Y4133694D01* +G01X2303672Y4153623D01* +G01X2292421Y4171793D01* +G01X2278023Y4187587D01* +G01X2260968Y4200467D01* +G01X2241837Y4209993D01* +G01X2221281Y4215842D01* +G01X2200000Y4217814D01* +G01X2178719Y4215842D01* +G01X2158163Y4209993D01* +G01X2139032Y4200467D01* +G01X2121977Y4187587D01* +G01X2107578Y4171793D01* +G01X2096328Y4153623D01* +G01X2088607Y4133694D01* +G01X2084680Y4112686D01* +G01X2061320Y4112686D01* +G01X2057393Y4133694D01* +G01X2049672Y4153623D01* +G01X2038421Y4171793D01* +G01X2024023Y4187587D01* +G01X2006968Y4200467D01* +G01X1987837Y4209993D01* +G01X1967281Y4215842D01* +G01X1946000Y4217814D01* +G01X1924719Y4215842D01* +G01X1904163Y4209993D01* +G01X1885032Y4200467D01* +G01X1867977Y4187587D01* +G01X1853578Y4171793D01* +G01X1842328Y4153623D01* +G01X1834607Y4133694D01* +G01X1830680Y4112686D01* +G01X1656814Y4112686D01* +G01X1660486Y4115363D01* +G01X1675828Y4131363D01* +G01X1688124Y4149807D01* +G01X1696993Y4170123D01* +G01X1702158Y4191680D01* +G01X1703459Y4213810D01* +G01X1700856Y4235824D01* +G01X1694431Y4257039D01* +G01X1684381Y4276798D01* +G01X1671020Y4294486D01* +G01X1671020Y4366686D01* +G01X1830680Y4366686D01* +G01X1830680Y4345314D01* +G01X1834607Y4324306D01* +G01X1842328Y4304377D01* +G01X1853578Y4286206D01* +G01X1867977Y4270412D01* +G01X1885032Y4257533D01* +G01X1904163Y4248007D01* +G01X1924719Y4242158D01* +G01X1946000Y4240186D01* +G01X1946000Y4240186D01* +G01X1967281Y4242158D01* +G01X1987837Y4248007D01* +G01X2006968Y4257533D01* +G01X2024023Y4270412D01* +G01X2038421Y4286206D01* +G01X2049672Y4304377D01* +G01X2057393Y4324306D01* +G01X2061320Y4345314D01* +G01X2061320Y4366686D01* +G01X2084680Y4366686D01* +G01X2084680Y4345314D01* +G01X2088607Y4324306D01* +G01X2096328Y4304377D01* +G01X2107578Y4286206D01* +G01X2121977Y4270412D01* +G01X2139032Y4257533D01* +G01X2158163Y4248007D01* +G01X2178719Y4242158D01* +G01X2200000Y4240186D01* +G01X2200000Y4240186D01* +G01X2221281Y4242158D01* +G01X2241837Y4248007D01* +G01X2260968Y4257533D01* +G01X2278023Y4270412D01* +G01X2292421Y4286206D01* +G01X2303672Y4304377D01* +G01X2311393Y4324306D01* +G01X2315320Y4345314D01* +G01X2315320Y4366686D01* +G01X2311393Y4387694D01* +G01X2303672Y4407623D01* +G01X2292421Y4425793D01* +G01X2278023Y4441587D01* +G01X2260968Y4454467D01* +G01X2241837Y4463993D01* +G01X2221281Y4469842D01* +G01X2200000Y4471814D01* +G01X2178719Y4469842D01* +G01X2158163Y4463993D01* +G01X2139032Y4454467D01* +G01X2121977Y4441587D01* +G01X2107578Y4425793D01* +G01X2096328Y4407623D01* +G01X2088607Y4387694D01* +G01X2084680Y4366686D01* +G01X2061320Y4366686D01* +G01X2057393Y4387694D01* +G01X2049672Y4407623D01* +G01X2038421Y4425793D01* +G01X2024023Y4441587D01* +G01X2006968Y4454467D01* +G01X1987837Y4463993D01* +G01X1967281Y4469842D01* +G01X1946000Y4471814D01* +G01X1924719Y4469842D01* +G01X1904163Y4463993D01* +G01X1885032Y4454467D01* +G01X1867977Y4441587D01* +G01X1853578Y4425793D01* +G01X1842328Y4407623D01* +G01X1834607Y4387694D01* +G01X1830680Y4366686D01* +G01X1671020Y4366686D01* +G01X1671020Y4620686D01* +G01X1830680Y4620686D01* +G01X1830680Y4599314D01* +G01X1834607Y4578306D01* +G01X1842328Y4558377D01* +G01X1853578Y4540206D01* +G01X1867977Y4524412D01* +G01X1885032Y4511533D01* +G01X1904163Y4502007D01* +G01X1924719Y4496158D01* +G01X1946000Y4494186D01* +G01X1946000Y4494186D01* +G01X1967281Y4496158D01* +G01X1987837Y4502007D01* +G01X2006968Y4511533D01* +G01X2024023Y4524412D01* +G01X2038421Y4540206D01* +G01X2049672Y4558377D01* +G01X2057393Y4578306D01* +G01X2061320Y4599314D01* +G01X2061320Y4620686D01* +G01X2084680Y4620686D01* +G01X2084680Y4599314D01* +G01X2088607Y4578306D01* +G01X2096328Y4558377D01* +G01X2107578Y4540206D01* +G01X2121977Y4524412D01* +G01X2139032Y4511533D01* +G01X2158163Y4502007D01* +G01X2178719Y4496158D01* +G01X2200000Y4494186D01* +G01X2200000Y4494186D01* +G01X2221281Y4496158D01* +G01X2241837Y4502007D01* +G01X2260968Y4511533D01* +G01X2278023Y4524412D01* +G01X2292421Y4540206D01* +G01X2303672Y4558377D01* +G01X2311393Y4578306D01* +G01X2315320Y4599314D01* +G01X2315320Y4620686D01* +G01X2311393Y4641694D01* +G01X2303672Y4661623D01* +G01X2292421Y4679793D01* +G01X2278023Y4695587D01* +G01X2260968Y4708467D01* +G01X2241837Y4717993D01* +G01X2221281Y4723842D01* +G01X2200000Y4725814D01* +G01X2178719Y4723842D01* +G01X2158163Y4717993D01* +G01X2139032Y4708467D01* +G01X2121977Y4695587D01* +G01X2107578Y4679793D01* +G01X2096328Y4661623D01* +G01X2088607Y4641694D01* +G01X2084680Y4620686D01* +G01X2061320Y4620686D01* +G01X2057393Y4641694D01* +G01X2049672Y4661623D01* +G01X2038421Y4679793D01* +G01X2024023Y4695587D01* +G01X2006968Y4708467D01* +G01X1987837Y4717993D01* +G01X1967281Y4723842D01* +G01X1946000Y4725814D01* +G01X1924719Y4723842D01* +G01X1904163Y4717993D01* +G01X1885032Y4708467D01* +G01X1867977Y4695587D01* +G01X1853578Y4679793D01* +G01X1842328Y4661623D01* +G01X1834607Y4641694D01* +G01X1830680Y4620686D01* +G01X1671020Y4620686D01* +G01X1671020Y4874686D01* +G01X1830680Y4874686D01* +G01X1830680Y4853314D01* +G01X1834607Y4832306D01* +G01X1842328Y4812377D01* +G01X1853578Y4794206D01* +G01X1867977Y4778412D01* +G01X1885032Y4765533D01* +G01X1904163Y4756007D01* +G01X1924719Y4750158D01* +G01X1946000Y4748186D01* +G01X1946000Y4748186D01* +G01X1967281Y4750158D01* +G01X1987837Y4756007D01* +G01X2006968Y4765533D01* +G01X2024023Y4778412D01* +G01X2038421Y4794206D01* +G01X2049672Y4812377D01* +G01X2057393Y4832306D01* +G01X2061320Y4853314D01* +G01X2061320Y4874686D01* +G01X2084680Y4874686D01* +G01X2084680Y4853314D01* +G01X2088607Y4832306D01* +G01X2096328Y4812377D01* +G01X2107578Y4794206D01* +G01X2121977Y4778412D01* +G01X2139032Y4765533D01* +G01X2158163Y4756007D01* +G01X2178719Y4750158D01* +G01X2200000Y4748186D01* +G01X2200000Y4748186D01* +G01X2221281Y4750158D01* +G01X2241837Y4756007D01* +G01X2260968Y4765533D01* +G01X2278023Y4778412D01* +G01X2292421Y4794206D01* +G01X2303672Y4812377D01* +G01X2311393Y4832306D01* +G01X2315320Y4853314D01* +G01X2315320Y4874686D01* +G01X2311393Y4895694D01* +G01X2303672Y4915623D01* +G01X2292421Y4933793D01* +G01X2278023Y4949587D01* +G01X2260968Y4962467D01* +G01X2241837Y4971993D01* +G01X2221281Y4977842D01* +G01X2200000Y4979814D01* +G01X2178719Y4977842D01* +G01X2158163Y4971993D01* +G01X2139032Y4962467D01* +G01X2121977Y4949587D01* +G01X2107578Y4933793D01* +G01X2096328Y4915623D01* +G01X2088607Y4895694D01* +G01X2084680Y4874686D01* +G01X2061320Y4874686D01* +G01X2057393Y4895694D01* +G01X2049672Y4915623D01* +G01X2038421Y4933793D01* +G01X2024023Y4949587D01* +G01X2006968Y4962467D01* +G01X1987837Y4971993D01* +G01X1967281Y4977842D01* +G01X1946000Y4979814D01* +G01X1924719Y4977842D01* +G01X1904163Y4971993D01* +G01X1885032Y4962467D01* +G01X1867977Y4949587D01* +G01X1853578Y4933793D01* +G01X1842328Y4915623D01* +G01X1834607Y4895694D01* +G01X1830680Y4874686D01* +G01X1671020Y4874686D01* +G01X1671020Y5128686D01* +G01X1830680Y5128686D01* +G01X1830680Y5107314D01* +G01X1834607Y5086306D01* +G01X1842328Y5066377D01* +G01X1853578Y5048206D01* +G01X1867977Y5032412D01* +G01X1885032Y5019533D01* +G01X1904163Y5010007D01* +G01X1924719Y5004158D01* +G01X1946000Y5002186D01* +G01X1946000Y5002186D01* +G01X1967281Y5004158D01* +G01X1987837Y5010007D01* +G01X2006968Y5019533D01* +G01X2024023Y5032412D01* +G01X2038421Y5048206D01* +G01X2049672Y5066377D01* +G01X2057393Y5086306D01* +G01X2061320Y5107314D01* +G01X2061320Y5128686D01* +G01X2084680Y5128686D01* +G01X2084680Y5107314D01* +G01X2088607Y5086306D01* +G01X2096328Y5066377D01* +G01X2107578Y5048206D01* +G01X2121977Y5032412D01* +G01X2139032Y5019533D01* +G01X2158163Y5010007D01* +G01X2178719Y5004158D01* +G01X2200000Y5002186D01* +G01X2200000Y5002186D01* +G01X2221281Y5004158D01* +G01X2241837Y5010007D01* +G01X2260968Y5019533D01* +G01X2278023Y5032412D01* +G01X2292421Y5048206D01* +G01X2303672Y5066377D01* +G01X2311393Y5086306D01* +G01X2315320Y5107314D01* +G01X2315320Y5128686D01* +G01X2311393Y5149694D01* +G01X2303672Y5169623D01* +G01X2292421Y5187793D01* +G01X2278023Y5203587D01* +G01X2260968Y5216467D01* +G01X2241837Y5225993D01* +G01X2221281Y5231842D01* +G01X2200000Y5233814D01* +G01X2178719Y5231842D01* +G01X2158163Y5225993D01* +G01X2139032Y5216467D01* +G01X2121977Y5203587D01* +G01X2107578Y5187793D01* +G01X2096328Y5169623D01* +G01X2088607Y5149694D01* +G01X2084680Y5128686D01* +G01X2061320Y5128686D01* +G01X2057393Y5149694D01* +G01X2049672Y5169623D01* +G01X2038421Y5187793D01* +G01X2024023Y5203587D01* +G01X2006968Y5216467D01* +G01X1987837Y5225993D01* +G01X1967281Y5231842D01* +G01X1946000Y5233814D01* +G01X1924719Y5231842D01* +G01X1904163Y5225993D01* +G01X1885032Y5216467D01* +G01X1867977Y5203587D01* +G01X1853578Y5187793D01* +G01X1842328Y5169623D01* +G01X1834607Y5149694D01* +G01X1830680Y5128686D01* +G01X1671020Y5128686D01* +G01X1671020Y5382686D01* +G01X1830680Y5382686D01* +G01X1830680Y5361314D01* +G01X1834607Y5340306D01* +G01X1842328Y5320377D01* +G01X1853578Y5302206D01* +G01X1867977Y5286412D01* +G01X1885032Y5273533D01* +G01X1904163Y5264007D01* +G01X1924719Y5258158D01* +G01X1946000Y5256186D01* +G01X1946000Y5256186D01* +G01X1967281Y5258158D01* +G01X1987837Y5264007D01* +G01X2006968Y5273533D01* +G01X2024023Y5286412D01* +G01X2038421Y5302206D01* +G01X2049672Y5320377D01* +G01X2057393Y5340306D01* +G01X2061320Y5361314D01* +G01X2061320Y5382686D01* +G01X2084680Y5382686D01* +G01X2084680Y5361314D01* +G01X2088607Y5340306D01* +G01X2096328Y5320377D01* +G01X2107578Y5302206D01* +G01X2121977Y5286412D01* +G01X2139032Y5273533D01* +G01X2158163Y5264007D01* +G01X2178719Y5258158D01* +G01X2200000Y5256186D01* +G01X2200000Y5256186D01* +G01X2221281Y5258158D01* +G01X2241837Y5264007D01* +G01X2260968Y5273533D01* +G01X2278023Y5286412D01* +G01X2292421Y5302206D01* +G01X2303672Y5320377D01* +G01X2311393Y5340306D01* +G01X2315320Y5361314D01* +G01X2315320Y5382686D01* +G01X2311393Y5403694D01* +G01X2303672Y5423623D01* +G01X2292421Y5441793D01* +G01X2278023Y5457587D01* +G01X2260968Y5470467D01* +G01X2241837Y5479993D01* +G01X2221281Y5485842D01* +G01X2200000Y5487814D01* +G01X2178719Y5485842D01* +G01X2158163Y5479993D01* +G01X2139032Y5470467D01* +G01X2121977Y5457587D01* +G01X2107578Y5441793D01* +G01X2096328Y5423623D01* +G01X2088607Y5403694D01* +G01X2084680Y5382686D01* +G01X2061320Y5382686D01* +G01X2057393Y5403694D01* +G01X2049672Y5423623D01* +G01X2038421Y5441793D01* +G01X2024023Y5457587D01* +G01X2006968Y5470467D01* +G01X1987837Y5479993D01* +G01X1967281Y5485842D01* +G01X1946000Y5487814D01* +G01X1924719Y5485842D01* +G01X1904163Y5479993D01* +G01X1885032Y5470467D01* +G01X1867977Y5457587D01* +G01X1853578Y5441793D01* +G01X1842328Y5423623D01* +G01X1834607Y5403694D01* +G01X1830680Y5382686D01* +G01X1671020Y5382686D01* +G01X1671020Y6018937D01* +G01X3457551Y6018937D01* +G01X3457551Y5997095D01* +G01X3461564Y5975624D01* +G01X3469455Y5955257D01* +G01X3480953Y5936686D01* +G01X3495669Y5920544D01* +G01X3513099Y5907381D01* +G01X3532652Y5897645D01* +G01X3553661Y5891667D01* +G01X3575410Y5889652D01* +G01X3597159Y5891667D01* +G01X3618168Y5897645D01* +G01X3637721Y5907381D01* +G01X3655151Y5920544D01* +G01X3669866Y5936686D01* +G01X3681365Y5955257D01* +G01X3689255Y5975624D01* +G01X3693269Y5997095D01* +G01X3693269Y6018937D01* +G01X3693269Y6018937D01* +G01X3711551Y6018937D01* +G01X3711551Y5997095D01* +G01X3715564Y5975624D01* +G01X3723455Y5955257D01* +G01X3734953Y5936686D01* +G01X3749669Y5920544D01* +G01X3767099Y5907381D01* +G01X3786652Y5897645D01* +G01X3807661Y5891667D01* +G01X3829410Y5889652D01* +G01X3851159Y5891667D01* +G01X3872168Y5897645D01* +G01X3891721Y5907381D01* +G01X3909151Y5920544D01* +G01X3923866Y5936686D01* +G01X3935365Y5955257D01* +G01X3943255Y5975624D01* +G01X3947269Y5997095D01* +G01X3947269Y6018937D01* +G01X3943255Y6040408D01* +G01X3935365Y6060775D01* +G01X3923866Y6079346D01* +G01X3909151Y6095488D01* +G01X3891721Y6108651D01* +G01X3872168Y6118387D01* +G01X3851159Y6124365D01* +G01X3829410Y6126380D01* +G01X3829410Y6126380D01* +G01X3807661Y6124365D01* +G01X3786652Y6118387D01* +G01X3767099Y6108651D01* +G01X3749669Y6095488D01* +G01X3734953Y6079346D01* +G01X3723455Y6060775D01* +G01X3715564Y6040408D01* +G01X3711551Y6018937D01* +G01X3693269Y6018937D01* +G01X3689255Y6040408D01* +G01X3681365Y6060775D01* +G01X3669866Y6079346D01* +G01X3655151Y6095488D01* +G01X3637721Y6108651D01* +G01X3618168Y6118387D01* +G01X3597159Y6124365D01* +G01X3575410Y6126380D01* +G01X3575410Y6126380D01* +G01X3553661Y6124365D01* +G01X3532652Y6118387D01* +G01X3513099Y6108651D01* +G01X3495669Y6095488D01* +G01X3480953Y6079346D01* +G01X3469455Y6060775D01* +G01X3461564Y6040408D01* +G01X3457551Y6018937D01* +G01X1671020Y6018937D01* +G01X1671020Y6080986D01* +G01X1679405Y6080986D01* +G01X1690472Y6082739D01* +G01X1700456Y6087826D01* +G01X1708379Y6095749D01* +G01X1713466Y6105733D01* +G01X1715219Y6116800D01* +G01X1715219Y6354400D01* +G01X1973581Y6354400D01* +G01X1973581Y6116800D01* +G01X1975333Y6105733D01* +G01X1980420Y6095749D01* +G01X1988344Y6087826D01* +G01X1998327Y6082739D01* +G01X2009395Y6080986D01* +G01X2199394Y6080986D01* +G01X2210461Y6082739D01* +G01X2220445Y6087826D01* +G01X2228368Y6095749D01* +G01X2233455Y6105733D01* +G01X2235208Y6116800D01* +G01X2235208Y6354400D01* +G01X2235208Y6354400D01* +G01X2233455Y6365467D01* +G01X2228368Y6375450D01* +G01X2220445Y6383374D01* +G01X2210461Y6388461D01* +G01X2199394Y6390214D01* +G01X2009395Y6390214D01* +G01X1998327Y6388461D01* +G01X1988344Y6383374D01* +G01X1980420Y6375450D01* +G01X1975333Y6365467D01* +G01X1973581Y6354400D01* +G01X1715219Y6354400D01* +G01X1713466Y6365467D01* +G01X1708379Y6375450D01* +G01X1700456Y6383374D01* +G01X1690472Y6388461D01* +G01X1679405Y6390214D01* +G01X1671020Y6390214D01* +G01X1671020Y6444218D01* +G01X1794988Y6568186D01* +G01X2607484Y6568186D01* +G01X2624382Y6569850D01* +G01X2640630Y6574779D01* +G01X2655604Y6582783D01* +G01X2668729Y6593555D01* +G01X3042549Y6967374D01* +G01X3053321Y6980500D01* +G01X3061325Y6995474D01* +G01X3066254Y7011722D01* +G01X3067918Y7028620D01* +G01X3067918Y9229100D01* +G01X3103966Y9229100D01* +G01X3103966Y6647430D01* +G01X3105879Y6632902D01* +G01X3111487Y6619363D01* +G01X3120407Y6607738D01* +G01X3378491Y6349654D01* +G01X3390117Y6340733D01* +G01X3403655Y6335125D01* +G01X3418184Y6333213D01* +G01X3480853Y6333213D01* +G01X3480853Y6333213D01* +G01X3469387Y6314638D01* +G01X3461526Y6294274D01* +G01X3457539Y6272812D01* +G01X3457561Y6250984D01* +G01X3461591Y6229530D01* +G01X3469492Y6209182D01* +G01X3480995Y6190630D01* +G01X3495710Y6174506D01* +G01X3513135Y6161359D01* +G01X3532678Y6151635D01* +G01X3553674Y6145665D01* +G01X3575410Y6143652D01* +G01X3575410Y6143652D01* +G01X3597146Y6145665D01* +G01X3618142Y6151635D01* +G01X3637685Y6161359D01* +G01X3655110Y6174506D01* +G01X3669824Y6190630D01* +G01X3681328Y6209182D01* +G01X3689229Y6229530D01* +G01X3693259Y6250984D01* +G01X3693281Y6272812D01* +G01X3689294Y6294274D01* +G01X3681433Y6314638D01* +G01X3669967Y6333213D01* +G01X3678828Y6333213D01* +G01X3716032Y6296008D01* +G01X3711825Y6275573D01* +G01X3711271Y6254716D01* +G01X3714388Y6234086D01* +G01X3721079Y6214324D01* +G01X3731136Y6196044D01* +G01X3744246Y6179814D01* +G01X3760003Y6166137D01* +G01X3777916Y6155440D01* +G01X3797429Y6148054D01* +G01X3817935Y6144209D01* +G01X3838798Y6144025D01* +G01X3859370Y6147506D01* +G01X3879011Y6154546D01* +G01X3897110Y6164925D01* +G01X3913106Y6178320D01* +G01X3926501Y6194316D01* +G01X3936880Y6212415D01* +G01X3943919Y6232056D01* +G01X3947401Y6252627D01* +G01X3947216Y6273491D01* +G01X3943371Y6293997D01* +G01X3935986Y6313510D01* +G01X3925288Y6331423D01* +G01X3911612Y6347180D01* +G01X3895382Y6360290D01* +G01X3877101Y6370347D01* +G01X3857339Y6377038D01* +G01X3836710Y6380155D01* +G01X3815853Y6379601D01* +G01X3795417Y6375394D01* +G01X3741772Y6429039D01* +G01X3730146Y6437960D01* +G01X3716608Y6443568D01* +G01X3702079Y6445481D01* +G01X3670461Y6445481D01* +G01X3681731Y6463998D01* +G01X3689435Y6484261D01* +G01X3693314Y6505588D01* +G01X3693238Y6527266D01* +G01X3689210Y6548566D01* +G01X3681366Y6568774D01* +G01X3669967Y6587213D01* +G01X3678828Y6587213D01* +G01X3716032Y6550008D01* +G01X3711825Y6529573D01* +G01X3711271Y6508716D01* +G01X3714388Y6488086D01* +G01X3721079Y6468324D01* +G01X3731136Y6450044D01* +G01X3744246Y6433814D01* +G01X3760003Y6420137D01* +G01X3777916Y6409440D01* +G01X3797429Y6402054D01* +G01X3817935Y6398209D01* +G01X3838798Y6398025D01* +G01X3859370Y6401506D01* +G01X3879011Y6408546D01* +G01X3897110Y6418925D01* +G01X3913106Y6432320D01* +G01X3926501Y6448316D01* +G01X3936880Y6466415D01* +G01X3943919Y6486056D01* +G01X3947401Y6506627D01* +G01X3947216Y6527491D01* +G01X3943371Y6547997D01* +G01X3935986Y6567510D01* +G01X3925288Y6585423D01* +G01X3911612Y6601180D01* +G01X3895382Y6614290D01* +G01X3877101Y6624347D01* +G01X3857339Y6631038D01* +G01X3836710Y6634155D01* +G01X3815853Y6633601D01* +G01X3795417Y6629394D01* +G01X3741772Y6683039D01* +G01X3730146Y6691960D01* +G01X3716608Y6697568D01* +G01X3702079Y6699481D01* +G01X3670461Y6699481D01* +G01X3681198Y6716923D01* +G01X3688767Y6735956D01* +G01X3692942Y6756008D01* +G01X3693090Y6760627D01* +G01X3711419Y6760627D01* +G01X3714900Y6740056D01* +G01X3721940Y6720415D01* +G01X3732319Y6702316D01* +G01X3745714Y6686320D01* +G01X3745714Y6686320D01* +G01X3761710Y6672925D01* +G01X3779809Y6662546D01* +G01X3799450Y6655506D01* +G01X3820021Y6652025D01* +G01X3840885Y6652209D01* +G01X3861391Y6656054D01* +G01X3880904Y6663440D01* +G01X3898817Y6674137D01* +G01X3914574Y6687814D01* +G01X3927684Y6704044D01* +G01X3937741Y6722324D01* +G01X3944432Y6742086D01* +G01X3947549Y6762716D01* +G01X3946995Y6783573D01* +G01X3942788Y6804008D01* +G01X4787293Y7648513D01* +G01X4796214Y7660139D01* +G01X4801821Y7673678D01* +G01X4803734Y7688206D01* +G01X4803734Y10183400D01* +G01X4801821Y10197928D01* +G01X4796214Y10211467D01* +G01X4787293Y10223092D01* +G01X4658235Y10352150D01* +G01X4661711Y10372765D01* +G01X4661295Y10393666D01* +G01X4657003Y10414127D01* +G01X4648984Y10433433D01* +G01X4637517Y10450913D01* +G01X4623002Y10465958D01* +G01X4605943Y10478044D01* +G01X4586936Y10486749D01* +G01X4566643Y10491771D01* +G01X4545770Y10492934D01* +G01X4525044Y10490198D01* +G01X4505187Y10483659D01* +G01X4486892Y10473544D01* +G01X4470794Y10460206D01* +G01X4470794Y10460206D01* +G01X4457456Y10444108D01* +G01X4447340Y10425813D01* +G01X4440801Y10405956D01* +G01X4438066Y10385230D01* +G01X4439229Y10364357D01* +G01X4444251Y10344063D01* +G01X4452956Y10325056D01* +G01X4465042Y10307998D01* +G01X4480087Y10293483D01* +G01X4497567Y10282016D01* +G01X4516873Y10273996D01* +G01X4537333Y10269704D01* +G01X4558235Y10269289D01* +G01X4578850Y10272765D01* +G01X4691466Y10160148D01* +G01X4691466Y7711458D01* +G01X4691466Y7711458D01* +G01X3863402Y6883394D01* +G01X3842967Y6887601D01* +G01X3822110Y6888155D01* +G01X3801480Y6885038D01* +G01X3781718Y6878347D01* +G01X3763438Y6868290D01* +G01X3747208Y6855180D01* +G01X3733531Y6839423D01* +G01X3722834Y6821510D01* +G01X3715448Y6801997D01* +G01X3711603Y6781491D01* +G01X3711419Y6760627D01* +G01X3693090Y6760627D01* +G01X3693597Y6776480D01* +G01X3690713Y6796758D01* +G01X3684377Y6816235D01* +G01X3674777Y6834329D01* +G01X3662202Y6850496D01* +G01X3647028Y6864254D01* +G01X3629710Y6875190D01* +G01X3610765Y6882976D01* +G01X3590762Y6887380D01* +G01X3590762Y6887380D01* +G01X3570299Y6888270D01* +G01X3549989Y6885618D01* +G01X3530440Y6879505D01* +G01X3512238Y6870113D01* +G01X3495928Y6857724D01* +G01X3481997Y6842708D01* +G01X3470864Y6825516D01* +G01X3462862Y6806661D01* +G01X3458229Y6786710D01* +G01X3457106Y6766258D01* +G01X3459525Y6745919D01* +G01X3465414Y6726302D01* +G01X3368634Y6823082D01* +G01X3368634Y7034937D01* +G01X3457551Y7034937D01* +G01X3457551Y7013095D01* +G01X3461564Y6991624D01* +G01X3469455Y6971257D01* +G01X3480953Y6952686D01* +G01X3495669Y6936544D01* +G01X3513099Y6923381D01* +G01X3532652Y6913645D01* +G01X3553661Y6907667D01* +G01X3575410Y6905652D01* +G01X3597159Y6907667D01* +G01X3618168Y6913645D01* +G01X3637721Y6923381D01* +G01X3655151Y6936544D01* +G01X3669866Y6952686D01* +G01X3681365Y6971257D01* +G01X3689255Y6991624D01* +G01X3693269Y7013095D01* +G01X3693269Y7034937D01* +G01X3711551Y7034937D01* +G01X3711551Y7013095D01* +G01X3715564Y6991624D01* +G01X3723455Y6971257D01* +G01X3734953Y6952686D01* +G01X3749669Y6936544D01* +G01X3767099Y6923381D01* +G01X3786652Y6913645D01* +G01X3807661Y6907667D01* +G01X3829410Y6905652D01* +G01X3851159Y6907667D01* +G01X3872168Y6913645D01* +G01X3891721Y6923381D01* +G01X3909151Y6936544D01* +G01X3923866Y6952686D01* +G01X3935365Y6971257D01* +G01X3943255Y6991624D01* +G01X3947269Y7013095D01* +G01X3947269Y7034937D01* +G01X3943255Y7056408D01* +G01X3935365Y7076775D01* +G01X3923866Y7095346D01* +G01X3909151Y7111488D01* +G01X3891721Y7124651D01* +G01X3872168Y7134387D01* +G01X3851159Y7140365D01* +G01X3829410Y7142380D01* +G01X3829410Y7142380D01* +G01X3807661Y7140365D01* +G01X3786652Y7134387D01* +G01X3767099Y7124651D01* +G01X3749669Y7111488D01* +G01X3734953Y7095346D01* +G01X3723455Y7076775D01* +G01X3715564Y7056408D01* +G01X3711551Y7034937D01* +G01X3693269Y7034937D01* +G01X3689255Y7056408D01* +G01X3681365Y7076775D01* +G01X3669866Y7095346D01* +G01X3655151Y7111488D01* +G01X3637721Y7124651D01* +G01X3618168Y7134387D01* +G01X3597159Y7140365D01* +G01X3575410Y7142380D01* +G01X3575410Y7142380D01* +G01X3553661Y7140365D01* +G01X3532652Y7134387D01* +G01X3513099Y7124651D01* +G01X3495669Y7111488D01* +G01X3480953Y7095346D01* +G01X3469455Y7076775D01* +G01X3461564Y7056408D01* +G01X3457551Y7034937D01* +G01X3368634Y7034937D01* +G01X3368634Y7288937D01* +G01X3457551Y7288937D01* +G01X3457551Y7267095D01* +G01X3461564Y7245624D01* +G01X3469455Y7225257D01* +G01X3480953Y7206686D01* +G01X3495669Y7190544D01* +G01X3513099Y7177381D01* +G01X3532652Y7167645D01* +G01X3553661Y7161667D01* +G01X3575410Y7159652D01* +G01X3597159Y7161667D01* +G01X3618168Y7167645D01* +G01X3637721Y7177381D01* +G01X3655151Y7190544D01* +G01X3669866Y7206686D01* +G01X3681365Y7225257D01* +G01X3689255Y7245624D01* +G01X3693269Y7267095D01* +G01X3693269Y7288937D01* +G01X3711551Y7288937D01* +G01X3711551Y7267095D01* +G01X3715564Y7245624D01* +G01X3723455Y7225257D01* +G01X3734953Y7206686D01* +G01X3749669Y7190544D01* +G01X3767099Y7177381D01* +G01X3786652Y7167645D01* +G01X3807661Y7161667D01* +G01X3829410Y7159652D01* +G01X3851159Y7161667D01* +G01X3872168Y7167645D01* +G01X3891721Y7177381D01* +G01X3909151Y7190544D01* +G01X3923866Y7206686D01* +G01X3935365Y7225257D01* +G01X3943255Y7245624D01* +G01X3947269Y7267095D01* +G01X3947269Y7288937D01* +G01X3943255Y7310408D01* +G01X3935365Y7330775D01* +G01X3923866Y7349346D01* +G01X3909151Y7365488D01* +G01X3891721Y7378651D01* +G01X3872168Y7388387D01* +G01X3851159Y7394365D01* +G01X3829410Y7396380D01* +G01X3829410Y7396380D01* +G01X3807661Y7394365D01* +G01X3786652Y7388387D01* +G01X3767099Y7378651D01* +G01X3749669Y7365488D01* +G01X3734953Y7349346D01* +G01X3723455Y7330775D01* +G01X3715564Y7310408D01* +G01X3711551Y7288937D01* +G01X3693269Y7288937D01* +G01X3689255Y7310408D01* +G01X3681365Y7330775D01* +G01X3669866Y7349346D01* +G01X3655151Y7365488D01* +G01X3637721Y7378651D01* +G01X3618168Y7388387D01* +G01X3597159Y7394365D01* +G01X3575410Y7396380D01* +G01X3575410Y7396380D01* +G01X3553661Y7394365D01* +G01X3532652Y7388387D01* +G01X3513099Y7378651D01* +G01X3495669Y7365488D01* +G01X3480953Y7349346D01* +G01X3469455Y7330775D01* +G01X3461564Y7310408D01* +G01X3457551Y7288937D01* +G01X3368634Y7288937D01* +G01X3368634Y7542937D01* +G01X3457551Y7542937D01* +G01X3457551Y7521095D01* +G01X3461564Y7499624D01* +G01X3469455Y7479257D01* +G01X3480953Y7460686D01* +G01X3495669Y7444544D01* +G01X3513099Y7431381D01* +G01X3532652Y7421645D01* +G01X3553661Y7415667D01* +G01X3575410Y7413652D01* +G01X3597159Y7415667D01* +G01X3618168Y7421645D01* +G01X3637721Y7431381D01* +G01X3655151Y7444544D01* +G01X3669866Y7460686D01* +G01X3681365Y7479257D01* +G01X3689255Y7499624D01* +G01X3693269Y7521095D01* +G01X3693269Y7542937D01* +G01X3711551Y7542937D01* +G01X3711551Y7521095D01* +G01X3715564Y7499624D01* +G01X3723455Y7479257D01* +G01X3734953Y7460686D01* +G01X3749669Y7444544D01* +G01X3767099Y7431381D01* +G01X3786652Y7421645D01* +G01X3807661Y7415667D01* +G01X3829410Y7413652D01* +G01X3851159Y7415667D01* +G01X3872168Y7421645D01* +G01X3891721Y7431381D01* +G01X3909151Y7444544D01* +G01X3923866Y7460686D01* +G01X3935365Y7479257D01* +G01X3943255Y7499624D01* +G01X3947269Y7521095D01* +G01X3947269Y7542937D01* +G01X3943255Y7564408D01* +G01X3935365Y7584775D01* +G01X3923866Y7603346D01* +G01X3909151Y7619488D01* +G01X3891721Y7632651D01* +G01X3872168Y7642387D01* +G01X3851159Y7648365D01* +G01X3829410Y7650380D01* +G01X3829410Y7650380D01* +G01X3807661Y7648365D01* +G01X3786652Y7642387D01* +G01X3767099Y7632651D01* +G01X3749669Y7619488D01* +G01X3734953Y7603346D01* +G01X3723455Y7584775D01* +G01X3715564Y7564408D01* +G01X3711551Y7542937D01* +G01X3693269Y7542937D01* +G01X3689255Y7564408D01* +G01X3681365Y7584775D01* +G01X3669866Y7603346D01* +G01X3655151Y7619488D01* +G01X3637721Y7632651D01* +G01X3618168Y7642387D01* +G01X3597159Y7648365D01* +G01X3575410Y7650380D01* +G01X3575410Y7650380D01* +G01X3553661Y7648365D01* +G01X3532652Y7642387D01* +G01X3513099Y7632651D01* +G01X3495669Y7619488D01* +G01X3480953Y7603346D01* +G01X3469455Y7584775D01* +G01X3461564Y7564408D01* +G01X3457551Y7542937D01* +G01X3368634Y7542937D01* +G01X3368634Y7796937D01* +G01X3457551Y7796937D01* +G01X3457551Y7775095D01* +G01X3461564Y7753624D01* +G01X3469455Y7733257D01* +G01X3480953Y7714686D01* +G01X3495669Y7698544D01* +G01X3513099Y7685381D01* +G01X3532652Y7675645D01* +G01X3553661Y7669667D01* +G01X3575410Y7667652D01* +G01X3597159Y7669667D01* +G01X3618168Y7675645D01* +G01X3637721Y7685381D01* +G01X3655151Y7698544D01* +G01X3669866Y7714686D01* +G01X3681365Y7733257D01* +G01X3689255Y7753624D01* +G01X3693269Y7775095D01* +G01X3693269Y7796937D01* +G01X3711551Y7796937D01* +G01X3711551Y7775095D01* +G01X3715564Y7753624D01* +G01X3723455Y7733257D01* +G01X3734953Y7714686D01* +G01X3749669Y7698544D01* +G01X3767099Y7685381D01* +G01X3786652Y7675645D01* +G01X3807661Y7669667D01* +G01X3829410Y7667652D01* +G01X3851159Y7669667D01* +G01X3872168Y7675645D01* +G01X3891721Y7685381D01* +G01X3909151Y7698544D01* +G01X3923866Y7714686D01* +G01X3935365Y7733257D01* +G01X3943255Y7753624D01* +G01X3947269Y7775095D01* +G01X3947269Y7796937D01* +G01X3943255Y7818408D01* +G01X3935365Y7838775D01* +G01X3923866Y7857346D01* +G01X3909151Y7873488D01* +G01X3891721Y7886651D01* +G01X3872168Y7896387D01* +G01X3851159Y7902365D01* +G01X3829410Y7904380D01* +G01X3829410Y7904380D01* +G01X3807661Y7902365D01* +G01X3786652Y7896387D01* +G01X3767099Y7886651D01* +G01X3749669Y7873488D01* +G01X3734953Y7857346D01* +G01X3723455Y7838775D01* +G01X3715564Y7818408D01* +G01X3711551Y7796937D01* +G01X3693269Y7796937D01* +G01X3693269Y7796937D01* +G01X3689255Y7818408D01* +G01X3681365Y7838775D01* +G01X3669866Y7857346D01* +G01X3655151Y7873488D01* +G01X3637721Y7886651D01* +G01X3618168Y7896387D01* +G01X3597159Y7902365D01* +G01X3575410Y7904380D01* +G01X3575410Y7904380D01* +G01X3553661Y7902365D01* +G01X3532652Y7896387D01* +G01X3513099Y7886651D01* +G01X3495669Y7873488D01* +G01X3480953Y7857346D01* +G01X3469455Y7838775D01* +G01X3461564Y7818408D01* +G01X3457551Y7796937D01* +G01X3368634Y7796937D01* +G01X3368634Y9016149D01* +G01X3770297Y9417811D01* +G01X3779217Y9429437D01* +G01X3784825Y9442975D01* +G01X3786738Y9457504D01* +G01X3786738Y9946396D01* +G01X3784825Y9960924D01* +G01X3779217Y9974463D01* +G01X3770297Y9986089D01* +G01X3658235Y10098150D01* +G01X3661521Y10116501D01* +G01X3661718Y10135142D01* +G01X3658820Y10153557D01* +G01X3652908Y10171238D01* +G01X3644146Y10187692D01* +G01X3632777Y10202466D01* +G01X3887148Y10202466D01* +G01X4187765Y9901850D01* +G01X4187765Y9901850D01* +G01X4184408Y9882714D01* +G01X4184408Y9863286D01* +G01X4187765Y9844150D01* +G01X4009407Y9665793D01* +G01X4000487Y9654167D01* +G01X3994879Y9640629D01* +G01X3992966Y9626100D01* +G01X3992966Y8300651D01* +G01X3937008Y8244693D01* +G01X3943995Y8264346D01* +G01X3947424Y8284920D01* +G01X3947188Y8305777D01* +G01X3943295Y8326268D01* +G01X3935866Y8345758D01* +G01X3925130Y8363641D01* +G01X3911422Y8379362D01* +G01X3895168Y8392433D01* +G01X3876871Y8402448D01* +G01X3857101Y8409095D01* +G01X3836471Y8412169D01* +G01X3815622Y8411574D01* +G01X3795200Y8407328D01* +G01X3775841Y8399564D01* +G01X3758146Y8388522D01* +G01X3742663Y8374546D01* +G01X3729874Y8358068D01* +G01X3720177Y8339602D01* +G01X3713871Y8319720D01* +G01X3711153Y8299040D01* +G01X3712107Y8278204D01* +G01X3716704Y8257859D01* +G01X3724800Y8238637D01* +G01X3736145Y8221134D01* +G01X3700394Y8221134D01* +G01X3693774Y8220742D01* +G01X3693774Y8376566D01* +G01X3692021Y8387633D01* +G01X3686934Y8397617D01* +G01X3679011Y8405540D01* +G01X3669027Y8410627D01* +G01X3657960Y8412380D01* +G01X3492860Y8412380D01* +G01X3481793Y8410627D01* +G01X3471809Y8405540D01* +G01X3463886Y8397617D01* +G01X3458799Y8387633D01* +G01X3457046Y8376566D01* +G01X3457046Y8211466D01* +G01X3458799Y8200399D01* +G01X3463886Y8190415D01* +G01X3471809Y8182492D01* +G01X3481793Y8177405D01* +G01X3492860Y8175652D01* +G01X3631660Y8175652D01* +G01X3609402Y8153394D01* +G01X3588967Y8157601D01* +G01X3568110Y8158155D01* +G01X3547480Y8155038D01* +G01X3527718Y8148347D01* +G01X3509438Y8138290D01* +G01X3493208Y8125180D01* +G01X3479531Y8109423D01* +G01X3468834Y8091510D01* +G01X3461448Y8071997D01* +G01X3457603Y8051491D01* +G01X3457419Y8030627D01* +G01X3460900Y8010056D01* +G01X3467940Y7990415D01* +G01X3478319Y7972316D01* +G01X3491714Y7956320D01* +G01X3491714Y7956320D01* +G01X3507710Y7942925D01* +G01X3525809Y7932546D01* +G01X3545450Y7925506D01* +G01X3566021Y7922025D01* +G01X3586885Y7922209D01* +G01X3607391Y7926054D01* +G01X3626904Y7933440D01* +G01X3644817Y7944137D01* +G01X3660574Y7957814D01* +G01X3673684Y7974044D01* +G01X3683741Y7992324D01* +G01X3690432Y8012086D01* +G01X3693549Y8032716D01* +G01X3692995Y8053573D01* +G01X3688788Y8074008D01* +G01X3723645Y8108866D01* +G01X3733131Y8108866D01* +G01X3733131Y8108866D01* +G01X3722227Y8090235D01* +G01X3714889Y8069933D01* +G01X3711360Y8048637D01* +G01X3711758Y8027053D01* +G01X3716069Y8005901D01* +G01X3724150Y7985883D01* +G01X3735732Y7967666D01* +G01X3750430Y7951856D01* +G01X3767755Y7938978D01* +G01X3787131Y7929460D01* +G01X3807913Y7923620D01* +G01X3829410Y7921652D01* +G01X3829410Y7921652D01* +G01X3850907Y7923620D01* +G01X3871689Y7929460D01* +G01X3891065Y7938978D01* +G01X3908390Y7951856D01* +G01X3923088Y7967666D01* +G01X3934670Y7985883D01* +G01X3942751Y8005901D01* +G01X3947062Y8027053D01* +G01X3947460Y8048637D01* +G01X3943931Y8069933D01* +G01X3936592Y8090235D01* +G01X3925689Y8108866D01* +G01X3936700Y8108866D01* +G01X3951229Y8110779D01* +G01X3964767Y8116387D01* +G01X3976393Y8125307D01* +G01X4088793Y8237707D01* +G01X4097714Y8249333D01* +G01X4103321Y8262871D01* +G01X4105234Y8277400D01* +G01X4105234Y9602849D01* +G01X4131721Y9629335D01* +G01X4184464Y9629335D01* +G01X4184464Y9608665D01* +G01X4188262Y9588346D01* +G01X4195729Y9569071D01* +G01X4206611Y9551496D01* +G01X4220537Y9536221D01* +G01X4237032Y9523764D01* +G01X4255536Y9514550D01* +G01X4275417Y9508893D01* +G01X4296000Y9506986D01* +G01X4296000Y9506986D01* +G01X4316582Y9508893D01* +G01X4336464Y9514550D01* +G01X4354968Y9523764D01* +G01X4371463Y9536221D01* +G01X4385389Y9551496D01* +G01X4396271Y9569071D01* +G01X4403738Y9588346D01* +G01X4407536Y9608665D01* +G01X4407536Y9629335D01* +G01X4403738Y9649654D01* +G01X4396271Y9668929D01* +G01X4385389Y9686503D01* +G01X4377461Y9695200D01* +G01X4437986Y9695200D01* +G01X4437986Y9542800D01* +G01X4439739Y9531733D01* +G01X4444826Y9521749D01* +G01X4452749Y9513826D01* +G01X4462733Y9508739D01* +G01X4473800Y9506986D01* +G01X4626200Y9506986D01* +G01X4637267Y9508739D01* +G01X4647251Y9513826D01* +G01X4655174Y9521749D01* +G01X4660261Y9531733D01* +G01X4662014Y9542800D01* +G01X4662014Y9695200D01* +G01X4662014Y9695200D01* +G01X4660261Y9706267D01* +G01X4655174Y9716251D01* +G01X4647251Y9724174D01* +G01X4637267Y9729261D01* +G01X4626200Y9731014D01* +G01X4473800Y9731014D01* +G01X4462733Y9729261D01* +G01X4452749Y9724174D01* +G01X4444826Y9716251D01* +G01X4439739Y9706267D01* +G01X4437986Y9695200D01* +G01X4377461Y9695200D01* +G01X4371463Y9701779D01* +G01X4354968Y9714236D01* +G01X4336464Y9723450D01* +G01X4316582Y9729107D01* +G01X4296000Y9731014D01* +G01X4275417Y9729107D01* +G01X4255536Y9723450D01* +G01X4237032Y9714236D01* +G01X4220537Y9701779D01* +G01X4206611Y9686503D01* +G01X4195729Y9668929D01* +G01X4188262Y9649654D01* +G01X4184464Y9629335D01* +G01X4131721Y9629335D01* +G01X4267150Y9764765D01* +G01X4287343Y9761321D01* +G01X4307825Y9761612D01* +G01X4327912Y9765628D01* +G01X4346932Y9773235D01* +G01X4364248Y9784178D01* +G01X4379282Y9798092D01* +G01X4391531Y9814510D01* +G01X4400585Y9832885D01* +G01X4406141Y9852601D01* +G01X4408014Y9873000D01* +G01X4407065Y9883335D01* +G01X4438464Y9883335D01* +G01X4438464Y9862665D01* +G01X4442262Y9842346D01* +G01X4449729Y9823071D01* +G01X4460611Y9805496D01* +G01X4474537Y9790221D01* +G01X4491032Y9777764D01* +G01X4509536Y9768550D01* +G01X4529417Y9762893D01* +G01X4550000Y9760986D01* +G01X4550000Y9760986D01* +G01X4570582Y9762893D01* +G01X4590464Y9768550D01* +G01X4608968Y9777764D01* +G01X4625463Y9790221D01* +G01X4639389Y9805496D01* +G01X4650271Y9823071D01* +G01X4657738Y9842346D01* +G01X4661536Y9862665D01* +G01X4661536Y9883335D01* +G01X4657738Y9903654D01* +G01X4650271Y9922929D01* +G01X4639389Y9940503D01* +G01X4625463Y9955779D01* +G01X4608968Y9968236D01* +G01X4590464Y9977450D01* +G01X4570582Y9983107D01* +G01X4550000Y9985014D01* +G01X4529417Y9983107D01* +G01X4509536Y9977450D01* +G01X4491032Y9968236D01* +G01X4474537Y9955779D01* +G01X4460611Y9940503D01* +G01X4449729Y9922929D01* +G01X4442262Y9903654D01* +G01X4438464Y9883335D01* +G01X4407065Y9883335D01* +G01X4406141Y9893398D01* +G01X4400585Y9913115D01* +G01X4391531Y9931490D01* +G01X4379282Y9947908D01* +G01X4364248Y9961822D01* +G01X4346932Y9972765D01* +G01X4327912Y9980372D01* +G01X4307825Y9984388D01* +G01X4287343Y9984679D01* +G01X4267150Y9981235D01* +G01X4111050Y10137335D01* +G01X4184464Y10137335D01* +G01X4184464Y10116665D01* +G01X4188262Y10096346D01* +G01X4195729Y10077071D01* +G01X4206611Y10059496D01* +G01X4220537Y10044221D01* +G01X4237032Y10031764D01* +G01X4255536Y10022550D01* +G01X4275417Y10016893D01* +G01X4296000Y10014986D01* +G01X4296000Y10014986D01* +G01X4316582Y10016893D01* +G01X4336464Y10022550D01* +G01X4354968Y10031764D01* +G01X4371463Y10044221D01* +G01X4385389Y10059496D01* +G01X4396271Y10077071D01* +G01X4403738Y10096346D01* +G01X4407536Y10116665D01* +G01X4407536Y10137335D01* +G01X4438464Y10137335D01* +G01X4438464Y10116665D01* +G01X4442262Y10096346D01* +G01X4449729Y10077071D01* +G01X4460611Y10059496D01* +G01X4474537Y10044221D01* +G01X4491032Y10031764D01* +G01X4509536Y10022550D01* +G01X4529417Y10016893D01* +G01X4550000Y10014986D01* +G01X4550000Y10014986D01* +G01X4570582Y10016893D01* +G01X4590464Y10022550D01* +G01X4608968Y10031764D01* +G01X4625463Y10044221D01* +G01X4639389Y10059496D01* +G01X4650271Y10077071D01* +G01X4657738Y10096346D01* +G01X4661536Y10116665D01* +G01X4661536Y10137335D01* +G01X4657738Y10157654D01* +G01X4650271Y10176929D01* +G01X4639389Y10194503D01* +G01X4625463Y10209779D01* +G01X4608968Y10222236D01* +G01X4590464Y10231450D01* +G01X4570582Y10237107D01* +G01X4550000Y10239014D01* +G01X4529417Y10237107D01* +G01X4509536Y10231450D01* +G01X4491032Y10222236D01* +G01X4474537Y10209779D01* +G01X4460611Y10194503D01* +G01X4449729Y10176929D01* +G01X4442262Y10157654D01* +G01X4438464Y10137335D01* +G01X4407536Y10137335D01* +G01X4403738Y10157654D01* +G01X4396271Y10176929D01* +G01X4385389Y10194503D01* +G01X4371463Y10209779D01* +G01X4354968Y10222236D01* +G01X4336464Y10231450D01* +G01X4316582Y10237107D01* +G01X4296000Y10239014D01* +G01X4275417Y10237107D01* +G01X4255536Y10231450D01* +G01X4237032Y10222236D01* +G01X4220537Y10209779D01* +G01X4206611Y10194503D01* +G01X4195729Y10176929D01* +G01X4188262Y10157654D01* +G01X4184464Y10137335D01* +G01X4111050Y10137335D01* +G01X3950093Y10298293D01* +G01X3938467Y10307213D01* +G01X3924928Y10312821D01* +G01X3910400Y10314734D01* +G01X3640310Y10314734D01* +G01X3651159Y10332897D01* +G01X3658400Y10352776D01* +G01X3661773Y10373661D01* +G01X3661260Y10391335D01* +G01X4184464Y10391335D01* +G01X4184464Y10370665D01* +G01X4188262Y10350346D01* +G01X4195729Y10331071D01* +G01X4206611Y10313496D01* +G01X4220537Y10298221D01* +G01X4237032Y10285764D01* +G01X4255536Y10276550D01* +G01X4275417Y10270893D01* +G01X4296000Y10268986D01* +G01X4296000Y10268986D01* +G01X4316582Y10270893D01* +G01X4336464Y10276550D01* +G01X4354968Y10285764D01* +G01X4371463Y10298221D01* +G01X4385389Y10313496D01* +G01X4396271Y10331071D01* +G01X4403738Y10350346D01* +G01X4407536Y10370665D01* +G01X4407536Y10391335D01* +G01X4403738Y10411654D01* +G01X4396271Y10430929D01* +G01X4385389Y10448503D01* +G01X4371463Y10463779D01* +G01X4354968Y10476236D01* +G01X4336464Y10485450D01* +G01X4316582Y10491107D01* +G01X4296000Y10493014D01* +G01X4275417Y10491107D01* +G01X4255536Y10485450D01* +G01X4237032Y10476236D01* +G01X4220537Y10463779D01* +G01X4206611Y10448503D01* +G01X4195729Y10430929D01* +G01X4188262Y10411654D01* +G01X4184464Y10391335D01* +G01X3661260Y10391335D01* +G01X3661159Y10394809D01* +G01X3656580Y10415464D01* +G01X3648199Y10434889D01* +G01X3636315Y10452392D01* +G01X3621352Y10467349D01* +G01X3603843Y10479225D01* +G01X3584413Y10487597D01* +G01X3563756Y10492166D01* +G01X3542609Y10492770D01* +G01X3521725Y10489386D01* +G01X3501849Y10482137D01* +G01X3483691Y10471279D01* +G01X3467899Y10457201D01* +G01X3455035Y10440404D01* +G01X3445560Y10421489D01* +G01X3439809Y10401129D01* +G01X3437990Y10380051D01* +G01X3440166Y10359007D01* +G01X3446261Y10338747D01* +G01X3456056Y10319995D01* +G01X3469202Y10303419D01* +G01X3463307Y10298293D01* +G01X3386111Y10221097D01* +G01X3380115Y10214016D01* +G01X3375367Y10206044D01* +G01X3360051Y10218894D01* +G01X3342695Y10228817D01* +G01X3323850Y10235496D01* +G01X3304119Y10238719D01* +G01X3284129Y10238383D01* +G01X3264518Y10234499D01* +G01X3245909Y10227190D01* +G01X3228896Y10216689D01* +G01X3214020Y10203331D01* +G01X3201756Y10187542D01* +G01X3192495Y10169824D01* +G01X3186531Y10150741D01* +G01X3184054Y10130902D01* +G01X3184054Y10130902D01* +G01X3185143Y10110939D01* +G01X3189764Y10091488D01* +G01X3197769Y10073168D01* +G01X3208904Y10056563D01* +G01X3222813Y10042201D01* +G01X3239053Y10030542D01* +G01X3257108Y10021954D01* +G01X3276402Y10016714D01* +G01X3296320Y10014986D01* +G01X3316227Y10016827D01* +G01X3335491Y10022178D01* +G01X3353496Y10030868D01* +G01X3369670Y10042621D01* +G01X3369670Y10026055D01* +G01X3324850Y9981235D01* +G01X3304235Y9984711D01* +G01X3283333Y9984295D01* +G01X3262873Y9980003D01* +G01X3243567Y9971984D01* +G01X3226087Y9960517D01* +G01X3211042Y9946002D01* +G01X3198956Y9928943D01* +G01X3190251Y9909936D01* +G01X3185229Y9889643D01* +G01X3184066Y9868770D01* +G01X3186801Y9848044D01* +G01X3193340Y9828187D01* +G01X3203456Y9809892D01* +G01X3216794Y9793794D01* +G01X3232892Y9780456D01* +G01X3251187Y9770341D01* +G01X3271044Y9763801D01* +G01X3291770Y9761066D01* +G01X3312643Y9762229D01* +G01X3332936Y9767251D01* +G01X3351943Y9775956D01* +G01X3369002Y9788042D01* +G01X3383517Y9803087D01* +G01X3394984Y9820567D01* +G01X3403003Y9839873D01* +G01X3407295Y9860333D01* +G01X3407711Y9881235D01* +G01X3407357Y9883335D01* +G01X3438464Y9883335D01* +G01X3438464Y9862665D01* +G01X3442262Y9842346D01* +G01X3449729Y9823071D01* +G01X3460611Y9805496D01* +G01X3474537Y9790221D01* +G01X3491032Y9777764D01* +G01X3509536Y9768550D01* +G01X3529417Y9762893D01* +G01X3550000Y9760986D01* +G01X3550000Y9760986D01* +G01X3570582Y9762893D01* +G01X3590464Y9768550D01* +G01X3608968Y9777764D01* +G01X3625463Y9790221D01* +G01X3639389Y9805496D01* +G01X3650271Y9823071D01* +G01X3657738Y9842346D01* +G01X3661536Y9862665D01* +G01X3661536Y9883335D01* +G01X3657738Y9903654D01* +G01X3650271Y9922929D01* +G01X3639389Y9940503D01* +G01X3625463Y9955779D01* +G01X3608968Y9968236D01* +G01X3590464Y9977450D01* +G01X3570582Y9983107D01* +G01X3550000Y9985014D01* +G01X3529417Y9983107D01* +G01X3509536Y9977450D01* +G01X3491032Y9968236D01* +G01X3474537Y9955779D01* +G01X3460611Y9940503D01* +G01X3449729Y9922929D01* +G01X3442262Y9903654D01* +G01X3438464Y9883335D01* +G01X3407357Y9883335D01* +G01X3404235Y9901850D01* +G01X3465497Y9963111D01* +G01X3474417Y9974737D01* +G01X3480025Y9988275D01* +G01X3481938Y10002804D01* +G01X3481938Y10038035D01* +G01X3499235Y10027150D01* +G01X3518223Y10019588D01* +G01X3538268Y10015602D01* +G01X3558704Y10015325D01* +G01X3578850Y10018765D01* +G01X3674470Y9923144D01* +G01X3674470Y9480755D01* +G01X3272807Y9079093D01* +G01X3263887Y9067467D01* +G01X3258279Y9053929D01* +G01X3256366Y9039400D01* +G01X3256366Y6799830D01* +G01X3258279Y6785302D01* +G01X3263887Y6771763D01* +G01X3272807Y6760138D01* +G01X3429291Y6603654D01* +G01X3440917Y6594733D01* +G01X3454455Y6589125D01* +G01X3468984Y6587213D01* +G01X3480853Y6587213D01* +G01X3480853Y6587213D01* +G01X3469454Y6568774D01* +G01X3461609Y6548566D01* +G01X3457582Y6527266D01* +G01X3457506Y6505588D01* +G01X3461385Y6484261D01* +G01X3469089Y6463998D01* +G01X3480358Y6445481D01* +G01X3441435Y6445481D01* +G01X3216234Y6670682D01* +G01X3216234Y9205849D01* +G01X3517371Y9506986D01* +G01X3626200Y9506986D01* +G01X3637267Y9508739D01* +G01X3647251Y9513826D01* +G01X3655174Y9521749D01* +G01X3660261Y9531733D01* +G01X3662014Y9542800D01* +G01X3662014Y9695200D01* +G01X3660261Y9706267D01* +G01X3655174Y9716251D01* +G01X3647251Y9724174D01* +G01X3637267Y9729261D01* +G01X3626200Y9731014D01* +G01X3473800Y9731014D01* +G01X3462733Y9729261D01* +G01X3452749Y9724174D01* +G01X3444826Y9716251D01* +G01X3439739Y9706267D01* +G01X3437986Y9695200D01* +G01X3437986Y9586371D01* +G01X3120407Y9268793D01* +G01X3120407Y9268793D01* +G01X3111487Y9257167D01* +G01X3105879Y9243629D01* +G01X3103966Y9229100D01* +G01X3067918Y9229100D01* +G01X3067918Y9629335D01* +G01X3184464Y9629335D01* +G01X3184464Y9608665D01* +G01X3188262Y9588346D01* +G01X3195729Y9569071D01* +G01X3206611Y9551496D01* +G01X3220537Y9536221D01* +G01X3237032Y9523764D01* +G01X3255536Y9514550D01* +G01X3275417Y9508893D01* +G01X3296000Y9506986D01* +G01X3296000Y9506986D01* +G01X3316582Y9508893D01* +G01X3336464Y9514550D01* +G01X3354968Y9523764D01* +G01X3371463Y9536221D01* +G01X3385389Y9551496D01* +G01X3396271Y9569071D01* +G01X3403738Y9588346D01* +G01X3407536Y9608665D01* +G01X3407536Y9629335D01* +G01X3403738Y9649654D01* +G01X3396271Y9668929D01* +G01X3385389Y9686503D01* +G01X3371463Y9701779D01* +G01X3354968Y9714236D01* +G01X3336464Y9723450D01* +G01X3316582Y9729107D01* +G01X3296000Y9731014D01* +G01X3275417Y9729107D01* +G01X3255536Y9723450D01* +G01X3237032Y9714236D01* +G01X3220537Y9701779D01* +G01X3206611Y9686503D01* +G01X3195729Y9668929D01* +G01X3188262Y9649654D01* +G01X3184464Y9629335D01* +G01X3067918Y9629335D01* +G01X3067918Y10391335D01* +G01X3184464Y10391335D01* +G01X3184464Y10370665D01* +G01X3188262Y10350346D01* +G01X3195729Y10331071D01* +G01X3206611Y10313496D01* +G01X3220537Y10298221D01* +G01X3237032Y10285764D01* +G01X3255536Y10276550D01* +G01X3275417Y10270893D01* +G01X3296000Y10268986D01* +G01X3296000Y10268986D01* +G01X3316582Y10270893D01* +G01X3336464Y10276550D01* +G01X3354968Y10285764D01* +G01X3371463Y10298221D01* +G01X3385389Y10313496D01* +G01X3396271Y10331071D01* +G01X3403738Y10350346D01* +G01X3407536Y10370665D01* +G01X3407536Y10391335D01* +G01X3403738Y10411654D01* +G01X3396271Y10430929D01* +G01X3385389Y10448503D01* +G01X3371463Y10463779D01* +G01X3354968Y10476236D01* +G01X3336464Y10485450D01* +G01X3316582Y10491107D01* +G01X3296000Y10493014D01* +G01X3275417Y10491107D01* +G01X3255536Y10485450D01* +G01X3237032Y10476236D01* +G01X3220537Y10463779D01* +G01X3206611Y10448503D01* +G01X3195729Y10430929D01* +G01X3188262Y10411654D01* +G01X3184464Y10391335D01* +G01X3067918Y10391335D01* +G01X3067918Y10645335D01* +G01X3184464Y10645335D01* +G01X3184464Y10624665D01* +G01X3188262Y10604346D01* +G01X3195729Y10585071D01* +G01X3206611Y10567496D01* +G01X3220537Y10552221D01* +G01X3237032Y10539764D01* +G01X3255536Y10530550D01* +G01X3275417Y10524893D01* +G01X3296000Y10522986D01* +G01X3296000Y10522986D01* +G01X3316582Y10524893D01* +G01X3336464Y10530550D01* +G01X3354968Y10539764D01* +G01X3371463Y10552221D01* +G01X3385389Y10567496D01* +G01X3396271Y10585071D01* +G01X3403738Y10604346D01* +G01X3407536Y10624665D01* +G01X3407536Y10645335D01* +G01X3403738Y10665654D01* +G01X3396271Y10684929D01* +G01X3385389Y10702503D01* +G01X3371463Y10717779D01* +G01X3354968Y10730236D01* +G01X3336464Y10739450D01* +G01X3316582Y10745107D01* +G01X3296000Y10747014D01* +G01X3275417Y10745107D01* +G01X3255536Y10739450D01* +G01X3237032Y10730236D01* +G01X3220537Y10717779D01* +G01X3206611Y10702503D01* +G01X3195729Y10684929D01* +G01X3188262Y10665654D01* +G01X3184464Y10645335D01* +G01X3067918Y10645335D01* +G01X3067918Y10691627D01* +G01X3129103Y10752813D01* +G01X3415327Y10752813D01* +G01X3462814Y10705326D01* +G01X3462814Y10705326D01* +G01X3451235Y10687845D01* +G01X3443117Y10668513D01* +G01X3438744Y10648006D01* +G01X3438269Y10627044D01* +G01X3441709Y10606360D01* +G01X3448944Y10586680D01* +G01X3459720Y10568693D01* +G01X3473659Y10553029D01* +G01X3490273Y10540238D01* +G01X3508980Y10530767D01* +G01X3529124Y10524948D01* +G01X3550000Y10522986D01* +G01X3570876Y10524948D01* +G01X3591020Y10530767D01* +G01X3609727Y10540238D01* +G01X3626341Y10553029D01* +G01X3640280Y10568693D01* +G01X3651056Y10586680D01* +G01X3658291Y10606360D01* +G01X3661731Y10627044D01* +G01X3661317Y10645335D01* +G01X4184464Y10645335D01* +G01X4184464Y10624665D01* +G01X4188262Y10604346D01* +G01X4195729Y10585071D01* +G01X4206611Y10567496D01* +G01X4220537Y10552221D01* +G01X4237032Y10539764D01* +G01X4255536Y10530550D01* +G01X4275417Y10524893D01* +G01X4296000Y10522986D01* +G01X4296000Y10522986D01* +G01X4316582Y10524893D01* +G01X4336464Y10530550D01* +G01X4354968Y10539764D01* +G01X4371463Y10552221D01* +G01X4385389Y10567496D01* +G01X4396271Y10585071D01* +G01X4403738Y10604346D01* +G01X4407536Y10624665D01* +G01X4407536Y10645335D01* +G01X4403738Y10665654D01* +G01X4396271Y10684929D01* +G01X4385389Y10702503D01* +G01X4371463Y10717779D01* +G01X4354968Y10730236D01* +G01X4336464Y10739450D01* +G01X4316582Y10745107D01* +G01X4296000Y10747014D01* +G01X4275417Y10745107D01* +G01X4255536Y10739450D01* +G01X4237032Y10730236D01* +G01X4220537Y10717779D01* +G01X4206611Y10702503D01* +G01X4195729Y10684929D01* +G01X4188262Y10665654D01* +G01X4184464Y10645335D01* +G01X3661317Y10645335D01* +G01X3661256Y10648006D01* +G01X3656883Y10668513D01* +G01X3648765Y10687845D01* +G01X3637186Y10705326D01* +G01X3687477Y10755617D01* +G01X4418627Y10755617D01* +G01X4463386Y10710858D01* +G01X4463386Y10706029D01* +G01X4463386Y10706029D01* +G01X4451630Y10688576D01* +G01X4443345Y10669233D01* +G01X4438825Y10648681D01* +G01X4438228Y10627647D01* +G01X4441575Y10606872D01* +G01X4448749Y10587089D01* +G01X4459497Y10568998D01* +G01X4473438Y10553236D01* +G01X4490081Y10540359D01* +G01X4508839Y10530822D01* +G01X4529050Y10524962D01* +G01X4550000Y10522986D01* +G01X4550000Y10522986D01* +G01X4570950Y10524962D01* +G01X4591160Y10530822D01* +G01X4609918Y10540359D01* +G01X4626562Y10553236D01* +G01X4640503Y10568998D01* +G01X4651251Y10587089D01* +G01X4658425Y10606872D01* +G01X4661772Y10627647D01* +G01X4661175Y10648681D01* +G01X4656655Y10669233D01* +G01X4648370Y10688576D01* +G01X4636614Y10706029D01* +G01X4636614Y10746735D01* +G01X4634950Y10763632D01* +G01X4630021Y10779880D01* +G01X4622017Y10794855D01* +G01X4611245Y10807980D01* +G01X4515749Y10903476D01* +G01X4502624Y10914247D01* +G01X4487650Y10922251D01* +G01X4471401Y10927180D01* +G01X4454504Y10928845D01* +G01X3651600Y10928845D01* +G01X3634702Y10927180D01* +G01X3618454Y10922251D01* +G01X3603480Y10914247D01* +G01X3590355Y10903476D01* +G01X3550000Y10863121D01* +G01X3512449Y10900672D01* +G01X3499324Y10911443D01* +G01X3484350Y10919447D01* +G01X3468101Y10924376D01* +G01X3451204Y10926041D01* +G01X3093227Y10926041D01* +G01X3076329Y10924376D01* +G01X3060081Y10919447D01* +G01X3045107Y10911443D01* +G01X3031981Y10900672D01* +G01X2920059Y10788749D01* +G01X2909287Y10775624D01* +G01X2901283Y10760650D01* +G01X2896354Y10744401D01* +G01X2894690Y10727504D01* +G01X2894690Y7064497D01* +G01X2894690Y7064497D01* +G01X2571607Y6741414D01* +G01X1759111Y6741414D01* +G01X1742213Y6739750D01* +G01X1725965Y6734821D01* +G01X1710991Y6726817D01* +G01X1697866Y6716045D01* +G01X1584406Y6602585D01* +G01X938341Y7248649D01* +G01X2602787Y7248649D01* +G01X2602787Y7229150D01* +G01X2606370Y7209984D01* +G01X2613413Y7191801D01* +G01X2623678Y7175223D01* +G01X2636815Y7160813D01* +G01X2652375Y7149063D01* +G01X2669830Y7140371D01* +G01X2688584Y7135035D01* +G01X2708000Y7133236D01* +G01X2758800Y7133236D01* +G01X2778216Y7135035D01* +G01X2796970Y7140371D01* +G01X2814425Y7149063D01* +G01X2829985Y7160813D01* +G01X2843122Y7175223D01* +G01X2853386Y7191801D01* +G01X2860430Y7209984D01* +G01X2864013Y7229150D01* +G01X2864013Y7248649D01* +G01X2860430Y7267816D01* +G01X2853386Y7285998D01* +G01X2843122Y7302577D01* +G01X2829985Y7316987D01* +G01X2814425Y7328737D01* +G01X2796970Y7337429D01* +G01X2778216Y7342765D01* +G01X2758800Y7344564D01* +G01X2758800Y7344564D01* +G01X2708000Y7344564D01* +G01X2688584Y7342765D01* +G01X2669830Y7337429D01* +G01X2652375Y7328737D01* +G01X2636815Y7316987D01* +G01X2623678Y7302577D01* +G01X2613413Y7285998D01* +G01X2606370Y7267816D01* +G01X2602787Y7248649D01* +G01X938341Y7248649D01* +G01X684341Y7502649D01* +G01X2602787Y7502649D01* +G01X2602787Y7483150D01* +G01X2606370Y7463984D01* +G01X2613413Y7445801D01* +G01X2623678Y7429223D01* +G01X2636815Y7414813D01* +G01X2652375Y7403063D01* +G01X2669830Y7394371D01* +G01X2688584Y7389035D01* +G01X2708000Y7387236D01* +G01X2758800Y7387236D01* +G01X2778216Y7389035D01* +G01X2796970Y7394371D01* +G01X2814425Y7403063D01* +G01X2829985Y7414813D01* +G01X2843122Y7429223D01* +G01X2853386Y7445801D01* +G01X2860430Y7463984D01* +G01X2864013Y7483150D01* +G01X2864013Y7502649D01* +G01X2860430Y7521816D01* +G01X2853386Y7539998D01* +G01X2843122Y7556577D01* +G01X2829985Y7570987D01* +G01X2814425Y7582737D01* +G01X2796970Y7591429D01* +G01X2778216Y7596765D01* +G01X2758800Y7598564D01* +G01X2758800Y7598564D01* +G01X2708000Y7598564D01* +G01X2688584Y7596765D01* +G01X2669830Y7591429D01* +G01X2652375Y7582737D01* +G01X2636815Y7570987D01* +G01X2623678Y7556577D01* +G01X2613413Y7539998D01* +G01X2606370Y7521816D01* +G01X2602787Y7502649D01* +G01X684341Y7502649D01* +G01X632845Y7554145D01* +G01X619720Y7564917D01* +G01X604746Y7572921D01* +G01X588498Y7577850D01* +G01X571600Y7579514D01* +G01X279322Y7579514D01* +G01X265465Y7587701D01* +G01X250525Y7593689D01* +G01X234848Y7597338D01* +G01X218800Y7598564D01* +G01X168000Y7598564D01* +G01X151951Y7597338D01* +G01X136275Y7593689D01* +G01X121335Y7587701D01* +G01X107478Y7579514D01* +G01X-195828Y7579514D01* +G01X-212489Y7592462D01* +G01X-231186Y7602246D01* +G01X-251322Y7608555D01* +G01X-272259Y7611188D01* +G01X-293331Y7610061D01* +G01X-313867Y7605211D01* +G01X-333216Y7596791D01* +G01X-350763Y7585069D01* +G01X-365949Y7570417D01* +G01X-378292Y7553302D01* +G01X-387400Y7534267D01* +G01X-392983Y7513918D01* +G01X-394864Y7492900D01* +G01X-2536486Y7492900D01* +G01X-2536486Y7757821D01* +G01X-2426359Y7757821D01* +G01X-2426359Y7735979D01* +G01X-2422346Y7714508D01* +G01X-2414455Y7694141D01* +G01X-2402957Y7675570D01* +G01X-2388241Y7659428D01* +G01X-2370811Y7646265D01* +G01X-2351258Y7636529D01* +G01X-2330249Y7630551D01* +G01X-2308500Y7628536D01* +G01X-2308500Y7628536D01* +G01X-2286751Y7630551D01* +G01X-2265742Y7636529D01* +G01X-2246189Y7646265D01* +G01X-2228759Y7659428D01* +G01X-2214044Y7675570D01* +G01X-2202545Y7694141D01* +G01X-2194655Y7714508D01* +G01X-2190641Y7735979D01* +G01X-2190641Y7757821D01* +G01X-2190641Y7757821D01* +G01X-394359Y7757821D01* +G01X-394359Y7735979D01* +G01X-390346Y7714508D01* +G01X-382455Y7694141D01* +G01X-370957Y7675570D01* +G01X-356241Y7659428D01* +G01X-338811Y7646265D01* +G01X-319258Y7636529D01* +G01X-298249Y7630551D01* +G01X-276500Y7628536D01* +G01X-276500Y7628536D01* +G01X-254751Y7630551D01* +G01X-233742Y7636529D01* +G01X-214189Y7646265D01* +G01X-196759Y7659428D01* +G01X-182044Y7675570D01* +G01X-170545Y7694141D01* +G01X-162655Y7714508D01* +G01X-158641Y7735979D01* +G01X-158641Y7756649D01* +G01X62787Y7756649D01* +G01X62787Y7737150D01* +G01X66370Y7717984D01* +G01X73413Y7699801D01* +G01X83678Y7683223D01* +G01X96815Y7668813D01* +G01X112375Y7657063D01* +G01X129830Y7648371D01* +G01X148584Y7643035D01* +G01X168000Y7641236D01* +G01X218800Y7641236D01* +G01X238216Y7643035D01* +G01X256970Y7648371D01* +G01X274425Y7657063D01* +G01X289985Y7668813D01* +G01X303122Y7683223D01* +G01X313386Y7699801D01* +G01X320430Y7717984D01* +G01X324013Y7737150D01* +G01X324013Y7756649D01* +G01X2602787Y7756649D01* +G01X2602787Y7737150D01* +G01X2606370Y7717984D01* +G01X2613413Y7699801D01* +G01X2623678Y7683223D01* +G01X2636815Y7668813D01* +G01X2652375Y7657063D01* +G01X2669830Y7648371D01* +G01X2688584Y7643035D01* +G01X2708000Y7641236D01* +G01X2758800Y7641236D01* +G01X2778216Y7643035D01* +G01X2796970Y7648371D01* +G01X2814425Y7657063D01* +G01X2829985Y7668813D01* +G01X2843122Y7683223D01* +G01X2853386Y7699801D01* +G01X2860430Y7717984D01* +G01X2864013Y7737150D01* +G01X2864013Y7756649D01* +G01X2860430Y7775816D01* +G01X2853386Y7793998D01* +G01X2843122Y7810577D01* +G01X2829985Y7824987D01* +G01X2814425Y7836737D01* +G01X2796970Y7845429D01* +G01X2778216Y7850765D01* +G01X2758800Y7852564D01* +G01X2758800Y7852564D01* +G01X2708000Y7852564D01* +G01X2688584Y7850765D01* +G01X2669830Y7845429D01* +G01X2652375Y7836737D01* +G01X2636815Y7824987D01* +G01X2623678Y7810577D01* +G01X2613413Y7793998D01* +G01X2606370Y7775816D01* +G01X2602787Y7756649D01* +G01X324013Y7756649D01* +G01X320430Y7775816D01* +G01X313386Y7793998D01* +G01X303122Y7810577D01* +G01X289985Y7824987D01* +G01X274425Y7836737D01* +G01X256970Y7845429D01* +G01X238216Y7850765D01* +G01X218800Y7852564D01* +G01X218800Y7852564D01* +G01X168000Y7852564D01* +G01X148584Y7850765D01* +G01X129830Y7845429D01* +G01X112375Y7836737D01* +G01X96815Y7824987D01* +G01X83678Y7810577D01* +G01X73413Y7793998D01* +G01X66370Y7775816D01* +G01X62787Y7756649D01* +G01X-158641Y7756649D01* +G01X-158641Y7757821D01* +G01X-162655Y7779292D01* +G01X-170545Y7799659D01* +G01X-182044Y7818230D01* +G01X-196759Y7834372D01* +G01X-214189Y7847535D01* +G01X-233742Y7857271D01* +G01X-254751Y7863249D01* +G01X-276500Y7865264D01* +G01X-298249Y7863249D01* +G01X-319258Y7857271D01* +G01X-338811Y7847535D01* +G01X-356241Y7834372D01* +G01X-370957Y7818230D01* +G01X-382455Y7799659D01* +G01X-390346Y7779292D01* +G01X-394359Y7757821D01* +G01X-2190641Y7757821D01* +G01X-2194655Y7779292D01* +G01X-2202545Y7799659D01* +G01X-2214044Y7818230D01* +G01X-2228759Y7834372D01* +G01X-2246189Y7847535D01* +G01X-2265742Y7857271D01* +G01X-2286751Y7863249D01* +G01X-2308500Y7865264D01* +G01X-2330249Y7863249D01* +G01X-2351258Y7857271D01* +G01X-2370811Y7847535D01* +G01X-2388241Y7834372D01* +G01X-2402957Y7818230D01* +G01X-2414455Y7799659D01* +G01X-2422346Y7779292D01* +G01X-2426359Y7757821D01* +G01X-2536486Y7757821D01* +G01X-2536486Y8011821D01* +G01X-2426359Y8011821D01* +G01X-2426359Y7989979D01* +G01X-2422346Y7968508D01* +G01X-2414455Y7948141D01* +G01X-2402957Y7929570D01* +G01X-2388241Y7913428D01* +G01X-2370811Y7900265D01* +G01X-2351258Y7890529D01* +G01X-2330249Y7884551D01* +G01X-2308500Y7882536D01* +G01X-2308500Y7882536D01* +G01X-2286751Y7884551D01* +G01X-2265742Y7890529D01* +G01X-2246189Y7900265D01* +G01X-2228759Y7913428D01* +G01X-2214044Y7929570D01* +G01X-2202545Y7948141D01* +G01X-2194655Y7968508D01* +G01X-2190641Y7989979D01* +G01X-2190641Y8011821D01* +G01X-2190641Y8011821D01* +G01X-394359Y8011821D01* +G01X-394359Y7989979D01* +G01X-390346Y7968508D01* +G01X-382455Y7948141D01* +G01X-370957Y7929570D01* +G01X-356241Y7913428D01* +G01X-338811Y7900265D01* +G01X-319258Y7890529D01* +G01X-298249Y7884551D01* +G01X-276500Y7882536D01* +G01X-276500Y7882536D01* +G01X-254751Y7884551D01* +G01X-233742Y7890529D01* +G01X-214189Y7900265D01* +G01X-196759Y7913428D01* +G01X-182044Y7929570D01* +G01X-170545Y7948141D01* +G01X-162655Y7968508D01* +G01X-158641Y7989979D01* +G01X-158641Y8010649D01* +G01X62787Y8010649D01* +G01X62787Y7991150D01* +G01X66370Y7971984D01* +G01X73413Y7953801D01* +G01X83678Y7937223D01* +G01X96815Y7922813D01* +G01X112375Y7911063D01* +G01X129830Y7902371D01* +G01X148584Y7897035D01* +G01X168000Y7895236D01* +G01X218800Y7895236D01* +G01X238216Y7897035D01* +G01X256970Y7902371D01* +G01X274425Y7911063D01* +G01X289985Y7922813D01* +G01X303122Y7937223D01* +G01X313386Y7953801D01* +G01X320430Y7971984D01* +G01X324013Y7991150D01* +G01X324013Y8010649D01* +G01X2602787Y8010649D01* +G01X2602787Y7991150D01* +G01X2606370Y7971984D01* +G01X2613413Y7953801D01* +G01X2623678Y7937223D01* +G01X2636815Y7922813D01* +G01X2652375Y7911063D01* +G01X2669830Y7902371D01* +G01X2688584Y7897035D01* +G01X2708000Y7895236D01* +G01X2758800Y7895236D01* +G01X2778216Y7897035D01* +G01X2796970Y7902371D01* +G01X2814425Y7911063D01* +G01X2829985Y7922813D01* +G01X2843122Y7937223D01* +G01X2853386Y7953801D01* +G01X2860430Y7971984D01* +G01X2864013Y7991150D01* +G01X2864013Y8010649D01* +G01X2860430Y8029816D01* +G01X2853386Y8047998D01* +G01X2843122Y8064577D01* +G01X2829985Y8078987D01* +G01X2814425Y8090737D01* +G01X2796970Y8099429D01* +G01X2778216Y8104765D01* +G01X2758800Y8106564D01* +G01X2758800Y8106564D01* +G01X2708000Y8106564D01* +G01X2688584Y8104765D01* +G01X2669830Y8099429D01* +G01X2652375Y8090737D01* +G01X2636815Y8078987D01* +G01X2623678Y8064577D01* +G01X2613413Y8047998D01* +G01X2606370Y8029816D01* +G01X2602787Y8010649D01* +G01X324013Y8010649D01* +G01X320430Y8029816D01* +G01X313386Y8047998D01* +G01X303122Y8064577D01* +G01X289985Y8078987D01* +G01X274425Y8090737D01* +G01X256970Y8099429D01* +G01X238216Y8104765D01* +G01X218800Y8106564D01* +G01X218800Y8106564D01* +G01X168000Y8106564D01* +G01X148584Y8104765D01* +G01X129830Y8099429D01* +G01X112375Y8090737D01* +G01X96815Y8078987D01* +G01X83678Y8064577D01* +G01X73413Y8047998D01* +G01X66370Y8029816D01* +G01X62787Y8010649D01* +G01X-158641Y8010649D01* +G01X-158641Y8011821D01* +G01X-162655Y8033292D01* +G01X-170545Y8053659D01* +G01X-182044Y8072230D01* +G01X-196759Y8088372D01* +G01X-214189Y8101535D01* +G01X-233742Y8111271D01* +G01X-254751Y8117249D01* +G01X-276500Y8119264D01* +G01X-298249Y8117249D01* +G01X-319258Y8111271D01* +G01X-338811Y8101535D01* +G01X-356241Y8088372D01* +G01X-370957Y8072230D01* +G01X-382455Y8053659D01* +G01X-390346Y8033292D01* +G01X-394359Y8011821D01* +G01X-2190641Y8011821D01* +G01X-2194655Y8033292D01* +G01X-2202545Y8053659D01* +G01X-2214044Y8072230D01* +G01X-2228759Y8088372D01* +G01X-2246189Y8101535D01* +G01X-2265742Y8111271D01* +G01X-2286751Y8117249D01* +G01X-2308500Y8119264D01* +G01X-2330249Y8117249D01* +G01X-2351258Y8111271D01* +G01X-2370811Y8101535D01* +G01X-2388241Y8088372D01* +G01X-2402957Y8072230D01* +G01X-2414455Y8053659D01* +G01X-2422346Y8033292D01* +G01X-2426359Y8011821D01* +G01X-2536486Y8011821D01* +G01X-2536486Y8265821D01* +G01X-2426359Y8265821D01* +G01X-2426359Y8243979D01* +G01X-2422346Y8222508D01* +G01X-2414455Y8202141D01* +G01X-2402957Y8183570D01* +G01X-2388241Y8167428D01* +G01X-2370811Y8154265D01* +G01X-2351258Y8144529D01* +G01X-2330249Y8138551D01* +G01X-2308500Y8136536D01* +G01X-2308500Y8136536D01* +G01X-2286751Y8138551D01* +G01X-2265742Y8144529D01* +G01X-2246189Y8154265D01* +G01X-2228759Y8167428D01* +G01X-2214044Y8183570D01* +G01X-2202545Y8202141D01* +G01X-2194655Y8222508D01* +G01X-2190641Y8243979D01* +G01X-2190641Y8245511D01* +G01X-394491Y8245511D01* +G01X-391010Y8224940D01* +G01X-383970Y8205299D01* +G01X-373591Y8187200D01* +G01X-360196Y8171204D01* +G01X-344200Y8157809D01* +G01X-326101Y8147430D01* +G01X-306460Y8140390D01* +G01X-285889Y8136909D01* +G01X-265025Y8137093D01* +G01X-244519Y8140938D01* +G01X-225006Y8148324D01* +G01X-207093Y8159021D01* +G01X-191336Y8172698D01* +G01X-178226Y8188928D01* +G01X-168169Y8207208D01* +G01X-161478Y8226970D01* +G01X-158361Y8247600D01* +G01X-158814Y8264649D01* +G01X62787Y8264649D01* +G01X62787Y8245150D01* +G01X66370Y8225984D01* +G01X73413Y8207801D01* +G01X83678Y8191223D01* +G01X96815Y8176813D01* +G01X112375Y8165063D01* +G01X129830Y8156371D01* +G01X148584Y8151035D01* +G01X168000Y8149236D01* +G01X218800Y8149236D01* +G01X238216Y8151035D01* +G01X256970Y8156371D01* +G01X274425Y8165063D01* +G01X289985Y8176813D01* +G01X303122Y8191223D01* +G01X313386Y8207801D01* +G01X320430Y8225984D01* +G01X324013Y8245150D01* +G01X324013Y8264649D01* +G01X2602787Y8264649D01* +G01X2602787Y8245150D01* +G01X2606370Y8225984D01* +G01X2613413Y8207801D01* +G01X2623678Y8191223D01* +G01X2636815Y8176813D01* +G01X2652375Y8165063D01* +G01X2669830Y8156371D01* +G01X2688584Y8151035D01* +G01X2708000Y8149236D01* +G01X2758800Y8149236D01* +G01X2778216Y8151035D01* +G01X2796970Y8156371D01* +G01X2814425Y8165063D01* +G01X2829985Y8176813D01* +G01X2843122Y8191223D01* +G01X2853386Y8207801D01* +G01X2860430Y8225984D01* +G01X2864013Y8245150D01* +G01X2864013Y8264649D01* +G01X2860430Y8283816D01* +G01X2853386Y8301998D01* +G01X2843122Y8318577D01* +G01X2829985Y8332987D01* +G01X2814425Y8344737D01* +G01X2796970Y8353429D01* +G01X2778216Y8358765D01* +G01X2758800Y8360564D01* +G01X2758800Y8360564D01* +G01X2708000Y8360564D01* +G01X2688584Y8358765D01* +G01X2669830Y8353429D01* +G01X2652375Y8344737D01* +G01X2636815Y8332987D01* +G01X2623678Y8318577D01* +G01X2613413Y8301998D01* +G01X2606370Y8283816D01* +G01X2602787Y8264649D01* +G01X324013Y8264649D01* +G01X320430Y8283816D01* +G01X313386Y8301998D01* +G01X303122Y8318577D01* +G01X289985Y8332987D01* +G01X274425Y8344737D01* +G01X256970Y8353429D01* +G01X238216Y8358765D01* +G01X218800Y8360564D01* +G01X218800Y8360564D01* +G01X168000Y8360564D01* +G01X148584Y8358765D01* +G01X129830Y8353429D01* +G01X112375Y8344737D01* +G01X96815Y8332987D01* +G01X83678Y8318577D01* +G01X73413Y8301998D01* +G01X66370Y8283816D01* +G01X62787Y8264649D01* +G01X-158814Y8264649D01* +G01X-158915Y8268457D01* +G01X-163122Y8288892D01* +G01X-52403Y8399611D01* +G01X-43483Y8411237D01* +G01X-37875Y8424775D01* +G01X-35962Y8439304D01* +G01X-35962Y8518649D01* +G01X62787Y8518649D01* +G01X62787Y8499150D01* +G01X66370Y8479984D01* +G01X73413Y8461801D01* +G01X83678Y8445223D01* +G01X96815Y8430813D01* +G01X112375Y8419063D01* +G01X129830Y8410371D01* +G01X148584Y8405035D01* +G01X168000Y8403236D01* +G01X218800Y8403236D01* +G01X238216Y8405035D01* +G01X256970Y8410371D01* +G01X274425Y8419063D01* +G01X289985Y8430813D01* +G01X303122Y8445223D01* +G01X313386Y8461801D01* +G01X320430Y8479984D01* +G01X324013Y8499150D01* +G01X324013Y8518649D01* +G01X2602787Y8518649D01* +G01X2602787Y8499150D01* +G01X2606370Y8479984D01* +G01X2613413Y8461801D01* +G01X2623678Y8445223D01* +G01X2636815Y8430813D01* +G01X2652375Y8419063D01* +G01X2669830Y8410371D01* +G01X2688584Y8405035D01* +G01X2708000Y8403236D01* +G01X2758800Y8403236D01* +G01X2778216Y8405035D01* +G01X2796970Y8410371D01* +G01X2814425Y8419063D01* +G01X2829985Y8430813D01* +G01X2843122Y8445223D01* +G01X2853386Y8461801D01* +G01X2860430Y8479984D01* +G01X2864013Y8499150D01* +G01X2864013Y8518649D01* +G01X2860430Y8537816D01* +G01X2853386Y8555998D01* +G01X2843122Y8572577D01* +G01X2829985Y8586987D01* +G01X2814425Y8598737D01* +G01X2796970Y8607429D01* +G01X2778216Y8612765D01* +G01X2758800Y8614564D01* +G01X2758800Y8614564D01* +G01X2708000Y8614564D01* +G01X2688584Y8612765D01* +G01X2669830Y8607429D01* +G01X2652375Y8598737D01* +G01X2636815Y8586987D01* +G01X2623678Y8572577D01* +G01X2613413Y8555998D01* +G01X2606370Y8537816D01* +G01X2602787Y8518649D01* +G01X324013Y8518649D01* +G01X320430Y8537816D01* +G01X313386Y8555998D01* +G01X303122Y8572577D01* +G01X289985Y8586987D01* +G01X274425Y8598737D01* +G01X256970Y8607429D01* +G01X238216Y8612765D01* +G01X218800Y8614564D01* +G01X218800Y8614564D01* +G01X168000Y8614564D01* +G01X148584Y8612765D01* +G01X129830Y8607429D01* +G01X112375Y8598737D01* +G01X96815Y8586987D01* +G01X83678Y8572577D01* +G01X73413Y8555998D01* +G01X66370Y8537816D01* +G01X62787Y8518649D01* +G01X-35962Y8518649D01* +G01X-35962Y8772649D01* +G01X62787Y8772649D01* +G01X62787Y8753150D01* +G01X66370Y8733984D01* +G01X73413Y8715801D01* +G01X83678Y8699223D01* +G01X96815Y8684813D01* +G01X112375Y8673063D01* +G01X129830Y8664371D01* +G01X148584Y8659035D01* +G01X168000Y8657236D01* +G01X218800Y8657236D01* +G01X238216Y8659035D01* +G01X256970Y8664371D01* +G01X274425Y8673063D01* +G01X289985Y8684813D01* +G01X303122Y8699223D01* +G01X313386Y8715801D01* +G01X320430Y8733984D01* +G01X324013Y8753150D01* +G01X324013Y8772649D01* +G01X2602787Y8772649D01* +G01X2602787Y8753150D01* +G01X2606370Y8733984D01* +G01X2613413Y8715801D01* +G01X2623678Y8699223D01* +G01X2636815Y8684813D01* +G01X2652375Y8673063D01* +G01X2669830Y8664371D01* +G01X2688584Y8659035D01* +G01X2708000Y8657236D01* +G01X2758800Y8657236D01* +G01X2778216Y8659035D01* +G01X2796970Y8664371D01* +G01X2814425Y8673063D01* +G01X2829985Y8684813D01* +G01X2843122Y8699223D01* +G01X2853386Y8715801D01* +G01X2860430Y8733984D01* +G01X2864013Y8753150D01* +G01X2864013Y8772649D01* +G01X2860430Y8791816D01* +G01X2853386Y8809998D01* +G01X2843122Y8826577D01* +G01X2829985Y8840987D01* +G01X2814425Y8852737D01* +G01X2796970Y8861429D01* +G01X2778216Y8866765D01* +G01X2758800Y8868564D01* +G01X2758800Y8868564D01* +G01X2708000Y8868564D01* +G01X2688584Y8866765D01* +G01X2669830Y8861429D01* +G01X2652375Y8852737D01* +G01X2636815Y8840987D01* +G01X2623678Y8826577D01* +G01X2613413Y8809998D01* +G01X2606370Y8791816D01* +G01X2602787Y8772649D01* +G01X324013Y8772649D01* +G01X320430Y8791816D01* +G01X313386Y8809998D01* +G01X303122Y8826577D01* +G01X289985Y8840987D01* +G01X274425Y8852737D01* +G01X256970Y8861429D01* +G01X238216Y8866765D01* +G01X218800Y8868564D01* +G01X218800Y8868564D01* +G01X168000Y8868564D01* +G01X148584Y8866765D01* +G01X129830Y8861429D01* +G01X112375Y8852737D01* +G01X96815Y8840987D01* +G01X83678Y8826577D01* +G01X73413Y8809998D01* +G01X66370Y8791816D01* +G01X62787Y8772649D01* +G01X-35962Y8772649D01* +G01X-35962Y9026649D01* +G01X62787Y9026649D01* +G01X62787Y9007150D01* +G01X66370Y8987984D01* +G01X73413Y8969801D01* +G01X83678Y8953223D01* +G01X96815Y8938813D01* +G01X112375Y8927063D01* +G01X129830Y8918371D01* +G01X148584Y8913035D01* +G01X168000Y8911236D01* +G01X218800Y8911236D01* +G01X238216Y8913035D01* +G01X256970Y8918371D01* +G01X274425Y8927063D01* +G01X289985Y8938813D01* +G01X303122Y8953223D01* +G01X313386Y8969801D01* +G01X320430Y8987984D01* +G01X324013Y9007150D01* +G01X324013Y9026649D01* +G01X2602787Y9026649D01* +G01X2602787Y9007150D01* +G01X2606370Y8987984D01* +G01X2613413Y8969801D01* +G01X2623678Y8953223D01* +G01X2636815Y8938813D01* +G01X2652375Y8927063D01* +G01X2669830Y8918371D01* +G01X2688584Y8913035D01* +G01X2708000Y8911236D01* +G01X2758800Y8911236D01* +G01X2778216Y8913035D01* +G01X2796970Y8918371D01* +G01X2814425Y8927063D01* +G01X2829985Y8938813D01* +G01X2843122Y8953223D01* +G01X2853386Y8969801D01* +G01X2860430Y8987984D01* +G01X2864013Y9007150D01* +G01X2864013Y9026649D01* +G01X2860430Y9045816D01* +G01X2853386Y9063998D01* +G01X2843122Y9080577D01* +G01X2829985Y9094987D01* +G01X2814425Y9106737D01* +G01X2796970Y9115429D01* +G01X2778216Y9120765D01* +G01X2758800Y9122564D01* +G01X2758800Y9122564D01* +G01X2708000Y9122564D01* +G01X2688584Y9120765D01* +G01X2669830Y9115429D01* +G01X2652375Y9106737D01* +G01X2636815Y9094987D01* +G01X2623678Y9080577D01* +G01X2613413Y9063998D01* +G01X2606370Y9045816D01* +G01X2602787Y9026649D01* +G01X324013Y9026649D01* +G01X324013Y9026649D01* +G01X320430Y9045816D01* +G01X313386Y9063998D01* +G01X303122Y9080577D01* +G01X289985Y9094987D01* +G01X274425Y9106737D01* +G01X256970Y9115429D01* +G01X238216Y9120765D01* +G01X218800Y9122564D01* +G01X218800Y9122564D01* +G01X168000Y9122564D01* +G01X148584Y9120765D01* +G01X129830Y9115429D01* +G01X112375Y9106737D01* +G01X96815Y9094987D01* +G01X83678Y9080577D01* +G01X73413Y9063998D01* +G01X66370Y9045816D01* +G01X62787Y9026649D01* +G01X-35962Y9026649D01* +G01X-35962Y9280649D01* +G01X62787Y9280649D01* +G01X62787Y9261150D01* +G01X66370Y9241984D01* +G01X73413Y9223801D01* +G01X83678Y9207223D01* +G01X96815Y9192813D01* +G01X112375Y9181063D01* +G01X129830Y9172371D01* +G01X148584Y9167035D01* +G01X168000Y9165236D01* +G01X218800Y9165236D01* +G01X238216Y9167035D01* +G01X256970Y9172371D01* +G01X274425Y9181063D01* +G01X289985Y9192813D01* +G01X303122Y9207223D01* +G01X313386Y9223801D01* +G01X320430Y9241984D01* +G01X324013Y9261150D01* +G01X324013Y9280649D01* +G01X2602787Y9280649D01* +G01X2602787Y9261150D01* +G01X2606370Y9241984D01* +G01X2613413Y9223801D01* +G01X2623678Y9207223D01* +G01X2636815Y9192813D01* +G01X2652375Y9181063D01* +G01X2669830Y9172371D01* +G01X2688584Y9167035D01* +G01X2708000Y9165236D01* +G01X2758800Y9165236D01* +G01X2778216Y9167035D01* +G01X2796970Y9172371D01* +G01X2814425Y9181063D01* +G01X2829985Y9192813D01* +G01X2843122Y9207223D01* +G01X2853386Y9223801D01* +G01X2860430Y9241984D01* +G01X2864013Y9261150D01* +G01X2864013Y9280649D01* +G01X2860430Y9299816D01* +G01X2853386Y9317998D01* +G01X2843122Y9334577D01* +G01X2829985Y9348987D01* +G01X2814425Y9360737D01* +G01X2796970Y9369429D01* +G01X2778216Y9374765D01* +G01X2758800Y9376564D01* +G01X2758800Y9376564D01* +G01X2708000Y9376564D01* +G01X2688584Y9374765D01* +G01X2669830Y9369429D01* +G01X2652375Y9360737D01* +G01X2636815Y9348987D01* +G01X2623678Y9334577D01* +G01X2613413Y9317998D01* +G01X2606370Y9299816D01* +G01X2602787Y9280649D01* +G01X324013Y9280649D01* +G01X324013Y9280649D01* +G01X320430Y9299816D01* +G01X313386Y9317998D01* +G01X303122Y9334577D01* +G01X289985Y9348987D01* +G01X274425Y9360737D01* +G01X256970Y9369429D01* +G01X238216Y9374765D01* +G01X218800Y9376564D01* +G01X218800Y9376564D01* +G01X168000Y9376564D01* +G01X148584Y9374765D01* +G01X129830Y9369429D01* +G01X112375Y9360737D01* +G01X96815Y9348987D01* +G01X83678Y9334577D01* +G01X73413Y9317998D01* +G01X66370Y9299816D01* +G01X62787Y9280649D01* +G01X-35962Y9280649D01* +G01X-35962Y9534649D01* +G01X62787Y9534649D01* +G01X62787Y9515150D01* +G01X66370Y9495984D01* +G01X73413Y9477801D01* +G01X83678Y9461223D01* +G01X96815Y9446813D01* +G01X112375Y9435063D01* +G01X129830Y9426371D01* +G01X148584Y9421035D01* +G01X168000Y9419236D01* +G01X218800Y9419236D01* +G01X238216Y9421035D01* +G01X256970Y9426371D01* +G01X274425Y9435063D01* +G01X289985Y9446813D01* +G01X303122Y9461223D01* +G01X313386Y9477801D01* +G01X320430Y9495984D01* +G01X324013Y9515150D01* +G01X324013Y9534649D01* +G01X2602787Y9534649D01* +G01X2602787Y9515150D01* +G01X2606370Y9495984D01* +G01X2613413Y9477801D01* +G01X2623678Y9461223D01* +G01X2636815Y9446813D01* +G01X2652375Y9435063D01* +G01X2669830Y9426371D01* +G01X2688584Y9421035D01* +G01X2708000Y9419236D01* +G01X2758800Y9419236D01* +G01X2778216Y9421035D01* +G01X2796970Y9426371D01* +G01X2814425Y9435063D01* +G01X2829985Y9446813D01* +G01X2843122Y9461223D01* +G01X2853386Y9477801D01* +G01X2860430Y9495984D01* +G01X2864013Y9515150D01* +G01X2864013Y9534649D01* +G01X2860430Y9553816D01* +G01X2853386Y9571998D01* +G01X2843122Y9588577D01* +G01X2829985Y9602987D01* +G01X2814425Y9614737D01* +G01X2796970Y9623429D01* +G01X2778216Y9628765D01* +G01X2758800Y9630564D01* +G01X2758800Y9630564D01* +G01X2708000Y9630564D01* +G01X2688584Y9628765D01* +G01X2669830Y9623429D01* +G01X2652375Y9614737D01* +G01X2636815Y9602987D01* +G01X2623678Y9588577D01* +G01X2613413Y9571998D01* +G01X2606370Y9553816D01* +G01X2602787Y9534649D01* +G01X324013Y9534649D01* +G01X324013Y9534649D01* +G01X320430Y9553816D01* +G01X313386Y9571998D01* +G01X303122Y9588577D01* +G01X289985Y9602987D01* +G01X274425Y9614737D01* +G01X256970Y9623429D01* +G01X238216Y9628765D01* +G01X218800Y9630564D01* +G01X218800Y9630564D01* +G01X168000Y9630564D01* +G01X148584Y9628765D01* +G01X129830Y9623429D01* +G01X112375Y9614737D01* +G01X96815Y9602987D01* +G01X83678Y9588577D01* +G01X73413Y9571998D01* +G01X66370Y9553816D01* +G01X62787Y9534649D01* +G01X-35962Y9534649D01* +G01X-35962Y9788649D01* +G01X62787Y9788649D01* +G01X62787Y9769150D01* +G01X66370Y9749984D01* +G01X73413Y9731801D01* +G01X83678Y9715223D01* +G01X96815Y9700813D01* +G01X112375Y9689063D01* +G01X129830Y9680371D01* +G01X148584Y9675035D01* +G01X168000Y9673236D01* +G01X218800Y9673236D01* +G01X238216Y9675035D01* +G01X256970Y9680371D01* +G01X274425Y9689063D01* +G01X289985Y9700813D01* +G01X303122Y9715223D01* +G01X313386Y9731801D01* +G01X320430Y9749984D01* +G01X324013Y9769150D01* +G01X324013Y9788649D01* +G01X320430Y9807816D01* +G01X313386Y9825998D01* +G01X306848Y9836558D01* +G01X957178Y9836558D01* +G01X957178Y9671458D01* +G01X958931Y9660391D01* +G01X964018Y9650407D01* +G01X971941Y9642484D01* +G01X981925Y9637397D01* +G01X992992Y9635644D01* +G01X1158092Y9635644D01* +G01X1158092Y9635644D01* +G01X1169159Y9637397D01* +G01X1179143Y9642484D01* +G01X1187066Y9650407D01* +G01X1192153Y9660391D01* +G01X1193906Y9671458D01* +G01X1193906Y9754008D01* +G01X1211178Y9754008D01* +G01X1213193Y9732259D01* +G01X1219171Y9711250D01* +G01X1228907Y9691697D01* +G01X1242070Y9674267D01* +G01X1258212Y9659551D01* +G01X1276783Y9648053D01* +G01X1297150Y9640162D01* +G01X1318621Y9636149D01* +G01X1340463Y9636149D01* +G01X1361934Y9640162D01* +G01X1382301Y9648053D01* +G01X1400872Y9659551D01* +G01X1417014Y9674267D01* +G01X1430177Y9691697D01* +G01X1439913Y9711250D01* +G01X1445891Y9732259D01* +G01X1447906Y9754008D01* +G01X1465178Y9754008D01* +G01X1467193Y9732259D01* +G01X1473171Y9711250D01* +G01X1482907Y9691697D01* +G01X1496070Y9674267D01* +G01X1512212Y9659551D01* +G01X1530783Y9648053D01* +G01X1551150Y9640162D01* +G01X1572621Y9636149D01* +G01X1594463Y9636149D01* +G01X1615934Y9640162D01* +G01X1636301Y9648053D01* +G01X1654872Y9659551D01* +G01X1671014Y9674267D01* +G01X1684177Y9691697D01* +G01X1693913Y9711250D01* +G01X1699891Y9732259D01* +G01X1701906Y9754008D01* +G01X1719178Y9754008D01* +G01X1721193Y9732259D01* +G01X1727171Y9711250D01* +G01X1736907Y9691697D01* +G01X1750070Y9674267D01* +G01X1766212Y9659551D01* +G01X1784783Y9648053D01* +G01X1805150Y9640162D01* +G01X1826621Y9636149D01* +G01X1848463Y9636149D01* +G01X1869934Y9640162D01* +G01X1890301Y9648053D01* +G01X1908872Y9659551D01* +G01X1925014Y9674267D01* +G01X1938177Y9691697D01* +G01X1947913Y9711250D01* +G01X1953891Y9732259D01* +G01X1955906Y9754008D01* +G01X1973178Y9754008D01* +G01X1975193Y9732259D01* +G01X1981171Y9711250D01* +G01X1990907Y9691697D01* +G01X2004070Y9674267D01* +G01X2020212Y9659551D01* +G01X2038783Y9648053D01* +G01X2059150Y9640162D01* +G01X2080621Y9636149D01* +G01X2102463Y9636149D01* +G01X2123934Y9640162D01* +G01X2144301Y9648053D01* +G01X2162872Y9659551D01* +G01X2179014Y9674267D01* +G01X2192177Y9691697D01* +G01X2201913Y9711250D01* +G01X2207891Y9732259D01* +G01X2209906Y9754008D01* +G01X2207891Y9775757D01* +G01X2204222Y9788649D01* +G01X2602787Y9788649D01* +G01X2602787Y9769150D01* +G01X2606370Y9749984D01* +G01X2613413Y9731801D01* +G01X2623678Y9715223D01* +G01X2636815Y9700813D01* +G01X2652375Y9689063D01* +G01X2669830Y9680371D01* +G01X2688584Y9675035D01* +G01X2708000Y9673236D01* +G01X2758800Y9673236D01* +G01X2778216Y9675035D01* +G01X2796970Y9680371D01* +G01X2814425Y9689063D01* +G01X2829985Y9700813D01* +G01X2843122Y9715223D01* +G01X2853386Y9731801D01* +G01X2860430Y9749984D01* +G01X2864013Y9769150D01* +G01X2864013Y9788649D01* +G01X2860430Y9807816D01* +G01X2853386Y9825998D01* +G01X2843122Y9842577D01* +G01X2829985Y9856987D01* +G01X2814425Y9868737D01* +G01X2796970Y9877429D01* +G01X2778216Y9882765D01* +G01X2758800Y9884564D01* +G01X2758800Y9884564D01* +G01X2708000Y9884564D01* +G01X2688584Y9882765D01* +G01X2669830Y9877429D01* +G01X2652375Y9868737D01* +G01X2636815Y9856987D01* +G01X2623678Y9842577D01* +G01X2613413Y9825998D01* +G01X2606370Y9807816D01* +G01X2602787Y9788649D01* +G01X2204222Y9788649D01* +G01X2201913Y9796766D01* +G01X2192177Y9816319D01* +G01X2179014Y9833749D01* +G01X2162872Y9848464D01* +G01X2144301Y9859963D01* +G01X2123934Y9867853D01* +G01X2102463Y9871867D01* +G01X2080621Y9871867D01* +G01X2059150Y9867853D01* +G01X2038783Y9859963D01* +G01X2020212Y9848464D01* +G01X2004070Y9833749D01* +G01X1990907Y9816319D01* +G01X1981171Y9796766D01* +G01X1975193Y9775757D01* +G01X1973178Y9754008D01* +G01X1973178Y9754008D01* +G01X1955906Y9754008D01* +G01X1953891Y9775757D01* +G01X1947913Y9796766D01* +G01X1938177Y9816319D01* +G01X1925014Y9833749D01* +G01X1908872Y9848464D01* +G01X1890301Y9859963D01* +G01X1869934Y9867853D01* +G01X1848463Y9871867D01* +G01X1826621Y9871867D01* +G01X1805150Y9867853D01* +G01X1784783Y9859963D01* +G01X1766212Y9848464D01* +G01X1750070Y9833749D01* +G01X1736907Y9816319D01* +G01X1727171Y9796766D01* +G01X1721193Y9775757D01* +G01X1719178Y9754008D01* +G01X1719178Y9754008D01* +G01X1701906Y9754008D01* +G01X1699891Y9775757D01* +G01X1693913Y9796766D01* +G01X1684177Y9816319D01* +G01X1671014Y9833749D01* +G01X1654872Y9848464D01* +G01X1636301Y9859963D01* +G01X1615934Y9867853D01* +G01X1594463Y9871867D01* +G01X1572621Y9871867D01* +G01X1551150Y9867853D01* +G01X1530783Y9859963D01* +G01X1512212Y9848464D01* +G01X1496070Y9833749D01* +G01X1482907Y9816319D01* +G01X1473171Y9796766D01* +G01X1467193Y9775757D01* +G01X1465178Y9754008D01* +G01X1465178Y9754008D01* +G01X1447906Y9754008D01* +G01X1445891Y9775757D01* +G01X1439913Y9796766D01* +G01X1430177Y9816319D01* +G01X1417014Y9833749D01* +G01X1400872Y9848464D01* +G01X1382301Y9859963D01* +G01X1361934Y9867853D01* +G01X1340463Y9871867D01* +G01X1318621Y9871867D01* +G01X1297150Y9867853D01* +G01X1276783Y9859963D01* +G01X1258212Y9848464D01* +G01X1242070Y9833749D01* +G01X1228907Y9816319D01* +G01X1219171Y9796766D01* +G01X1213193Y9775757D01* +G01X1211178Y9754008D01* +G01X1211178Y9754008D01* +G01X1193906Y9754008D01* +G01X1193906Y9836558D01* +G01X1192153Y9847625D01* +G01X1187066Y9857609D01* +G01X1179143Y9865532D01* +G01X1169159Y9870619D01* +G01X1158092Y9872372D01* +G01X992992Y9872372D01* +G01X981925Y9870619D01* +G01X971941Y9865532D01* +G01X964018Y9857609D01* +G01X958931Y9847625D01* +G01X957178Y9836558D01* +G01X306848Y9836558D01* +G01X303122Y9842577D01* +G01X289985Y9856987D01* +G01X274425Y9868737D01* +G01X256970Y9877429D01* +G01X238216Y9882765D01* +G01X218800Y9884564D01* +G01X218800Y9884564D01* +G01X168000Y9884564D01* +G01X148584Y9882765D01* +G01X129830Y9877429D01* +G01X112375Y9868737D01* +G01X96815Y9856987D01* +G01X83678Y9842577D01* +G01X73413Y9825998D01* +G01X66370Y9807816D01* +G01X62787Y9788649D01* +G01X-35962Y9788649D01* +G01X-35962Y10042649D01* +G01X62787Y10042649D01* +G01X62787Y10023150D01* +G01X66370Y10003984D01* +G01X73413Y9985801D01* +G01X83678Y9969223D01* +G01X96815Y9954813D01* +G01X112375Y9943063D01* +G01X129830Y9934371D01* +G01X148584Y9929035D01* +G01X168000Y9927236D01* +G01X218800Y9927236D01* +G01X238216Y9929035D01* +G01X256970Y9934371D01* +G01X274425Y9943063D01* +G01X289985Y9954813D01* +G01X303122Y9969223D01* +G01X313386Y9985801D01* +G01X320430Y10003984D01* +G01X321183Y10008008D01* +G01X957178Y10008008D01* +G01X959193Y9986259D01* +G01X965171Y9965250D01* +G01X974907Y9945697D01* +G01X988070Y9928267D01* +G01X1004212Y9913551D01* +G01X1022783Y9902053D01* +G01X1043150Y9894162D01* +G01X1064621Y9890149D01* +G01X1086463Y9890149D01* +G01X1107934Y9894162D01* +G01X1128301Y9902053D01* +G01X1146872Y9913551D01* +G01X1163014Y9928267D01* +G01X1176177Y9945697D01* +G01X1185913Y9965250D01* +G01X1191891Y9986259D01* +G01X1193906Y10008008D01* +G01X1211178Y10008008D01* +G01X1213193Y9986259D01* +G01X1219171Y9965250D01* +G01X1228907Y9945697D01* +G01X1242070Y9928267D01* +G01X1258212Y9913551D01* +G01X1276783Y9902053D01* +G01X1297150Y9894162D01* +G01X1318621Y9890149D01* +G01X1340463Y9890149D01* +G01X1361934Y9894162D01* +G01X1382301Y9902053D01* +G01X1400872Y9913551D01* +G01X1417014Y9928267D01* +G01X1430177Y9945697D01* +G01X1439913Y9965250D01* +G01X1445891Y9986259D01* +G01X1447906Y10008008D01* +G01X1465178Y10008008D01* +G01X1467193Y9986259D01* +G01X1473171Y9965250D01* +G01X1482907Y9945697D01* +G01X1496070Y9928267D01* +G01X1512212Y9913551D01* +G01X1530783Y9902053D01* +G01X1551150Y9894162D01* +G01X1572621Y9890149D01* +G01X1594463Y9890149D01* +G01X1615934Y9894162D01* +G01X1636301Y9902053D01* +G01X1654872Y9913551D01* +G01X1671014Y9928267D01* +G01X1684177Y9945697D01* +G01X1693913Y9965250D01* +G01X1699891Y9986259D01* +G01X1701906Y10008008D01* +G01X1719178Y10008008D01* +G01X1721193Y9986259D01* +G01X1727171Y9965250D01* +G01X1736907Y9945697D01* +G01X1750070Y9928267D01* +G01X1766212Y9913551D01* +G01X1784783Y9902053D01* +G01X1805150Y9894162D01* +G01X1826621Y9890149D01* +G01X1848463Y9890149D01* +G01X1869934Y9894162D01* +G01X1890301Y9902053D01* +G01X1908872Y9913551D01* +G01X1925014Y9928267D01* +G01X1938177Y9945697D01* +G01X1947913Y9965250D01* +G01X1953891Y9986259D01* +G01X1955906Y10008008D01* +G01X1973178Y10008008D01* +G01X1975193Y9986259D01* +G01X1981171Y9965250D01* +G01X1990907Y9945697D01* +G01X2004070Y9928267D01* +G01X2020212Y9913551D01* +G01X2038783Y9902053D01* +G01X2059150Y9894162D01* +G01X2080621Y9890149D01* +G01X2102463Y9890149D01* +G01X2123934Y9894162D01* +G01X2144301Y9902053D01* +G01X2162872Y9913551D01* +G01X2179014Y9928267D01* +G01X2192177Y9945697D01* +G01X2201913Y9965250D01* +G01X2207891Y9986259D01* +G01X2209906Y10008008D01* +G01X2207891Y10029757D01* +G01X2204222Y10042649D01* +G01X2602787Y10042649D01* +G01X2602787Y10023150D01* +G01X2606370Y10003984D01* +G01X2613413Y9985801D01* +G01X2623678Y9969223D01* +G01X2636815Y9954813D01* +G01X2652375Y9943063D01* +G01X2669830Y9934371D01* +G01X2688584Y9929035D01* +G01X2708000Y9927236D01* +G01X2758800Y9927236D01* +G01X2778216Y9929035D01* +G01X2796970Y9934371D01* +G01X2814425Y9943063D01* +G01X2829985Y9954813D01* +G01X2843122Y9969223D01* +G01X2853386Y9985801D01* +G01X2860430Y10003984D01* +G01X2864013Y10023150D01* +G01X2864013Y10042649D01* +G01X2860430Y10061816D01* +G01X2853386Y10079998D01* +G01X2843122Y10096577D01* +G01X2829985Y10110987D01* +G01X2814425Y10122737D01* +G01X2796970Y10131429D01* +G01X2778216Y10136765D01* +G01X2758800Y10138564D01* +G01X2758800Y10138564D01* +G01X2708000Y10138564D01* +G01X2688584Y10136765D01* +G01X2669830Y10131429D01* +G01X2652375Y10122737D01* +G01X2636815Y10110987D01* +G01X2623678Y10096577D01* +G01X2613413Y10079998D01* +G01X2606370Y10061816D01* +G01X2602787Y10042649D01* +G01X2204222Y10042649D01* +G01X2201913Y10050766D01* +G01X2192177Y10070319D01* +G01X2179014Y10087749D01* +G01X2162872Y10102464D01* +G01X2144301Y10113963D01* +G01X2123934Y10121853D01* +G01X2102463Y10125867D01* +G01X2080621Y10125867D01* +G01X2059150Y10121853D01* +G01X2038783Y10113963D01* +G01X2020212Y10102464D01* +G01X2004070Y10087749D01* +G01X1990907Y10070319D01* +G01X1981171Y10050766D01* +G01X1975193Y10029757D01* +G01X1973178Y10008008D01* +G01X1973178Y10008008D01* +G01X1955906Y10008008D01* +G01X1953891Y10029757D01* +G01X1947913Y10050766D01* +G01X1938177Y10070319D01* +G01X1925014Y10087749D01* +G01X1908872Y10102464D01* +G01X1890301Y10113963D01* +G01X1869934Y10121853D01* +G01X1848463Y10125867D01* +G01X1826621Y10125867D01* +G01X1805150Y10121853D01* +G01X1784783Y10113963D01* +G01X1766212Y10102464D01* +G01X1750070Y10087749D01* +G01X1736907Y10070319D01* +G01X1727171Y10050766D01* +G01X1721193Y10029757D01* +G01X1719178Y10008008D01* +G01X1719178Y10008008D01* +G01X1701906Y10008008D01* +G01X1699891Y10029757D01* +G01X1693913Y10050766D01* +G01X1684177Y10070319D01* +G01X1671014Y10087749D01* +G01X1654872Y10102464D01* +G01X1636301Y10113963D01* +G01X1615934Y10121853D01* +G01X1594463Y10125867D01* +G01X1572621Y10125867D01* +G01X1551150Y10121853D01* +G01X1530783Y10113963D01* +G01X1512212Y10102464D01* +G01X1496070Y10087749D01* +G01X1482907Y10070319D01* +G01X1473171Y10050766D01* +G01X1467193Y10029757D01* +G01X1465178Y10008008D01* +G01X1465178Y10008008D01* +G01X1447906Y10008008D01* +G01X1445891Y10029757D01* +G01X1439913Y10050766D01* +G01X1430177Y10070319D01* +G01X1417014Y10087749D01* +G01X1400872Y10102464D01* +G01X1382301Y10113963D01* +G01X1361934Y10121853D01* +G01X1340463Y10125867D01* +G01X1318621Y10125867D01* +G01X1297150Y10121853D01* +G01X1276783Y10113963D01* +G01X1258212Y10102464D01* +G01X1242070Y10087749D01* +G01X1228907Y10070319D01* +G01X1219171Y10050766D01* +G01X1213193Y10029757D01* +G01X1211178Y10008008D01* +G01X1211178Y10008008D01* +G01X1193906Y10008008D01* +G01X1191891Y10029757D01* +G01X1185913Y10050766D01* +G01X1176177Y10070319D01* +G01X1163014Y10087749D01* +G01X1146872Y10102464D01* +G01X1128301Y10113963D01* +G01X1107934Y10121853D01* +G01X1086463Y10125867D01* +G01X1064621Y10125867D01* +G01X1043150Y10121853D01* +G01X1022783Y10113963D01* +G01X1004212Y10102464D01* +G01X988070Y10087749D01* +G01X974907Y10070319D01* +G01X965171Y10050766D01* +G01X959193Y10029757D01* +G01X957178Y10008008D01* +G01X957178Y10008008D01* +G01X321183Y10008008D01* +G01X324013Y10023150D01* +G01X324013Y10042649D01* +G01X320430Y10061816D01* +G01X313386Y10079998D01* +G01X303122Y10096577D01* +G01X289985Y10110987D01* +G01X274425Y10122737D01* +G01X256970Y10131429D01* +G01X238216Y10136765D01* +G01X218800Y10138564D01* +G01X218800Y10138564D01* +G01X168000Y10138564D01* +G01X148584Y10136765D01* +G01X129830Y10131429D01* +G01X112375Y10122737D01* +G01X96815Y10110987D01* +G01X83678Y10096577D01* +G01X73413Y10079998D01* +G01X66370Y10061816D01* +G01X62787Y10042649D01* +G01X-35962Y10042649D01* +G01X-35962Y10231975D01* +G01X88057Y10355994D01* +G01X76431Y10339626D01* +G01X68111Y10321354D01* +G01X63397Y10301839D01* +G01X62460Y10281784D01* +G01X65333Y10261913D01* +G01X71912Y10242945D01* +G01X81961Y10225564D01* +G01X95116Y10210397D01* +G01X110902Y10197992D01* +G01X128749Y10188797D01* +G01X148014Y10183143D01* +G01X168000Y10181236D01* +G01X218800Y10181236D01* +G01X238216Y10183035D01* +G01X256970Y10188371D01* +G01X274425Y10197063D01* +G01X289985Y10208813D01* +G01X303122Y10223223D01* +G01X313386Y10239801D01* +G01X320430Y10257984D01* +G01X324013Y10277150D01* +G01X324013Y10296649D01* +G01X2602787Y10296649D01* +G01X2602787Y10277150D01* +G01X2606370Y10257984D01* +G01X2613413Y10239801D01* +G01X2623678Y10223223D01* +G01X2636815Y10208813D01* +G01X2652375Y10197063D01* +G01X2669830Y10188371D01* +G01X2688584Y10183035D01* +G01X2708000Y10181236D01* +G01X2758800Y10181236D01* +G01X2778216Y10183035D01* +G01X2796970Y10188371D01* +G01X2814425Y10197063D01* +G01X2829985Y10208813D01* +G01X2843122Y10223223D01* +G01X2853386Y10239801D01* +G01X2860430Y10257984D01* +G01X2864013Y10277150D01* +G01X2864013Y10296649D01* +G01X2860430Y10315816D01* +G01X2853386Y10333998D01* +G01X2843122Y10350577D01* +G01X2829985Y10364987D01* +G01X2814425Y10376737D01* +G01X2796970Y10385429D01* +G01X2778216Y10390765D01* +G01X2758800Y10392564D01* +G01X2758800Y10392564D01* +G01X2708000Y10392564D01* +G01X2688584Y10390765D01* +G01X2669830Y10385429D01* +G01X2652375Y10376737D01* +G01X2636815Y10364987D01* +G01X2623678Y10350577D01* +G01X2613413Y10333998D01* +G01X2606370Y10315816D01* +G01X2602787Y10296649D01* +G01X324013Y10296649D01* +G01X320430Y10315816D01* +G01X313386Y10333998D01* +G01X303122Y10350577D01* +G01X289985Y10364987D01* +G01X274425Y10376737D01* +G01X256970Y10385429D01* +G01X238216Y10390765D01* +G01X218800Y10392564D01* +G01X168000Y10392564D01* +G01X149272Y10390891D01* +G01X131137Y10385925D01* +G01X114169Y10377823D01* +G01X98905Y10366843D01* +G01X167301Y10435238D01* +G01X168000Y10435236D01* +G01X218800Y10435236D01* +G01X238216Y10437035D01* +G01X256970Y10442371D01* +G01X274425Y10451063D01* +G01X289985Y10462813D01* +G01X303122Y10477223D01* +G01X313386Y10493801D01* +G01X320430Y10511984D01* +G01X324013Y10531150D01* +G01X324013Y10550649D01* +G01X2602787Y10550649D01* +G01X2602787Y10531150D01* +G01X2606370Y10511984D01* +G01X2613413Y10493801D01* +G01X2623678Y10477223D01* +G01X2636815Y10462813D01* +G01X2652375Y10451063D01* +G01X2669830Y10442371D01* +G01X2688584Y10437035D01* +G01X2708000Y10435236D01* +G01X2758800Y10435236D01* +G01X2778216Y10437035D01* +G01X2796970Y10442371D01* +G01X2814425Y10451063D01* +G01X2829985Y10462813D01* +G01X2843122Y10477223D01* +G01X2853386Y10493801D01* +G01X2860430Y10511984D01* +G01X2864013Y10531150D01* +G01X2864013Y10550649D01* +G01X2860430Y10569816D01* +G01X2853386Y10587998D01* +G01X2843122Y10604577D01* +G01X2829985Y10618987D01* +G01X2814425Y10630737D01* +G01X2796970Y10639429D01* +G01X2778216Y10644765D01* +G01X2758800Y10646564D01* +G01X2758800Y10646564D01* +G01X2708000Y10646564D01* +G01X2688584Y10644765D01* +G01X2669830Y10639429D01* +G01X2652375Y10630737D01* +G01X2636815Y10618987D01* +G01X2623678Y10604577D01* +G01X2613413Y10587998D01* +G01X2606370Y10569816D01* +G01X2602787Y10550649D01* +G01X324013Y10550649D01* +G01X320430Y10569816D01* +G01X313386Y10587998D01* +G01X303122Y10604577D01* +G01X289985Y10618987D01* +G01X274425Y10630737D01* +G01X256970Y10639429D01* +G01X238216Y10644765D01* +G01X218800Y10646564D01* +G01X168000Y10646564D01* +G01X149009Y10644843D01* +G01X130636Y10639737D01* +G01X113481Y10631413D01* +G01X98101Y10620140D01* +G01X84997Y10606287D01* +G01X74597Y10590304D01* +G01X67238Y10572712D01* +G01X63162Y10554084D01* +G01X62499Y10535027D01* +G01X65273Y10516161D01* +G01X71392Y10498100D01* +G01X-131789Y10294919D01* +G01X-140710Y10283294D01* +G01X-146317Y10269755D01* +G01X-148230Y10255227D01* +G01X-148230Y8462555D01* +G01X-148230Y8462555D01* +G01X-242508Y8368278D01* +G01X-262943Y8372485D01* +G01X-283800Y8373039D01* +G01X-304430Y8369922D01* +G01X-324192Y8363231D01* +G01X-342472Y8353174D01* +G01X-358702Y8340064D01* +G01X-372379Y8324307D01* +G01X-383076Y8306394D01* +G01X-390462Y8286881D01* +G01X-394307Y8266375D01* +G01X-394491Y8245511D01* +G01X-2190641Y8245511D01* +G01X-2190641Y8265821D01* +G01X-2194655Y8287292D01* +G01X-2202545Y8307659D01* +G01X-2214044Y8326230D01* +G01X-2228759Y8342372D01* +G01X-2246189Y8355535D01* +G01X-2265742Y8365271D01* +G01X-2286751Y8371249D01* +G01X-2308500Y8373264D01* +G01X-2330249Y8371249D01* +G01X-2351258Y8365271D01* +G01X-2370811Y8355535D01* +G01X-2388241Y8342372D01* +G01X-2402957Y8326230D01* +G01X-2414455Y8307659D01* +G01X-2422346Y8287292D01* +G01X-2426359Y8265821D01* +G01X-2536486Y8265821D01* +G01X-2536486Y8519821D01* +G01X-2426359Y8519821D01* +G01X-2426359Y8497979D01* +G01X-2422346Y8476508D01* +G01X-2414455Y8456141D01* +G01X-2402957Y8437570D01* +G01X-2388241Y8421428D01* +G01X-2370811Y8408265D01* +G01X-2351258Y8398529D01* +G01X-2330249Y8392551D01* +G01X-2308500Y8390536D01* +G01X-2308500Y8390536D01* +G01X-2286751Y8392551D01* +G01X-2265742Y8398529D01* +G01X-2246189Y8408265D01* +G01X-2228759Y8421428D01* +G01X-2214044Y8437570D01* +G01X-2202545Y8456141D01* +G01X-2194655Y8476508D01* +G01X-2190641Y8497979D01* +G01X-2190641Y8519821D01* +G01X-2190641Y8519821D01* +G01X-394359Y8519821D01* +G01X-394359Y8497979D01* +G01X-390346Y8476508D01* +G01X-382455Y8456141D01* +G01X-370957Y8437570D01* +G01X-356241Y8421428D01* +G01X-338811Y8408265D01* +G01X-319258Y8398529D01* +G01X-298249Y8392551D01* +G01X-276500Y8390536D01* +G01X-276500Y8390536D01* +G01X-254751Y8392551D01* +G01X-233742Y8398529D01* +G01X-214189Y8408265D01* +G01X-196759Y8421428D01* +G01X-182044Y8437570D01* +G01X-170545Y8456141D01* +G01X-162655Y8476508D01* +G01X-158641Y8497979D01* +G01X-158641Y8519821D01* +G01X-162655Y8541292D01* +G01X-170545Y8561659D01* +G01X-182044Y8580230D01* +G01X-196759Y8596372D01* +G01X-214189Y8609535D01* +G01X-233742Y8619271D01* +G01X-254751Y8625249D01* +G01X-276500Y8627264D01* +G01X-298249Y8625249D01* +G01X-319258Y8619271D01* +G01X-338811Y8609535D01* +G01X-356241Y8596372D01* +G01X-370957Y8580230D01* +G01X-382455Y8561659D01* +G01X-390346Y8541292D01* +G01X-394359Y8519821D01* +G01X-2190641Y8519821D01* +G01X-2194655Y8541292D01* +G01X-2202545Y8561659D01* +G01X-2214044Y8580230D01* +G01X-2228759Y8596372D01* +G01X-2246189Y8609535D01* +G01X-2265742Y8619271D01* +G01X-2286751Y8625249D01* +G01X-2308500Y8627264D01* +G01X-2330249Y8625249D01* +G01X-2351258Y8619271D01* +G01X-2370811Y8609535D01* +G01X-2388241Y8596372D01* +G01X-2402957Y8580230D01* +G01X-2414455Y8561659D01* +G01X-2422346Y8541292D01* +G01X-2426359Y8519821D01* +G01X-2536486Y8519821D01* +G01X-2536486Y8773821D01* +G01X-2426359Y8773821D01* +G01X-2426359Y8751979D01* +G01X-2422346Y8730508D01* +G01X-2414455Y8710141D01* +G01X-2402957Y8691570D01* +G01X-2388241Y8675428D01* +G01X-2370811Y8662265D01* +G01X-2351258Y8652529D01* +G01X-2330249Y8646551D01* +G01X-2308500Y8644536D01* +G01X-2308500Y8644536D01* +G01X-2286751Y8646551D01* +G01X-2265742Y8652529D01* +G01X-2246189Y8662265D01* +G01X-2228759Y8675428D01* +G01X-2214044Y8691570D01* +G01X-2202545Y8710141D01* +G01X-2194655Y8730508D01* +G01X-2190641Y8751979D01* +G01X-2190641Y8773821D01* +G01X-2194655Y8795292D01* +G01X-2202545Y8815659D01* +G01X-2214044Y8834230D01* +G01X-2228759Y8850372D01* +G01X-2246189Y8863535D01* +G01X-2265742Y8873271D01* +G01X-2286751Y8879249D01* +G01X-2308500Y8881264D01* +G01X-2330249Y8879249D01* +G01X-2351258Y8873271D01* +G01X-2370811Y8863535D01* +G01X-2388241Y8850372D01* +G01X-2402957Y8834230D01* +G01X-2414455Y8815659D01* +G01X-2422346Y8795292D01* +G01X-2426359Y8773821D01* +G01X-2536486Y8773821D01* +G01X-2536486Y9027821D01* +G01X-2426359Y9027821D01* +G01X-2426359Y9005979D01* +G01X-2422346Y8984508D01* +G01X-2414455Y8964141D01* +G01X-2402957Y8945570D01* +G01X-2388241Y8929428D01* +G01X-2370811Y8916265D01* +G01X-2351258Y8906529D01* +G01X-2330249Y8900551D01* +G01X-2308500Y8898536D01* +G01X-2308500Y8898536D01* +G01X-2286751Y8900551D01* +G01X-2265742Y8906529D01* +G01X-2246189Y8916265D01* +G01X-2228759Y8929428D01* +G01X-2214044Y8945570D01* +G01X-2205421Y8959496D01* +G01X-529230Y8959496D01* +G01X-529230Y8959496D01* +G01X-527317Y8944967D01* +G01X-521710Y8931429D01* +G01X-512789Y8919803D01* +G01X-389878Y8796892D01* +G01X-394085Y8776457D01* +G01X-394639Y8755600D01* +G01X-391522Y8734970D01* +G01X-384831Y8715208D01* +G01X-374774Y8696928D01* +G01X-361664Y8680698D01* +G01X-345907Y8667021D01* +G01X-327994Y8656324D01* +G01X-308481Y8648938D01* +G01X-287975Y8645093D01* +G01X-267112Y8644909D01* +G01X-246540Y8648390D01* +G01X-226899Y8655430D01* +G01X-208800Y8665809D01* +G01X-192804Y8679204D01* +G01X-179409Y8695200D01* +G01X-169030Y8713299D01* +G01X-161991Y8732940D01* +G01X-158509Y8753511D01* +G01X-158694Y8774375D01* +G01X-162539Y8794881D01* +G01X-169924Y8814394D01* +G01X-180622Y8832307D01* +G01X-194298Y8848064D01* +G01X-210528Y8861174D01* +G01X-228809Y8871231D01* +G01X-248571Y8877922D01* +G01X-269200Y8881039D01* +G01X-290057Y8880485D01* +G01X-310493Y8876278D01* +G01X-416962Y8982747D01* +G01X-416962Y9027821D01* +G01X-394359Y9027821D01* +G01X-394359Y9005979D01* +G01X-390346Y8984508D01* +G01X-382455Y8964141D01* +G01X-370957Y8945570D01* +G01X-356241Y8929428D01* +G01X-338811Y8916265D01* +G01X-319258Y8906529D01* +G01X-298249Y8900551D01* +G01X-276500Y8898536D01* +G01X-276500Y8898536D01* +G01X-254751Y8900551D01* +G01X-233742Y8906529D01* +G01X-214189Y8916265D01* +G01X-196759Y8929428D01* +G01X-182044Y8945570D01* +G01X-170545Y8964141D01* +G01X-162655Y8984508D01* +G01X-158641Y9005979D01* +G01X-158641Y9027821D01* +G01X-162655Y9049292D01* +G01X-170545Y9069659D01* +G01X-182044Y9088230D01* +G01X-196759Y9104372D01* +G01X-214189Y9117535D01* +G01X-233742Y9127271D01* +G01X-254751Y9133249D01* +G01X-276500Y9135264D01* +G01X-298249Y9133249D01* +G01X-319258Y9127271D01* +G01X-338811Y9117535D01* +G01X-356241Y9104372D01* +G01X-370957Y9088230D01* +G01X-382455Y9069659D01* +G01X-390346Y9049292D01* +G01X-394359Y9027821D01* +G01X-416962Y9027821D01* +G01X-416962Y9281821D01* +G01X-394359Y9281821D01* +G01X-394359Y9259979D01* +G01X-390346Y9238508D01* +G01X-382455Y9218141D01* +G01X-370957Y9199570D01* +G01X-356241Y9183428D01* +G01X-338811Y9170265D01* +G01X-319258Y9160529D01* +G01X-298249Y9154551D01* +G01X-276500Y9152536D01* +G01X-276500Y9152536D01* +G01X-254751Y9154551D01* +G01X-233742Y9160529D01* +G01X-214189Y9170265D01* +G01X-196759Y9183428D01* +G01X-182044Y9199570D01* +G01X-170545Y9218141D01* +G01X-162655Y9238508D01* +G01X-158641Y9259979D01* +G01X-158641Y9281821D01* +G01X-162655Y9303292D01* +G01X-170545Y9323659D01* +G01X-182044Y9342230D01* +G01X-196759Y9358372D01* +G01X-214189Y9371535D01* +G01X-233742Y9381271D01* +G01X-254751Y9387249D01* +G01X-276500Y9389264D01* +G01X-298249Y9387249D01* +G01X-319258Y9381271D01* +G01X-338811Y9371535D01* +G01X-356241Y9358372D01* +G01X-370957Y9342230D01* +G01X-382455Y9323659D01* +G01X-390346Y9303292D01* +G01X-394359Y9281821D01* +G01X-416962Y9281821D01* +G01X-416962Y9535821D01* +G01X-394359Y9535821D01* +G01X-394359Y9513979D01* +G01X-390346Y9492508D01* +G01X-382455Y9472141D01* +G01X-370957Y9453570D01* +G01X-356241Y9437428D01* +G01X-338811Y9424265D01* +G01X-319258Y9414529D01* +G01X-298249Y9408551D01* +G01X-276500Y9406536D01* +G01X-276500Y9406536D01* +G01X-254751Y9408551D01* +G01X-233742Y9414529D01* +G01X-214189Y9424265D01* +G01X-196759Y9437428D01* +G01X-182044Y9453570D01* +G01X-170545Y9472141D01* +G01X-162655Y9492508D01* +G01X-158641Y9513979D01* +G01X-158641Y9535821D01* +G01X-162655Y9557292D01* +G01X-170545Y9577659D01* +G01X-182044Y9596230D01* +G01X-196759Y9612372D01* +G01X-214189Y9625535D01* +G01X-233742Y9635271D01* +G01X-254751Y9641249D01* +G01X-276500Y9643264D01* +G01X-298249Y9641249D01* +G01X-319258Y9635271D01* +G01X-338811Y9625535D01* +G01X-356241Y9612372D01* +G01X-370957Y9596230D01* +G01X-382455Y9577659D01* +G01X-390346Y9557292D01* +G01X-394359Y9535821D01* +G01X-416962Y9535821D01* +G01X-416962Y10231975D01* +G01X83083Y10732020D01* +G01X96229Y10717352D01* +G01X111868Y10705378D01* +G01X129459Y10696516D01* +G01X148389Y10691072D01* +G01X168000Y10689236D01* +G01X218800Y10689236D01* +G01X238216Y10691035D01* +G01X256970Y10696371D01* +G01X274425Y10705063D01* +G01X289985Y10716813D01* +G01X303122Y10731223D01* +G01X313386Y10747801D01* +G01X320430Y10765984D01* +G01X324013Y10785150D01* +G01X324013Y10804649D01* +G01X2602787Y10804649D01* +G01X2602787Y10785150D01* +G01X2606370Y10765984D01* +G01X2613413Y10747801D01* +G01X2623678Y10731223D01* +G01X2636815Y10716813D01* +G01X2652375Y10705063D01* +G01X2669830Y10696371D01* +G01X2688584Y10691035D01* +G01X2708000Y10689236D01* +G01X2758800Y10689236D01* +G01X2778216Y10691035D01* +G01X2796970Y10696371D01* +G01X2814425Y10705063D01* +G01X2829985Y10716813D01* +G01X2843122Y10731223D01* +G01X2853386Y10747801D01* +G01X2860430Y10765984D01* +G01X2864013Y10785150D01* +G01X2864013Y10804649D01* +G01X2860430Y10823816D01* +G01X2853386Y10841998D01* +G01X2843122Y10858577D01* +G01X2829985Y10872987D01* +G01X2814425Y10884737D01* +G01X2796970Y10893429D01* +G01X2778216Y10898765D01* +G01X2758800Y10900564D01* +G01X2758800Y10900564D01* +G01X2708000Y10900564D01* +G01X2688584Y10898765D01* +G01X2669830Y10893429D01* +G01X2652375Y10884737D01* +G01X2636815Y10872987D01* +G01X2623678Y10858577D01* +G01X2613413Y10841998D01* +G01X2606370Y10823816D01* +G01X2602787Y10804649D01* +G01X324013Y10804649D01* +G01X320430Y10823816D01* +G01X313386Y10841998D01* +G01X303122Y10858577D01* +G01X289985Y10872987D01* +G01X274425Y10884737D01* +G01X256970Y10893429D01* +G01X238216Y10898765D01* +G01X218800Y10900564D01* +G01X168000Y10900564D01* +G01X150250Y10899062D01* +G01X133005Y10894601D01* +G01X116754Y10887305D01* +G01X101960Y10877384D01* +G01X89042Y10865118D01* +G01X78369Y10850857D01* +G01X66400Y10850857D01* +G01X51871Y10848944D01* +G01X38333Y10843336D01* +G01X26707Y10834415D01* +G01X-512789Y10294919D01* +G01X-521710Y10283294D01* +G01X-527317Y10269755D01* +G01X-529230Y10255227D01* +G01X-529230Y8959496D01* +G01X-2205421Y8959496D01* +G01X-2202545Y8964141D01* +G01X-2194655Y8984508D01* +G01X-2190641Y9005979D01* +G01X-2190641Y9027821D01* +G01X-2194655Y9049292D01* +G01X-2202545Y9069659D01* +G01X-2214044Y9088230D01* +G01X-2228759Y9104372D01* +G01X-2246189Y9117535D01* +G01X-2265742Y9127271D01* +G01X-2286751Y9133249D01* +G01X-2308500Y9135264D01* +G01X-2330249Y9133249D01* +G01X-2351258Y9127271D01* +G01X-2370811Y9117535D01* +G01X-2388241Y9104372D01* +G01X-2402957Y9088230D01* +G01X-2414455Y9069659D01* +G01X-2422346Y9049292D01* +G01X-2426359Y9027821D01* +G01X-2536486Y9027821D01* +G01X-2536486Y10699650D01* +G01X-2426864Y10699650D01* +G01X-2425111Y10688583D01* +G01X-2420024Y10678599D01* +G01X-2412101Y10670676D01* +G01X-2402117Y10665589D01* +G01X-2391050Y10663836D01* +G01X-2225950Y10663836D01* +G01X-2225950Y10663836D01* +G01X-2214883Y10665589D01* +G01X-2204899Y10670676D01* +G01X-2196976Y10678599D01* +G01X-2191889Y10688583D01* +G01X-2190136Y10699650D01* +G01X-2190136Y10782200D01* +G01X-2172864Y10782200D01* +G01X-2170849Y10760451D01* +G01X-2164871Y10739442D01* +G01X-2155135Y10719889D01* +G01X-2141972Y10702459D01* +G01X-2125830Y10687743D01* +G01X-2107259Y10676245D01* +G01X-2086892Y10668354D01* +G01X-2065421Y10664341D01* +G01X-2043579Y10664341D01* +G01X-2022108Y10668354D01* +G01X-2001741Y10676245D01* +G01X-1983170Y10687743D01* +G01X-1967028Y10702459D01* +G01X-1953865Y10719889D01* +G01X-1944129Y10739442D01* +G01X-1938151Y10760451D01* +G01X-1936136Y10782200D01* +G01X-1918864Y10782200D01* +G01X-1916849Y10760451D01* +G01X-1910871Y10739442D01* +G01X-1901135Y10719889D01* +G01X-1887972Y10702459D01* +G01X-1871830Y10687743D01* +G01X-1853259Y10676245D01* +G01X-1832892Y10668354D01* +G01X-1811421Y10664341D01* +G01X-1789579Y10664341D01* +G01X-1768108Y10668354D01* +G01X-1747741Y10676245D01* +G01X-1729170Y10687743D01* +G01X-1713028Y10702459D01* +G01X-1699865Y10719889D01* +G01X-1690129Y10739442D01* +G01X-1684151Y10760451D01* +G01X-1682136Y10782200D01* +G01X-1664864Y10782200D01* +G01X-1662849Y10760451D01* +G01X-1656871Y10739442D01* +G01X-1647135Y10719889D01* +G01X-1633972Y10702459D01* +G01X-1617830Y10687743D01* +G01X-1599259Y10676245D01* +G01X-1578892Y10668354D01* +G01X-1557421Y10664341D01* +G01X-1535579Y10664341D01* +G01X-1514108Y10668354D01* +G01X-1493741Y10676245D01* +G01X-1475170Y10687743D01* +G01X-1459028Y10702459D01* +G01X-1445865Y10719889D01* +G01X-1436129Y10739442D01* +G01X-1430151Y10760451D01* +G01X-1428136Y10782200D01* +G01X-1430151Y10803949D01* +G01X-1436129Y10824958D01* +G01X-1445865Y10844511D01* +G01X-1459028Y10861941D01* +G01X-1475170Y10876656D01* +G01X-1493741Y10888155D01* +G01X-1514108Y10896045D01* +G01X-1535579Y10900059D01* +G01X-1557421Y10900059D01* +G01X-1578892Y10896045D01* +G01X-1599259Y10888155D01* +G01X-1617830Y10876656D01* +G01X-1633972Y10861941D01* +G01X-1647135Y10844511D01* +G01X-1656871Y10824958D01* +G01X-1662849Y10803949D01* +G01X-1664864Y10782200D01* +G01X-1664864Y10782200D01* +G01X-1682136Y10782200D01* +G01X-1684151Y10803949D01* +G01X-1690129Y10824958D01* +G01X-1699865Y10844511D01* +G01X-1713028Y10861941D01* +G01X-1729170Y10876656D01* +G01X-1747741Y10888155D01* +G01X-1768108Y10896045D01* +G01X-1789579Y10900059D01* +G01X-1811421Y10900059D01* +G01X-1832892Y10896045D01* +G01X-1853259Y10888155D01* +G01X-1871830Y10876656D01* +G01X-1887972Y10861941D01* +G01X-1901135Y10844511D01* +G01X-1910871Y10824958D01* +G01X-1916849Y10803949D01* +G01X-1918864Y10782200D01* +G01X-1918864Y10782200D01* +G01X-1936136Y10782200D01* +G01X-1938151Y10803949D01* +G01X-1944129Y10824958D01* +G01X-1953865Y10844511D01* +G01X-1967028Y10861941D01* +G01X-1983170Y10876656D01* +G01X-2001741Y10888155D01* +G01X-2022108Y10896045D01* +G01X-2043579Y10900059D01* +G01X-2065421Y10900059D01* +G01X-2086892Y10896045D01* +G01X-2107259Y10888155D01* +G01X-2125830Y10876656D01* +G01X-2141972Y10861941D01* +G01X-2155135Y10844511D01* +G01X-2164871Y10824958D01* +G01X-2170849Y10803949D01* +G01X-2172864Y10782200D01* +G01X-2172864Y10782200D01* +G01X-2190136Y10782200D01* +G01X-2190136Y10864750D01* +G01X-2191889Y10875817D01* +G01X-2196976Y10885801D01* +G01X-2204899Y10893724D01* +G01X-2214883Y10898811D01* +G01X-2225950Y10900564D01* +G01X-2391050Y10900564D01* +G01X-2402117Y10898811D01* +G01X-2412101Y10893724D01* +G01X-2420024Y10885801D01* +G01X-2425111Y10875817D01* +G01X-2426864Y10864750D01* +G01X-2426864Y10699650D01* +G01X-2536486Y10699650D01* +G01X-2536486Y10796000D01* +G01X-2534751Y10815828D01* +G01X-2529600Y10835054D01* +G01X-2521188Y10853093D01* +G01X-2509772Y10869397D01* +G01X-2495697Y10883471D01* +G01X-2479393Y10894888D01* +G01X-2461354Y10903300D01* +G01X-2442128Y10908451D01* +G01X-2422300Y10910186D01* +G01X0Y10910186D01* +G01X11067Y10911939D01* +G01X21051Y10917026D01* +G01X28974Y10924949D01* +G01X34061Y10934933D01* +G01X35814Y10946000D01* +G01X35814Y11058649D01* +G01X62787Y11058649D01* +G01X62787Y11039150D01* +G01X66370Y11019984D01* +G01X73413Y11001801D01* +G01X83678Y10985223D01* +G01X96815Y10970813D01* +G01X112375Y10959063D01* +G01X129830Y10950371D01* +G01X148584Y10945035D01* +G01X168000Y10943236D01* +G01X218800Y10943236D01* +G01X238216Y10945035D01* +G01X256970Y10950371D01* +G01X274425Y10959063D01* +G01X289985Y10970813D01* +G01X303122Y10985223D01* +G01X313386Y11001801D01* +G01X320430Y11019984D01* +G01X324013Y11039150D01* +G01X324013Y11058649D01* +G01X2602787Y11058649D01* +G01X2602787Y11039150D01* +G01X2606370Y11019984D01* +G01X2613413Y11001801D01* +G01X2623678Y10985223D01* +G01X2636815Y10970813D01* +G01X2652375Y10959063D01* +G01X2669830Y10950371D01* +G01X2688584Y10945035D01* +G01X2708000Y10943236D01* +G01X2758800Y10943236D01* +G01X2778216Y10945035D01* +G01X2796970Y10950371D01* +G01X2814425Y10959063D01* +G01X2829985Y10970813D01* +G01X2843122Y10985223D01* +G01X2853386Y11001801D01* +G01X2860430Y11019984D01* +G01X2864013Y11039150D01* +G01X2864013Y11058649D01* +G01X2860430Y11077816D01* +G01X2853386Y11095998D01* +G01X2843122Y11112577D01* +G01X2829985Y11126987D01* +G01X2814425Y11138737D01* +G01X2796970Y11147429D01* +G01X2778216Y11152765D01* +G01X2758800Y11154564D01* +G01X2758800Y11154564D01* +G01X2708000Y11154564D01* +G01X2688584Y11152765D01* +G01X2669830Y11147429D01* +G01X2652375Y11138737D01* +G01X2636815Y11126987D01* +G01X2623678Y11112577D01* +G01X2613413Y11095998D01* +G01X2606370Y11077816D01* +G01X2602787Y11058649D01* +G01X324013Y11058649D01* +G01X320430Y11077816D01* +G01X313386Y11095998D01* +G01X303122Y11112577D01* +G01X289985Y11126987D01* +G01X274425Y11138737D01* +G01X256970Y11147429D01* +G01X238216Y11152765D01* +G01X218800Y11154564D01* +G01X218800Y11154564D01* +G01X168000Y11154564D01* +G01X148584Y11152765D01* +G01X129830Y11147429D01* +G01X112375Y11138737D01* +G01X96815Y11126987D01* +G01X83678Y11112577D01* +G01X73413Y11095998D01* +G01X66370Y11077816D01* +G01X62787Y11058649D01* +G01X35814Y11058649D01* +G01X35814Y11312649D01* +G01X62787Y11312649D01* +G01X62787Y11293150D01* +G01X66370Y11273984D01* +G01X73413Y11255801D01* +G01X83678Y11239223D01* +G01X96815Y11224813D01* +G01X112375Y11213063D01* +G01X129830Y11204371D01* +G01X148584Y11199035D01* +G01X168000Y11197236D01* +G01X218800Y11197236D01* +G01X238216Y11199035D01* +G01X256970Y11204371D01* +G01X274425Y11213063D01* +G01X289985Y11224813D01* +G01X303122Y11239223D01* +G01X313386Y11255801D01* +G01X320430Y11273984D01* +G01X324013Y11293150D01* +G01X324013Y11312649D01* +G01X320430Y11331816D01* +G01X313386Y11349998D01* +G01X303122Y11366577D01* +G01X289985Y11380987D01* +G01X274425Y11392737D01* +G01X256970Y11401429D01* +G01X238216Y11406765D01* +G01X218800Y11408564D01* +G01X218800Y11408564D01* +G01X168000Y11408564D01* +G01X148584Y11406765D01* +G01X129830Y11401429D01* +G01X112375Y11392737D01* +G01X96815Y11380987D01* +G01X83678Y11366577D01* +G01X73413Y11349998D01* +G01X66370Y11331816D01* +G01X62787Y11312649D01* +G01X35814Y11312649D01* +G01X35814Y11566649D01* +G01X62787Y11566649D01* +G01X62787Y11547150D01* +G01X66370Y11527984D01* +G01X73413Y11509801D01* +G01X83678Y11493223D01* +G01X96815Y11478813D01* +G01X112375Y11467063D01* +G01X129830Y11458371D01* +G01X148584Y11453035D01* +G01X168000Y11451236D01* +G01X218800Y11451236D01* +G01X238216Y11453035D01* +G01X256970Y11458371D01* +G01X274425Y11467063D01* +G01X289985Y11478813D01* +G01X303122Y11493223D01* +G01X313386Y11509801D01* +G01X320430Y11527984D01* +G01X324013Y11547150D01* +G01X324013Y11566649D01* +G01X320430Y11585816D01* +G01X313386Y11603998D01* +G01X303122Y11620577D01* +G01X289985Y11634987D01* +G01X274425Y11646737D01* +G01X256970Y11655429D01* +G01X238216Y11660765D01* +G01X218800Y11662564D01* +G01X218800Y11662564D01* +G01X168000Y11662564D01* +G01X148584Y11660765D01* +G01X129830Y11655429D01* +G01X112375Y11646737D01* +G01X96815Y11634987D01* +G01X83678Y11620577D01* +G01X73413Y11603998D01* +G01X66370Y11585816D01* +G01X62787Y11566649D01* +G01X35814Y11566649D01* +G01X35814Y11820649D01* +G01X62787Y11820649D01* +G01X62787Y11801150D01* +G01X66370Y11781984D01* +G01X73413Y11763801D01* +G01X83678Y11747223D01* +G01X96815Y11732813D01* +G01X112375Y11721063D01* +G01X129830Y11712371D01* +G01X148584Y11707035D01* +G01X168000Y11705236D01* +G01X218800Y11705236D01* +G01X238216Y11707035D01* +G01X256970Y11712371D01* +G01X274425Y11721063D01* +G01X289985Y11732813D01* +G01X303122Y11747223D01* +G01X313386Y11763801D01* +G01X320430Y11781984D01* +G01X324013Y11801150D01* +G01X324013Y11820649D01* +G01X320430Y11839816D01* +G01X313386Y11857998D01* +G01X303122Y11874577D01* +G01X289985Y11888987D01* +G01X274425Y11900737D01* +G01X256970Y11909429D01* +G01X238216Y11914765D01* +G01X218800Y11916564D01* +G01X218800Y11916564D01* +G01X168000Y11916564D01* +G01X148584Y11914765D01* +G01X129830Y11909429D01* +G01X112375Y11900737D01* +G01X96815Y11888987D01* +G01X83678Y11874577D01* +G01X73413Y11857998D01* +G01X66370Y11839816D01* +G01X62787Y11820649D01* +G01X35814Y11820649D01* +G01X35814Y12074649D01* +G01X62787Y12074649D01* +G01X62787Y12055150D01* +G01X66370Y12035984D01* +G01X73413Y12017801D01* +G01X83678Y12001223D01* +G01X96815Y11986813D01* +G01X112375Y11975063D01* +G01X129830Y11966371D01* +G01X148584Y11961035D01* +G01X168000Y11959236D01* +G01X218800Y11959236D01* +G01X238216Y11961035D01* +G01X256970Y11966371D01* +G01X274425Y11975063D01* +G01X289985Y11986813D01* +G01X303122Y12001223D01* +G01X313386Y12017801D01* +G01X320430Y12035984D01* +G01X324013Y12055150D01* +G01X324013Y12074649D01* +G01X320430Y12093816D01* +G01X313386Y12111998D01* +G01X303122Y12128577D01* +G01X289985Y12142987D01* +G01X274425Y12154737D01* +G01X256970Y12163429D01* +G01X238216Y12168765D01* +G01X218800Y12170564D01* +G01X218800Y12170564D01* +G01X168000Y12170564D01* +G01X148584Y12168765D01* +G01X129830Y12163429D01* +G01X112375Y12154737D01* +G01X96815Y12142987D01* +G01X83678Y12128577D01* +G01X73413Y12111998D01* +G01X66370Y12093816D01* +G01X62787Y12074649D01* +G01X35814Y12074649D01* +G01X35814Y12328649D01* +G01X62787Y12328649D01* +G01X62787Y12309150D01* +G01X66370Y12289984D01* +G01X73413Y12271801D01* +G01X83678Y12255223D01* +G01X96815Y12240813D01* +G01X112375Y12229063D01* +G01X129830Y12220371D01* +G01X148584Y12215035D01* +G01X168000Y12213236D01* +G01X218800Y12213236D01* +G01X238216Y12215035D01* +G01X256970Y12220371D01* +G01X274425Y12229063D01* +G01X289985Y12240813D01* +G01X303122Y12255223D01* +G01X313386Y12271801D01* +G01X320430Y12289984D01* +G01X324013Y12309150D01* +G01X324013Y12328649D01* +G01X320430Y12347816D01* +G01X313386Y12365998D01* +G01X303122Y12382577D01* +G01X289985Y12396987D01* +G01X274425Y12408737D01* +G01X256970Y12417429D01* +G01X238216Y12422765D01* +G01X218800Y12424564D01* +G01X218800Y12424564D01* +G01X168000Y12424564D01* +G01X148584Y12422765D01* +G01X129830Y12417429D01* +G01X112375Y12408737D01* +G01X96815Y12396987D01* +G01X83678Y12382577D01* +G01X73413Y12365998D01* +G01X66370Y12347816D01* +G01X62787Y12328649D01* +G01X35814Y12328649D01* +G01X35814Y12642750D01* +G01X62336Y12642750D01* +G01X62336Y12503050D01* +G01X64089Y12491983D01* +G01X69176Y12481999D01* +G01X77099Y12474076D01* +G01X87083Y12468989D01* +G01X98150Y12467236D01* +G01X288650Y12467236D01* +G01X288650Y12467236D01* +G01X299717Y12468989D01* +G01X309701Y12474076D01* +G01X317624Y12481999D01* +G01X322711Y12491983D01* +G01X324464Y12503050D01* +G01X324464Y12642750D01* +G01X322711Y12653817D01* +G01X317624Y12663801D01* +G01X309701Y12671724D01* +G01X299717Y12676811D01* +G01X288650Y12678564D01* +G01X98150Y12678564D01* +G01X87083Y12676811D01* +G01X77099Y12671724D01* +G01X69176Y12663801D01* +G01X64089Y12653817D01* +G01X62336Y12642750D01* +G01X35814Y12642750D01* +G01X35814Y13350000D01* +G01X37549Y13369828D01* +G01X42700Y13389054D01* +G01X51112Y13407093D01* +G01X62528Y13423397D01* +G01X76603Y13437471D01* +G01X92907Y13448888D01* +G01X110946Y13457300D01* +G01X130172Y13462451D01* +G01X150000Y13464186D01* +G01X2750004Y13464183D01* +G01X2769832Y13462448D01* +G01X2789058Y13457296D01* +G01X2807097Y13448884D01* +G01X2823401Y13437468D01* +G01X2837475Y13423394D01* +G01X2848892Y13407090D01* +G01X2857304Y13389050D01* +G01X2862455Y13369825D01* +G01X2864190Y13349997D01* +G01X2864188Y12580525D01* +G01X2860925Y12600018D01* +G01X2854088Y12618562D01* +G01X2843918Y12635508D01* +G01X2830769Y12650265D01* +G01X2815103Y12662314D01* +G01X2797467Y12671235D01* +G01X2778477Y12676716D01* +G01X2758800Y12678564D01* +G01X2708000Y12678564D01* +G01X2688584Y12676765D01* +G01X2669830Y12671429D01* +G01X2652375Y12662737D01* +G01X2636815Y12650987D01* +G01X2623678Y12636577D01* +G01X2613413Y12619998D01* +G01X2606370Y12601816D01* +G01X2602787Y12582649D01* +G01X2602787Y12563150D01* +G01X2606370Y12543984D01* +G01X2613413Y12525801D01* +G01X2623678Y12509223D01* +G01X2636815Y12494813D01* +G01X2652375Y12483063D01* +G01X2669830Y12474371D01* +G01X2688584Y12469035D01* +G01X2708000Y12467236D01* +G01X2758800Y12467236D01* +G01X2778477Y12469084D01* +G01X2797467Y12474565D01* +G01X2815103Y12483486D01* +G01X2830769Y12495535D01* +G01X2843918Y12510291D01* +G01X2854088Y12527238D01* +G01X2860925Y12545782D01* +G01X2864188Y12565274D01* +G01X2864188Y12326532D01* +G01X2864188Y12326532D01* +G01X2860923Y12346023D01* +G01X2854086Y12364566D01* +G01X2843915Y12381512D01* +G01X2830767Y12396267D01* +G01X2815101Y12408315D01* +G01X2797465Y12417236D01* +G01X2778477Y12422716D01* +G01X2758800Y12424564D01* +G01X2708000Y12424564D01* +G01X2688584Y12422765D01* +G01X2669830Y12417429D01* +G01X2652375Y12408737D01* +G01X2636815Y12396987D01* +G01X2623678Y12382577D01* +G01X2613413Y12365998D01* +G01X2606370Y12347816D01* +G01X2602787Y12328649D01* +G01X2602787Y12309150D01* +G01X2606370Y12289984D01* +G01X2613413Y12271801D01* +G01X2623678Y12255223D01* +G01X2636815Y12240813D01* +G01X2652375Y12229063D01* +G01X2669830Y12220371D01* +G01X2688584Y12215035D01* +G01X2708000Y12213236D01* +G01X2758800Y12213236D01* +G01X2778477Y12215084D01* +G01X2797465Y12220564D01* +G01X2815101Y12229485D01* +G01X2830767Y12241533D01* +G01X2843915Y12256288D01* +G01X2854086Y12273233D01* +G01X2860923Y12291776D01* +G01X2864188Y12311268D01* +G37* +G54D10* +G01X2864188Y12311268D02* +G01X2864187Y12072538D01* +G03X2758800Y12170564I-105388J-7638D01* +G01X2708000Y12170564D01* +G03X2708000Y11959236I0J-105664D01* +G01X2758800Y11959236D01* +G03X2864187Y12057261I0J105664D01* +G01X2864187Y11818545D01* +G03X2758800Y11916564I-105387J-7645D01* +G01X2708000Y11916564D01* +G03X2708000Y11705236I0J-105664D01* +G01X2758800Y11705236D01* +G03X2864187Y11803255I0J105664D01* +G01X2864187Y11564551D01* +G03X2758800Y11662564I-105387J-7651D01* +G01X2708000Y11662564D01* +G03X2708000Y11451236I0J-105664D01* +G01X2758800Y11451236D01* +G03X2864187Y11549248I0J105664D01* +G01X2864186Y11310558D01* +G03X2758800Y11408564I-105386J-7658D01* +G01X2708000Y11408564D01* +G03X2708000Y11197236I0J-105664D01* +G01X2758800Y11197236D01* +G03X2864304Y11297093I0J105664D01* +G03X2900000Y11264186I35696J2907D01* +G01X4750000Y11264186D01* +G02X4864186Y11150000I0J-114186D01* +G01X4891892Y5650013D01* +G02X4777706Y5535830I-114186J2D01* +G01X2454000Y5535830D01* +G03X2418186Y5500016I0J-35814D01* +G01X2418186Y150000D01* +G02X2304000Y35814I-114186J0D01* +G01X150000Y35814D01* +G02X35814Y150000I0J114186D01* +G01X35814Y6646000D01* +G03X0Y6681814I-35814J0D01* +G01X-2422300Y6681814D01* +G02X-2536486Y6796000I0J114186D01* +G01X-2536486Y10796000D01* +G02X-2422300Y10910186I114186J0D01* +G01X0Y10910186D01* +G03X35814Y10946000I0J35814D01* +G01X35814Y13350000D01* +G02X150000Y13464186I114186J0D01* +G01X2750004Y13464183D01* +G02X2864190Y13349997I0J-114186D01* +G01X2864188Y12580525D01* +G03X2758800Y12678564I-105389J-7625D01* +G01X2708000Y12678564D01* +G03X2708000Y12467236I0J-105664D01* +G01X2758800Y12467236D01* +G03X2864188Y12565274I0J105664D01* +G01X2864188Y12326532D01* +G03X2758800Y12424564I-105388J-7632D01* +G01X2708000Y12424564D01* +G03X2708000Y12213236I0J-105664D01* +G01X2758800Y12213236D01* +G03X2864188Y12311268I0J105664D01* +G01X-2308500Y8898536D02* +G03X-2308500Y9135264I0J118364D01* +G03X-2308500Y8898536I0J-118364D01* +G01X-2308500Y8136536D02* +G03X-2308500Y8373264I0J118364D01* +G03X-2308500Y8136536I0J-118364D01* +G01X-2308500Y8390536D02* +G03X-2308500Y8627264I0J118364D01* +G03X-2308500Y8390536I0J-118364D01* +G01X-2308500Y8644536D02* +G03X-2308500Y8881264I0J118364D01* +G03X-2308500Y8644536I0J-118364D01* +G01X-2308500Y7628536D02* +G03X-2308500Y7865264I0J118364D01* +G03X-2308500Y7628536I0J-118364D01* +G01X-2308500Y7882536D02* +G03X-2308500Y8119264I0J118364D01* +G03X-2308500Y7882536I0J-118364D01* +G01X-2225950Y10663836D02* +G03X-2190136Y10699650I0J35814D01* +G01X-2190136Y10864750D01* +G03X-2225950Y10900564I-35814J0D01* +G01X-2391050Y10900564D01* +G03X-2426864Y10864750I0J-35814D01* +G01X-2426864Y10699650D01* +G03X-2391050Y10663836I35814J0D01* +G01X-2225950Y10663836D01* +G01X-2172864Y10782200D02* +G03X-1936136Y10782200I118364J0D01* +G03X-2172864Y10782200I-118364J0D01* +G01X-1918864Y10782200D02* +G03X-1682136Y10782200I118364J0D01* +G03X-1918864Y10782200I-118364J0D01* +G01X-1664864Y10782200D02* +G03X-1428136Y10782200I118364J0D01* +G03X-1664864Y10782200I-118364J0D01* +G01X-529230Y8959496D02* +G03X-512789Y8919803I56134J0D01* +G01X-389878Y8796892D01* +G03X-192804Y8679204I113378J-33992D01* +G03X-310493Y8876278I-83696J83696D01* +G01X-416962Y8982747D01* +G01X-416962Y10231975D01* +G01X83083Y10732020D01* +G03X168000Y10689236I84917J62880D01* +G01X218800Y10689236D01* +G03X218800Y10900564I0J105664D01* +G01X168000Y10900564D01* +G03X78369Y10850857I0J-105664D01* +G01X66400Y10850857D01* +G03X26707Y10834415I0J-56134D01* +G01X-512789Y10294919D01* +G03X-529230Y10255227I39693J-39693D01* +G01X-529230Y8959496D01* +G01X-148230Y8462555D02* +G01X-242508Y8368278D01* +G03X-360196Y8171204I-33992J-113378D01* +G03X-163122Y8288892I83696J83696D01* +G01X-52403Y8399611D01* +G03X-35962Y8439304I-39693J39693D01* +G01X-35962Y10231975D01* +G01X88057Y10355994D01* +G03X168000Y10181236I79943J-69094D01* +G01X218800Y10181236D01* +G03X218800Y10392564I0J105664D01* +G01X168000Y10392564D01* +G03X98905Y10366843I0J-105664D01* +G01X167301Y10435238D01* +G01X168000Y10435236D01* +G01X218800Y10435236D01* +G03X218800Y10646564I0J105664D01* +G01X168000Y10646564D01* +G03X71392Y10498100I0J-105664D01* +G01X-131789Y10294919D01* +G03X-148230Y10255227I39693J-39693D01* +G01X-148230Y8462555D01* +G01X-276500Y8390536D02* +G03X-276500Y8627264I0J118364D01* +G03X-276500Y8390536I0J-118364D01* +G01X-276500Y7628536D02* +G03X-276500Y7865264I0J118364D01* +G03X-276500Y7628536I0J-118364D01* +G01X-276500Y7882536D02* +G03X-276500Y8119264I0J118364D01* +G03X-276500Y7882536I0J-118364D01* +G01X-276500Y9406536D02* +G03X-276500Y9643264I0J118364D01* +G03X-276500Y9406536I0J-118364D01* +G01X-276500Y9152536D02* +G03X-276500Y9389264I0J118364D01* +G03X-276500Y9152536I0J-118364D01* +G01X-276500Y8898536D02* +G03X-276500Y9135264I0J118364D01* +G03X-276500Y8898536I0J-118364D01* +G01X2894690Y7064497D02* +G01X2571607Y6741414D01* +G01X1759111Y6741414D01* +G03X1697866Y6716045I0J-86614D01* +G01X1584406Y6602585D01* +G01X632845Y7554145D01* +G03X571600Y7579514I-61245J-61245D01* +G01X279322Y7579514D01* +G03X218800Y7598564I-60522J-86614D01* +G01X168000Y7598564D01* +G03X107478Y7579514I0J-105664D01* +G01X-195828Y7579514D01* +G03X-394864Y7492900I-80672J-86614D01* +G03X-195828Y7406286I118364J0D01* +G01X107478Y7406286D01* +G03X168000Y7387236I60522J86614D01* +G01X218800Y7387236D01* +G03X279322Y7406286I0J105664D01* +G01X535723Y7406286D01* +G01X1497792Y6444218D01* +G01X1497792Y6390214D01* +G01X1489406Y6390214D01* +G03X1453592Y6354400I0J-35814D01* +G01X1453592Y6116800D01* +G03X1489406Y6080986I35814J0D01* +G01X1497792Y6080986D01* +G01X1497792Y4307281D01* +G03X1452997Y4226788I79908J-97179D01* +G01X1192573Y3966364D01* +G01X1114150Y3966364D01* +G03X1078336Y3930550I0J-35814D01* +G01X1078336Y3765450D01* +G03X1114150Y3729636I35814J0D01* +G01X1279250Y3729636D01* +G03X1315064Y3765450I0J35814D01* +G01X1315064Y3843873D01* +G01X1557166Y4085975D01* +G03X1688124Y4149807I20534J124127D01* +G03X1671020Y4294486I-110425J60295D01* +G01X1671020Y6080986D01* +G01X1679405Y6080986D01* +G03X1715219Y6116800I0J35814D01* +G01X1715219Y6354400D01* +G03X1679405Y6390214I-35814J0D01* +G01X1671020Y6390214D01* +G01X1671020Y6444218D01* +G01X1794988Y6568186D01* +G01X2607484Y6568186D01* +G03X2668729Y6593555I0J86614D01* +G01X3042549Y6967374D01* +G03X3067918Y7028620I-61245J61245D01* +G01X3067918Y10691627D01* +G01X3129103Y10752813D01* +G01X3415327Y10752813D01* +G01X3462814Y10705326D01* +G03X3550000Y10522986I87186J-70326D01* +G03X3637186Y10705326I0J112014D01* +G01X3687477Y10755617D01* +G01X4418627Y10755617D01* +G01X4463386Y10710858D01* +G01X4463386Y10706029D01* +G03X4550000Y10522986I86614J-71029D01* +G03X4636614Y10706029I0J112014D01* +G01X4636614Y10746735D01* +G03X4611245Y10807980I-86614J0D01* +G01X4515749Y10903476D01* +G03X4454504Y10928845I-61245J-61245D01* +G01X3651600Y10928845D01* +G03X3590355Y10903476I0J-86614D01* +G01X3550000Y10863121D01* +G01X3512449Y10900672D01* +G03X3451204Y10926041I-61245J-61245D01* +G01X3093227Y10926041D01* +G03X3031981Y10900672I0J-86614D01* +G01X2920059Y10788749D01* +G03X2894690Y10727504I61245J-61245D01* +G01X2894690Y7064497D01* +G01X218800Y12170564D02* +G01X168000Y12170564D01* +G03X168000Y11959236I0J-105664D01* +G01X218800Y11959236D01* +G03X218800Y12170564I0J105664D01* +G01X218800Y12424564D02* +G01X168000Y12424564D01* +G03X168000Y12213236I0J-105664D01* +G01X218800Y12213236D01* +G03X218800Y12424564I0J105664D01* +G01X288650Y12467236D02* +G03X324464Y12503050I0J35814D01* +G01X324464Y12642750D01* +G03X288650Y12678564I-35814J0D01* +G01X98150Y12678564D01* +G03X62336Y12642750I0J-35814D01* +G01X62336Y12503050D01* +G03X98150Y12467236I35814J0D01* +G01X288650Y12467236D01* +G01X218800Y11408564D02* +G01X168000Y11408564D01* +G03X168000Y11197236I0J-105664D01* +G01X218800Y11197236D01* +G03X218800Y11408564I0J105664D01* +G01X218800Y11662564D02* +G01X168000Y11662564D01* +G03X168000Y11451236I0J-105664D01* +G01X218800Y11451236D01* +G03X218800Y11662564I0J105664D01* +G01X218800Y11916564D02* +G01X168000Y11916564D01* +G03X168000Y11705236I0J-105664D01* +G01X218800Y11705236D01* +G03X218800Y11916564I0J105664D01* +G01X218800Y11154564D02* +G01X168000Y11154564D01* +G03X168000Y10943236I0J-105664D01* +G01X218800Y10943236D01* +G03X218800Y11154564I0J105664D01* +G01X218800Y9884564D02* +G01X168000Y9884564D01* +G03X168000Y9673236I0J-105664D01* +G01X218800Y9673236D01* +G03X218800Y9884564I0J105664D01* +G01X218800Y10138564D02* +G01X168000Y10138564D01* +G03X168000Y9927236I0J-105664D01* +G01X218800Y9927236D01* +G03X218800Y10138564I0J105664D01* +G01X218800Y9122564D02* +G01X168000Y9122564D01* +G03X168000Y8911236I0J-105664D01* +G01X218800Y8911236D01* +G03X218800Y9122564I0J105664D01* +G01X218800Y9376564D02* +G01X168000Y9376564D01* +G03X168000Y9165236I0J-105664D01* +G01X218800Y9165236D01* +G03X218800Y9376564I0J105664D01* +G01X218800Y9630564D02* +G01X168000Y9630564D01* +G03X168000Y9419236I0J-105664D01* +G01X218800Y9419236D01* +G03X218800Y9630564I0J105664D01* +G01X218800Y8360564D02* +G01X168000Y8360564D01* +G03X168000Y8149236I0J-105664D01* +G01X218800Y8149236D01* +G03X218800Y8360564I0J105664D01* +G01X218800Y8614564D02* +G01X168000Y8614564D01* +G03X168000Y8403236I0J-105664D01* +G01X218800Y8403236D01* +G03X218800Y8614564I0J105664D01* +G01X218800Y8868564D02* +G01X168000Y8868564D01* +G03X168000Y8657236I0J-105664D01* +G01X218800Y8657236D01* +G03X218800Y8868564I0J105664D01* +G01X218800Y7852564D02* +G01X168000Y7852564D01* +G03X168000Y7641236I0J-105664D01* +G01X218800Y7641236D01* +G03X218800Y7852564I0J105664D01* +G01X218800Y8106564D02* +G01X168000Y8106564D01* +G03X168000Y7895236I0J-105664D01* +G01X218800Y7895236D01* +G03X218800Y8106564I0J105664D01* +G01X218800Y7344564D02* +G01X168000Y7344564D01* +G03X168000Y7133236I0J-105664D01* +G01X218800Y7133236D01* +G03X218800Y7344564I0J105664D01* +G01X358500Y684186D02* +G03X358500Y915814I0J115814D01* +G03X358500Y684186I0J-115814D01* +G01X358500Y430186D02* +G03X358500Y661814I0J115814D01* +G03X358500Y430186I0J-115814D01* +G01X358500Y2208186D02* +G03X358500Y2439814I0J115814D01* +G03X358500Y2208186I0J-115814D01* +G01X358500Y1954186D02* +G03X358500Y2185814I0J115814D01* +G03X358500Y1954186I0J-115814D01* +G01X358500Y1700186D02* +G03X358500Y1931814I0J115814D01* +G03X358500Y1700186I0J-115814D01* +G01X358500Y1446186D02* +G03X358500Y1677814I0J115814D01* +G03X358500Y1446186I0J-115814D01* +G01X358500Y1192186D02* +G03X358500Y1423814I0J115814D01* +G03X358500Y1192186I0J-115814D01* +G01X358500Y938186D02* +G03X358500Y1169814I0J115814D01* +G03X358500Y938186I0J-115814D01* +G01X358500Y3224186D02* +G03X358500Y3455814I0J115814D01* +G03X358500Y3224186I0J-115814D01* +G01X358500Y5002186D02* +G03X358500Y5233814I0J115814D01* +G03X358500Y5002186I0J-115814D01* +G01X358500Y5256186D02* +G03X358500Y5487814I0J115814D01* +G03X358500Y5256186I0J-115814D01* +G01X358500Y4748186D02* +G03X358500Y4979814I0J115814D01* +G03X358500Y4748186I0J-115814D01* +G01X358500Y4494186D02* +G03X358500Y4725814I0J115814D01* +G03X358500Y4494186I0J-115814D01* +G01X358500Y4240186D02* +G03X358500Y4471814I0J115814D01* +G03X358500Y4240186I0J-115814D01* +G01X358500Y3986186D02* +G03X358500Y4217814I0J115814D01* +G03X358500Y3986186I0J-115814D01* +G01X358500Y3732186D02* +G03X358500Y3963814I0J115814D01* +G03X358500Y3732186I0J-115814D01* +G01X358500Y3478186D02* +G03X358500Y3709814I0J115814D01* +G03X358500Y3478186I0J-115814D01* +G01X358500Y2462186D02* +G03X358500Y2693814I0J115814D01* +G03X358500Y2462186I0J-115814D01* +G01X708924Y3032954D02* +G01X703884Y3032954D01* +G03X612500Y3191664I-91384J53046D01* +G03X521116Y3032954I0J-105664D01* +G01X485540Y3032954D01* +G03X458688Y3027904I0J-73914D01* +G03X283471Y3174224I-100188J58096D01* +G03X399752Y2977782I75029J-88224D01* +G01X369281Y2947311D01* +G03X276607Y2750107I-10781J-115311D01* +G03X473811Y2842781I81893J81893D01* +G01X516156Y2885126D01* +G01X521163Y2885126D01* +G03X612500Y2726336I91337J-53126D01* +G03X703837Y2885126I0J105664D01* +G01X739540Y2885126D01* +G03X791805Y2906775I0J73914D01* +G01X1248965Y3363935D01* +G03X1270614Y3416200I-52265J52265D01* +G01X1270614Y3501551D01* +G03X1196700Y3712364I-73914J92449D01* +G03X1122786Y3501551I0J-118364D01* +G01X1122786Y3446816D01* +G01X708924Y3032954D01* +G01X728314Y626000D02* +G03X692500Y661814I-35814J0D01* +G01X532500Y661814D01* +G03X496686Y626000I0J-35814D01* +G01X496686Y466000D01* +G03X532500Y430186I35814J0D01* +G01X692500Y430186D01* +G03X728314Y466000I0J35814D01* +G01X728314Y626000D01* +G01X612500Y2462186D02* +G03X612500Y2693814I0J115814D01* +G03X612500Y2462186I0J-115814D01* +G01X612500Y2208186D02* +G03X612500Y2439814I0J115814D01* +G03X612500Y2208186I0J-115814D01* +G01X612500Y1954186D02* +G03X612500Y2185814I0J115814D01* +G03X612500Y1954186I0J-115814D01* +G01X612500Y1700186D02* +G03X612500Y1931814I0J115814D01* +G03X612500Y1700186I0J-115814D01* +G01X612500Y1446186D02* +G03X612500Y1677814I0J115814D01* +G03X612500Y1446186I0J-115814D01* +G01X612500Y1192186D02* +G03X612500Y1423814I0J115814D01* +G03X612500Y1192186I0J-115814D01* +G01X612500Y938186D02* +G03X612500Y1169814I0J115814D01* +G03X612500Y938186I0J-115814D01* +G01X612500Y684186D02* +G03X612500Y915814I0J115814D01* +G03X612500Y684186I0J-115814D01* +G01X612500Y5256186D02* +G03X612500Y5487814I0J115814D01* +G03X612500Y5256186I0J-115814D01* +G01X612500Y5002186D02* +G03X612500Y5233814I0J115814D01* +G03X612500Y5002186I0J-115814D01* +G01X612500Y4748186D02* +G03X612500Y4979814I0J115814D01* +G03X612500Y4748186I0J-115814D01* +G01X612500Y4494186D02* +G03X612500Y4725814I0J115814D01* +G03X612500Y4494186I0J-115814D01* +G01X612500Y4240186D02* +G03X612500Y4471814I0J115814D01* +G03X612500Y4240186I0J-115814D01* +G01X612500Y3986186D02* +G03X612500Y4217814I0J115814D01* +G03X612500Y3986186I0J-115814D01* +G01X612500Y3732186D02* +G03X612500Y3963814I0J115814D01* +G03X612500Y3732186I0J-115814D01* +G01X612500Y3478186D02* +G03X612500Y3709814I0J115814D01* +G03X612500Y3478186I0J-115814D01* +G01X612500Y3224186D02* +G03X612500Y3455814I0J115814D01* +G03X612500Y3224186I0J-115814D01* +G01X957178Y10008008D02* +G03X1193906Y10008008I118364J0D01* +G03X957178Y10008008I-118364J0D01* +G01X1158092Y9635644D02* +G03X1193906Y9671458I0J35814D01* +G01X1193906Y9836558D01* +G03X1158092Y9872372I-35814J0D01* +G01X992992Y9872372D01* +G03X957178Y9836558I0J-35814D01* +G01X957178Y9671458D01* +G03X992992Y9635644I35814J0D01* +G01X1158092Y9635644D01* +G01X1211178Y10008008D02* +G03X1447906Y10008008I118364J0D01* +G03X1211178Y10008008I-118364J0D01* +G01X1211178Y9754008D02* +G03X1447906Y9754008I118364J0D01* +G03X1211178Y9754008I-118364J0D01* +G01X1577700Y3465915D02* +G03X1577700Y3214288I0J-125814D01* +G03X1577700Y3465915I0J125814D01* +G01X1465178Y10008008D02* +G03X1701906Y10008008I118364J0D01* +G03X1465178Y10008008I-118364J0D01* +G01X1465178Y9754008D02* +G03X1701906Y9754008I118364J0D01* +G03X1465178Y9754008I-118364J0D01* +G01X1719178Y10008008D02* +G03X1955906Y10008008I118364J0D01* +G03X1719178Y10008008I-118364J0D01* +G01X1719178Y9754008D02* +G03X1955906Y9754008I118364J0D01* +G03X1719178Y9754008I-118364J0D01* +G01X1946000Y5002186D02* +G03X1946000Y5233814I0J115814D01* +G03X1946000Y5002186I0J-115814D01* +G01X1946000Y5256186D02* +G03X1946000Y5487814I0J115814D01* +G03X1946000Y5256186I0J-115814D01* +G01X1946000Y4748186D02* +G03X1946000Y4979814I0J115814D01* +G03X1946000Y4748186I0J-115814D01* +G01X1946000Y2716186D02* +G03X1946000Y2947814I0J115814D01* +G03X1946000Y2716186I0J-115814D01* +G01X1946000Y2970186D02* +G03X1946000Y3201814I0J115814D01* +G03X1946000Y2970186I0J-115814D01* +G01X1946000Y2462186D02* +G03X1946000Y2693814I0J115814D01* +G03X1946000Y2462186I0J-115814D01* +G01X1946000Y1954186D02* +G03X1946000Y2185814I0J115814D01* +G03X1946000Y1954186I0J-115814D01* +G01X1946000Y2208186D02* +G03X1946000Y2439814I0J115814D01* +G03X1946000Y2208186I0J-115814D01* +G01X1946000Y1700186D02* +G03X1946000Y1931814I0J115814D01* +G03X1946000Y1700186I0J-115814D01* +G01X1946000Y1192186D02* +G03X1946000Y1423814I0J115814D01* +G03X1946000Y1192186I0J-115814D01* +G01X1946000Y1446186D02* +G03X1946000Y1677814I0J115814D01* +G03X1946000Y1446186I0J-115814D01* +G01X1946000Y938186D02* +G03X1946000Y1169814I0J115814D01* +G03X1946000Y938186I0J-115814D01* +G01X1946000Y684186D02* +G03X1946000Y915814I0J115814D01* +G03X1946000Y684186I0J-115814D01* +G01X1946000Y3224186D02* +G03X1946000Y3455814I0J115814D01* +G03X1946000Y3224186I0J-115814D01* +G01X1946000Y3732186D02* +G03X1946000Y3963814I0J115814D01* +G03X1946000Y3732186I0J-115814D01* +G01X1946000Y4240186D02* +G03X1946000Y4471814I0J115814D01* +G03X1946000Y4240186I0J-115814D01* +G01X1946000Y4494186D02* +G03X1946000Y4725814I0J115814D01* +G03X1946000Y4494186I0J-115814D01* +G01X1946000Y3986186D02* +G03X1946000Y4217814I0J115814D01* +G03X1946000Y3986186I0J-115814D01* +G01X1946000Y430186D02* +G03X1946000Y661814I0J115814D01* +G03X1946000Y430186I0J-115814D01* +G01X1946000Y3478186D02* +G03X1946000Y3709814I0J115814D01* +G03X1946000Y3478186I0J-115814D01* +G01X1973178Y9754008D02* +G03X2209906Y9754008I118364J0D01* +G03X1973178Y9754008I-118364J0D01* +G01X1973178Y10008008D02* +G03X2209906Y10008008I118364J0D01* +G03X1973178Y10008008I-118364J0D01* +G01X2235208Y6354400D02* +G03X2199394Y6390214I-35814J0D01* +G01X2009395Y6390214D01* +G03X1973581Y6354400I0J-35814D01* +G01X1973581Y6116800D01* +G03X2009395Y6080986I35814J0D01* +G01X2199394Y6080986D01* +G03X2235208Y6116800I0J35814D01* +G01X2235208Y6354400D01* +G01X2200000Y5002186D02* +G03X2200000Y5233814I0J115814D01* +G03X2200000Y5002186I0J-115814D01* +G01X2200000Y5256186D02* +G03X2200000Y5487814I0J115814D01* +G03X2200000Y5256186I0J-115814D01* +G01X2200000Y4748186D02* +G03X2200000Y4979814I0J115814D01* +G03X2200000Y4748186I0J-115814D01* +G01X2200000Y2716186D02* +G03X2200000Y2947814I0J115814D01* +G03X2200000Y2716186I0J-115814D01* +G01X2200000Y2970186D02* +G03X2200000Y3201814I0J115814D01* +G03X2200000Y2970186I0J-115814D01* +G01X2200000Y2462186D02* +G03X2200000Y2693814I0J115814D01* +G03X2200000Y2462186I0J-115814D01* +G01X2200000Y1954186D02* +G03X2200000Y2185814I0J115814D01* +G03X2200000Y1954186I0J-115814D01* +G01X2200000Y2208186D02* +G03X2200000Y2439814I0J115814D01* +G03X2200000Y2208186I0J-115814D01* +G01X2200000Y1700186D02* +G03X2200000Y1931814I0J115814D01* +G03X2200000Y1700186I0J-115814D01* +G01X2200000Y1192186D02* +G03X2200000Y1423814I0J115814D01* +G03X2200000Y1192186I0J-115814D01* +G01X2200000Y1446186D02* +G03X2200000Y1677814I0J115814D01* +G03X2200000Y1446186I0J-115814D01* +G01X2200000Y938186D02* +G03X2200000Y1169814I0J115814D01* +G03X2200000Y938186I0J-115814D01* +G01X2200000Y3224186D02* +G03X2200000Y3455814I0J115814D01* +G03X2200000Y3224186I0J-115814D01* +G01X2200000Y3732186D02* +G03X2200000Y3963814I0J115814D01* +G03X2200000Y3732186I0J-115814D01* +G01X2200000Y4494186D02* +G03X2200000Y4725814I0J115814D01* +G03X2200000Y4494186I0J-115814D01* +G01X2200000Y4240186D02* +G03X2200000Y4471814I0J115814D01* +G03X2200000Y4240186I0J-115814D01* +G01X2200000Y3986186D02* +G03X2200000Y4217814I0J115814D01* +G03X2200000Y3986186I0J-115814D01* +G01X2200000Y3478186D02* +G03X2200000Y3709814I0J115814D01* +G03X2200000Y3478186I0J-115814D01* +G01X2315814Y626000D02* +G03X2280000Y661814I-35814J0D01* +G01X2120000Y661814D01* +G03X2084186Y626000I0J-35814D01* +G01X2084186Y466000D01* +G03X2120000Y430186I35814J0D01* +G01X2280000Y430186D01* +G03X2315814Y466000I0J35814D01* +G01X2315814Y626000D01* +G01X2200000Y684186D02* +G03X2200000Y915814I0J115814D01* +G03X2200000Y684186I0J-115814D01* +G01X2758800Y10392564D02* +G01X2708000Y10392564D01* +G03X2708000Y10181236I0J-105664D01* +G01X2758800Y10181236D01* +G03X2758800Y10392564I0J105664D01* +G01X2758800Y10138564D02* +G01X2708000Y10138564D01* +G03X2708000Y9927236I0J-105664D01* +G01X2758800Y9927236D01* +G03X2758800Y10138564I0J105664D01* +G01X2758800Y9884564D02* +G01X2708000Y9884564D01* +G03X2708000Y9673236I0J-105664D01* +G01X2758800Y9673236D01* +G03X2758800Y9884564I0J105664D01* +G01X2758800Y9122564D02* +G01X2708000Y9122564D01* +G03X2708000Y8911236I0J-105664D01* +G01X2758800Y8911236D01* +G03X2758800Y9122564I0J105664D01* +G01X2758800Y9376564D02* +G01X2708000Y9376564D01* +G03X2708000Y9165236I0J-105664D01* +G01X2758800Y9165236D01* +G03X2758800Y9376564I0J105664D01* +G01X2758800Y9630564D02* +G01X2708000Y9630564D01* +G03X2708000Y9419236I0J-105664D01* +G01X2758800Y9419236D01* +G03X2758800Y9630564I0J105664D01* +G01X2758800Y11154564D02* +G01X2708000Y11154564D01* +G03X2708000Y10943236I0J-105664D01* +G01X2758800Y10943236D01* +G03X2758800Y11154564I0J105664D01* +G01X2758800Y7598564D02* +G01X2708000Y7598564D01* +G03X2708000Y7387236I0J-105664D01* +G01X2758800Y7387236D01* +G03X2758800Y7598564I0J105664D01* +G01X2758800Y7344564D02* +G01X2708000Y7344564D01* +G03X2708000Y7133236I0J-105664D01* +G01X2758800Y7133236D01* +G03X2758800Y7344564I0J105664D01* +G01X2758800Y10646564D02* +G01X2708000Y10646564D01* +G03X2708000Y10435236I0J-105664D01* +G01X2758800Y10435236D01* +G03X2758800Y10646564I0J105664D01* +G01X2758800Y10900564D02* +G01X2708000Y10900564D01* +G03X2708000Y10689236I0J-105664D01* +G01X2758800Y10689236D01* +G03X2758800Y10900564I0J105664D01* +G01X2758800Y8868564D02* +G01X2708000Y8868564D01* +G03X2708000Y8657236I0J-105664D01* +G01X2758800Y8657236D01* +G03X2758800Y8868564I0J105664D01* +G01X2758800Y8614564D02* +G01X2708000Y8614564D01* +G03X2708000Y8403236I0J-105664D01* +G01X2758800Y8403236D01* +G03X2758800Y8614564I0J105664D01* +G01X2758800Y8360564D02* +G01X2708000Y8360564D01* +G03X2708000Y8149236I0J-105664D01* +G01X2758800Y8149236D01* +G03X2758800Y8360564I0J105664D01* +G01X2758800Y8106564D02* +G01X2708000Y8106564D01* +G03X2708000Y7895236I0J-105664D01* +G01X2758800Y7895236D01* +G03X2758800Y8106564I0J105664D01* +G01X2758800Y7852564D02* +G01X2708000Y7852564D01* +G03X2708000Y7641236I0J-105664D01* +G01X2758800Y7641236D01* +G03X2758800Y7852564I0J105664D01* +G01X3120407Y9268793D02* +G03X3103966Y9229100I39693J-39693D01* +G01X3103966Y6647430D01* +G03X3120407Y6607738I56134J0D01* +G01X3378491Y6349654D01* +G03X3418184Y6333213I39693J39693D01* +G01X3480853Y6333213D01* +G03X3575410Y6143652I94557J-71197D01* +G03X3669967Y6333213I0J118364D01* +G01X3678828Y6333213D01* +G01X3716032Y6296008D01* +G03X3913106Y6178320I113378J-33992D01* +G03X3795417Y6375394I-83696J83696D01* +G01X3741772Y6429039D01* +G03X3702079Y6445481I-39693J-39693D01* +G01X3670461Y6445481D01* +G03X3669967Y6587213I-95052J70535D01* +G01X3678828Y6587213D01* +G01X3716032Y6550008D01* +G03X3913106Y6432320I113378J-33992D01* +G03X3795417Y6629394I-83696J83696D01* +G01X3741772Y6683039D01* +G03X3702079Y6699481I-39693J-39693D01* +G01X3670461Y6699481D01* +G03X3590762Y6887380I-95052J70535D01* +G03X3465414Y6726302I-15352J-117364D01* +G01X3368634Y6823082D01* +G01X3368634Y9016149D01* +G01X3770297Y9417811D01* +G03X3786738Y9457504I-39693J39693D01* +G01X3786738Y9946396D01* +G03X3770297Y9986089I-56134J0D01* +G01X3658235Y10098150D01* +G03X3632777Y10202466I-108235J28850D01* +G01X3887148Y10202466D01* +G01X4187765Y9901850D01* +G03X4187765Y9844150I108235J-28850D01* +G01X4009407Y9665793D01* +G03X3992966Y9626100I39693J-39693D01* +G01X3992966Y8300651D01* +G01X3937008Y8244693D01* +G03X3815622Y8411574I-107598J49323D01* +G03X3736145Y8221134I13788J-117558D01* +G01X3700394Y8221134D01* +G03X3693774Y8220742I0J-56134D01* +G01X3693774Y8376566D01* +G03X3657960Y8412380I-35814J0D01* +G01X3492860Y8412380D01* +G03X3457046Y8376566I0J-35814D01* +G01X3457046Y8211466D01* +G03X3492860Y8175652I35814J0D01* +G01X3631660Y8175652D01* +G01X3609402Y8153394D01* +G03X3491714Y7956320I-33992J-113378D01* +G03X3688788Y8074008I83696J83696D01* +G01X3723645Y8108866D01* +G01X3733131Y8108866D01* +G03X3829410Y7921652I96279J-68850D01* +G03X3925689Y8108866I0J118364D01* +G01X3936700Y8108866D01* +G03X3976393Y8125307I0J56134D01* +G01X4088793Y8237707D01* +G03X4105234Y8277400I-39693J39693D01* +G01X4105234Y9602849D01* +G01X4267150Y9764765D01* +G03X4408014Y9873000I28850J108235D01* +G03X4267150Y9981235I-112014J0D01* +G01X3950093Y10298293D01* +G03X3910400Y10314734I-39693J-39693D01* +G01X3640310Y10314734D01* +G03X3542609Y10492770I-90310J66266D01* +G03X3469202Y10303419I7391J-111770D01* +G03X3463307Y10298293I33798J-44819D01* +G01X3386111Y10221097D01* +G03X3375367Y10206044I39693J-39693D01* +G03X3184054Y10130902I-79367J-79044D01* +G03X3369670Y10042621I111946J-3903D01* +G01X3369670Y10026055D01* +G01X3324850Y9981235D01* +G03X3216794Y9793794I-28850J-108235D01* +G03X3404235Y9901850I79206J79206D01* +G01X3465497Y9963111D01* +G03X3481938Y10002804I-39693J39693D01* +G01X3481938Y10038035D01* +G03X3578850Y10018765I68062J88965D01* +G01X3674470Y9923144D01* +G01X3674470Y9480755D01* +G01X3272807Y9079093D01* +G03X3256366Y9039400I39693J-39693D01* +G01X3256366Y6799830D01* +G03X3272807Y6760138I56134J0D01* +G01X3429291Y6603654D01* +G03X3468984Y6587213I39693J39693D01* +G01X3480853Y6587213D01* +G03X3480358Y6445481I94557J-71197D01* +G01X3441435Y6445481D01* +G01X3216234Y6670682D01* +G01X3216234Y9205849D01* +G01X3517371Y9506986D01* +G01X3626200Y9506986D01* +G03X3662014Y9542800I0J35814D01* +G01X3662014Y9695200D01* +G03X3626200Y9731014I-35814J0D01* +G01X3473800Y9731014D01* +G03X3437986Y9695200I0J-35814D01* +G01X3437986Y9586371D01* +G01X3120407Y9268793D01* +G01X3296000Y9506986D02* +G03X3296000Y9731014I0J112014D01* +G03X3296000Y9506986I0J-112014D01* +G01X3296000Y10522986D02* +G03X3296000Y10747014I0J112014D01* +G03X3296000Y10522986I0J-112014D01* +G01X3296000Y10268986D02* +G03X3296000Y10493014I0J112014D01* +G03X3296000Y10268986I0J-112014D01* +G01X3550000Y9760986D02* +G03X3550000Y9985014I0J112014D01* +G03X3550000Y9760986I0J-112014D01* +G01X3575410Y6126380D02* +G03X3575410Y5889652I0J-118364D01* +G03X3575410Y6126380I0J118364D01* +G01X3575410Y7904380D02* +G03X3575410Y7667652I0J-118364D01* +G03X3575410Y7904380I0J118364D01* +G01X3575410Y7142380D02* +G03X3575410Y6905652I0J-118364D01* +G03X3575410Y7142380I0J118364D01* +G01X3575410Y7650380D02* +G03X3575410Y7413652I0J-118364D01* +G03X3575410Y7650380I0J118364D01* +G01X3575410Y7396380D02* +G03X3575410Y7159652I0J-118364D01* +G03X3575410Y7396380I0J118364D01* +G01X3829410Y6126380D02* +G03X3829410Y5889652I0J-118364D01* +G03X3829410Y6126380I0J118364D01* +G01X3829410Y7396380D02* +G03X3829410Y7159652I0J-118364D01* +G03X3829410Y7396380I0J118364D01* +G01X4691466Y7711458D02* +G01X3863402Y6883394D01* +G03X3745714Y6686320I-33992J-113378D01* +G03X3942788Y6804008I83696J83696D01* +G01X4787293Y7648513D01* +G03X4803734Y7688206I-39693J39693D01* +G01X4803734Y10183400D01* +G03X4787293Y10223092I-56134J0D01* +G01X4658235Y10352150D01* +G03X4470794Y10460206I-108235J28850D01* +G03X4578850Y10272765I79206J-79206D01* +G01X4691466Y10160148D01* +G01X4691466Y7711458D01* +G01X3829410Y7142380D02* +G03X3829410Y6905652I0J-118364D01* +G03X3829410Y7142380I0J118364D01* +G01X3829410Y7650380D02* +G03X3829410Y7413652I0J-118364D01* +G03X3829410Y7650380I0J118364D01* +G01X3829410Y7904380D02* +G03X3829410Y7667652I0J-118364D01* +G03X3829410Y7904380I0J118364D01* +G01X4296000Y9506986D02* +G03X4296000Y9731014I0J112014D01* +G03X4296000Y9506986I0J-112014D01* +G01X4296000Y10014986D02* +G03X4296000Y10239014I0J112014D01* +G03X4296000Y10014986I0J-112014D01* +G01X4296000Y10522986D02* +G03X4296000Y10747014I0J112014D01* +G03X4296000Y10522986I0J-112014D01* +G01X4296000Y10268986D02* +G03X4296000Y10493014I0J112014D01* +G03X4296000Y10268986I0J-112014D01* +G01X4550000Y9760986D02* +G03X4550000Y9985014I0J112014D01* +G03X4550000Y9760986I0J-112014D01* +G01X4662014Y9695200D02* +G03X4626200Y9731014I-35814J0D01* +G01X4473800Y9731014D01* +G03X4437986Y9695200I0J-35814D01* +G01X4437986Y9542800D01* +G03X4473800Y9506986I35814J0D01* +G01X4626200Y9506986D01* +G03X4662014Y9542800I0J35814D01* +G01X4662014Y9695200D01* +G01X4550000Y10014986D02* +G03X4550000Y10239014I0J112014D01* +G03X4550000Y10014986I0J-112014D01* +G54D11* +G01X612500Y2832000D02* +G01X612500Y2736496D01* +G01X612500Y2832000D02* +G01X516996Y2832000D01* +G01X612500Y2832000D02* +G01X708004Y2832000D01* +G01X358500Y3086000D02* +G01X358500Y2980346D01* +G01X358500Y3086000D02* +G01X358500Y3191654D01* +G01X358500Y3086000D02* +G01X252846Y3086000D01* +G01X358500Y3086000D02* +G01X464154Y3086000D01* +G01X358500Y3340000D02* +G01X358500Y3234346D01* +G01X358500Y3340000D02* +G01X358500Y3445654D01* +G01X358500Y3340000D02* +G01X252846Y3340000D01* +G01X358500Y3340000D02* +G01X464154Y3340000D01* +G01X358500Y3594000D02* +G01X358500Y3488346D01* +G01X358500Y3594000D02* +G01X358500Y3699654D01* +G01X358500Y3594000D02* +G01X252846Y3594000D01* +G01X358500Y3594000D02* +G01X464154Y3594000D01* +G01X358500Y4102000D02* +G01X358500Y3996346D01* +G01X358500Y4102000D02* +G01X358500Y4207654D01* +G01X358500Y4102000D02* +G01X252846Y4102000D01* +G01X358500Y4102000D02* +G01X464154Y4102000D01* +G01X1946000Y546000D02* +G01X1946000Y440346D01* +G01X1946000Y546000D02* +G01X1946000Y651654D01* +G01X1946000Y546000D02* +G01X1840346Y546000D01* +G01X1946000Y546000D02* +G01X2051654Y546000D01* +G01X1946000Y3086000D02* +G01X1946000Y2980346D01* +G01X1946000Y3086000D02* +G01X1946000Y3191654D01* +G01X1946000Y3086000D02* +G01X1840346Y3086000D01* +G01X1946000Y3086000D02* +G01X2051654Y3086000D01* +G01X1946000Y5372000D02* +G01X1946000Y5266346D01* +G01X1946000Y5372000D02* +G01X1946000Y5477654D01* +G01X1946000Y5372000D02* +G01X1840346Y5372000D01* +G01X1946000Y5372000D02* +G01X2051654Y5372000D01* +G01X1946000Y4102000D02* +G01X1946000Y3996346D01* +G01X1946000Y4102000D02* +G01X1946000Y4207654D01* +G01X1946000Y4102000D02* +G01X1840346Y4102000D01* +G01X1946000Y4102000D02* +G01X2051654Y4102000D01* +G01X1946000Y3594000D02* +G01X1946000Y3488346D01* +G01X1946000Y3594000D02* +G01X1946000Y3699654D01* +G01X1946000Y3594000D02* +G01X1840346Y3594000D01* +G01X1946000Y3594000D02* +G01X2051654Y3594000D01* +G01X1946000Y3340000D02* +G01X1946000Y3234346D01* +G01X1946000Y3340000D02* +G01X1946000Y3445654D01* +G01X1946000Y3340000D02* +G01X1840346Y3340000D01* +G01X1946000Y3340000D02* +G01X2051654Y3340000D01* +G01X2200000Y2832000D02* +G01X2200000Y2726346D01* +G01X2200000Y2832000D02* +G01X2200000Y2937654D01* +G01X2200000Y2832000D02* +G01X2094346Y2832000D01* +G01X2200000Y2832000D02* +G01X2305654Y2832000D01* +G01X358500Y5372000D02* +G01X358500Y5266346D01* +G01X358500Y5372000D02* +G01X358500Y5477654D01* +G01X358500Y5372000D02* +G01X252846Y5372000D01* +G01X358500Y5372000D02* +G01X464154Y5372000D01* +G01X3575410Y6516016D02* +G01X3683614Y6516016D01* +G01X3575410Y6516016D02* +G01X3467206Y6516016D01* +G01X2733400Y7238900D02* +G01X2612496Y7238900D01* +G01X2733400Y7238900D02* +G01X2854304Y7238900D01* +G01X2733400Y7238900D02* +G01X2733400Y7334404D01* +G01X2733400Y7238900D02* +G01X2733400Y7143396D01* +G01X-276500Y8000900D02* +G01X-276500Y7892696D01* +G01X-276500Y8000900D02* +G01X-276500Y8109104D01* +G01X-276500Y8000900D02* +G01X-384704Y8000900D01* +G01X-276500Y8000900D02* +G01X-168296Y8000900D01* +G01X2091542Y10008008D02* +G01X1983338Y10008008D01* +G01X2091542Y10008008D02* +G01X2199746Y10008008D01* +G01X2091542Y10008008D02* +G01X2091542Y10116212D01* +G01X2091542Y10008008D02* +G01X2091542Y9899804D01* +G01X1075542Y10008008D02* +G01X967338Y10008008D01* +G01X1075542Y10008008D02* +G01X1183746Y10008008D01* +G01X1075542Y10008008D02* +G01X1075542Y10116212D01* +G01X1075542Y10008008D02* +G01X1075542Y9899804D01* +G01X3296000Y10127000D02* +G01X3296000Y10025146D01* +G01X3296000Y10127000D02* +G01X3296000Y10228854D01* +G01X3296000Y10127000D02* +G01X3194146Y10127000D01* +G01X2733400Y7492900D02* +G01X2612496Y7492900D01* +G01X2733400Y7492900D02* +G01X2854304Y7492900D01* +G01X2733400Y7492900D02* +G01X2733400Y7588404D01* +G01X2733400Y7492900D02* +G01X2733400Y7397396D01* +G01X4296000Y10127000D02* +G01X4296000Y10025146D01* +G01X4296000Y10127000D02* +G01X4296000Y10228854D01* +G01X4296000Y10127000D02* +G01X4194146Y10127000D01* +G01X4296000Y10127000D02* +G01X4397854Y10127000D01* +G01X2733400Y12572900D02* +G01X2612496Y12572900D01* +G01X2733400Y12572900D02* +G01X2733400Y12668404D01* +G01X2733400Y12572900D02* +G01X2733400Y12477396D01* +G01X193400Y7238900D02* +G01X72496Y7238900D01* +G01X193400Y7238900D02* +G01X314304Y7238900D01* +G01X193400Y7238900D02* +G01X193400Y7334404D01* +G01X193400Y7238900D02* +G01X193400Y7143396D01* +G01X2104394Y6235600D02* +G01X2225048Y6235600D01* +G01X2104394Y6235600D02* +G01X1983741Y6235600D01* +G01X2104394Y6235600D02* +G01X2104394Y6091146D01* +G01X2104394Y6235600D02* +G01X2104394Y6380054D01* +G04 Copper End* + +G04 Pad Start* +G54D12* +G01X1196700Y3594000D03* +G54D13* +G01X1196700Y3848000D03* +G54D14* +G01X2733400Y12572900D03* +G01X2733400Y12318900D03* +G01X2733400Y12064900D03* +G01X2733400Y11810900D03* +G01X2733400Y11556900D03* +G01X2733400Y11302900D03* +G01X2733400Y11048900D03* +G01X2733400Y10794900D03* +G01X2733400Y10540900D03* +G01X2733400Y10286900D03* +G01X2733400Y10032900D03* +G01X2733400Y9778900D03* +G01X2733400Y9524900D03* +G01X2733400Y9270900D03* +G01X2733400Y9016900D03* +G01X2733400Y8762900D03* +G01X2733400Y8508900D03* +G01X2733400Y8254900D03* +G01X2733400Y8000900D03* +G01X2733400Y7746900D03* +G01X2733400Y7492900D03* +G01X2733400Y7238900D03* +G01X193400Y7238900D03* +G01X193400Y7492900D03* +G01X193400Y7746900D03* +G01X193400Y8000900D03* +G01X193400Y8254900D03* +G01X193400Y8508900D03* +G01X193400Y8762900D03* +G01X193400Y9016900D03* +G01X193400Y9270900D03* +G01X193400Y9524900D03* +G01X193400Y9778900D03* +G01X193400Y10032900D03* +G01X193400Y10286900D03* +G01X193400Y10540900D03* +G01X193400Y10794900D03* +G01X193400Y11048900D03* +G01X193400Y11302900D03* +G01X193400Y11556900D03* +G01X193400Y11810900D03* +G01X193400Y12064900D03* +G01X193400Y12318900D03* +G54D16* +G01X193400Y12572900D03* +G54D12* +G01X-276500Y7492900D03* +G01X-276500Y7746900D03* +G01X-276500Y8000900D03* +G01X-276500Y8254900D03* +G01X-276500Y8508900D03* +G01X-276500Y8762900D03* +G01X-276500Y9016900D03* +G01X-276500Y9270900D03* +G01X-276500Y9524900D03* +G01X-2308500Y9016900D03* +G01X-2308500Y8762900D03* +G01X-2308500Y8508900D03* +G01X-2308500Y8254900D03* +G01X-2308500Y8000900D03* +G01X-2308500Y7746900D03* +G54D17* +G01X1946000Y5372000D03* +G01X2200000Y5372000D03* +G01X1946000Y5118000D03* +G01X2200000Y5118000D03* +G01X1946000Y4864000D03* +G01X2200000Y4864000D03* +G01X1946000Y4610000D03* +G01X2200000Y4610000D03* +G01X1946000Y4356000D03* +G01X2200000Y4356000D03* +G01X1946000Y4102000D03* +G01X2200000Y4102000D03* +G01X1946000Y3848000D03* +G01X2200000Y3848000D03* +G01X1946000Y3594000D03* +G01X2200000Y3594000D03* +G01X1946000Y3340000D03* +G01X2200000Y3340000D03* +G01X1946000Y3086000D03* +G01X2200000Y3086000D03* +G01X1946000Y2832000D03* +G01X2200000Y2832000D03* +G01X1946000Y2578000D03* +G01X2200000Y2578000D03* +G01X1946000Y2324000D03* +G01X2200000Y2324000D03* +G01X1946000Y2070000D03* +G01X2200000Y2070000D03* +G01X1946000Y1816000D03* +G01X2200000Y1816000D03* +G01X1946000Y1562000D03* +G01X2200000Y1562000D03* +G01X1946000Y1308000D03* +G01X2200000Y1308000D03* +G01X1946000Y1054000D03* +G01X2200000Y1054000D03* +G01X1946000Y800000D03* +G01X2200000Y800000D03* +G01X1946000Y546000D03* +G54D18* +G01X2200000Y546000D03* +G01X612500Y546000D03* +G54D17* +G01X358500Y546000D03* +G01X612500Y800000D03* +G01X358500Y800000D03* +G01X612500Y1054000D03* +G01X358500Y1054000D03* +G01X612500Y1308000D03* +G01X358500Y1308000D03* +G01X612500Y1562000D03* +G01X358500Y1562000D03* +G01X612500Y1816000D03* +G01X358500Y1816000D03* +G01X612500Y2070000D03* +G01X358500Y2070000D03* +G01X612500Y2324000D03* +G01X358500Y2324000D03* +G01X612500Y2578000D03* +G01X358500Y2578000D03* +G54D19* +G01X612500Y2832000D03* +G54D17* +G01X358500Y2832000D03* +G54D19* +G01X612500Y3086000D03* +G54D17* +G01X358500Y3086000D03* +G01X612500Y3340000D03* +G01X358500Y3340000D03* +G01X612500Y3594000D03* +G01X358500Y3594000D03* +G01X612500Y3848000D03* +G01X358500Y3848000D03* +G01X612500Y4102000D03* +G01X358500Y4102000D03* +G01X612500Y4356000D03* +G01X358500Y4356000D03* +G01X612500Y4610000D03* +G01X358500Y4610000D03* +G01X612500Y4864000D03* +G01X358500Y4864000D03* +G01X612500Y5118000D03* +G01X358500Y5118000D03* +G01X612500Y5372000D03* +G01X358500Y5372000D03* +G54D12* +G01X3829410Y6008016D03* +G01X3575410Y6008016D03* +G01X3829410Y6262016D03* +G01X3575410Y6262016D03* +G01X3829410Y6516016D03* +G01X3575410Y6516016D03* +G01X3829410Y6770016D03* +G01X3575410Y6770016D03* +G01X3829410Y7024016D03* +G01X3575410Y7024016D03* +G01X3829410Y7278016D03* +G01X3575410Y7278016D03* +G01X3829410Y7532016D03* +G01X3575410Y7532016D03* +G01X3829410Y7786016D03* +G01X3575410Y7786016D03* +G01X3829410Y8040016D03* +G01X3575410Y8040016D03* +G01X3829410Y8294016D03* +G54D13* +G01X3575410Y8294016D03* +G54D20* +G01X3550000Y9619000D03* +G54D21* +G01X3296000Y9619000D03* +G01X3550000Y9873000D03* +G01X3296000Y9873000D03* +G01X3550000Y10127000D03* +G01X3296000Y10127000D03* +G01X3550000Y10381000D03* +G01X3296000Y10381000D03* +G01X3550000Y10635000D03* +G01X3296000Y10635000D03* +G54D12* +G01X2091542Y10008008D03* +G01X2091542Y9754008D03* +G01X1837542Y10008008D03* +G01X1837542Y9754008D03* +G01X1583542Y10008008D03* +G01X1583542Y9754008D03* +G01X1329542Y10008008D03* +G01X1329542Y9754008D03* +G01X1075542Y10008008D03* +G54D13* +G01X1075542Y9754008D03* +G54D20* +G01X4550000Y9619000D03* +G54D21* +G01X4296000Y9619000D03* +G01X4550000Y9873000D03* +G01X4296000Y9873000D03* +G01X4550000Y10127000D03* +G01X4296000Y10127000D03* +G01X4550000Y10381000D03* +G01X4296000Y10381000D03* +G01X4550000Y10635000D03* +G01X4296000Y10635000D03* +G54D13* +G01X-2308500Y10782200D03* +G54D12* +G01X-2054500Y10782200D03* +G01X-1800500Y10782200D03* +G01X-1546500Y10782200D03* +G54D22* +G01X1584406Y6235600D03* +G01X2104394Y6235600D03* +G54D23* +G01X1577700Y4210102D03* +G01X1577700Y3340102D03* +G04 Pad End* + +G04 Track Start* +G54D24* +G01X1558802Y4210102D02* +G01X1577700Y4210102D01* +G54D25* +G01X1196700Y3594000D02* +G01X1196700Y3416200D01* +G01X739540Y2959040D01* +G01X485540Y2959040D01* +G01X358500Y2832000D01* +G54D26* +G01X3829410Y6516016D02* +G01X3702079Y6643347D01* +G01X3468984Y6643347D01* +G01X3418184Y6389347D02* +G01X3702079Y6389347D01* +G01X3829410Y6262016D01* +G54D24* +G01X1196700Y3848000D02* +G01X1558802Y4210102D01* +G01X-276500Y7492900D02* +G01X193400Y7492900D01* +G54D26* +G01X-276500Y8762900D02* +G01X-473096Y8959496D01* +G01X-473096Y10255227D01* +G01X66400Y10794723D01* +G01X193400Y10794723D01* +G01X-276500Y8254900D02* +G01X-92096Y8439304D01* +G01X-92096Y10255227D01* +G01X193400Y10540723D01* +G01X3296000Y9873000D02* +G01X3425804Y10002804D01* +G01X3730604Y9946396D02* +G01X3550000Y10127000D01* +G01X3910400Y10258600D02* +G01X4296000Y9873000D01* +G01X3425804Y10002804D02* +G01X3425804Y10181404D01* +G01X3503000Y10258600D01* +G01X3910400Y10258600D01* +G01X3730604Y9457504D02* +G01X3730604Y9946396D01* +G01X3550000Y9619000D02* +G01X3160100Y9229100D01* +G01X3160100Y6647430D01* +G01X3418184Y6389347D01* +G01X3468984Y6643347D02* +G01X3312500Y6799830D01* +G01X3312500Y9039400D01* +G01X3730604Y9457504D01* +G54D24* +G01X3451204Y10839427D02* +G01X3550000Y10740631D01* +G01X3550000Y10635000D01* +G01X2981304Y10727504D02* +G01X3093227Y10839427D01* +G01X3451204Y10839427D01* +G01X3550000Y10740631D02* +G01X3651600Y10842231D01* +G01X4454504Y10842231D01* +G01X4550000Y10746735D01* +G01X4550000Y10635000D01* +G54D26* +G01X4049100Y8277400D02* +G01X4049100Y9626100D01* +G01X4296000Y9873000D01* +G01X3575410Y8040016D02* +G01X3700394Y8165000D01* +G01X3936700Y8165000D01* +G01X4049100Y8277400D01* +G01X4550000Y10381000D02* +G01X4747600Y10183400D01* +G01X4747600Y7688206D01* +G01X3829410Y6770016D01* +G54D24* +G01X1577700Y4210102D02* +G01X1584406Y4216808D01* +G01X1584406Y6235600D01* +G01X2981304Y7028620D02* +G01X2981304Y10727504D01* +G01X1584406Y6235600D02* +G01X1584406Y6480094D01* +G01X571600Y7492900D01* +G01X193400Y7492900D01* +G01X1584406Y6480094D02* +G01X1759111Y6654800D01* +G01X2607484Y6654800D01* +G01X2981304Y7028620D01* +G04 Track End* + +M02* + diff --git a/hardware/gerber/Gerber_TopPasteMaskLayer.GTP b/hardware/gerber/Gerber_TopPasteMaskLayer.GTP new file mode 100644 index 0000000..9b57141 --- /dev/null +++ b/hardware/gerber/Gerber_TopPasteMaskLayer.GTP @@ -0,0 +1,25 @@ +G04 Layer: TopPasteMaskLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%ADD10R,1.9X2.37599*% +%ADD11C,0.8733*% +G75* + + +G04 Pad Start* +G54D10* +G01X1584406Y6235600D03* +G01X2104394Y6235600D03* +G04 Pad End* + +M02* + diff --git a/hardware/gerber/Gerber_TopSilkscreenLayer.GTO b/hardware/gerber/Gerber_TopSilkscreenLayer.GTO new file mode 100644 index 0000000..e889f30 --- /dev/null +++ b/hardware/gerber/Gerber_TopSilkscreenLayer.GTO @@ -0,0 +1,16753 @@ +G04 Layer: TopSilkscreenLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%ADD10C,0.1524*% +%ADD11C,0.2032*% +%ADD12C,0.15001*% +%ADD13C,0.254*% +%ADD14C,0.5792*% +G75* + + +G04 Image Start* +G36* +G01X1463742Y7640471D02* +G01X1035978Y7640287D01* +G01X1034341Y7641359D01* +G01X1032705Y7642432D01* +G01X1032199Y7645577D01* +G01X1031692Y7648722D01* +G01X1030759Y7650199D01* +G01X1029825Y7651677D01* +G01X1028790Y7656788D01* +G01X1026141Y7664121D01* +G01X1025237Y7666688D01* +G01X1024334Y7669255D01* +G01X1022367Y7675855D01* +G01X1021107Y7679521D01* +G01X1019846Y7683188D01* +G01X1018593Y7686855D01* +G01X1017341Y7690521D01* +G01X1015534Y7695655D01* +G01X1014551Y7698955D01* +G01X1013567Y7702255D01* +G01X1012307Y7705921D01* +G01X1011046Y7709588D01* +G01X1008541Y7716921D01* +G01X1006734Y7722054D01* +G01X1004767Y7728655D01* +G01X1003515Y7732321D01* +G01X1002262Y7735987D01* +G01X1000914Y7739423D01* +G01X999566Y7742859D01* +G01X999566Y7745578D01* +G01X998100Y7748454D01* +G01X996633Y7751331D01* +G01X996633Y7754378D01* +G01X995166Y7757254D01* +G01X993700Y7760131D01* +G01X993700Y7763177D01* +G01X992233Y7766054D01* +G01X990766Y7768931D01* +G01X990766Y7771977D01* +G01X989299Y7774854D01* +G01X987833Y7777731D01* +G01X987833Y7781092D01* +G01X986366Y7783829D01* +G01X984899Y7786565D01* +G01X984899Y7789893D01* +G01X983433Y7792629D01* +G01X981966Y7795365D01* +G01X981966Y7798692D01* +G01X980500Y7801429D01* +G01X979033Y7804166D01* +G01X979033Y7807492D01* +G01X977566Y7810229D01* +G01X976100Y7812965D01* +G01X976100Y7816292D01* +G01X974633Y7819029D01* +G01X973167Y7821765D01* +G01X973167Y7825092D01* +G01X971700Y7827829D01* +G01X970233Y7830565D01* +G01X970233Y7834293D01* +G01X968154Y7837261D01* +G01X967645Y7840158D01* +G01X967135Y7843053D01* +G01X966171Y7844596D01* +G01X965206Y7846139D01* +G01X964202Y7851854D01* +G01X963237Y7853396D01* +G01X962273Y7854939D01* +G01X961771Y7857796D01* +G01X961269Y7860653D01* +G01X960304Y7862196D01* +G01X959339Y7863739D01* +G01X958837Y7866596D01* +G01X958335Y7869453D01* +G01X957371Y7870996D01* +G01X956406Y7872539D01* +G01X955904Y7875396D01* +G01X955402Y7878253D01* +G01X953473Y7881339D01* +G01X952970Y7884196D01* +G01X952468Y7887053D01* +G01X951547Y7888530D01* +G01X950625Y7890008D01* +G01X949850Y7893297D01* +G01X949075Y7896586D01* +G01X946512Y7903919D01* +G01X945260Y7907586D01* +G01X944007Y7911253D01* +G01X943104Y7913819D01* +G01X942201Y7916386D01* +G01X940234Y7922986D01* +G01X937713Y7930319D01* +G01X936460Y7933986D01* +G01X935208Y7937653D01* +G01X934304Y7940219D01* +G01X933401Y7942786D01* +G01X932417Y7946085D01* +G01X931434Y7949385D01* +G01X930173Y7953053D01* +G01X928913Y7956719D01* +G01X927660Y7960385D01* +G01X926408Y7964052D01* +G01X924601Y7969185D01* +G01X922633Y7975785D01* +G01X921381Y7979452D01* +G01X920128Y7983119D01* +G01X917433Y7989991D01* +G01X917408Y7991321D01* +G01X917383Y7992652D01* +G01X915966Y7995585D01* +G01X914549Y7998519D01* +G01X914500Y7999985D01* +G01X914450Y8001452D01* +G01X913033Y8004386D01* +G01X911616Y8007319D01* +G01X911567Y8008785D01* +G01X911516Y8010252D01* +G01X910100Y8013185D01* +G01X908683Y8016118D01* +G01X908658Y8017771D01* +G01X908633Y8019423D01* +G01X907167Y8022160D01* +G01X905700Y8024896D01* +G01X905700Y8028224D01* +G01X904233Y8030960D01* +G01X902766Y8033697D01* +G01X902766Y8037024D01* +G01X901300Y8039760D01* +G01X899833Y8042497D01* +G01X899833Y8045823D01* +G01X898366Y8048560D01* +G01X896900Y8051296D01* +G01X896900Y8054623D01* +G01X895433Y8057360D01* +G01X893966Y8060096D01* +G01X893966Y8063825D01* +G01X891887Y8066793D01* +G01X891378Y8069689D01* +G01X890868Y8072585D01* +G01X889904Y8074128D01* +G01X888940Y8075670D01* +G01X888437Y8078527D01* +G01X887935Y8081384D01* +G01X886970Y8082927D01* +G01X886006Y8084470D01* +G01X885504Y8087327D01* +G01X885002Y8090185D01* +G01X884037Y8091727D01* +G01X883073Y8093270D01* +G01X882570Y8096127D01* +G01X882068Y8098984D01* +G01X881104Y8100527D01* +G01X880140Y8102070D01* +G01X879637Y8104927D01* +G01X879135Y8107784D01* +G01X878171Y8109327D01* +G01X877206Y8110870D01* +G01X876704Y8113727D01* +G01X876201Y8116584D01* +G01X875238Y8118127D01* +G01X874273Y8119670D01* +G01X873771Y8122527D01* +G01X873268Y8125384D01* +G01X872304Y8126927D01* +G01X871340Y8128470D01* +G01X870838Y8131327D01* +G01X870335Y8134184D01* +G01X869413Y8135662D01* +G01X868492Y8137139D01* +G01X867717Y8140428D01* +G01X866942Y8143717D01* +G01X865660Y8147384D01* +G01X864379Y8151051D01* +G01X861875Y8158384D01* +G01X860067Y8163517D01* +G01X858100Y8170117D01* +G01X855579Y8177450D01* +G01X854327Y8181117D01* +G01X853074Y8184784D01* +G01X852171Y8187350D01* +G01X851268Y8189917D01* +G01X849300Y8196517D01* +G01X846795Y8203850D01* +G01X844100Y8210722D01* +G01X844100Y8213440D01* +G01X842633Y8216317D01* +G01X841167Y8219193D01* +G01X841167Y8222240D01* +G01X838233Y8227993D01* +G01X838233Y8231355D01* +G01X836766Y8234091D01* +G01X835300Y8236828D01* +G01X835300Y8240155D01* +G01X833833Y8242891D01* +G01X832366Y8245628D01* +G01X832366Y8248955D01* +G01X830900Y8251692D01* +G01X829433Y8254428D01* +G01X829433Y8257755D01* +G01X827966Y8260491D01* +G01X826499Y8263228D01* +G01X826499Y8266555D01* +G01X825033Y8269291D01* +G01X823566Y8272028D01* +G01X823566Y8275355D01* +G01X822099Y8278091D01* +G01X820633Y8280828D01* +G01X820633Y8284154D01* +G01X819166Y8286891D01* +G01X817700Y8289627D01* +G01X817700Y8292955D01* +G01X816233Y8295691D01* +G01X814766Y8298427D01* +G01X814766Y8301755D01* +G01X813300Y8304491D01* +G01X811833Y8307228D01* +G01X811833Y8310956D01* +G01X810793Y8312440D01* +G01X809754Y8313924D01* +G01X809245Y8316820D01* +G01X808735Y8319715D01* +G01X806806Y8322801D01* +G01X806304Y8325658D01* +G01X805802Y8328516D01* +G01X804838Y8330058D01* +G01X803873Y8331601D01* +G01X803371Y8334458D01* +G01X802868Y8337315D01* +G01X801904Y8338859D01* +G01X800940Y8340401D01* +G01X800437Y8343258D01* +G01X799935Y8346115D01* +G01X798971Y8347658D01* +G01X798006Y8349201D01* +G01X797002Y8354916D01* +G01X796037Y8356458D01* +G01X795073Y8358001D01* +G01X794571Y8360858D01* +G01X794069Y8363715D01* +G01X793104Y8365258D01* +G01X792140Y8366801D01* +G01X791637Y8369658D01* +G01X791135Y8372515D01* +G01X790214Y8373993D01* +G01X789292Y8375470D01* +G01X788775Y8378026D01* +G01X788256Y8380581D01* +G01X786933Y8384249D01* +G01X785608Y8387915D01* +G01X783801Y8393048D01* +G01X781833Y8399648D01* +G01X780581Y8403315D01* +G01X779328Y8406981D01* +G01X777980Y8410417D01* +G01X776633Y8413853D01* +G01X776633Y8416571D01* +G01X775167Y8419448D01* +G01X773700Y8422325D01* +G01X773700Y8425371D01* +G01X770766Y8431124D01* +G01X770766Y8434171D01* +G01X769300Y8437048D01* +G01X767833Y8439925D01* +G01X767833Y8442971D01* +G01X766366Y8445848D01* +G01X764900Y8448725D01* +G01X764900Y8449698D01* +G01X777304Y8449698D01* +G01X777806Y8446307D01* +G01X778309Y8442914D01* +G01X781033Y8437803D01* +G01X781033Y8434476D01* +G01X782500Y8431740D01* +G01X783966Y8429003D01* +G01X783966Y8425274D01* +G01X786045Y8422306D01* +G01X786555Y8419411D01* +G01X787064Y8416514D01* +G01X788029Y8414972D01* +G01X788993Y8413429D01* +G01X789495Y8410572D01* +G01X789998Y8407715D01* +G01X790962Y8406172D01* +G01X791926Y8404629D01* +G01X792428Y8401772D01* +G01X792931Y8398915D01* +G01X793895Y8397372D01* +G01X794860Y8395830D01* +G01X795362Y8392972D01* +G01X795864Y8390115D01* +G01X796828Y8388572D01* +G01X797793Y8387029D01* +G01X798295Y8384172D01* +G01X798797Y8381315D01* +G01X799719Y8379838D01* +G01X800641Y8378360D01* +G01X801676Y8373249D01* +G01X803001Y8369582D01* +G01X804325Y8365915D01* +G01X805228Y8363348D01* +G01X806132Y8360782D01* +G01X807115Y8357482D01* +G01X808099Y8354182D01* +G01X809359Y8350515D01* +G01X810620Y8346849D01* +G01X811873Y8343182D01* +G01X813125Y8339516D01* +G01X814029Y8336949D01* +G01X814932Y8334382D01* +G01X816899Y8327782D01* +G01X818159Y8324116D01* +G01X819420Y8320449D01* +G01X820673Y8316782D01* +G01X821925Y8313116D01* +G01X823732Y8307983D01* +G01X825699Y8301382D01* +G01X826951Y8297716D01* +G01X828204Y8294049D01* +G01X829552Y8290614D01* +G01X830900Y8287178D01* +G01X830900Y8284459D01* +G01X832366Y8281583D01* +G01X833833Y8278706D01* +G01X833833Y8275659D01* +G01X835300Y8272783D01* +G01X836766Y8269906D01* +G01X836766Y8266860D01* +G01X838233Y8263983D01* +G01X839700Y8261106D01* +G01X839700Y8257744D01* +G01X841167Y8255008D01* +G01X842633Y8252271D01* +G01X842633Y8248944D01* +G01X845567Y8243472D01* +G01X845567Y8240144D01* +G01X847033Y8237408D01* +G01X848500Y8234671D01* +G01X848500Y8231344D01* +G01X849966Y8228608D01* +G01X851433Y8225871D01* +G01X851433Y8222545D01* +G01X852899Y8219808D01* +G01X854366Y8217072D01* +G01X854366Y8213744D01* +G01X855833Y8211008D01* +G01X857299Y8208272D01* +G01X857299Y8204945D01* +G01X858766Y8202208D01* +G01X860233Y8199472D01* +G01X860233Y8196145D01* +G01X861700Y8193408D01* +G01X863166Y8190672D01* +G01X863166Y8186943D01* +G01X865245Y8183975D01* +G01X865754Y8181080D01* +G01X866264Y8178183D01* +G01X867229Y8176641D01* +G01X868193Y8175098D01* +G01X868695Y8172241D01* +G01X869197Y8169384D01* +G01X870162Y8167841D01* +G01X871127Y8166298D01* +G01X871629Y8163441D01* +G01X872131Y8160584D01* +G01X873095Y8159041D01* +G01X874060Y8157498D01* +G01X875064Y8151784D01* +G01X876029Y8150241D01* +G01X876993Y8148698D01* +G01X877496Y8145841D01* +G01X877998Y8142984D01* +G01X878962Y8141441D01* +G01X879926Y8139898D01* +G01X880429Y8137041D01* +G01X880931Y8134184D01* +G01X881895Y8132641D01* +G01X882859Y8131099D01* +G01X883362Y8128241D01* +G01X883864Y8125384D01* +G01X884786Y8123907D01* +G01X885707Y8122429D01* +G01X886742Y8117317D01* +G01X889392Y8109984D01* +G01X890295Y8107418D01* +G01X891198Y8104851D01* +G01X893165Y8098251D01* +G01X894426Y8094585D01* +G01X895686Y8090917D01* +G01X896939Y8087251D01* +G01X898191Y8083585D01* +G01X899999Y8078451D01* +G01X901966Y8071851D01* +G01X904487Y8064518D01* +G01X905739Y8060851D01* +G01X906991Y8057185D01* +G01X908799Y8052051D01* +G01X910766Y8045451D01* +G01X912019Y8041785D01* +G01X913271Y8038118D01* +G01X914619Y8034682D01* +G01X915966Y8031246D01* +G01X915991Y8029915D01* +G01X916016Y8028585D01* +G01X917433Y8025651D01* +G01X918850Y8022718D01* +G01X918899Y8021252D01* +G01X918950Y8019785D01* +G01X921783Y8013919D01* +G01X921808Y8012266D01* +G01X921833Y8010613D01* +G01X923299Y8007877D01* +G01X924766Y8005141D01* +G01X924766Y8001813D01* +G01X926233Y7999077D01* +G01X927700Y7996340D01* +G01X927700Y7993013D01* +G01X929166Y7990277D01* +G01X930633Y7987540D01* +G01X930633Y7984214D01* +G01X932100Y7981477D01* +G01X933566Y7978741D01* +G01X933566Y7975413D01* +G01X935033Y7972677D01* +G01X936500Y7969940D01* +G01X936500Y7966614D01* +G01X937966Y7963877D01* +G01X939433Y7961141D01* +G01X939433Y7957412D01* +G01X941512Y7954444D01* +G01X942021Y7951548D01* +G01X942531Y7948652D01* +G01X943496Y7947110D01* +G01X944460Y7945567D01* +G01X944962Y7942710D01* +G01X945464Y7939852D01* +G01X946429Y7938310D01* +G01X947393Y7936767D01* +G01X947895Y7933909D01* +G01X948398Y7931053D01* +G01X949362Y7929510D01* +G01X950326Y7927967D01* +G01X950829Y7925110D01* +G01X951331Y7922253D01* +G01X952295Y7920710D01* +G01X953259Y7919167D01* +G01X953762Y7916310D01* +G01X954265Y7913452D01* +G01X955228Y7911910D01* +G01X956193Y7910367D01* +G01X956695Y7907510D01* +G01X957198Y7904653D01* +G01X958162Y7903110D01* +G01X959126Y7901567D01* +G01X959628Y7898710D01* +G01X960131Y7895853D01* +G01X961095Y7894310D01* +G01X962060Y7892768D01* +G01X962562Y7889910D01* +G01X963064Y7887053D01* +G01X964907Y7884098D01* +G01X965682Y7880809D01* +G01X966457Y7877519D01* +G01X969020Y7870186D01* +G01X970272Y7866520D01* +G01X971525Y7862853D01* +G01X972429Y7860286D01* +G01X973332Y7857720D01* +G01X974315Y7854420D01* +G01X975299Y7851120D01* +G01X976559Y7847453D01* +G01X977820Y7843787D01* +G01X979073Y7840120D01* +G01X980325Y7836454D01* +G01X982132Y7831320D01* +G01X983116Y7828020D01* +G01X984099Y7824720D01* +G01X985352Y7821054D01* +G01X986604Y7817387D01* +G01X989299Y7810515D01* +G01X989299Y7807797D01* +G01X990766Y7804921D01* +G01X992233Y7802043D01* +G01X992233Y7798997D01* +G01X993700Y7796121D01* +G01X995166Y7793244D01* +G01X995166Y7790198D01* +G01X996633Y7787320D01* +G01X998100Y7784444D01* +G01X998100Y7781082D01* +G01X999566Y7778345D01* +G01X1001033Y7775609D01* +G01X1001033Y7772282D01* +G01X1002500Y7769546D01* +G01X1003967Y7766809D01* +G01X1003967Y7763482D01* +G01X1005433Y7760746D01* +G01X1006900Y7758009D01* +G01X1006900Y7754682D01* +G01X1008367Y7751945D01* +G01X1009833Y7749209D01* +G01X1009833Y7745883D01* +G01X1011300Y7743146D01* +G01X1012766Y7740410D01* +G01X1012766Y7737082D01* +G01X1014233Y7734346D01* +G01X1015700Y7731609D01* +G01X1015700Y7728282D01* +G01X1017166Y7725546D01* +G01X1018633Y7722809D01* +G01X1018633Y7719483D01* +G01X1020099Y7716746D01* +G01X1021566Y7714010D01* +G01X1021566Y7710682D01* +G01X1023033Y7707946D01* +G01X1024499Y7705210D01* +G01X1024499Y7701481D01* +G01X1026578Y7698513D01* +G01X1027088Y7695617D01* +G01X1027598Y7692721D01* +G01X1028562Y7691178D01* +G01X1029526Y7689636D01* +G01X1030028Y7686779D01* +G01X1030531Y7683922D01* +G01X1031495Y7682379D01* +G01X1032460Y7680836D01* +G01X1032962Y7677979D01* +G01X1033464Y7675121D01* +G01X1034429Y7673579D01* +G01X1035393Y7672036D01* +G01X1035895Y7669179D01* +G01X1036397Y7666322D01* +G01X1037362Y7664779D01* +G01X1038326Y7663236D01* +G01X1038829Y7660379D01* +G01X1039331Y7657522D01* +G01X1041134Y7654588D01* +G01X1041134Y7654588D01* +G01X1041631Y7652572D01* +G01X1042128Y7650555D01* +G01X1883128Y7650555D01* +G01X1884179Y7651606D01* +G01X1885230Y7652657D01* +G01X1885715Y7655691D01* +G01X1886200Y7658725D01* +G01X1888202Y7661922D01* +G01X1888704Y7664779D01* +G01X1889206Y7667636D01* +G01X1890171Y7669179D01* +G01X1891135Y7670721D01* +G01X1891638Y7673579D01* +G01X1892140Y7676436D01* +G01X1893104Y7677979D01* +G01X1894068Y7679521D01* +G01X1895073Y7685236D01* +G01X1896037Y7686779D01* +G01X1897001Y7688322D01* +G01X1897511Y7691217D01* +G01X1898021Y7694113D01* +G01X1899060Y7695597D01* +G01X1900100Y7697081D01* +G01X1900100Y7700809D01* +G01X1901566Y7703546D01* +G01X1903033Y7706282D01* +G01X1903033Y7709610D01* +G01X1904499Y7712346D01* +G01X1905966Y7715083D01* +G01X1905966Y7718410D01* +G01X1907433Y7721146D01* +G01X1908899Y7723883D01* +G01X1908899Y7727209D01* +G01X1910366Y7729946D01* +G01X1911833Y7732682D01* +G01X1911833Y7736010D01* +G01X1913300Y7738746D01* +G01X1914766Y7741482D01* +G01X1914766Y7744809D01* +G01X1916233Y7747546D01* +G01X1917700Y7750282D01* +G01X1917700Y7753609D01* +G01X1919166Y7756345D01* +G01X1920633Y7759082D01* +G01X1920633Y7762444D01* +G01X1922100Y7765321D01* +G01X1923566Y7768198D01* +G01X1923566Y7771244D01* +G01X1925033Y7774121D01* +G01X1926500Y7776997D01* +G01X1926500Y7780044D01* +G01X1927967Y7782921D01* +G01X1929433Y7785797D01* +G01X1929433Y7788844D01* +G01X1930900Y7791720D01* +G01X1932366Y7794597D01* +G01X1932366Y7797315D01* +G01X1935061Y7804187D01* +G01X1937567Y7811520D01* +G01X1939534Y7818120D01* +G01X1940437Y7820687D01* +G01X1941341Y7823253D01* +G01X1942593Y7826920D01* +G01X1943846Y7830587D01* +G01X1946367Y7837920D01* +G01X1948334Y7844520D01* +G01X1949238Y7847087D01* +G01X1950141Y7849653D01* +G01X1951394Y7853320D01* +G01X1952646Y7856987D01* +G01X1955209Y7864320D01* +G01X1955983Y7867609D01* +G01X1956759Y7870898D01* +G01X1957680Y7872376D01* +G01X1958601Y7873853D01* +G01X1959104Y7876710D01* +G01X1959606Y7879567D01* +G01X1960571Y7881110D01* +G01X1961535Y7882653D01* +G01X1962540Y7888368D01* +G01X1963504Y7889910D01* +G01X1964468Y7891453D01* +G01X1964971Y7894310D01* +G01X1965473Y7897167D01* +G01X1966437Y7898710D01* +G01X1967402Y7900253D01* +G01X1967904Y7903110D01* +G01X1968407Y7905967D01* +G01X1969370Y7907510D01* +G01X1970335Y7909053D01* +G01X1970837Y7911910D01* +G01X1971340Y7914767D01* +G01X1972304Y7916310D01* +G01X1973268Y7917853D01* +G01X1973770Y7920710D01* +G01X1974273Y7923567D01* +G01X1975237Y7925110D01* +G01X1976202Y7926653D01* +G01X1976711Y7929548D01* +G01X1977221Y7932444D01* +G01X1979300Y7935412D01* +G01X1979300Y7939141D01* +G01X1980766Y7941877D01* +G01X1982233Y7944614D01* +G01X1982233Y7947941D01* +G01X1983700Y7950677D01* +G01X1985166Y7953414D01* +G01X1985166Y7956741D01* +G01X1986633Y7959477D01* +G01X1988100Y7962214D01* +G01X1988100Y7965540D01* +G01X1989566Y7968277D01* +G01X1991033Y7971013D01* +G01X1991033Y7974341D01* +G01X1993967Y7979813D01* +G01X1993967Y7983141D01* +G01X1995433Y7985877D01* +G01X1996900Y7988614D01* +G01X1996900Y7991940D01* +G01X1998366Y7994677D01* +G01X1999833Y7997413D01* +G01X1999833Y8000740D01* +G01X2001300Y8003477D01* +G01X2002766Y8006213D01* +G01X2002766Y8009575D01* +G01X2004233Y8012452D01* +G01X2005699Y8015328D01* +G01X2005699Y8018375D01* +G01X2007166Y8021252D01* +G01X2008633Y8024129D01* +G01X2008633Y8027175D01* +G01X2010099Y8030051D01* +G01X2011566Y8032928D01* +G01X2011566Y8035975D01* +G01X2013033Y8038852D01* +G01X2014500Y8041728D01* +G01X2014500Y8044775D01* +G01X2015966Y8047651D01* +G01X2017433Y8050528D01* +G01X2017433Y8053575D01* +G01X2018900Y8056451D01* +G01X2020366Y8059328D01* +G01X2020366Y8062374D01* +G01X2021833Y8065252D01* +G01X2023300Y8068128D01* +G01X2023300Y8070846D01* +G01X2025995Y8077718D01* +G01X2027248Y8081384D01* +G01X2028500Y8085051D01* +G01X2029484Y8088351D01* +G01X2030468Y8091651D01* +G01X2031371Y8094217D01* +G01X2032274Y8096784D01* +G01X2033527Y8100451D01* +G01X2034779Y8104118D01* +G01X2037342Y8111451D01* +G01X2038117Y8114740D01* +G01X2038892Y8118029D01* +G01X2040735Y8120984D01* +G01X2041237Y8123841D01* +G01X2041740Y8126699D01* +G01X2042704Y8128241D01* +G01X2043669Y8129784D01* +G01X2044171Y8132641D01* +G01X2044673Y8135498D01* +G01X2045637Y8137041D01* +G01X2046602Y8138584D01* +G01X2047104Y8141441D01* +G01X2047606Y8144298D01* +G01X2048571Y8145841D01* +G01X2049535Y8147384D01* +G01X2050037Y8150241D01* +G01X2050540Y8153098D01* +G01X2051504Y8154641D01* +G01X2052468Y8156184D01* +G01X2052971Y8159041D01* +G01X2053473Y8161898D01* +G01X2054438Y8163441D01* +G01X2055402Y8164984D01* +G01X2055904Y8167841D01* +G01X2056406Y8170698D01* +G01X2057371Y8172241D01* +G01X2058335Y8173784D01* +G01X2058844Y8176680D01* +G01X2059354Y8179575D01* +G01X2060393Y8181059D01* +G01X2061433Y8182543D01* +G01X2061433Y8186272D01* +G01X2062900Y8189008D01* +G01X2064366Y8191745D01* +G01X2064366Y8195072D01* +G01X2065833Y8197809D01* +G01X2067300Y8200545D01* +G01X2067300Y8203871D01* +G01X2068766Y8206608D01* +G01X2070233Y8209344D01* +G01X2070233Y8212672D01* +G01X2071699Y8215408D01* +G01X2073166Y8218145D01* +G01X2073166Y8221472D01* +G01X2074633Y8224208D01* +G01X2076099Y8226945D01* +G01X2076099Y8230271D01* +G01X2077566Y8233008D01* +G01X2079033Y8235744D01* +G01X2079033Y8239072D01* +G01X2080500Y8241808D01* +G01X2081966Y8244544D01* +G01X2081966Y8247871D01* +G01X2083433Y8250608D01* +G01X2084900Y8253344D01* +G01X2084900Y8256671D01* +G01X2086366Y8259407D01* +G01X2087833Y8262144D01* +G01X2087833Y8265506D01* +G01X2089300Y8268383D01* +G01X2090767Y8271260D01* +G01X2090767Y8274306D01* +G01X2092233Y8277183D01* +G01X2093700Y8280059D01* +G01X2093716Y8281554D01* +G01X2093732Y8283050D01* +G01X2096633Y8289443D01* +G01X2096633Y8291753D01* +G01X2097981Y8294734D01* +G01X2099330Y8297716D01* +G01X2100101Y8300649D01* +G01X2100872Y8303583D01* +G01X2102674Y8308716D01* +G01X2103927Y8312382D01* +G01X2105179Y8316049D01* +G01X2106440Y8319715D01* +G01X2107700Y8323382D01* +G01X2108684Y8326683D01* +G01X2109667Y8329982D01* +G01X2111475Y8335115D01* +G01X2112727Y8338782D01* +G01X2113979Y8342449D01* +G01X2115260Y8346115D01* +G01X2116542Y8349782D01* +G01X2117317Y8353072D01* +G01X2118092Y8356361D01* +G01X2119013Y8357838D01* +G01X2119935Y8359315D01* +G01X2120438Y8362172D01* +G01X2120940Y8365030D01* +G01X2121904Y8366572D01* +G01X2122868Y8368115D01* +G01X2123371Y8370972D01* +G01X2123873Y8373830D01* +G01X2124838Y8375373D01* +G01X2125801Y8376915D01* +G01X2126304Y8379772D01* +G01X2126807Y8382629D01* +G01X2127771Y8384172D01* +G01X2128735Y8385715D01* +G01X2129740Y8391430D01* +G01X2130704Y8392972D01* +G01X2131668Y8394515D01* +G01X2132170Y8397372D01* +G01X2132673Y8400229D01* +G01X2133637Y8401772D01* +G01X2134602Y8403315D01* +G01X2135104Y8406172D01* +G01X2135606Y8409029D01* +G01X2136570Y8410572D01* +G01X2137535Y8412115D01* +G01X2138037Y8414972D01* +G01X2138540Y8417829D01* +G01X2140469Y8420915D01* +G01X2141487Y8426706D01* +G01X2143566Y8429674D01* +G01X2143566Y8433403D01* +G01X2145033Y8436140D01* +G01X2146500Y8438876D01* +G01X2146500Y8442203D01* +G01X2147966Y8444939D01* +G01X2149433Y8447676D01* +G01X2149433Y8449624D01* +G01X2141287Y8455381D01* +G01X2138576Y8457389D01* +G01X2135866Y8459397D01* +G01X2134793Y8460322D01* +G01X2133720Y8461248D01* +G01X2132475Y8461981D01* +G01X2131229Y8462714D01* +G01X2127908Y8465043D01* +G01X2124589Y8467371D01* +G01X2122160Y8469076D01* +G01X2119733Y8470781D01* +G01X2117818Y8472247D01* +G01X2115904Y8473714D01* +G01X2114518Y8474609D01* +G01X2113133Y8475505D01* +G01X2109466Y8478080D01* +G01X2105800Y8480655D01* +G01X2101766Y8483403D01* +G01X2097733Y8486152D01* +G01X2097473Y8486763D01* +G01X2097212Y8487375D01* +G01X2095640Y8488065D01* +G01X2094066Y8488755D01* +G01X2085266Y8495369D01* +G01X2076099Y8501451D01* +G01X2076099Y8502681D01* +G01X2074499Y8502681D01* +G01X2072549Y8504172D01* +G01X2070600Y8505664D01* +G01X2066898Y8508389D01* +G01X2063196Y8511114D01* +G01X2062051Y8511847D01* +G01X2060905Y8512580D01* +G01X2058786Y8513996D01* +G01X2056666Y8515411D01* +G01X2055916Y8516196D01* +G01X2055166Y8516981D01* +G01X2053985Y8517714D01* +G01X2052803Y8518447D01* +G01X2048502Y8521355D01* +G01X2044199Y8524263D01* +G01X2043749Y8524905D01* +G01X2043298Y8525546D01* +G01X2041837Y8526396D01* +G01X2040376Y8527247D01* +G01X2037521Y8529223D01* +G01X2034666Y8531199D01* +G01X2031000Y8533826D01* +G01X2027333Y8536455D01* +G01X2025499Y8537708D01* +G01X2023666Y8538961D01* +G01X2022697Y8539888D01* +G01X2021728Y8540813D01* +G01X2020623Y8540813D01* +G01X2016278Y8544110D01* +G01X2011933Y8547406D01* +G01X2010466Y8548525D01* +G01X2008633Y8549775D01* +G01X2006800Y8551025D01* +G01X2000566Y8555427D01* +G01X1994333Y8559829D01* +G01X1990299Y8562578D01* +G01X1986267Y8565327D01* +G01X1985680Y8566270D01* +G01X1985094Y8567213D01* +G01X1983565Y8567213D01* +G01X1981616Y8568705D01* +G01X1979666Y8570197D01* +G01X1975964Y8572922D01* +G01X1972263Y8575647D01* +G01X1969972Y8577113D01* +G01X1967853Y8578529D01* +G01X1965733Y8579944D01* +G01X1964983Y8580728D01* +G01X1964233Y8581513D01* +G01X1963051Y8582247D01* +G01X1961870Y8582980D01* +G01X1957568Y8585888D01* +G01X1953266Y8588796D01* +G01X1952815Y8589437D01* +G01X1952365Y8590079D01* +G01X1950903Y8590930D01* +G01X1949443Y8591780D01* +G01X1946588Y8593755D01* +G01X1943733Y8595731D01* +G01X1940066Y8598360D01* +G01X1936399Y8600987D01* +G01X1932733Y8603479D01* +G01X1932282Y8604112D01* +G01X1931831Y8604746D01* +G01X1930341Y8605596D01* +G01X1928852Y8606446D01* +G01X1924559Y8609367D01* +G01X1920267Y8612288D01* +G01X1919533Y8612859D01* +G01X1918800Y8613431D01* +G01X1913466Y8617446D01* +G01X1912099Y8618342D01* +G01X1910733Y8619236D01* +G01X1907066Y8621812D01* +G01X1903400Y8624387D01* +G01X1899366Y8627123D01* +G01X1895333Y8629860D01* +G01X1894747Y8630803D01* +G01X1894160Y8631746D01* +G01X1892631Y8631746D01* +G01X1890683Y8633238D01* +G01X1888733Y8634730D01* +G01X1885031Y8637454D01* +G01X1881330Y8640179D01* +G01X1879898Y8641113D01* +G01X1878466Y8642047D01* +G01X1876083Y8643569D01* +G01X1873699Y8645091D01* +G01X1873699Y8646413D01* +G01X1872098Y8646413D01* +G01X1870149Y8647904D01* +G01X1868200Y8649396D01* +G01X1864498Y8652121D01* +G01X1860796Y8654846D01* +G01X1859364Y8655780D01* +G01X1857933Y8656713D01* +G01X1855550Y8658235D01* +G01X1853166Y8659757D01* +G01X1853166Y8661079D01* +G01X1851751Y8661079D01* +G01X1848609Y8663303D01* +G01X1845466Y8665527D01* +G01X1841800Y8668010D01* +G01X1841213Y8668945D01* +G01X1840627Y8669879D01* +G01X1839078Y8669879D01* +G01X1837014Y8671529D01* +G01X1834951Y8673179D01* +G01X1827423Y8678312D01* +G01X1824977Y8680146D01* +G01X1822532Y8681979D01* +G01X1819799Y8683770D01* +G01X1812466Y8688919D01* +G01X1808433Y8691668D01* +G01X1804399Y8694417D01* +G01X1804140Y8695028D01* +G01X1803879Y8695640D01* +G01X1802306Y8696330D01* +G01X1800733Y8697019D01* +G01X1796333Y8700312D01* +G01X1791933Y8703605D01* +G01X1783866Y8709059D01* +G01X1783280Y8710002D01* +G01X1782693Y8710945D01* +G01X1781165Y8710945D01* +G01X1779216Y8712437D01* +G01X1777266Y8713929D01* +G01X1773564Y8716654D01* +G01X1769863Y8719379D01* +G01X1768717Y8720112D01* +G01X1767572Y8720845D01* +G01X1765452Y8722260D01* +G01X1763333Y8723676D01* +G01X1762583Y8724461D01* +G01X1761833Y8725245D01* +G01X1760651Y8725978D01* +G01X1759470Y8726712D01* +G01X1755168Y8729620D01* +G01X1750866Y8732528D01* +G01X1750415Y8733170D01* +G01X1749965Y8733811D01* +G01X1748503Y8734661D01* +G01X1747043Y8735512D01* +G01X1744188Y8737488D01* +G01X1741333Y8739464D01* +G01X1737667Y8742091D01* +G01X1733999Y8744719D01* +G01X1732166Y8745973D01* +G01X1730333Y8747226D01* +G01X1729364Y8748152D01* +G01X1728395Y8749078D01* +G01X1727289Y8749078D01* +G01X1722945Y8752375D01* +G01X1718599Y8755671D01* +G01X1717866Y8756231D01* +G01X1717133Y8756790D01* +G01X1715299Y8758040D01* +G01X1713466Y8759290D01* +G01X1707233Y8763692D01* +G01X1701000Y8768094D01* +G01X1692933Y8773592D01* +G01X1692347Y8774535D01* +G01X1691760Y8775478D01* +G01X1690231Y8775478D01* +G01X1688282Y8776970D01* +G01X1686333Y8778462D01* +G01X1678929Y8783911D01* +G01X1677784Y8784645D01* +G01X1676639Y8785378D01* +G01X1672399Y8788209D01* +G01X1671649Y8788993D01* +G01X1670900Y8789778D01* +G01X1669718Y8790511D01* +G01X1668537Y8791245D01* +G01X1664235Y8794152D01* +G01X1659933Y8797061D01* +G01X1659482Y8797702D01* +G01X1659031Y8798344D01* +G01X1656109Y8800045D01* +G01X1653255Y8802020D01* +G01X1650400Y8803996D01* +G01X1646733Y8806624D01* +G01X1643066Y8809252D01* +G01X1639400Y8811744D01* +G01X1638949Y8812377D01* +G01X1638498Y8813011D01* +G01X1637008Y8813861D01* +G01X1635519Y8814711D01* +G01X1626933Y8820553D01* +G01X1626200Y8821124D01* +G01X1625467Y8821695D01* +G01X1622800Y8823703D01* +G01X1620132Y8825711D01* +G01X1618766Y8826606D01* +G01X1617399Y8827501D01* +G01X1613733Y8830077D01* +G01X1610067Y8832652D01* +G01X1606033Y8835388D01* +G01X1601999Y8838125D01* +G01X1601413Y8839068D01* +G01X1600827Y8840011D01* +G01X1599298Y8840011D01* +G01X1597349Y8841503D01* +G01X1595400Y8842994D01* +G01X1587996Y8848444D01* +G01X1586565Y8849378D01* +G01X1585133Y8850311D01* +G01X1582749Y8851833D01* +G01X1580366Y8853356D01* +G01X1580366Y8854678D01* +G01X1578765Y8854678D01* +G01X1576815Y8856169D01* +G01X1574867Y8857661D01* +G01X1567462Y8863110D01* +G01X1566031Y8864044D01* +G01X1564600Y8864978D01* +G01X1562216Y8866500D01* +G01X1559833Y8868022D01* +G01X1559833Y8869344D01* +G01X1558418Y8869344D01* +G01X1555276Y8871568D01* +G01X1552133Y8873792D01* +G01X1548466Y8876275D01* +G01X1547880Y8877210D01* +G01X1547294Y8878144D01* +G01X1545745Y8878144D01* +G01X1543681Y8879794D01* +G01X1541618Y8881444D01* +G01X1534089Y8886577D01* +G01X1529199Y8890244D01* +G01X1527833Y8891139D01* +G01X1526466Y8892034D01* +G01X1519133Y8897184D01* +G01X1515100Y8899922D01* +G01X1511066Y8902660D01* +G01X1510700Y8903164D01* +G01X1510333Y8903669D01* +G01X1504466Y8907748D01* +G01X1498600Y8911826D01* +G01X1490533Y8917324D01* +G01X1489947Y8918267D01* +G01X1489360Y8919210D01* +G01X1487832Y8919210D01* +G01X1485882Y8920702D01* +G01X1483933Y8922194D01* +G01X1476529Y8927644D01* +G01X1473667Y8929510D01* +G01X1471283Y8931032D01* +G01X1468900Y8932555D01* +G01X1468900Y8933877D01* +G01X1467298Y8933877D01* +G01X1465433Y8935343D01* +G01X1463569Y8936810D01* +G01X1461746Y8936810D01* +G01X1460884Y8935771D01* +G01X1460022Y8934733D01* +G01X1449831Y8927644D01* +G01X1447449Y8925982D01* +G01X1445066Y8924321D01* +G01X1443681Y8923416D01* +G01X1442296Y8922510D01* +G01X1440381Y8921043D01* +G01X1438466Y8919577D01* +G01X1436038Y8917872D01* +G01X1433611Y8916167D01* +G01X1430291Y8913839D01* +G01X1426971Y8911510D01* +G01X1424479Y8910043D01* +G01X1423406Y8909099D01* +G01X1422333Y8908155D01* +G01X1417761Y8904883D01* +G01X1413189Y8901610D01* +G01X1411699Y8901610D01* +G01X1411699Y8900289D01* +G01X1409316Y8898767D01* +G01X1406933Y8897244D01* +G01X1405501Y8896310D01* +G01X1404070Y8895377D01* +G01X1400368Y8892652D01* +G01X1396666Y8889927D01* +G01X1394717Y8888436D01* +G01X1392768Y8886944D01* +G01X1391239Y8886944D01* +G01X1390653Y8886001D01* +G01X1390066Y8885058D01* +G01X1386033Y8882330D01* +G01X1382000Y8879603D01* +G01X1377599Y8876311D01* +G01X1373199Y8873018D01* +G01X1371627Y8872328D01* +G01X1370054Y8871639D01* +G01X1369533Y8870415D01* +G01X1365499Y8867666D01* +G01X1361467Y8864918D01* +G01X1357799Y8862343D01* +G01X1354133Y8859768D01* +G01X1352767Y8858872D01* +G01X1351401Y8857977D01* +G01X1346510Y8854311D01* +G01X1342745Y8851744D01* +G01X1338982Y8849177D01* +G01X1336918Y8847528D01* +G01X1334854Y8845877D01* +G01X1333306Y8845877D01* +G01X1332719Y8844943D01* +G01X1332133Y8844009D01* +G01X1328466Y8841519D01* +G01X1324800Y8838890D01* +G01X1321133Y8836263D01* +G01X1318278Y8834287D01* +G01X1315423Y8832311D01* +G01X1313962Y8831460D01* +G01X1312502Y8830610D01* +G01X1312051Y8829969D01* +G01X1311599Y8829327D01* +G01X1307298Y8826419D01* +G01X1302996Y8823511D01* +G01X1301815Y8822777D01* +G01X1300634Y8822045D01* +G01X1299883Y8821260D01* +G01X1299133Y8820475D01* +G01X1294894Y8817644D01* +G01X1293749Y8816911D01* +G01X1292603Y8816178D01* +G01X1288901Y8813453D01* +G01X1285200Y8810728D01* +G01X1283250Y8809236D01* +G01X1281301Y8807745D01* +G01X1279773Y8807745D01* +G01X1279186Y8806802D01* +G01X1278600Y8805859D01* +G01X1274566Y8803122D01* +G01X1270533Y8800385D01* +G01X1266866Y8797810D01* +G01X1263200Y8795235D01* +G01X1261833Y8794340D01* +G01X1260467Y8793444D01* +G01X1255665Y8789778D01* +G01X1254299Y8788853D01* +G01X1252933Y8787930D01* +G01X1247800Y8784278D01* +G01X1242666Y8780626D01* +G01X1241300Y8779703D01* +G01X1239934Y8778778D01* +G01X1235043Y8775112D01* +G01X1231279Y8772545D01* +G01X1227515Y8769978D01* +G01X1225451Y8768328D01* +G01X1223388Y8766678D01* +G01X1221839Y8766678D01* +G01X1221253Y8765735D01* +G01X1220666Y8764792D01* +G01X1216365Y8761885D01* +G01X1212062Y8758978D01* +G01X1209700Y8757511D01* +G01X1208950Y8756727D01* +G01X1208200Y8755942D01* +G01X1203961Y8753112D01* +G01X1202815Y8752378D01* +G01X1201670Y8751645D01* +G01X1197968Y8748920D01* +G01X1194267Y8746195D01* +G01X1190368Y8743212D01* +G01X1188839Y8743212D01* +G01X1188253Y8742268D01* +G01X1187666Y8741325D01* +G01X1183633Y8738577D01* +G01X1179599Y8735828D01* +G01X1173733Y8731750D01* +G01X1167866Y8727671D01* +G01X1167499Y8727179D01* +G01X1167133Y8726688D01* +G01X1161816Y8723033D01* +G01X1156497Y8719379D01* +G01X1154116Y8717718D01* +G01X1151733Y8716056D01* +G01X1150347Y8715151D01* +G01X1148963Y8714245D01* +G01X1147047Y8712779D01* +G01X1145133Y8711312D01* +G01X1142705Y8709607D01* +G01X1140278Y8707903D01* +G01X1136957Y8705574D01* +G01X1133637Y8703245D01* +G01X1131146Y8701779D01* +G01X1128999Y8699890D01* +G01X1124428Y8696618D01* +G01X1119856Y8693345D01* +G01X1118366Y8693345D01* +G01X1118366Y8692024D01* +G01X1115983Y8690502D01* +G01X1113599Y8688979D01* +G01X1110737Y8687112D01* +G01X1103333Y8681663D01* +G01X1101384Y8680171D01* +G01X1099434Y8678679D01* +G01X1097906Y8678679D01* +G01X1097319Y8677736D01* +G01X1096733Y8676793D01* +G01X1088666Y8671338D01* +G01X1084266Y8668046D01* +G01X1079866Y8664753D01* +G01X1078293Y8664063D01* +G01X1076720Y8663374D01* +G01X1076460Y8662762D01* +G01X1076200Y8662150D01* +G01X1072166Y8659402D01* +G01X1068133Y8656653D01* +G01X1060800Y8651503D01* +G01X1059433Y8650608D01* +G01X1058067Y8649712D01* +G01X1053177Y8646046D01* +G01X1045648Y8640913D01* +G01X1043585Y8639263D01* +G01X1041521Y8637612D01* +G01X1039972Y8637612D01* +G01X1039386Y8636678D01* +G01X1038800Y8635744D01* +G01X1035133Y8633254D01* +G01X1031467Y8630626D01* +G01X1027799Y8627998D01* +G01X1024944Y8626022D01* +G01X1022090Y8624046D01* +G01X1020629Y8623196D01* +G01X1019168Y8622345D01* +G01X1018717Y8621704D01* +G01X1018266Y8621062D01* +G01X1013965Y8618154D01* +G01X1009663Y8615246D01* +G01X1008481Y8614513D01* +G01X1007300Y8613780D01* +G01X1006550Y8612995D01* +G01X1005800Y8612210D01* +G01X1001561Y8609379D01* +G01X1000415Y8608647D01* +G01X999270Y8607913D01* +G01X991866Y8602464D01* +G01X989917Y8600971D01* +G01X987968Y8599480D01* +G01X986439Y8599480D01* +G01X985853Y8598537D01* +G01X985267Y8597594D01* +G01X977199Y8592120D01* +G01X969866Y8586970D01* +G01X968500Y8586075D01* +G01X967134Y8585180D01* +G01X962332Y8581513D01* +G01X960966Y8580589D01* +G01X959600Y8579665D01* +G01X954466Y8576013D01* +G01X949333Y8572362D01* +G01X947967Y8571438D01* +G01X946601Y8570513D01* +G01X941710Y8566847D01* +G01X934181Y8561714D01* +G01X932118Y8560063D01* +G01X930055Y8558413D01* +G01X928506Y8558413D01* +G01X927920Y8557470D01* +G01X927333Y8556528D01* +G01X923031Y8553621D01* +G01X918729Y8550714D01* +G01X917548Y8549980D01* +G01X916366Y8549247D01* +G01X915617Y8548462D01* +G01X914867Y8547678D01* +G01X910627Y8544847D01* +G01X908336Y8543380D01* +G01X904635Y8540655D01* +G01X900933Y8537930D01* +G01X898983Y8536439D01* +G01X897035Y8534947D01* +G01X895506Y8534947D01* +G01X894919Y8534004D01* +G01X894333Y8533061D01* +G01X890300Y8530312D01* +G01X886266Y8527564D01* +G01X880399Y8523485D01* +G01X874533Y8519406D01* +G01X873800Y8518423D01* +G01X868482Y8514768D01* +G01X863164Y8511114D01* +G01X860782Y8509453D01* +G01X858400Y8507792D01* +G01X855629Y8505981D01* +G01X851800Y8503047D01* +G01X849372Y8501343D01* +G01X846944Y8499638D01* +G01X840304Y8494981D01* +G01X839058Y8494247D01* +G01X837813Y8493514D01* +G01X835666Y8491625D01* +G01X831094Y8488353D01* +G01X826523Y8485081D01* +G01X825033Y8485081D01* +G01X825033Y8483759D01* +G01X822649Y8482237D01* +G01X820266Y8480714D01* +G01X818835Y8479781D01* +G01X817403Y8478847D01* +G01X813702Y8476123D01* +G01X810000Y8473398D01* +G01X808050Y8471906D01* +G01X806101Y8470414D01* +G01X804573Y8470414D01* +G01X803399Y8468528D01* +G01X799366Y8465801D01* +G01X795333Y8463074D01* +G01X790933Y8459778D01* +G01X786533Y8456482D01* +G01X785433Y8455996D01* +G01X784333Y8455509D01* +G01X783233Y8454532D01* +G01X782133Y8453556D01* +G01X779718Y8451626D01* +G01X777304Y8449698D01* +G01X764900Y8449698D01* +G01X764900Y8454281D01* +G01X766366Y8455748D01* +G01X767833Y8457214D01* +G01X769195Y8457214D01* +G01X770164Y8458140D01* +G01X771133Y8459067D01* +G01X772966Y8460320D01* +G01X774800Y8461573D01* +G01X778466Y8464201D01* +G01X782133Y8466830D01* +G01X784988Y8468805D01* +G01X787842Y8470781D01* +G01X790765Y8472482D01* +G01X791666Y8473748D01* +G01X795333Y8476240D01* +G01X798999Y8478868D01* +G01X802667Y8481496D01* +G01X805521Y8483471D01* +G01X808376Y8485448D01* +G01X809837Y8486298D01* +G01X811297Y8487148D01* +G01X811749Y8487790D01* +G01X812200Y8488431D01* +G01X816501Y8491340D01* +G01X820803Y8494247D01* +G01X823166Y8495714D01* +G01X823916Y8496498D01* +G01X824666Y8497283D01* +G01X828905Y8500114D01* +G01X830051Y8500847D01* +G01X831196Y8501581D01* +G01X838600Y8507030D01* +G01X840549Y8508522D01* +G01X842498Y8510014D01* +G01X844027Y8510014D01* +G01X844613Y8510957D01* +G01X845199Y8511900D01* +G01X853267Y8517398D01* +G01X859500Y8521800D01* +G01X865733Y8526202D01* +G01X867566Y8527452D01* +G01X869399Y8528702D01* +G01X870866Y8529882D01* +G01X876000Y8533507D01* +G01X881133Y8537132D01* +G01X882499Y8538056D01* +G01X883865Y8538980D01* +G01X886311Y8540813D01* +G01X888756Y8542647D01* +G01X896285Y8547780D01* +G01X898348Y8549430D01* +G01X900411Y8551080D01* +G01X901960Y8551080D01* +G01X902546Y8552023D01* +G01X903133Y8552966D01* +G01X907435Y8555873D01* +G01X911737Y8558780D01* +G01X914099Y8560247D01* +G01X914849Y8561032D01* +G01X915599Y8561816D01* +G01X919839Y8564647D01* +G01X920984Y8565380D01* +G01X922129Y8566113D01* +G01X929533Y8571563D01* +G01X931482Y8573055D01* +G01X933431Y8574547D01* +G01X934960Y8574547D01* +G01X935547Y8575490D01* +G01X936133Y8576433D01* +G01X944200Y8581930D01* +G01X950067Y8586009D01* +G01X955933Y8590088D01* +G01X956300Y8590579D01* +G01X956666Y8591071D01* +G01X961984Y8594726D01* +G01X967302Y8598380D01* +G01X969684Y8600041D01* +G01X972066Y8601702D01* +G01X974837Y8603513D01* +G01X976752Y8604979D01* +G01X978666Y8606446D01* +G01X981094Y8608151D01* +G01X983522Y8609856D01* +G01X990162Y8614513D01* +G01X991408Y8615246D01* +G01X992653Y8615979D01* +G01X994800Y8617868D01* +G01X999371Y8621141D01* +G01X1003943Y8624413D01* +G01X1005433Y8624413D01* +G01X1005433Y8625735D01* +G01X1007816Y8627257D01* +G01X1010200Y8628779D01* +G01X1011631Y8629713D01* +G01X1013063Y8630646D01* +G01X1016764Y8633371D01* +G01X1020466Y8636095D01* +G01X1022416Y8637588D01* +G01X1024365Y8639079D01* +G01X1025966Y8639079D01* +G01X1025966Y8640309D01* +G01X1035133Y8646391D01* +G01X1043933Y8653005D01* +G01X1045506Y8653695D01* +G01X1047079Y8654385D01* +G01X1047340Y8654997D01* +G01X1047599Y8655608D01* +G01X1051633Y8658357D01* +G01X1055666Y8661105D01* +G01X1062999Y8666255D01* +G01X1065732Y8668046D01* +G01X1068177Y8669879D01* +G01X1070623Y8671712D01* +G01X1078151Y8676846D01* +G01X1080214Y8678496D01* +G01X1082278Y8680146D01* +G01X1083827Y8680146D01* +G01X1084414Y8681080D01* +G01X1085000Y8682014D01* +G01X1086833Y8683259D01* +G01X1088666Y8684504D01* +G01X1092333Y8687132D01* +G01X1096000Y8689761D01* +G01X1098855Y8691736D01* +G01X1101710Y8693712D01* +G01X1103170Y8694563D01* +G01X1104631Y8695413D01* +G01X1105082Y8696055D01* +G01X1105533Y8696696D01* +G01X1109835Y8699604D01* +G01X1114137Y8702512D01* +G01X1115318Y8703245D01* +G01X1116499Y8703979D01* +G01X1117249Y8704763D01* +G01X1118000Y8705548D01* +G01X1120119Y8706963D01* +G01X1122239Y8708379D01* +G01X1124530Y8709846D01* +G01X1128231Y8712570D01* +G01X1131933Y8715295D01* +G01X1133883Y8716787D01* +G01X1135831Y8718278D01* +G01X1137360Y8718278D01* +G01X1137947Y8719222D01* +G01X1138533Y8720165D01* +G01X1142566Y8722914D01* +G01X1146600Y8725663D01* +G01X1152833Y8730064D01* +G01X1159066Y8734467D01* +G01X1160900Y8735717D01* +G01X1162733Y8736967D01* +G01X1163467Y8737557D01* +G01X1164199Y8738147D01* +G01X1169333Y8741772D01* +G01X1174466Y8745396D01* +G01X1175833Y8746321D01* +G01X1177199Y8747245D01* +G01X1179644Y8749078D01* +G01X1182089Y8750912D01* +G01X1189618Y8756045D01* +G01X1191682Y8757695D01* +G01X1193745Y8759345D01* +G01X1195293Y8759345D01* +G01X1195880Y8760288D01* +G01X1196466Y8761231D01* +G01X1200768Y8764138D01* +G01X1205070Y8767045D01* +G01X1206251Y8767778D01* +G01X1207433Y8768511D01* +G01X1208183Y8769296D01* +G01X1208933Y8770081D01* +G01X1211053Y8771496D01* +G01X1213172Y8772911D01* +G01X1215463Y8774378D01* +G01X1219164Y8777103D01* +G01X1222866Y8779828D01* +G01X1224816Y8781319D01* +G01X1226765Y8782812D01* +G01X1228294Y8782812D01* +G01X1228880Y8783754D01* +G01X1229467Y8784697D01* +G01X1233499Y8787446D01* +G01X1237533Y8790195D01* +G01X1249266Y8798352D01* +G01X1249633Y8798844D01* +G01X1250000Y8799336D01* +G01X1260635Y8806645D01* +G01X1265400Y8809967D01* +G01X1266766Y8810873D01* +G01X1268132Y8811778D01* +G01X1273023Y8815444D01* +G01X1276787Y8818011D01* +G01X1280551Y8820578D01* +G01X1282615Y8822227D01* +G01X1284678Y8823878D01* +G01X1286227Y8823878D01* +G01X1286813Y8824812D01* +G01X1287400Y8825746D01* +G01X1289233Y8826988D01* +G01X1291066Y8828229D01* +G01X1294209Y8830454D01* +G01X1297352Y8832678D01* +G01X1298766Y8832678D01* +G01X1298766Y8834000D01* +G01X1301150Y8835522D01* +G01X1303533Y8837044D01* +G01X1304964Y8837977D01* +G01X1306396Y8838911D01* +G01X1310098Y8841635D01* +G01X1313800Y8844360D01* +G01X1315749Y8845852D01* +G01X1317699Y8847344D01* +G01X1319299Y8847344D01* +G01X1319299Y8848574D01* +G01X1328466Y8854656D01* +G01X1337266Y8861270D01* +G01X1338840Y8861960D01* +G01X1340412Y8862649D01* +G01X1340673Y8863261D01* +G01X1340933Y8863873D01* +G01X1344966Y8866622D01* +G01X1349000Y8869370D01* +G01X1352666Y8871945D01* +G01X1356333Y8874520D01* +G01X1357699Y8875415D01* +G01X1359066Y8876311D01* +G01X1363956Y8879977D01* +G01X1367720Y8882544D01* +G01X1371484Y8885110D01* +G01X1373548Y8886761D01* +G01X1375611Y8888410D01* +G01X1377160Y8888410D01* +G01X1377747Y8889344D01* +G01X1378333Y8890279D01* +G01X1380166Y8891524D01* +G01X1382000Y8892769D01* +G01X1389333Y8898025D01* +G01X1392188Y8900001D01* +G01X1395043Y8901977D01* +G01X1396503Y8902827D01* +G01X1397964Y8903678D01* +G01X1398415Y8904320D01* +G01X1398866Y8904961D01* +G01X1403168Y8907869D01* +G01X1407470Y8910777D01* +G01X1408651Y8911510D01* +G01X1409833Y8912244D01* +G01X1410583Y8913028D01* +G01X1411333Y8913813D01* +G01X1413453Y8915228D01* +G01X1415572Y8916644D01* +G01X1417863Y8918110D01* +G01X1421564Y8920835D01* +G01X1425266Y8923560D01* +G01X1429165Y8926543D01* +G01X1430694Y8926543D01* +G01X1431280Y8927487D01* +G01X1431866Y8928430D01* +G01X1435899Y8931179D01* +G01X1439933Y8933927D01* +G01X1446166Y8938329D01* +G01X1452400Y8942732D01* +G01X1454233Y8943982D01* +G01X1456066Y8945232D01* +G01X1457035Y8945971D01* +G01X1458005Y8946710D01* +G01X1460466Y8949155D01* +G01X1462849Y8949216D01* +G01X1465233Y8949276D01* +G01X1466699Y8947993D01* +G01X1468166Y8946710D01* +G01X1469514Y8945610D01* +G01X1470862Y8944510D01* +G01X1471995Y8943777D01* +G01X1473129Y8943043D01* +G01X1477431Y8940135D01* +G01X1481733Y8937227D01* +G01X1482184Y8936585D01* +G01X1482635Y8935944D01* +G01X1484096Y8935094D01* +G01X1485556Y8934243D01* +G01X1488411Y8932268D01* +G01X1491266Y8930291D01* +G01X1494933Y8927664D01* +G01X1498600Y8925036D01* +G01X1502266Y8922544D01* +G01X1503168Y8921278D01* +G01X1504658Y8920427D01* +G01X1506147Y8919577D01* +G01X1510440Y8916656D01* +G01X1514733Y8913735D01* +G01X1516200Y8912593D01* +G01X1521534Y8908577D01* +G01X1524267Y8906786D01* +G01X1531600Y8901637D01* +G01X1539667Y8896163D01* +G01X1540253Y8895220D01* +G01X1540839Y8894277D01* +G01X1542368Y8894277D01* +G01X1544317Y8892785D01* +G01X1546266Y8891293D01* +G01X1549968Y8888569D01* +G01X1553670Y8885844D01* +G01X1555102Y8884910D01* +G01X1556533Y8883977D01* +G01X1558917Y8882454D01* +G01X1561300Y8880932D01* +G01X1561300Y8879611D01* +G01X1562901Y8879611D01* +G01X1564850Y8878118D01* +G01X1566800Y8876627D01* +G01X1570502Y8873902D01* +G01X1574203Y8871177D01* +G01X1575635Y8870244D01* +G01X1577066Y8869310D01* +G01X1579449Y8867788D01* +G01X1581833Y8866266D01* +G01X1581833Y8864944D01* +G01X1583248Y8864944D01* +G01X1586391Y8862720D01* +G01X1589533Y8860496D01* +G01X1591366Y8859254D01* +G01X1593200Y8858013D01* +G01X1593786Y8857079D01* +G01X1594372Y8856144D01* +G01X1595921Y8856144D01* +G01X1597985Y8854494D01* +G01X1600048Y8852844D01* +G01X1607577Y8847710D01* +G01X1612467Y8844044D01* +G01X1613833Y8843149D01* +G01X1615200Y8842254D01* +G01X1618866Y8839679D01* +G01X1622533Y8837104D01* +G01X1630600Y8831629D01* +G01X1630966Y8831124D01* +G01X1631333Y8830619D01* +G01X1637199Y8826540D01* +G01X1643066Y8822461D01* +G01X1647100Y8819712D01* +G01X1651133Y8816964D01* +G01X1651719Y8816021D01* +G01X1652306Y8815077D01* +G01X1653835Y8815077D01* +G01X1655784Y8813586D01* +G01X1657733Y8812094D01* +G01X1665137Y8806645D01* +G01X1666282Y8805911D01* +G01X1667427Y8805178D01* +G01X1671667Y8802347D01* +G01X1672417Y8801562D01* +G01X1673166Y8800778D01* +G01X1674348Y8800045D01* +G01X1675529Y8799311D01* +G01X1679831Y8796404D01* +G01X1684133Y8793497D01* +G01X1684720Y8792554D01* +G01X1685306Y8791611D01* +G01X1686855Y8791611D01* +G01X1688918Y8789962D01* +G01X1690981Y8788311D01* +G01X1698510Y8783178D01* +G01X1703401Y8779511D01* +G01X1704767Y8778587D01* +G01X1706133Y8777663D01* +G01X1711266Y8774038D01* +G01X1716400Y8770413D01* +G01X1717133Y8769823D01* +G01X1717866Y8769233D01* +G01X1719700Y8767983D01* +G01X1721533Y8766733D01* +G01X1727766Y8762331D01* +G01X1733999Y8757929D01* +G01X1738033Y8755180D01* +G01X1742066Y8752431D01* +G01X1742653Y8751488D01* +G01X1743239Y8750545D01* +G01X1744768Y8750545D01* +G01X1746717Y8749053D01* +G01X1748666Y8747561D01* +G01X1756070Y8742112D01* +G01X1757215Y8741378D01* +G01X1758361Y8740645D01* +G01X1762600Y8737815D01* +G01X1763350Y8737030D01* +G01X1764100Y8736245D01* +G01X1765281Y8735512D01* +G01X1766463Y8734779D01* +G01X1770765Y8731870D01* +G01X1775066Y8728963D01* +G01X1775517Y8728321D01* +G01X1775968Y8727679D01* +G01X1777429Y8726829D01* +G01X1778890Y8725978D01* +G01X1781745Y8724003D01* +G01X1784599Y8722027D01* +G01X1788267Y8719399D01* +G01X1791933Y8716771D01* +G01X1795600Y8714280D01* +G01X1796186Y8713346D01* +G01X1796772Y8712412D01* +G01X1798321Y8712412D01* +G01X1800385Y8710762D01* +G01X1802448Y8709112D01* +G01X1809977Y8703979D01* +G01X1814867Y8700312D01* +G01X1816233Y8699417D01* +G01X1817600Y8698522D01* +G01X1824933Y8693372D01* +G01X1833000Y8687898D01* +G01X1833586Y8686955D01* +G01X1834173Y8686012D01* +G01X1835701Y8686012D01* +G01X1837651Y8684520D01* +G01X1839600Y8683029D01* +G01X1843301Y8680304D01* +G01X1847003Y8677579D01* +G01X1849866Y8675712D01* +G01X1852250Y8674189D01* +G01X1854633Y8672667D01* +G01X1854633Y8671346D01* +G01X1856234Y8671346D01* +G01X1858184Y8669854D01* +G01X1860133Y8668362D01* +G01X1867537Y8662913D01* +G01X1870399Y8661046D01* +G01X1872783Y8659523D01* +G01X1875166Y8658001D01* +G01X1875166Y8656679D01* +G01X1876656Y8656679D01* +G01X1881228Y8653407D01* +G01X1885799Y8650135D01* +G01X1887946Y8648246D01* +G01X1890437Y8646779D01* +G01X1893757Y8644451D01* +G01X1897078Y8642122D01* +G01X1899505Y8640417D01* +G01X1901933Y8638713D01* +G01X1903847Y8637246D01* +G01X1905763Y8635779D01* +G01X1907147Y8634884D01* +G01X1908533Y8633989D01* +G01X1912200Y8631414D01* +G01X1915866Y8628839D01* +G01X1923933Y8623364D01* +G01X1924299Y8622859D01* +G01X1924666Y8622354D01* +G01X1930533Y8618275D01* +G01X1936399Y8614196D01* +G01X1940433Y8611448D01* +G01X1944466Y8608699D01* +G01X1945052Y8607756D01* +G01X1945639Y8606813D01* +G01X1947168Y8606813D01* +G01X1951067Y8603830D01* +G01X1954768Y8601105D01* +G01X1958470Y8598380D01* +G01X1959615Y8597647D01* +G01X1960760Y8596913D01* +G01X1965000Y8594082D01* +G01X1965750Y8593297D01* +G01X1966500Y8592513D01* +G01X1968862Y8591046D01* +G01X1973165Y8588139D01* +G01X1977466Y8585232D01* +G01X1978053Y8584289D01* +G01X1978639Y8583347D01* +G01X1980188Y8583347D01* +G01X1982251Y8581697D01* +G01X1984315Y8580046D01* +G01X1988079Y8577480D01* +G01X1991843Y8574913D01* +G01X1996734Y8571247D01* +G01X1998100Y8570322D01* +G01X1999466Y8569398D01* +G01X2004600Y8565773D01* +G01X2009733Y8562148D01* +G01X2011200Y8560969D01* +G01X2013033Y8559718D01* +G01X2014866Y8558469D01* +G01X2021099Y8554066D01* +G01X2027333Y8549665D01* +G01X2031366Y8546915D01* +G01X2035400Y8544166D01* +G01X2035986Y8543223D01* +G01X2036573Y8542280D01* +G01X2038101Y8542280D01* +G01X2040050Y8540789D01* +G01X2042000Y8539296D01* +G01X2045701Y8536572D01* +G01X2049403Y8533847D01* +G01X2050549Y8533113D01* +G01X2051694Y8532381D01* +G01X2055933Y8529550D01* +G01X2056683Y8528765D01* +G01X2057434Y8527980D01* +G01X2058615Y8527247D01* +G01X2059796Y8526514D01* +G01X2064098Y8523606D01* +G01X2068399Y8520698D01* +G01X2068851Y8520056D01* +G01X2069302Y8519415D01* +G01X2070762Y8518564D01* +G01X2072223Y8517714D01* +G01X2075078Y8515738D01* +G01X2077933Y8513762D01* +G01X2081600Y8511134D01* +G01X2085266Y8508506D01* +G01X2088933Y8506016D01* +G01X2089519Y8505082D01* +G01X2090106Y8504147D01* +G01X2091654Y8504147D01* +G01X2093718Y8502497D01* +G01X2095782Y8500847D01* +G01X2099545Y8498281D01* +G01X2103310Y8495714D01* +G01X2108201Y8492048D01* +G01X2109567Y8491152D01* +G01X2110933Y8490257D01* +G01X2114599Y8487682D01* +G01X2118267Y8485107D01* +G01X2122299Y8482358D01* +G01X2126333Y8479610D01* +G01X2126854Y8478386D01* +G01X2128427Y8477697D01* +G01X2129999Y8477007D01* +G01X2134399Y8473700D01* +G01X2138800Y8470392D01* +G01X2143383Y8467352D01* +G01X2147966Y8464311D01* +G01X2147966Y8463081D01* +G01X2149588Y8463081D01* +G01X2151679Y8461431D01* +G01X2153769Y8459781D01* +G01X2157816Y8456847D01* +G01X2161862Y8453914D01* +G01X2161900Y8449270D01* +G01X2161172Y8449026D01* +G01X2160444Y8448781D01* +G01X2159422Y8445115D01* +G01X2158399Y8441448D01* +G01X2156591Y8436314D01* +G01X2154087Y8428981D01* +G01X2152826Y8425315D01* +G01X2151566Y8421648D01* +G01X2150582Y8418348D01* +G01X2149599Y8415048D01* +G01X2147791Y8409915D01* +G01X2146539Y8406248D01* +G01X2145286Y8402581D01* +G01X2142765Y8395249D01* +G01X2140798Y8388648D01* +G01X2139895Y8386082D01* +G01X2138992Y8383515D01* +G01X2137739Y8379849D01* +G01X2136487Y8376182D01* +G01X2133924Y8368849D01* +G01X2133149Y8365559D01* +G01X2132374Y8362270D01* +G01X2131452Y8360792D01* +G01X2130531Y8359315D01* +G01X2130029Y8356458D01* +G01X2129526Y8353601D01* +G01X2128562Y8352058D01* +G01X2127598Y8350515D01* +G01X2127096Y8347658D01* +G01X2126593Y8344801D01* +G01X2125629Y8343258D01* +G01X2124664Y8341715D01* +G01X2124162Y8338859D01* +G01X2123660Y8336001D01* +G01X2122695Y8334458D01* +G01X2121731Y8332916D01* +G01X2121229Y8330058D01* +G01X2120727Y8327201D01* +G01X2119762Y8325658D01* +G01X2118797Y8324116D01* +G01X2117793Y8318401D01* +G01X2116829Y8316859D01* +G01X2115864Y8315315D01* +G01X2115354Y8312420D01* +G01X2114845Y8309524D01* +G01X2113806Y8308040D01* +G01X2112766Y8306556D01* +G01X2112766Y8302828D01* +G01X2111300Y8300091D01* +G01X2109833Y8297355D01* +G01X2109833Y8294027D01* +G01X2108366Y8291291D01* +G01X2106899Y8288554D01* +G01X2106899Y8285228D01* +G01X2105433Y8282491D01* +G01X2103966Y8279755D01* +G01X2103966Y8276428D01* +G01X2102499Y8273691D01* +G01X2101033Y8270955D01* +G01X2101033Y8267627D01* +G01X2098100Y8262155D01* +G01X2098100Y8258828D01* +G01X2096633Y8256091D01* +G01X2095166Y8253355D01* +G01X2095166Y8250028D01* +G01X2093700Y8247292D01* +G01X2092233Y8244555D01* +G01X2092233Y8241228D01* +G01X2090767Y8238491D01* +G01X2089300Y8235755D01* +G01X2089300Y8232393D01* +G01X2087833Y8229516D01* +G01X2086366Y8226640D01* +G01X2086366Y8223593D01* +G01X2084900Y8220717D01* +G01X2083433Y8217840D01* +G01X2083433Y8214946D01* +G01X2082084Y8211965D01* +G01X2080736Y8208983D01* +G01X2079965Y8206050D01* +G01X2079194Y8203116D01* +G01X2077392Y8197983D01* +G01X2076139Y8194317D01* +G01X2074887Y8190650D01* +G01X2073626Y8186984D01* +G01X2072366Y8183317D01* +G01X2071382Y8180017D01* +G01X2070398Y8176717D01* +G01X2069495Y8174151D01* +G01X2068592Y8171584D01* +G01X2067339Y8167917D01* +G01X2066087Y8164250D01* +G01X2064826Y8160584D01* +G01X2063566Y8156917D01* +G01X2062582Y8153617D01* +G01X2061598Y8150317D01* +G01X2060695Y8147751D01* +G01X2059792Y8145184D01* +G01X2058539Y8141518D01* +G01X2057287Y8137850D01* +G01X2054724Y8130518D01* +G01X2053949Y8127228D01* +G01X2053174Y8123939D01* +G01X2052253Y8122461D01* +G01X2051331Y8120984D01* +G01X2050327Y8115269D01* +G01X2049362Y8113727D01* +G01X2048397Y8112184D01* +G01X2047895Y8109327D01* +G01X2047393Y8106470D01* +G01X2046428Y8104927D01* +G01X2045464Y8103384D01* +G01X2044962Y8100527D01* +G01X2044460Y8097670D01* +G01X2043495Y8096127D01* +G01X2042531Y8094585D01* +G01X2042028Y8091727D01* +G01X2041526Y8088870D01* +G01X2040562Y8087327D01* +G01X2039598Y8085784D01* +G01X2039088Y8082889D01* +G01X2038578Y8079993D01* +G01X2036499Y8077025D01* +G01X2036499Y8073296D01* +G01X2035033Y8070560D01* +G01X2033566Y8067823D01* +G01X2033566Y8064496D01* +G01X2030633Y8059024D01* +G01X2030633Y8055696D01* +G01X2029167Y8052960D01* +G01X2027700Y8050223D01* +G01X2027700Y8046896D01* +G01X2026233Y8044160D01* +G01X2024767Y8041423D01* +G01X2024767Y8038097D01* +G01X2023300Y8035360D01* +G01X2021833Y8032624D01* +G01X2021833Y8029296D01* +G01X2020366Y8026560D01* +G01X2018900Y8023824D01* +G01X2018900Y8020497D01* +G01X2017433Y8017760D01* +G01X2015966Y8015024D01* +G01X2015966Y8011697D01* +G01X2014500Y8008960D01* +G01X2013033Y8006224D01* +G01X2013033Y8002897D01* +G01X2011566Y8000160D01* +G01X2010099Y7997424D01* +G01X2010099Y7994097D01* +G01X2008633Y7991361D01* +G01X2007166Y7988624D01* +G01X2007166Y7985262D01* +G01X2005699Y7982386D01* +G01X2004233Y7979508D01* +G01X2004233Y7976462D01* +G01X2002766Y7973586D01* +G01X2001300Y7970709D01* +G01X2001300Y7967663D01* +G01X1999833Y7964785D01* +G01X1998366Y7961909D01* +G01X1998366Y7958862D01* +G01X1995433Y7953109D01* +G01X1995433Y7950062D01* +G01X1993967Y7947186D01* +G01X1992500Y7944309D01* +G01X1992500Y7941263D01* +G01X1991033Y7938385D01* +G01X1989566Y7935509D01* +G01X1989566Y7932463D01* +G01X1988100Y7929586D01* +G01X1986633Y7926709D01* +G01X1986633Y7923991D01* +G01X1983938Y7917120D01* +G01X1982685Y7913452D01* +G01X1981432Y7909786D01* +G01X1979465Y7903186D01* +G01X1978561Y7900619D01* +G01X1977658Y7898053D01* +G01X1975009Y7890720D01* +G01X1973974Y7885608D01* +G01X1973052Y7884130D01* +G01X1972131Y7882653D01* +G01X1971629Y7879796D01* +G01X1971126Y7876938D01* +G01X1970162Y7875396D01* +G01X1969198Y7873853D01* +G01X1968695Y7870996D01* +G01X1968193Y7868139D01* +G01X1967229Y7866596D01* +G01X1966264Y7865053D01* +G01X1965762Y7862196D01* +G01X1965259Y7859339D01* +G01X1964296Y7857796D01* +G01X1963331Y7856253D01* +G01X1962829Y7853396D01* +G01X1962326Y7850539D01* +G01X1961362Y7848996D01* +G01X1960398Y7847453D01* +G01X1959895Y7844596D01* +G01X1959393Y7841739D01* +G01X1958429Y7840196D01* +G01X1957464Y7838653D01* +G01X1956962Y7835796D01* +G01X1956460Y7832939D01* +G01X1955495Y7831396D01* +G01X1954531Y7829854D01* +G01X1954021Y7826957D01* +G01X1953512Y7824062D01* +G01X1951433Y7821094D01* +G01X1951433Y7817365D01* +G01X1949966Y7814629D01* +G01X1948500Y7811892D01* +G01X1948500Y7808565D01* +G01X1947033Y7805829D01* +G01X1945566Y7803092D01* +G01X1945566Y7799766D01* +G01X1944099Y7797029D01* +G01X1942633Y7794293D01* +G01X1942633Y7790965D01* +G01X1941166Y7788229D01* +G01X1939699Y7785492D01* +G01X1939699Y7782166D01* +G01X1938233Y7779429D01* +G01X1936766Y7776692D01* +G01X1936766Y7773366D01* +G01X1935300Y7770629D01* +G01X1933833Y7767893D01* +G01X1933833Y7764566D01* +G01X1932366Y7761829D01* +G01X1930900Y7759093D01* +G01X1930900Y7755766D01* +G01X1929433Y7753029D01* +G01X1927967Y7750293D01* +G01X1927967Y7746966D01* +G01X1926500Y7744230D01* +G01X1925033Y7741493D01* +G01X1925033Y7738131D01* +G01X1923566Y7735254D01* +G01X1922100Y7732378D01* +G01X1922100Y7729331D01* +G01X1920633Y7726454D01* +G01X1919166Y7723578D01* +G01X1919166Y7720860D01* +G01X1916471Y7713988D01* +G01X1915218Y7710321D01* +G01X1913965Y7706655D01* +G01X1912982Y7703354D01* +G01X1911999Y7700054D01* +G01X1910192Y7694921D01* +G01X1908939Y7691255D01* +G01X1907687Y7687588D01* +G01X1906426Y7683922D01* +G01X1905166Y7680255D01* +G01X1904182Y7676955D01* +G01X1903198Y7673655D01* +G01X1902295Y7671089D01* +G01X1901392Y7668522D01* +G01X1900139Y7664855D01* +G01X1898887Y7661188D01* +G01X1897610Y7657522D01* +G01X1896333Y7653855D01* +G01X1895633Y7650922D01* +G01X1894932Y7647989D01* +G01X1893742Y7645422D01* +G01X1892551Y7642855D01* +G01X1892029Y7641755D01* +G01X1891507Y7640655D01* +G01X1463742Y7640471D01* +G37* +G36* +G01X1859347Y7683922D02* +G01X1067701Y7683553D01* +G01X1064100Y7687155D01* +G01X1064100Y7690893D01* +G01X1062633Y7693630D01* +G01X1061166Y7696366D01* +G01X1061166Y7699693D01* +G01X1059700Y7702430D01* +G01X1058233Y7705166D01* +G01X1058233Y7708493D01* +G01X1055299Y7713966D01* +G01X1055299Y7717695D01* +G01X1054261Y7719179D01* +G01X1053221Y7720663D01* +G01X1052711Y7723559D01* +G01X1052202Y7726454D01* +G01X1051237Y7727997D01* +G01X1050273Y7729540D01* +G01X1049770Y7732397D01* +G01X1049268Y7735254D01* +G01X1048304Y7736797D01* +G01X1047340Y7738340D01* +G01X1046837Y7741197D01* +G01X1046335Y7744054D01* +G01X1045371Y7745597D01* +G01X1044407Y7747140D01* +G01X1043904Y7749997D01* +G01X1043401Y7752854D01* +G01X1042437Y7754397D01* +G01X1041473Y7755940D01* +G01X1040971Y7758797D01* +G01X1040468Y7761654D01* +G01X1039504Y7763197D01* +G01X1038540Y7764739D01* +G01X1037535Y7770454D01* +G01X1036571Y7771997D01* +G01X1035606Y7773540D01* +G01X1035104Y7776397D01* +G01X1034602Y7779254D01* +G01X1033680Y7780731D01* +G01X1032759Y7782209D01* +G01X1031983Y7785498D01* +G01X1031209Y7788787D01* +G01X1029927Y7792454D01* +G01X1028646Y7796121D01* +G01X1027394Y7799787D01* +G01X1026141Y7803454D01* +G01X1025237Y7806020D01* +G01X1024334Y7808587D01* +G01X1022367Y7815187D01* +G01X1019846Y7822520D01* +G01X1018593Y7826187D01* +G01X1017341Y7829854D01* +G01X1015534Y7834987D01* +G01X1014551Y7838287D01* +G01X1013567Y7841587D01* +G01X1011061Y7848920D01* +G01X1008367Y7855792D01* +G01X1008367Y7858510D01* +G01X1006900Y7861387D01* +G01X1005433Y7864263D01* +G01X1005433Y7867310D01* +G01X1003967Y7870186D01* +G01X1002500Y7873063D01* +G01X1002500Y7876425D01* +G01X999566Y7881898D01* +G01X999566Y7885225D01* +G01X998100Y7887961D01* +G01X996633Y7890698D01* +G01X996633Y7894025D01* +G01X995166Y7896762D01* +G01X993700Y7899498D01* +G01X993700Y7902825D01* +G01X992233Y7905561D01* +G01X990766Y7908298D01* +G01X990766Y7911625D01* +G01X989299Y7914361D01* +G01X987833Y7917097D01* +G01X987833Y7920425D01* +G01X986366Y7923161D01* +G01X984899Y7925898D01* +G01X984899Y7929224D01* +G01X983433Y7931961D01* +G01X981966Y7934697D01* +G01X981966Y7938024D01* +G01X980500Y7940761D01* +G01X979033Y7943497D01* +G01X979033Y7946825D01* +G01X977566Y7949561D01* +G01X976100Y7952298D01* +G01X976100Y7956026D01* +G01X975060Y7957510D01* +G01X974021Y7958994D01* +G01X973511Y7961890D01* +G01X973001Y7964785D01* +G01X972038Y7966328D01* +G01X971073Y7967871D01* +G01X970068Y7973586D01* +G01X969104Y7975128D01* +G01X968140Y7976671D01* +G01X967638Y7979528D01* +G01X967135Y7982386D01* +G01X966171Y7983928D01* +G01X965206Y7985471D01* +G01X964704Y7988328D01* +G01X964202Y7991185D01* +G01X963237Y7992728D01* +G01X962273Y7994271D01* +G01X961771Y7997128D01* +G01X961269Y7999985D01* +G01X959339Y8003071D01* +G01X958837Y8005928D01* +G01X958335Y8008785D01* +G01X957371Y8010328D01* +G01X956406Y8011871D01* +G01X955904Y8014728D01* +G01X955402Y8017585D01* +G01X954480Y8019062D01* +G01X953558Y8020540D01* +G01X952784Y8023829D01* +G01X952008Y8027118D01* +G01X950727Y8030785D01* +G01X949446Y8034452D01* +G01X948193Y8038118D01* +G01X946941Y8041785D01* +G01X945139Y8046918D01* +G01X944367Y8049852D01* +G01X943597Y8052785D01* +G01X942248Y8055766D01* +G01X940900Y8058748D01* +G01X940900Y8061641D01* +G01X939433Y8064518D01* +G01X937966Y8067395D01* +G01X937966Y8070441D01* +G01X936500Y8073318D01* +G01X935033Y8076194D01* +G01X935033Y8079241D01* +G01X933566Y8082118D01* +G01X932100Y8084995D01* +G01X932100Y8088041D01* +G01X930633Y8090917D01* +G01X929166Y8093795D01* +G01X929166Y8096841D01* +G01X927700Y8099718D01* +G01X926233Y8102594D01* +G01X926233Y8105641D01* +G01X923299Y8111394D01* +G01X923299Y8114441D01* +G01X921833Y8117317D01* +G01X920366Y8120194D01* +G01X920366Y8123556D01* +G01X918899Y8126292D01* +G01X917433Y8129029D01* +G01X917433Y8132356D01* +G01X915966Y8135093D01* +G01X914500Y8137829D01* +G01X914500Y8141156D01* +G01X913033Y8143892D01* +G01X911567Y8146629D01* +G01X911567Y8149956D01* +G01X910100Y8152692D01* +G01X908633Y8155429D01* +G01X908633Y8158756D01* +G01X907167Y8161492D01* +G01X905700Y8164229D01* +G01X905700Y8167556D01* +G01X904233Y8170292D01* +G01X902766Y8173029D01* +G01X902766Y8176356D01* +G01X901300Y8179092D01* +G01X899833Y8181828D01* +G01X899833Y8185156D01* +G01X898366Y8187892D01* +G01X896900Y8190629D01* +G01X896900Y8193955D01* +G01X895433Y8196692D01* +G01X893966Y8199428D01* +G01X893966Y8202755D01* +G01X892499Y8205492D01* +G01X891033Y8208228D01* +G01X891033Y8211957D01* +G01X888954Y8214925D01* +G01X888445Y8217820D01* +G01X887935Y8220717D01* +G01X886970Y8222260D01* +G01X886006Y8223802D01* +G01X885504Y8226659D01* +G01X885002Y8229516D01* +G01X884037Y8231059D01* +G01X883073Y8232602D01* +G01X882570Y8235459D01* +G01X882068Y8238316D01* +G01X881104Y8239859D01* +G01X880140Y8241402D01* +G01X879637Y8244259D01* +G01X879135Y8247116D01* +G01X878214Y8248593D01* +G01X877292Y8250071D01* +G01X876257Y8255183D01* +G01X874932Y8258849D01* +G01X873607Y8262516D01* +G01X872705Y8265083D01* +G01X871801Y8267650D01* +G01X870817Y8270950D01* +G01X869834Y8274249D01* +G01X868573Y8277916D01* +G01X867313Y8281583D01* +G01X866060Y8285249D01* +G01X864808Y8288916D01* +G01X863000Y8294049D01* +G01X862017Y8297349D01* +G01X861034Y8300649D01* +G01X859773Y8304315D01* +G01X858512Y8307983D01* +G01X856008Y8315315D01* +G01X854201Y8320449D01* +G01X852233Y8327049D01* +G01X850981Y8330715D01* +G01X849728Y8334382D01* +G01X848381Y8337818D01* +G01X847033Y8341254D01* +G01X847033Y8343972D01* +G01X845567Y8346849D01* +G01X844100Y8349725D01* +G01X844100Y8352772D01* +G01X842633Y8355648D01* +G01X841167Y8358526D01* +G01X841167Y8361887D01* +G01X839700Y8364623D01* +G01X838233Y8367360D01* +G01X838233Y8370687D01* +G01X836766Y8373424D01* +G01X835300Y8376160D01* +G01X835300Y8379487D01* +G01X832366Y8384960D01* +G01X832366Y8388287D01* +G01X830900Y8391023D01* +G01X829433Y8393760D01* +G01X829433Y8397087D01* +G01X827966Y8399823D01* +G01X826499Y8402560D01* +G01X826499Y8405887D01* +G01X825033Y8408623D01* +G01X823566Y8411360D01* +G01X823566Y8414687D01* +G01X822099Y8417423D01* +G01X820633Y8420159D01* +G01X820633Y8423436D01* +G01X819218Y8426209D01* +G01X817803Y8428981D01* +G01X817472Y8431760D01* +G01X828805Y8431760D01* +G01X829972Y8428171D01* +G01X831138Y8424581D01* +G01X833833Y8417710D01* +G01X833833Y8414992D01* +G01X835300Y8412115D01* +G01X836766Y8409238D01* +G01X836766Y8406775D01* +G01X838217Y8403578D01* +G01X839667Y8400382D01* +G01X839683Y8398886D01* +G01X839700Y8397392D01* +G01X841167Y8394515D01* +G01X842633Y8391638D01* +G01X842633Y8388592D01* +G01X844100Y8385715D01* +G01X845567Y8382838D01* +G01X845567Y8379477D01* +G01X847033Y8376740D01* +G01X848500Y8374004D01* +G01X848500Y8370677D01* +G01X849966Y8367940D01* +G01X851433Y8365204D01* +G01X851433Y8361876D01* +G01X852899Y8359140D01* +G01X854366Y8356403D01* +G01X854366Y8353077D01* +G01X855833Y8350340D01* +G01X857299Y8347604D01* +G01X857299Y8344277D01* +G01X858766Y8341540D01* +G01X860233Y8338804D01* +G01X860233Y8335477D01* +G01X861700Y8332740D01* +G01X863166Y8330004D01* +G01X863166Y8326677D01* +G01X864633Y8323941D01* +G01X866100Y8321204D01* +G01X866100Y8317877D01* +G01X867566Y8315140D01* +G01X869033Y8312404D01* +G01X869033Y8308675D01* +G01X871112Y8305707D01* +G01X871621Y8302812D01* +G01X872131Y8299916D01* +G01X873095Y8298373D01* +G01X874060Y8296830D01* +G01X874562Y8293973D01* +G01X875064Y8291116D01* +G01X876029Y8289573D01* +G01X876993Y8288030D01* +G01X877496Y8285173D01* +G01X877998Y8282316D01* +G01X878962Y8280773D01* +G01X879926Y8279231D01* +G01X880429Y8276373D01* +G01X880931Y8273516D01* +G01X881895Y8271973D01* +G01X882859Y8270430D01* +G01X883362Y8267573D01* +G01X883864Y8264716D01* +G01X884829Y8263174D01* +G01X885793Y8261631D01* +G01X886295Y8258774D01* +G01X886798Y8255916D01* +G01X887762Y8254373D01* +G01X888726Y8252831D01* +G01X889228Y8249973D01* +G01X889731Y8247116D01* +G01X890652Y8245639D01* +G01X891574Y8244162D01* +G01X892349Y8240873D01* +G01X893124Y8237583D01* +G01X894406Y8233916D01* +G01X895686Y8230250D01* +G01X896939Y8226583D01* +G01X898191Y8222916D01* +G01X899999Y8217783D01* +G01X900982Y8214483D01* +G01X901966Y8211183D01* +G01X903218Y8207517D01* +G01X904471Y8203850D01* +G01X905818Y8200414D01* +G01X907167Y8196978D01* +G01X907167Y8194260D01* +G01X908633Y8191384D01* +G01X910100Y8188507D01* +G01X910100Y8185460D01* +G01X911567Y8182583D01* +G01X913033Y8179707D01* +G01X913033Y8176661D01* +G01X914500Y8173784D01* +G01X915966Y8170907D01* +G01X915966Y8167860D01* +G01X917433Y8164984D01* +G01X918899Y8162107D01* +G01X918899Y8159061D01* +G01X920366Y8156184D01* +G01X921833Y8153307D01* +G01X921833Y8150261D01* +G01X923299Y8147384D01* +G01X924766Y8144507D01* +G01X924766Y8141145D01* +G01X926233Y8138409D01* +G01X927700Y8135672D01* +G01X927700Y8132345D01* +G01X929166Y8129609D01* +G01X930633Y8126873D01* +G01X930633Y8123545D01* +G01X932100Y8120809D01* +G01X933566Y8118072D01* +G01X933566Y8114746D01* +G01X935033Y8112009D01* +G01X936500Y8109273D01* +G01X936500Y8105946D01* +G01X937966Y8103209D01* +G01X939433Y8100473D01* +G01X939433Y8097145D01* +G01X942367Y8091673D01* +G01X942367Y8088346D01* +G01X943833Y8085610D01* +G01X945300Y8082873D01* +G01X945300Y8079546D01* +G01X946766Y8076809D01* +G01X948233Y8074073D01* +G01X948233Y8070746D01* +G01X949700Y8068009D01* +G01X951166Y8065273D01* +G01X951166Y8061545D01* +G01X953245Y8058577D01* +G01X953755Y8055680D01* +G01X954265Y8052785D01* +G01X955228Y8051242D01* +G01X956193Y8049699D01* +G01X956695Y8046842D01* +G01X957198Y8043985D01* +G01X958162Y8042442D01* +G01X959126Y8040900D01* +G01X960131Y8035185D01* +G01X961095Y8033642D01* +G01X962060Y8032099D01* +G01X962562Y8029242D01* +G01X963064Y8026385D01* +G01X964028Y8024842D01* +G01X964993Y8023299D01* +G01X965495Y8020442D01* +G01X965997Y8017585D01* +G01X966962Y8016042D01* +G01X967927Y8014500D01* +G01X968429Y8011642D01* +G01X968931Y8008785D01* +G01X970774Y8005830D01* +G01X971809Y8000718D01* +G01X974458Y7993386D01* +G01X976265Y7988252D01* +G01X978233Y7981652D01* +G01X979493Y7977986D01* +G01X980754Y7974319D01* +G01X983258Y7966986D01* +G01X985065Y7961852D01* +G01X987032Y7955252D01* +G01X989553Y7947919D01* +G01X990806Y7944252D01* +G01X992058Y7940586D01* +G01X992961Y7938019D01* +G01X993865Y7935452D01* +G01X995832Y7928852D01* +G01X998338Y7921519D01* +G01X1001033Y7914648D01* +G01X1001033Y7911930D01* +G01X1002500Y7909053D01* +G01X1003967Y7906176D01* +G01X1003967Y7903129D01* +G01X1005433Y7900253D01* +G01X1006900Y7897376D01* +G01X1006900Y7894014D01* +G01X1008367Y7891278D01* +G01X1009833Y7888542D01* +G01X1009833Y7885214D01* +G01X1011300Y7882478D01* +G01X1012766Y7879741D01* +G01X1012766Y7876415D01* +G01X1014233Y7873678D01* +G01X1015700Y7870941D01* +G01X1015700Y7867615D01* +G01X1017166Y7864878D01* +G01X1018633Y7862142D01* +G01X1018633Y7858814D01* +G01X1020099Y7856078D01* +G01X1021566Y7853341D01* +G01X1021566Y7850015D01* +G01X1023033Y7847278D01* +G01X1024499Y7844542D01* +G01X1024499Y7841215D01* +G01X1025966Y7838478D01* +G01X1027433Y7835742D01* +G01X1027433Y7832414D01* +G01X1028900Y7829678D01* +G01X1030366Y7826942D01* +G01X1030366Y7823213D01* +G01X1032445Y7820245D01* +G01X1032954Y7817349D01* +G01X1033464Y7814454D01* +G01X1034429Y7812911D01* +G01X1035393Y7811368D01* +G01X1035895Y7808511D01* +G01X1036397Y7805654D01* +G01X1038326Y7802568D01* +G01X1038829Y7799711D01* +G01X1039331Y7796854D01* +G01X1040295Y7795311D01* +G01X1041260Y7793768D01* +G01X1041762Y7790911D01* +G01X1042264Y7788054D01* +G01X1043229Y7786511D01* +G01X1044193Y7784968D01* +G01X1044696Y7782111D01* +G01X1045198Y7779254D01* +G01X1046119Y7777776D01* +G01X1047041Y7776299D01* +G01X1047816Y7773010D01* +G01X1048591Y7769721D01* +G01X1049872Y7766054D01* +G01X1051153Y7762387D01* +G01X1052406Y7758721D01* +G01X1053659Y7755054D01* +G01X1054562Y7752488D01* +G01X1055465Y7749921D01* +G01X1057432Y7743321D01* +G01X1058693Y7739655D01* +G01X1059953Y7735987D01* +G01X1061206Y7732321D01* +G01X1062458Y7728655D01* +G01X1063362Y7726088D01* +G01X1064265Y7723521D01* +G01X1066232Y7716921D01* +G01X1068738Y7709588D01* +G01X1071433Y7702716D01* +G01X1071433Y7700363D01* +G01X1071433Y7700363D01* +G01X1072915Y7697458D01* +G01X1074397Y7694553D01* +G01X1463517Y7694738D01* +G01X1852637Y7694921D01* +G01X1854429Y7701977D01* +G01X1855264Y7702813D01* +G01X1856100Y7703648D01* +G01X1856100Y7707291D01* +G01X1857448Y7710273D01* +G01X1858797Y7713255D01* +G01X1859568Y7716188D01* +G01X1860338Y7719121D01* +G01X1861240Y7721688D01* +G01X1862141Y7724255D01* +G01X1864646Y7731588D01* +G01X1865927Y7735254D01* +G01X1867208Y7738921D01* +G01X1867984Y7742210D01* +G01X1868759Y7745500D01* +G01X1869680Y7746977D01* +G01X1870602Y7748454D01* +G01X1871104Y7751311D01* +G01X1871606Y7754169D01* +G01X1872570Y7755712D01* +G01X1873535Y7757254D01* +G01X1874037Y7760112D01* +G01X1874540Y7762968D01* +G01X1875504Y7764511D01* +G01X1876468Y7766054D01* +G01X1876971Y7768911D01* +G01X1877473Y7771769D01* +G01X1878437Y7773311D01* +G01X1879402Y7774854D01* +G01X1879904Y7777711D01* +G01X1880406Y7780568D01* +G01X1881371Y7782111D01* +G01X1882335Y7783654D01* +G01X1882837Y7786511D01* +G01X1883339Y7789368D01* +G01X1884304Y7790911D01* +G01X1885269Y7792454D01* +G01X1885771Y7795311D01* +G01X1886273Y7798168D01* +G01X1887238Y7799711D01* +G01X1888202Y7801253D01* +G01X1889206Y7806968D01* +G01X1890171Y7808511D01* +G01X1891135Y7810054D01* +G01X1891645Y7812949D01* +G01X1892154Y7815846D01* +G01X1893193Y7817330D01* +G01X1894233Y7818814D01* +G01X1894233Y7822542D01* +G01X1897167Y7828015D01* +G01X1897167Y7831342D01* +G01X1898633Y7834078D01* +G01X1900100Y7836815D01* +G01X1900100Y7840142D01* +G01X1901566Y7842878D01* +G01X1903033Y7845615D01* +G01X1903033Y7848941D01* +G01X1904499Y7851678D01* +G01X1905966Y7854414D01* +G01X1905966Y7857742D01* +G01X1907433Y7860478D01* +G01X1908899Y7863214D01* +G01X1908899Y7866542D01* +G01X1910366Y7869278D01* +G01X1911833Y7872015D01* +G01X1911833Y7875341D01* +G01X1913300Y7878078D01* +G01X1914766Y7880814D01* +G01X1914766Y7884141D01* +G01X1916233Y7886878D01* +G01X1917700Y7889614D01* +G01X1917700Y7892941D01* +G01X1919166Y7895678D01* +G01X1920633Y7898414D01* +G01X1920633Y7901776D01* +G01X1922100Y7904653D01* +G01X1923566Y7907530D01* +G01X1923566Y7910576D01* +G01X1925033Y7913452D01* +G01X1926500Y7916330D01* +G01X1926500Y7919047D01* +G01X1929195Y7925919D01* +G01X1930447Y7929586D01* +G01X1931700Y7933253D01* +G01X1932684Y7936552D01* +G01X1933668Y7939852D01* +G01X1934571Y7942419D01* +G01X1935474Y7944986D01* +G01X1936727Y7948652D01* +G01X1937979Y7952319D01* +G01X1940500Y7959652D01* +G01X1942467Y7966252D01* +G01X1944275Y7971386D01* +G01X1945527Y7975052D01* +G01X1946779Y7978719D01* +G01X1949342Y7986052D01* +G01X1950117Y7989341D01* +G01X1950892Y7992631D01* +G01X1951813Y7994108D01* +G01X1952735Y7995585D01* +G01X1953238Y7998443D01* +G01X1953740Y8001299D01* +G01X1954704Y8002842D01* +G01X1955668Y8004386D01* +G01X1956171Y8007242D01* +G01X1956673Y8010100D01* +G01X1957638Y8011642D01* +G01X1958601Y8013185D01* +G01X1959104Y8016042D01* +G01X1959606Y8018900D01* +G01X1960571Y8020442D01* +G01X1961535Y8021985D01* +G01X1962037Y8024842D01* +G01X1962540Y8027699D01* +G01X1963504Y8029242D01* +G01X1964468Y8030785D01* +G01X1964971Y8033642D01* +G01X1965473Y8036499D01* +G01X1967402Y8039585D01* +G01X1967904Y8042442D01* +G01X1968407Y8045299D01* +G01X1969370Y8046842D01* +G01X1970335Y8048385D01* +G01X1970837Y8051242D01* +G01X1971340Y8054099D01* +G01X1972304Y8055642D01* +G01X1973268Y8057185D01* +G01X1973778Y8060081D01* +G01X1974287Y8062976D01* +G01X1976366Y8065944D01* +G01X1976366Y8069673D01* +G01X1977833Y8072409D01* +G01X1979300Y8075146D01* +G01X1979300Y8078473D01* +G01X1980766Y8081210D01* +G01X1982233Y8083946D01* +G01X1982233Y8087273D01* +G01X1983700Y8090009D01* +G01X1985166Y8092746D01* +G01X1985166Y8096073D01* +G01X1986633Y8098809D01* +G01X1988100Y8101546D01* +G01X1988100Y8104873D01* +G01X1989566Y8107609D01* +G01X1991033Y8110346D01* +G01X1991058Y8111998D01* +G01X1991083Y8113651D01* +G01X1992500Y8116584D01* +G01X1993916Y8119518D01* +G01X1993967Y8120984D01* +G01X1994016Y8122451D01* +G01X1995433Y8125384D01* +G01X1996850Y8128317D01* +G01X1996875Y8129648D01* +G01X1996900Y8130979D01* +G01X1999595Y8137850D01* +G01X2000847Y8141518D01* +G01X2002100Y8145184D01* +G01X2003084Y8148484D01* +G01X2004067Y8151784D01* +G01X2004971Y8154350D01* +G01X2005874Y8156917D01* +G01X2007127Y8160584D01* +G01X2008379Y8164250D01* +G01X2009640Y8167917D01* +G01X2010900Y8171584D01* +G01X2011884Y8174883D01* +G01X2012867Y8178183D01* +G01X2014675Y8183317D01* +G01X2015927Y8186984D01* +G01X2017179Y8190650D01* +G01X2018439Y8194317D01* +G01X2019701Y8197983D01* +G01X2020684Y8201283D01* +G01X2021667Y8204583D01* +G01X2023474Y8209717D01* +G01X2024727Y8213383D01* +G01X2025979Y8217050D01* +G01X2027261Y8220717D01* +G01X2028542Y8224383D01* +G01X2030092Y8230962D01* +G01X2031014Y8232439D01* +G01X2031935Y8233916D01* +G01X2032437Y8236774D01* +G01X2032940Y8239631D01* +G01X2033904Y8241174D01* +G01X2034868Y8242717D01* +G01X2035370Y8245573D01* +G01X2035873Y8248431D01* +G01X2036837Y8249973D01* +G01X2037802Y8251516D01* +G01X2038304Y8254373D01* +G01X2038806Y8257231D01* +G01X2039770Y8258774D01* +G01X2040735Y8260316D01* +G01X2041237Y8263174D01* +G01X2041740Y8266030D01* +G01X2042704Y8267573D01* +G01X2043669Y8269116D01* +G01X2044171Y8271973D01* +G01X2044673Y8274830D01* +G01X2045637Y8276373D01* +G01X2046602Y8277916D01* +G01X2047111Y8280812D01* +G01X2047621Y8283708D01* +G01X2048660Y8285191D01* +G01X2049700Y8286675D01* +G01X2049700Y8290404D01* +G01X2051166Y8293141D01* +G01X2052633Y8295877D01* +G01X2052633Y8299204D01* +G01X2054100Y8301941D01* +G01X2055566Y8304677D01* +G01X2055566Y8308004D01* +G01X2057033Y8310740D01* +G01X2058500Y8313477D01* +G01X2058500Y8316804D01* +G01X2059967Y8319541D01* +G01X2061433Y8322277D01* +G01X2061433Y8325604D01* +G01X2062900Y8328340D01* +G01X2064366Y8331077D01* +G01X2064366Y8334404D01* +G01X2065833Y8337140D01* +G01X2067300Y8339877D01* +G01X2067300Y8343204D01* +G01X2068766Y8345940D01* +G01X2070233Y8348677D01* +G01X2070233Y8352004D01* +G01X2071699Y8354740D01* +G01X2073166Y8357477D01* +G01X2073166Y8360838D01* +G01X2074633Y8363715D01* +G01X2076099Y8366592D01* +G01X2076099Y8369639D01* +G01X2079033Y8375392D01* +G01X2079033Y8378285D01* +G01X2080382Y8381267D01* +G01X2081730Y8384249D01* +G01X2082501Y8387182D01* +G01X2083272Y8390115D01* +G01X2084173Y8392682D01* +G01X2085074Y8395249D01* +G01X2086327Y8398915D01* +G01X2087580Y8402581D01* +G01X2088840Y8406248D01* +G01X2090100Y8409915D01* +G01X2091084Y8413215D01* +G01X2092068Y8416514D01* +G01X2092971Y8419081D01* +G01X2093874Y8421648D01* +G01X2096633Y8429010D01* +G01X2096633Y8432957D01* +G01X2095716Y8433728D01* +G01X2094799Y8434499D01* +G01X2089465Y8438515D01* +G01X2088099Y8439439D01* +G01X2086733Y8440363D01* +G01X2081600Y8443988D01* +G01X2076466Y8447613D01* +G01X2075000Y8448793D01* +G01X2073166Y8450043D01* +G01X2071333Y8451292D01* +G01X2065100Y8455695D01* +G01X2058866Y8460097D01* +G01X2054833Y8462846D01* +G01X2050800Y8465595D01* +G01X2050213Y8466538D01* +G01X2049627Y8467481D01* +G01X2048098Y8467481D01* +G01X2046149Y8468973D01* +G01X2044199Y8470465D01* +G01X2040498Y8473190D01* +G01X2036796Y8475914D01* +G01X2035650Y8476648D01* +G01X2034506Y8477381D01* +G01X2030266Y8480211D01* +G01X2029516Y8480996D01* +G01X2028766Y8481781D01* +G01X2027585Y8482514D01* +G01X2026404Y8483247D01* +G01X2022101Y8486156D01* +G01X2017799Y8489063D01* +G01X2017349Y8489705D01* +G01X2016898Y8490347D01* +G01X2015437Y8491197D01* +G01X2013976Y8492048D01* +G01X2011121Y8494023D01* +G01X2008266Y8495999D01* +G01X2004600Y8498627D01* +G01X2000933Y8501255D01* +G01X1999100Y8502501D01* +G01X1997266Y8503747D01* +G01X1996364Y8505013D01* +G01X1994863Y8505863D01* +G01X1993362Y8506714D01* +G01X1986999Y8511233D01* +G01X1983700Y8513545D01* +G01X1980400Y8515858D01* +G01X1974167Y8520244D01* +G01X1967933Y8524630D01* +G01X1963900Y8527390D01* +G01X1959866Y8530151D01* +G01X1959346Y8531375D01* +G01X1957773Y8532064D01* +G01X1956200Y8532754D01* +G01X1951799Y8536061D01* +G01X1947399Y8539369D01* +G01X1942816Y8542409D01* +G01X1938233Y8545450D01* +G01X1938233Y8546680D01* +G01X1936632Y8546680D01* +G01X1934682Y8548172D01* +G01X1932733Y8549664D01* +G01X1929031Y8552389D01* +G01X1925329Y8555113D01* +G01X1923898Y8556047D01* +G01X1922466Y8556980D01* +G01X1920083Y8558503D01* +G01X1917700Y8560025D01* +G01X1917700Y8561346D01* +G01X1916210Y8561346D01* +G01X1911638Y8564619D01* +G01X1907066Y8567891D01* +G01X1904920Y8569780D01* +G01X1903675Y8570513D01* +G01X1902429Y8571247D01* +G01X1899108Y8573575D01* +G01X1895789Y8575904D01* +G01X1893361Y8577609D01* +G01X1890933Y8579313D01* +G01X1887104Y8582247D01* +G01X1885718Y8583152D01* +G01X1884333Y8584057D01* +G01X1881951Y8585719D01* +G01X1879569Y8587380D01* +G01X1874251Y8591034D01* +G01X1868933Y8594689D01* +G01X1868566Y8595180D01* +G01X1868200Y8595672D01* +G01X1862333Y8599750D01* +G01X1856466Y8603830D01* +G01X1852433Y8606578D01* +G01X1848400Y8609327D01* +G01X1847813Y8610270D01* +G01X1847227Y8611213D01* +G01X1845698Y8611213D01* +G01X1841800Y8614196D01* +G01X1838098Y8616921D01* +G01X1834396Y8619646D01* +G01X1833251Y8620379D01* +G01X1832106Y8621113D01* +G01X1827866Y8623944D01* +G01X1827116Y8624728D01* +G01X1826366Y8625513D01* +G01X1825185Y8626246D01* +G01X1824003Y8626979D01* +G01X1819702Y8629886D01* +G01X1815399Y8632794D01* +G01X1814813Y8633736D01* +G01X1814227Y8634679D01* +G01X1812678Y8634679D01* +G01X1810615Y8636329D01* +G01X1808551Y8637979D01* +G01X1804787Y8640546D01* +G01X1801023Y8643113D01* +G01X1796132Y8646779D01* +G01X1794766Y8647704D01* +G01X1793400Y8648628D01* +G01X1788267Y8652253D01* +G01X1783133Y8655877D01* +G01X1781666Y8657057D01* +G01X1779833Y8658308D01* +G01X1778000Y8659557D01* +G01X1771766Y8663960D01* +G01X1765533Y8668361D01* +G01X1761499Y8671111D01* +G01X1757467Y8673860D01* +G01X1756880Y8674803D01* +G01X1756294Y8675746D01* +G01X1754765Y8675746D01* +G01X1752816Y8677237D01* +G01X1750866Y8678730D01* +G01X1747164Y8681454D01* +G01X1743463Y8684179D01* +G01X1742317Y8684913D01* +G01X1741172Y8685645D01* +G01X1739053Y8687061D01* +G01X1736933Y8688476D01* +G01X1736183Y8689261D01* +G01X1735433Y8690046D01* +G01X1734252Y8690779D01* +G01X1733070Y8691512D01* +G01X1728768Y8694420D01* +G01X1724466Y8697328D01* +G01X1724015Y8697970D01* +G01X1723564Y8698611D01* +G01X1722103Y8699462D01* +G01X1720643Y8700312D01* +G01X1717788Y8702288D01* +G01X1714933Y8704264D01* +G01X1711266Y8706892D01* +G01X1707599Y8709520D01* +G01X1703933Y8712010D01* +G01X1703347Y8712944D01* +G01X1702760Y8713878D01* +G01X1701211Y8713878D01* +G01X1699148Y8715529D01* +G01X1697084Y8717179D01* +G01X1693320Y8719745D01* +G01X1689556Y8722312D01* +G01X1684666Y8725978D01* +G01X1683299Y8726874D01* +G01X1681933Y8727769D01* +G01X1678266Y8730344D01* +G01X1674600Y8732919D01* +G01X1670566Y8735668D01* +G01X1666533Y8738416D01* +G01X1666013Y8739640D01* +G01X1664440Y8740329D01* +G01X1662866Y8741019D01* +G01X1658466Y8744312D01* +G01X1654066Y8747604D01* +G01X1650033Y8750332D01* +G01X1646000Y8753059D01* +G01X1645413Y8754002D01* +G01X1644827Y8754945D01* +G01X1643299Y8754945D01* +G01X1641349Y8756437D01* +G01X1639400Y8757929D01* +G01X1635698Y8760653D01* +G01X1631996Y8763378D01* +G01X1630564Y8764312D01* +G01X1629133Y8765245D01* +G01X1626750Y8766768D01* +G01X1624366Y8768290D01* +G01X1624366Y8769611D01* +G01X1622876Y8769611D01* +G01X1618305Y8772884D01* +G01X1613733Y8776156D01* +G01X1611587Y8778045D01* +G01X1610341Y8778778D01* +G01X1609096Y8779511D01* +G01X1602455Y8784168D01* +G01X1600027Y8785873D01* +G01X1597600Y8787578D01* +G01X1593770Y8790511D01* +G01X1592385Y8791417D01* +G01X1590999Y8792322D01* +G01X1588617Y8793984D01* +G01X1586235Y8795645D01* +G01X1580917Y8799299D01* +G01X1575599Y8802954D01* +G01X1574867Y8803936D01* +G01X1569000Y8808015D01* +G01X1563133Y8812094D01* +G01X1559099Y8814843D01* +G01X1555067Y8817591D01* +G01X1554480Y8818534D01* +G01X1553893Y8819478D01* +G01X1552365Y8819478D01* +G01X1550416Y8820970D01* +G01X1548466Y8822461D01* +G01X1544764Y8825186D01* +G01X1541063Y8827911D01* +G01X1538772Y8829378D01* +G01X1536652Y8830793D01* +G01X1534533Y8832208D01* +G01X1533783Y8832993D01* +G01X1533033Y8833777D01* +G01X1531851Y8834511D01* +G01X1530670Y8835244D01* +G01X1526368Y8838151D01* +G01X1522066Y8841058D01* +G01X1521480Y8842001D01* +G01X1520893Y8842944D01* +G01X1519345Y8842944D01* +G01X1517281Y8844594D01* +G01X1515218Y8846244D01* +G01X1507689Y8851378D01* +G01X1502798Y8855044D01* +G01X1501433Y8855969D01* +G01X1500066Y8856892D01* +G01X1494933Y8860544D01* +G01X1489799Y8864196D01* +G01X1488434Y8865119D01* +G01X1487067Y8866044D01* +G01X1484666Y8867877D01* +G01X1482266Y8869710D01* +G01X1479533Y8871501D01* +G01X1475866Y8874070D01* +G01X1472200Y8876639D01* +G01X1468937Y8878932D01* +G01X1465674Y8881224D01* +G01X1462449Y8882451D01* +G01X1457874Y8879381D01* +G01X1453299Y8876311D01* +G01X1452151Y8875577D01* +G01X1451003Y8874844D01* +G01X1443599Y8869394D01* +G01X1441651Y8867903D01* +G01X1439701Y8866410D01* +G01X1438100Y8866410D01* +G01X1438100Y8865089D01* +G01X1435716Y8863567D01* +G01X1433333Y8862044D01* +G01X1430470Y8860177D01* +G01X1426768Y8857453D01* +G01X1423067Y8854728D01* +G01X1421117Y8853236D01* +G01X1419168Y8851744D01* +G01X1417639Y8851744D01* +G01X1417053Y8850801D01* +G01X1416466Y8849858D01* +G01X1408399Y8844360D01* +G01X1402166Y8839958D01* +G01X1395933Y8835556D01* +G01X1394100Y8834306D01* +G01X1392267Y8833056D01* +G01X1390800Y8831876D01* +G01X1385666Y8828251D01* +G01X1380533Y8824627D01* +G01X1379167Y8823702D01* +G01X1377801Y8822777D01* +G01X1372910Y8819111D01* +G01X1365381Y8813978D01* +G01X1363318Y8812328D01* +G01X1361254Y8810678D01* +G01X1359706Y8810678D01* +G01X1359120Y8809735D01* +G01X1358533Y8808792D01* +G01X1354231Y8805885D01* +G01X1349929Y8802978D01* +G01X1348748Y8802244D01* +G01X1347567Y8801511D01* +G01X1346816Y8800727D01* +G01X1346067Y8799942D01* +G01X1341827Y8797111D01* +G01X1340682Y8796378D01* +G01X1339537Y8795645D01* +G01X1332133Y8790195D01* +G01X1330184Y8788703D01* +G01X1328234Y8787211D01* +G01X1326706Y8787211D01* +G01X1326119Y8786268D01* +G01X1325533Y8785325D01* +G01X1317466Y8779828D01* +G01X1311599Y8775749D01* +G01X1305733Y8771671D01* +G01X1305366Y8771166D01* +G01X1305000Y8770661D01* +G01X1300966Y8767923D01* +G01X1296933Y8765185D01* +G01X1289600Y8760036D01* +G01X1286829Y8758245D01* +G01X1284914Y8756778D01* +G01X1283000Y8755312D01* +G01X1278144Y8751902D01* +G01X1271504Y8747245D01* +G01X1270258Y8746511D01* +G01X1269012Y8745779D01* +G01X1267939Y8744834D01* +G01X1266866Y8743890D01* +G01X1262295Y8740617D01* +G01X1257723Y8737345D01* +G01X1256233Y8737345D01* +G01X1256233Y8736023D01* +G01X1253850Y8734501D01* +G01X1251466Y8732979D01* +G01X1250035Y8732046D01* +G01X1248603Y8731112D01* +G01X1244901Y8728387D01* +G01X1241199Y8725662D01* +G01X1239251Y8724170D01* +G01X1237301Y8722679D01* +G01X1235700Y8722679D01* +G01X1235700Y8721448D01* +G01X1231116Y8718408D01* +G01X1226533Y8715367D01* +G01X1222133Y8712060D01* +G01X1217733Y8708752D01* +G01X1216160Y8708063D01* +G01X1214587Y8707374D01* +G01X1214326Y8706761D01* +G01X1214067Y8706149D01* +G01X1205999Y8700653D01* +G01X1202333Y8698077D01* +G01X1198667Y8695502D01* +G01X1197300Y8694608D01* +G01X1195934Y8693712D01* +G01X1191043Y8690046D01* +G01X1183515Y8684913D01* +G01X1181452Y8683262D01* +G01X1179388Y8681612D01* +G01X1177839Y8681612D01* +G01X1177253Y8680678D01* +G01X1176666Y8679744D01* +G01X1173000Y8677253D01* +G01X1169333Y8674626D01* +G01X1165666Y8671997D01* +G01X1162811Y8670021D01* +G01X1159957Y8668046D01* +G01X1157035Y8666345D01* +G01X1156584Y8665703D01* +G01X1156133Y8665062D01* +G01X1151831Y8662154D01* +G01X1147529Y8659246D01* +G01X1146348Y8658513D01* +G01X1145166Y8657779D01* +G01X1144417Y8656994D01* +G01X1143667Y8656210D01* +G01X1139427Y8653379D01* +G01X1137136Y8651913D01* +G01X1133435Y8649188D01* +G01X1129733Y8646463D01* +G01X1127783Y8644971D01* +G01X1125835Y8643479D01* +G01X1124306Y8643479D01* +G01X1123719Y8642536D01* +G01X1123133Y8641593D01* +G01X1115066Y8636095D01* +G01X1108833Y8631693D01* +G01X1102600Y8627291D01* +G01X1100766Y8626041D01* +G01X1098933Y8624791D01* +G01X1098199Y8624201D01* +G01X1097467Y8623611D01* +G01X1092333Y8619986D01* +G01X1087200Y8616362D01* +G01X1084467Y8614513D01* +G01X1082022Y8612679D01* +G01X1079577Y8610846D01* +G01X1072048Y8605713D01* +G01X1069985Y8604063D01* +G01X1067921Y8602413D01* +G01X1066373Y8602413D01* +G01X1065786Y8601470D01* +G01X1065200Y8600527D01* +G01X1060898Y8597620D01* +G01X1056596Y8594713D01* +G01X1055415Y8593979D01* +G01X1054233Y8593247D01* +G01X1053483Y8592462D01* +G01X1052733Y8591677D01* +G01X1050614Y8590262D01* +G01X1048494Y8588846D01* +G01X1047349Y8588113D01* +G01X1046203Y8587380D01* +G01X1042502Y8584655D01* +G01X1038800Y8581930D01* +G01X1036850Y8580438D01* +G01X1034901Y8578947D01* +G01X1033373Y8578947D01* +G01X1032199Y8577061D01* +G01X1028166Y8574312D01* +G01X1024133Y8571563D01* +G01X1012399Y8563406D01* +G01X1012033Y8562901D01* +G01X1011666Y8562396D01* +G01X1007633Y8559658D01* +G01X1003600Y8556921D01* +G01X996267Y8551771D01* +G01X993534Y8549980D01* +G01X988643Y8546314D01* +G01X984879Y8543747D01* +G01X981115Y8541180D01* +G01X979051Y8539530D01* +G01X976988Y8537880D01* +G01X975439Y8537880D01* +G01X974853Y8536946D01* +G01X974266Y8536012D01* +G01X970600Y8533529D01* +G01X967457Y8531304D01* +G01X964314Y8529081D01* +G01X962900Y8529081D01* +G01X962900Y8527758D01* +G01X960516Y8526236D01* +G01X958133Y8524714D01* +G01X956702Y8523781D01* +G01X955270Y8522847D01* +G01X951568Y8520122D01* +G01X947866Y8517397D01* +G01X943967Y8514414D01* +G01X942367Y8514414D01* +G01X942367Y8513092D01* +G01X939983Y8511570D01* +G01X937600Y8510048D01* +G01X936168Y8509114D01* +G01X934736Y8508180D01* +G01X931035Y8505456D01* +G01X927333Y8502731D01* +G01X925383Y8501239D01* +G01X923435Y8499747D01* +G01X921906Y8499747D01* +G01X921319Y8498804D01* +G01X920733Y8497861D01* +G01X916700Y8495124D01* +G01X912666Y8492388D01* +G01X909000Y8489813D01* +G01X905333Y8487238D01* +G01X903967Y8486343D01* +G01X902600Y8485448D01* +G01X897266Y8481432D01* +G01X895799Y8480314D01* +G01X892499Y8478135D01* +G01X889200Y8475955D01* +G01X887285Y8474468D01* +G01X885370Y8472981D01* +G01X882067Y8470781D01* +G01X879622Y8468948D01* +G01X877176Y8467114D01* +G01X873413Y8464547D01* +G01X869648Y8461981D01* +G01X867584Y8460331D01* +G01X865521Y8458681D01* +G01X863973Y8458681D01* +G01X863386Y8457738D01* +G01X862800Y8456795D01* +G01X858498Y8453888D01* +G01X854196Y8450981D01* +G01X853014Y8450248D01* +G01X851833Y8449515D01* +G01X851083Y8448730D01* +G01X850333Y8447945D01* +G01X848213Y8446530D01* +G01X846094Y8445115D01* +G01X843803Y8443648D01* +G01X840102Y8440923D01* +G01X836400Y8438198D01* +G01X834450Y8436707D01* +G01X832501Y8435214D01* +G01X831068Y8435214D01* +G01X828805Y8431760D01* +G01X817472Y8431760D01* +G01X817312Y8433101D01* +G01X816821Y8437222D01* +G01X817811Y8438060D01* +G01X818799Y8438899D01* +G01X821511Y8440907D01* +G01X824223Y8442914D01* +G01X831710Y8448048D01* +G01X836600Y8451714D01* +G01X838233Y8452815D01* +G01X839865Y8453914D01* +G01X844756Y8457581D01* +G01X848521Y8460147D01* +G01X852284Y8462714D01* +G01X854348Y8464364D01* +G01X856412Y8466014D01* +G01X857960Y8466014D01* +G01X859133Y8467900D01* +G01X863435Y8470807D01* +G01X867737Y8473714D01* +G01X870099Y8475181D01* +G01X870850Y8475965D01* +G01X871600Y8476750D01* +G01X875839Y8479581D01* +G01X876984Y8480314D01* +G01X878129Y8481048D01* +G01X881831Y8483772D01* +G01X885533Y8486497D01* +G01X887482Y8487989D01* +G01X889432Y8489481D01* +G01X890960Y8489481D01* +G01X891546Y8490424D01* +G01X892133Y8491367D01* +G01X896166Y8494104D01* +G01X900199Y8496840D01* +G01X903866Y8499416D01* +G01X907533Y8501990D01* +G01X908900Y8502885D01* +G01X910265Y8503780D01* +G01X915067Y8507447D01* +G01X916685Y8508547D01* +G01X918302Y8509647D01* +G01X926943Y8515880D01* +G01X928360Y8515880D01* +G01X928946Y8516815D01* +G01X929533Y8517749D01* +G01X933200Y8520240D01* +G01X936866Y8522867D01* +G01X940533Y8525495D01* +G01X943388Y8527471D01* +G01X946243Y8529447D01* +G01X947704Y8530297D01* +G01X949164Y8531147D01* +G01X949615Y8531789D01* +G01X950067Y8532431D01* +G01X954368Y8535339D01* +G01X958670Y8538247D01* +G01X961032Y8539714D01* +G01X961783Y8540498D01* +G01X962533Y8541283D01* +G01X966772Y8544113D01* +G01X967918Y8544847D01* +G01X969063Y8545580D01* +G01X972765Y8548305D01* +G01X976466Y8551030D01* +G01X978415Y8552521D01* +G01X980365Y8554014D01* +G01X981893Y8554014D01* +G01X982480Y8554957D01* +G01X983066Y8555900D01* +G01X991133Y8561397D01* +G01X997366Y8565800D01* +G01X1003600Y8570201D01* +G01X1005433Y8571452D01* +G01X1007266Y8572701D01* +G01X1008733Y8573820D01* +G01X1013078Y8577117D01* +G01X1017423Y8580413D01* +G01X1018528Y8580413D01* +G01X1019497Y8581339D01* +G01X1020466Y8582266D01* +G01X1022300Y8583519D01* +G01X1024133Y8584772D01* +G01X1027799Y8587400D01* +G01X1031467Y8590028D01* +G01X1034321Y8592004D01* +G01X1037176Y8593979D01* +G01X1038637Y8594830D01* +G01X1040097Y8595681D01* +G01X1040549Y8596322D01* +G01X1041000Y8596964D01* +G01X1045301Y8599872D01* +G01X1049603Y8602780D01* +G01X1050785Y8603513D01* +G01X1051966Y8604246D01* +G01X1052716Y8605031D01* +G01X1053466Y8605816D01* +G01X1057705Y8608647D01* +G01X1058851Y8609379D01* +G01X1059996Y8610113D01* +G01X1067400Y8615562D01* +G01X1069349Y8617055D01* +G01X1071298Y8618546D01* +G01X1072827Y8618546D01* +G01X1073413Y8619489D01* +G01X1074000Y8620432D01* +G01X1082067Y8625930D01* +G01X1087933Y8630008D01* +G01X1093799Y8634087D01* +G01X1094166Y8634592D01* +G01X1094533Y8635097D01* +G01X1098566Y8637835D01* +G01X1102600Y8640572D01* +G01X1109933Y8645722D01* +G01X1111318Y8646617D01* +G01X1112703Y8647513D01* +G01X1114619Y8648980D01* +G01X1116533Y8650446D01* +G01X1121388Y8653856D01* +G01X1128029Y8658513D01* +G01X1129274Y8659246D01* +G01X1130520Y8659979D01* +G01X1131593Y8660924D01* +G01X1132667Y8661868D01* +G01X1137238Y8665140D01* +G01X1141810Y8668412D01* +G01X1143300Y8668412D01* +G01X1143300Y8669734D01* +G01X1145683Y8671256D01* +G01X1148067Y8672778D01* +G01X1149498Y8673712D01* +G01X1150929Y8674646D01* +G01X1158333Y8680095D01* +G01X1160282Y8681587D01* +G01X1162231Y8683079D01* +G01X1163833Y8683079D01* +G01X1163833Y8684309D01* +G01X1168416Y8687350D01* +G01X1173000Y8690391D01* +G01X1177400Y8693698D01* +G01X1181800Y8697005D01* +G01X1183373Y8697694D01* +G01X1184946Y8698384D01* +G01X1185206Y8698996D01* +G01X1185466Y8699608D01* +G01X1193533Y8705105D01* +G01X1197200Y8707680D01* +G01X1200866Y8710255D01* +G01X1202233Y8711150D01* +G01X1203599Y8712045D01* +G01X1208489Y8715712D01* +G01X1216018Y8720845D01* +G01X1218081Y8722495D01* +G01X1220145Y8724145D01* +G01X1221694Y8724145D01* +G01X1222280Y8725080D01* +G01X1222866Y8726014D01* +G01X1226533Y8728504D01* +G01X1230199Y8731132D01* +G01X1233866Y8733760D01* +G01X1236721Y8735736D01* +G01X1239576Y8737712D01* +G01X1242498Y8739412D01* +G01X1242949Y8740054D01* +G01X1243400Y8740696D01* +G01X1247701Y8743604D01* +G01X1252003Y8746511D01* +G01X1254366Y8747978D01* +G01X1255116Y8748763D01* +G01X1255866Y8749547D01* +G01X1260105Y8752378D01* +G01X1261251Y8753112D01* +G01X1262396Y8753845D01* +G01X1269800Y8759294D01* +G01X1271749Y8760786D01* +G01X1273698Y8762278D01* +G01X1275227Y8762278D01* +G01X1275813Y8763221D01* +G01X1276399Y8764164D01* +G01X1284466Y8769662D01* +G01X1290700Y8774064D01* +G01X1296933Y8778466D01* +G01X1298766Y8779717D01* +G01X1300600Y8780966D01* +G01X1301333Y8781556D01* +G01X1302066Y8782146D01* +G01X1307199Y8785771D01* +G01X1312333Y8789396D01* +G01X1313699Y8790320D01* +G01X1315065Y8791245D01* +G01X1319956Y8794911D01* +G01X1327485Y8800045D01* +G01X1329548Y8801694D01* +G01X1331611Y8803345D01* +G01X1333160Y8803345D01* +G01X1333746Y8804288D01* +G01X1334333Y8805231D01* +G01X1338635Y8808138D01* +G01X1342937Y8811045D01* +G01X1344118Y8811778D01* +G01X1345299Y8812511D01* +G01X1346049Y8813296D01* +G01X1346800Y8814081D01* +G01X1348919Y8815496D01* +G01X1351039Y8816911D01* +G01X1352184Y8817644D01* +G01X1353330Y8818378D01* +G01X1357031Y8821102D01* +G01X1360733Y8823827D01* +G01X1362683Y8825319D01* +G01X1364631Y8826811D01* +G01X1366160Y8826811D01* +G01X1366747Y8827754D01* +G01X1367333Y8828697D01* +G01X1375400Y8834195D01* +G01X1387133Y8842352D01* +G01X1387500Y8842844D01* +G01X1387866Y8843335D01* +G01X1393184Y8846990D01* +G01X1398502Y8850644D01* +G01X1400884Y8852305D01* +G01X1403266Y8853966D01* +G01X1405999Y8855777D01* +G01X1408444Y8857611D01* +G01X1410889Y8859444D01* +G01X1418418Y8864577D01* +G01X1420481Y8866228D01* +G01X1422545Y8867877D01* +G01X1424093Y8867877D01* +G01X1424680Y8868820D01* +G01X1425266Y8869763D01* +G01X1429568Y8872670D01* +G01X1433870Y8875577D01* +G01X1435051Y8876311D01* +G01X1436233Y8877044D01* +G01X1436983Y8877828D01* +G01X1437733Y8878613D01* +G01X1439852Y8880028D01* +G01X1441972Y8881444D01* +G01X1444263Y8882911D01* +G01X1447964Y8885635D01* +G01X1451666Y8888360D01* +G01X1453616Y8889852D01* +G01X1455565Y8891343D01* +G01X1457094Y8891343D01* +G01X1457680Y8892340D01* +G01X1458267Y8893336D01* +G01X1460418Y8894448D01* +G01X1462569Y8895559D01* +G01X1464451Y8894732D01* +G01X1466333Y8893905D01* +G01X1468533Y8892472D01* +G01X1470733Y8891040D01* +G01X1472647Y8889542D01* +G01X1474563Y8888044D01* +G01X1475948Y8887139D01* +G01X1477333Y8886233D01* +G01X1479715Y8884572D01* +G01X1482097Y8882911D01* +G01X1487415Y8879256D01* +G01X1492733Y8875602D01* +G01X1493100Y8875110D01* +G01X1493467Y8874618D01* +G01X1499333Y8870540D01* +G01X1505199Y8866461D01* +G01X1513266Y8860963D01* +G01X1513853Y8860020D01* +G01X1514439Y8859077D01* +G01X1515968Y8859077D01* +G01X1517917Y8857585D01* +G01X1519866Y8856094D01* +G01X1527270Y8850644D01* +G01X1528415Y8849911D01* +G01X1529561Y8849177D01* +G01X1533800Y8846346D01* +G01X1534550Y8845562D01* +G01X1535300Y8844777D01* +G01X1537663Y8843311D01* +G01X1541965Y8840404D01* +G01X1546266Y8837497D01* +G01X1546853Y8836554D01* +G01X1547439Y8835611D01* +G01X1548988Y8835611D01* +G01X1551052Y8833961D01* +G01X1553115Y8832311D01* +G01X1560643Y8827178D01* +G01X1563089Y8825344D01* +G01X1565534Y8823511D01* +G01X1566900Y8822587D01* +G01X1568266Y8821662D01* +G01X1573400Y8818038D01* +G01X1578533Y8814413D01* +G01X1580000Y8813233D01* +G01X1581833Y8811983D01* +G01X1583666Y8810733D01* +G01X1589900Y8806330D01* +G01X1596133Y8801929D01* +G01X1604200Y8796431D01* +G01X1604786Y8795488D01* +G01X1605373Y8794544D01* +G01X1606901Y8794544D01* +G01X1610800Y8791561D01* +G01X1614501Y8788836D01* +G01X1618203Y8786112D01* +G01X1619348Y8785378D01* +G01X1620494Y8784645D01* +G01X1624733Y8781814D01* +G01X1625483Y8781029D01* +G01X1626234Y8780245D01* +G01X1628596Y8778778D01* +G01X1632898Y8775870D01* +G01X1637199Y8772962D01* +G01X1637650Y8772321D01* +G01X1638102Y8771679D01* +G01X1639562Y8770829D01* +G01X1641023Y8769978D01* +G01X1643878Y8768002D01* +G01X1646733Y8766027D01* +G01X1650400Y8763398D01* +G01X1654066Y8760770D01* +G01X1655900Y8759525D01* +G01X1657733Y8758280D01* +G01X1658320Y8757346D01* +G01X1658906Y8756412D01* +G01X1660454Y8756412D01* +G01X1662518Y8754762D01* +G01X1664581Y8753112D01* +G01X1672110Y8747978D01* +G01X1677001Y8744312D01* +G01X1678366Y8743416D01* +G01X1679733Y8742521D01* +G01X1683399Y8739946D01* +G01X1687067Y8737371D01* +G01X1691099Y8734634D01* +G01X1695133Y8731898D01* +G01X1695719Y8730955D01* +G01X1696306Y8730012D01* +G01X1697834Y8730012D01* +G01X1699784Y8728520D01* +G01X1701733Y8727028D01* +G01X1705435Y8724303D01* +G01X1709137Y8721578D01* +G01X1710568Y8720645D01* +G01X1712000Y8719711D01* +G01X1716766Y8716667D01* +G01X1716766Y8715345D01* +G01X1718368Y8715345D01* +G01X1720317Y8713854D01* +G01X1722267Y8712361D01* +G01X1725968Y8709637D01* +G01X1729670Y8706912D01* +G01X1731101Y8705978D01* +G01X1732533Y8705045D01* +G01X1737300Y8702001D01* +G01X1737300Y8700679D01* +G01X1738714Y8700679D01* +G01X1741857Y8698455D01* +G01X1745000Y8696231D01* +G01X1746833Y8694989D01* +G01X1748666Y8693747D01* +G01X1749253Y8692813D01* +G01X1749839Y8691879D01* +G01X1751388Y8691879D01* +G01X1753451Y8690229D01* +G01X1755515Y8688579D01* +G01X1759279Y8686012D01* +G01X1763043Y8683446D01* +G01X1767934Y8679779D01* +G01X1769300Y8678874D01* +G01X1770666Y8677968D01* +G01X1773049Y8676307D01* +G01X1775431Y8674646D01* +G01X1780749Y8670979D01* +G01X1786066Y8667312D01* +G01X1786587Y8666117D01* +G01X1788160Y8665428D01* +G01X1789733Y8664739D01* +G01X1794133Y8661446D01* +G01X1798533Y8658153D01* +G01X1802566Y8655426D01* +G01X1806600Y8652699D01* +G01X1807186Y8651756D01* +G01X1807772Y8650813D01* +G01X1809301Y8650813D01* +G01X1811250Y8649320D01* +G01X1813200Y8647829D01* +G01X1816901Y8645104D01* +G01X1820603Y8642379D01* +G01X1821749Y8641646D01* +G01X1822894Y8640913D01* +G01X1827133Y8638082D01* +G01X1827883Y8637298D01* +G01X1828634Y8636513D01* +G01X1830996Y8635046D01* +G01X1835298Y8632139D01* +G01X1839600Y8629232D01* +G01X1840186Y8628289D01* +G01X1840773Y8627346D01* +G01X1842322Y8627346D01* +G01X1844385Y8625696D01* +G01X1846448Y8624046D01* +G01X1850212Y8621480D01* +G01X1853976Y8618913D01* +G01X1856422Y8617079D01* +G01X1858867Y8615246D01* +G01X1860234Y8614341D01* +G01X1861600Y8613436D01* +G01X1863982Y8611774D01* +G01X1866364Y8610113D01* +G01X1871682Y8606458D01* +G01X1877000Y8602804D01* +G01X1877367Y8602313D01* +G01X1877733Y8601821D01* +G01X1883600Y8597742D01* +G01X1889467Y8593663D01* +G01X1893499Y8590914D01* +G01X1897533Y8588166D01* +G01X1898120Y8587223D01* +G01X1898706Y8586280D01* +G01X1900234Y8586280D01* +G01X1904133Y8583296D01* +G01X1907835Y8580572D01* +G01X1911537Y8577847D01* +G01X1912682Y8577113D01* +G01X1913827Y8576380D01* +G01X1918066Y8573549D01* +G01X1918817Y8572764D01* +G01X1919567Y8571980D01* +G01X1920748Y8571247D01* +G01X1921930Y8570513D01* +G01X1926231Y8567606D01* +G01X1930533Y8564699D01* +G01X1931119Y8563756D01* +G01X1931706Y8562813D01* +G01X1933255Y8562813D01* +G01X1935318Y8561164D01* +G01X1937382Y8559513D01* +G01X1941146Y8556947D01* +G01X1944910Y8554380D01* +G01X1949800Y8550714D01* +G01X1951167Y8549789D01* +G01X1952533Y8548865D01* +G01X1957666Y8545240D01* +G01X1962799Y8541615D01* +G01X1964266Y8540436D01* +G01X1966100Y8539185D01* +G01X1967933Y8537936D01* +G01X1974167Y8533533D01* +G01X1980400Y8529131D01* +G01X1984433Y8526382D01* +G01X1988466Y8523633D01* +G01X1989053Y8522690D01* +G01X1989639Y8521747D01* +G01X1991167Y8521747D01* +G01X1993117Y8520255D01* +G01X1995066Y8518763D01* +G01X1998768Y8516038D01* +G01X2002470Y8513314D01* +G01X2003615Y8512580D01* +G01X2004760Y8511847D01* +G01X2009000Y8509017D01* +G01X2009750Y8508232D01* +G01X2010500Y8507447D01* +G01X2011681Y8506714D01* +G01X2012863Y8505981D01* +G01X2017164Y8503072D01* +G01X2021466Y8500165D01* +G01X2021917Y8499523D01* +G01X2022368Y8498881D01* +G01X2023829Y8498031D01* +G01X2025290Y8497180D01* +G01X2028145Y8495205D01* +G01X2031000Y8493229D01* +G01X2034666Y8490601D01* +G01X2038333Y8487973D01* +G01X2040167Y8486728D01* +G01X2042000Y8485482D01* +G01X2042586Y8484548D01* +G01X2043173Y8483614D01* +G01X2044721Y8483614D01* +G01X2046785Y8481964D01* +G01X2048848Y8480314D01* +G01X2052613Y8477748D01* +G01X2056376Y8475181D01* +G01X2061267Y8471515D01* +G01X2062634Y8470619D01* +G01X2063999Y8469724D01* +G01X2067667Y8467149D01* +G01X2071333Y8464574D01* +G01X2075367Y8461825D01* +G01X2079399Y8459077D01* +G01X2079920Y8457853D01* +G01X2081493Y8457164D01* +G01X2083067Y8456474D01* +G01X2087466Y8453181D01* +G01X2091866Y8449889D01* +G01X2095900Y8447194D01* +G01X2099933Y8444500D01* +G01X2100683Y8443707D01* +G01X2101433Y8442914D01* +G01X2104333Y8441047D01* +G01X2106638Y8439572D01* +G01X2108942Y8438096D01* +G01X2109361Y8436494D01* +G01X2109780Y8434892D01* +G01X2108868Y8431181D01* +G01X2107966Y8429715D01* +G01X2107064Y8428248D01* +G01X2106555Y8425352D01* +G01X2106045Y8422456D01* +G01X2103966Y8419488D01* +G01X2103966Y8415759D01* +G01X2102499Y8413023D01* +G01X2101033Y8410286D01* +G01X2101033Y8406960D01* +G01X2099566Y8404224D01* +G01X2098100Y8401487D01* +G01X2098100Y8398160D01* +G01X2096633Y8395423D01* +G01X2095166Y8392687D01* +G01X2095166Y8389360D01* +G01X2093700Y8386623D01* +G01X2092233Y8383887D01* +G01X2092233Y8380560D01* +G01X2090767Y8377824D01* +G01X2089300Y8375087D01* +G01X2089300Y8371760D01* +G01X2087833Y8369024D01* +G01X2086366Y8366287D01* +G01X2086366Y8362960D01* +G01X2084900Y8360224D01* +G01X2083433Y8357487D01* +G01X2083433Y8354160D01* +G01X2081966Y8351424D01* +G01X2080500Y8348688D01* +G01X2080500Y8345325D01* +G01X2077566Y8339572D01* +G01X2077566Y8336526D01* +G01X2076099Y8333649D01* +G01X2074633Y8330772D01* +G01X2074633Y8327726D01* +G01X2073166Y8324849D01* +G01X2071699Y8321972D01* +G01X2071699Y8319254D01* +G01X2069004Y8312382D01* +G01X2067752Y8308716D01* +G01X2066499Y8305049D01* +G01X2065515Y8301749D01* +G01X2064532Y8298449D01* +G01X2062725Y8293316D01* +G01X2061473Y8289649D01* +G01X2060220Y8285983D01* +G01X2057699Y8278650D01* +G01X2055732Y8272050D01* +G01X2054828Y8269483D01* +G01X2053925Y8266916D01* +G01X2052672Y8263250D01* +G01X2051420Y8259583D01* +G01X2048857Y8252250D01* +G01X2048083Y8248960D01* +G01X2047307Y8245671D01* +G01X2046386Y8244194D01* +G01X2045464Y8242717D01* +G01X2044460Y8237002D01* +G01X2043495Y8235459D01* +G01X2042531Y8233916D01* +G01X2042028Y8231059D01* +G01X2041526Y8228202D01* +G01X2040562Y8226659D01* +G01X2039598Y8225116D01* +G01X2039095Y8222260D01* +G01X2038593Y8219402D01* +G01X2037629Y8217859D01* +G01X2036664Y8216317D01* +G01X2036162Y8213459D01* +G01X2035659Y8210602D01* +G01X2034695Y8209059D01* +G01X2033731Y8207517D01* +G01X2032726Y8201802D01* +G01X2031762Y8200260D01* +G01X2030798Y8198717D01* +G01X2030296Y8195860D01* +G01X2029793Y8193002D01* +G01X2028829Y8191460D01* +G01X2027864Y8189917D01* +G01X2027355Y8187021D01* +G01X2026845Y8184125D01* +G01X2025805Y8182641D01* +G01X2024767Y8181157D01* +G01X2024767Y8177428D01* +G01X2023300Y8174692D01* +G01X2021833Y8171955D01* +G01X2021833Y8168629D01* +G01X2020366Y8165892D01* +G01X2018900Y8163156D01* +G01X2018900Y8159829D01* +G01X2017433Y8157092D01* +G01X2015966Y8154356D01* +G01X2015966Y8151029D01* +G01X2014500Y8148292D01* +G01X2013033Y8145556D01* +G01X2013033Y8142229D01* +G01X2011566Y8139493D01* +G01X2010099Y8136756D01* +G01X2010099Y8133429D01* +G01X2008633Y8130692D01* +G01X2007166Y8127956D01* +G01X2007142Y8126303D01* +G01X2007117Y8124651D01* +G01X2005699Y8121717D01* +G01X2004283Y8118784D01* +G01X2004233Y8116073D01* +G01X2003138Y8113762D01* +G01X2002042Y8111451D01* +G01X2001021Y8107784D01* +G01X1999998Y8104118D01* +G01X1999095Y8101551D01* +G01X1998192Y8098984D01* +G01X1996939Y8095318D01* +G01X1995687Y8091651D01* +G01X1993166Y8084318D01* +G01X1991199Y8077718D01* +G01X1989391Y8072585D01* +G01X1986887Y8065252D01* +G01X1985626Y8061585D01* +G01X1984366Y8057918D01* +G01X1982399Y8051318D01* +G01X1980592Y8046185D01* +G01X1979339Y8042518D01* +G01X1978086Y8038852D01* +G01X1976826Y8035185D01* +G01X1975566Y8031518D01* +G01X1973598Y8024918D01* +G01X1972695Y8022351D01* +G01X1971792Y8019785D01* +G01X1970539Y8016118D01* +G01X1969287Y8012452D01* +G01X1968005Y8008785D01* +G01X1966724Y8005118D01* +G01X1965949Y8001829D01* +G01X1965174Y7998540D01* +G01X1964252Y7997063D01* +G01X1963331Y7995585D01* +G01X1962829Y7992728D01* +G01X1962326Y7989871D01* +G01X1961362Y7988328D01* +G01X1960398Y7986785D01* +G01X1959895Y7983928D01* +G01X1959393Y7981071D01* +G01X1958429Y7979528D01* +G01X1957464Y7977986D01* +G01X1956962Y7975128D01* +G01X1956460Y7972271D01* +G01X1955495Y7970728D01* +G01X1954531Y7969185D01* +G01X1954029Y7966328D01* +G01X1953527Y7963471D01* +G01X1952562Y7961929D01* +G01X1951597Y7960385D01* +G01X1951088Y7957490D01* +G01X1950578Y7954594D01* +G01X1949539Y7953110D01* +G01X1948500Y7951626D01* +G01X1948500Y7947897D01* +G01X1945566Y7942425D01* +G01X1945566Y7939097D01* +G01X1944099Y7936361D01* +G01X1942633Y7933624D01* +G01X1942633Y7930298D01* +G01X1941166Y7927561D01* +G01X1939699Y7924825D01* +G01X1939699Y7921498D01* +G01X1938233Y7918761D01* +G01X1936766Y7916025D01* +G01X1936766Y7912697D01* +G01X1933833Y7907225D01* +G01X1933833Y7903898D01* +G01X1932366Y7901161D01* +G01X1930900Y7898425D01* +G01X1930900Y7895098D01* +G01X1929433Y7892361D01* +G01X1927967Y7889625D01* +G01X1927967Y7886263D01* +G01X1926500Y7883386D01* +G01X1925033Y7880510D01* +G01X1925033Y7877463D01* +G01X1923566Y7874586D01* +G01X1922100Y7871710D01* +G01X1922100Y7868663D01* +G01X1920633Y7865787D01* +G01X1919166Y7862909D01* +G01X1919166Y7860192D01* +G01X1916471Y7853320D01* +G01X1913965Y7845987D01* +G01X1912982Y7842687D01* +G01X1911999Y7839387D01* +G01X1910192Y7834253D01* +G01X1908939Y7830587D01* +G01X1907687Y7826920D01* +G01X1905166Y7819587D01* +G01X1903198Y7812987D01* +G01X1902295Y7810420D01* +G01X1901392Y7807854D01* +G01X1900139Y7804187D01* +G01X1898887Y7800521D01* +G01X1897626Y7796854D01* +G01X1896366Y7793187D01* +G01X1894399Y7786587D01* +G01X1892591Y7781454D01* +G01X1891267Y7777787D01* +G01X1889943Y7774121D01* +G01X1889425Y7771565D01* +G01X1888907Y7769009D01* +G01X1887064Y7766054D01* +G01X1886562Y7763197D01* +G01X1886060Y7760339D01* +G01X1885095Y7758797D01* +G01X1884131Y7757254D01* +G01X1883628Y7754397D01* +G01X1883126Y7751540D01* +G01X1882162Y7749997D01* +G01X1881198Y7748454D01* +G01X1880695Y7745597D01* +G01X1880193Y7742740D01* +G01X1879228Y7741197D01* +G01X1878264Y7739655D01* +G01X1877762Y7736797D01* +G01X1877260Y7733940D01* +G01X1875331Y7730854D01* +G01X1874828Y7727997D01* +G01X1874326Y7725140D01* +G01X1873362Y7723597D01* +G01X1872398Y7722054D01* +G01X1871888Y7719159D01* +G01X1871379Y7716263D01* +G01X1869300Y7713295D01* +G01X1869300Y7709566D01* +G01X1867833Y7706830D01* +G01X1866366Y7704093D01* +G01X1866366Y7700766D01* +G01X1864900Y7698030D01* +G01X1863433Y7695293D01* +G01X1863421Y7693641D01* +G01X1863409Y7691988D01* +G01X1861378Y7687955D01* +G01X1859347Y7683922D01* +G37* +G36* +G01X1414183Y7737197D02* +G01X1405233Y7736941D01* +G01X1402049Y7737703D01* +G01X1398866Y7738465D01* +G01X1391533Y7741121D01* +G01X1389333Y7742588D01* +G01X1387133Y7744054D01* +G01X1384200Y7747092D01* +G01X1381266Y7750130D01* +G01X1380487Y7751437D01* +G01X1379709Y7752744D01* +G01X1377966Y7751667D01* +G01X1377966Y7742548D01* +G01X1375683Y7739288D01* +G01X1299982Y7739288D01* +G01X1298641Y7740501D01* +G01X1297300Y7741715D01* +G01X1297300Y7847527D01* +G01X1295540Y7849287D01* +G01X1291726Y7849287D01* +G01X1290846Y7850166D01* +G01X1289966Y7851046D01* +G01X1289966Y7863262D01* +G01X1297203Y7863262D01* +G01X1297435Y7860866D01* +G01X1297666Y7858470D01* +G01X1300454Y7858021D01* +G01X1303241Y7857572D01* +G01X1305000Y7855814D01* +G01X1305366Y7801767D01* +G01X1305366Y7801767D01* +G01X1305733Y7747721D01* +G01X1369243Y7747339D01* +G01X1369022Y7751196D01* +G01X1368800Y7755054D01* +G01X1320197Y7755441D01* +G01X1319198Y7756643D01* +G01X1318200Y7757845D01* +G01X1317833Y7810349D01* +G01X1317466Y7862853D01* +G01X1297203Y7863262D01* +G01X1289966Y7863262D01* +G01X1289966Y7869576D01* +G01X1290455Y7870064D01* +G01X1290944Y7870553D01* +G01X1323580Y7870553D01* +G01X1324739Y7870108D01* +G01X1325900Y7869663D01* +G01X1325900Y7766324D01* +G01X1326659Y7764906D01* +G01X1327418Y7763487D01* +G01X1374876Y7763487D01* +G01X1375766Y7765807D01* +G01X1375764Y7769292D01* +G01X1383961Y7769292D01* +G01X1385418Y7758721D01* +G01X1386954Y7756154D01* +G01X1388490Y7753588D01* +G01X1391489Y7750663D01* +G01X1396365Y7747354D01* +G01X1398309Y7747354D01* +G01X1407491Y7744421D01* +G01X1407491Y7744421D01* +G01X1417639Y7744421D01* +G01X1419619Y7745432D01* +G01X1421600Y7746445D01* +G01X1424057Y7746973D01* +G01X1426513Y7747503D01* +G01X1429666Y7749630D01* +G01X1432817Y7751758D01* +G01X1435092Y7754348D01* +G01X1437366Y7756938D01* +G01X1437366Y7758354D01* +G01X1442343Y7758354D01* +G01X1442812Y7757131D01* +G01X1443281Y7755908D01* +G01X1443732Y7751597D01* +G01X1444182Y7747285D01* +G01X1451666Y7747721D01* +G01X1451666Y7815921D01* +G01X1449686Y7819220D01* +G01X1447707Y7822520D01* +G01X1444920Y7825169D01* +G01X1442133Y7827816D01* +G01X1439199Y7829326D01* +G01X1436266Y7830835D01* +G01X1428199Y7831999D01* +G01X1420133Y7833162D01* +G01X1417138Y7833157D01* +G01X1414144Y7833154D01* +G01X1413454Y7832463D01* +G01X1395631Y7830393D01* +G01X1390800Y7827578D01* +G01X1390574Y7822483D01* +G01X1390348Y7817387D01* +G01X1390790Y7815004D01* +G01X1391233Y7812620D01* +G01X1395221Y7812620D01* +G01X1398866Y7823252D01* +G01X1401066Y7824302D01* +G01X1403266Y7825352D01* +G01X1410391Y7826078D01* +G01X1417515Y7826804D01* +G01X1422124Y7826023D01* +G01X1426733Y7825242D01* +G01X1433162Y7822827D01* +G01X1435278Y7820840D01* +G01X1437395Y7818854D01* +G01X1438980Y7815921D01* +G01X1440565Y7812987D01* +G01X1440878Y7805601D01* +G01X1441190Y7798215D01* +G01X1438728Y7795754D01* +G01X1418523Y7795754D01* +G01X1411628Y7794298D01* +G01X1404733Y7792844D01* +G01X1403081Y7792832D01* +G01X1401428Y7792821D01* +G01X1398691Y7791354D01* +G01X1395955Y7789887D01* +G01X1394434Y7789887D01* +G01X1387866Y7783452D01* +G01X1386668Y7782086D01* +G01X1385470Y7780721D01* +G01X1384716Y7775007D01* +G01X1383961Y7769292D01* +G01X1375764Y7769292D01* +G01X1375763Y7770330D01* +G01X1375759Y7774854D01* +G01X1376955Y7778521D01* +G01X1378151Y7782187D01* +G01X1379505Y7785121D01* +G01X1380560Y7787036D01* +G01X1381616Y7788952D01* +G01X1388599Y7795112D01* +G01X1389473Y7795787D01* +G01X1390345Y7796463D01* +G01X1399600Y7799996D01* +G01X1403266Y7800905D01* +G01X1406933Y7801813D01* +G01X1410233Y7802407D01* +G01X1413533Y7803000D01* +G01X1422089Y7803043D01* +G01X1430647Y7803087D01* +G01X1431806Y7803532D01* +G01X1432966Y7803978D01* +G01X1432966Y7809376D01* +G01X1431317Y7812622D01* +G01X1429666Y7815869D01* +G01X1419399Y7818454D01* +G01X1415733Y7818411D01* +G01X1412067Y7818369D01* +G01X1405539Y7816653D01* +G01X1404135Y7811887D01* +G01X1402733Y7807120D01* +G01X1401643Y7804921D01* +G01X1385519Y7804508D01* +G01X1383786Y7805911D01* +G01X1382053Y7807314D01* +G01X1382026Y7819784D01* +G01X1382000Y7832254D01* +G01X1383327Y7833727D01* +G01X1384655Y7835200D01* +G01X1388599Y7835948D01* +G01X1391533Y7837086D01* +G01X1394466Y7838222D01* +G01X1397124Y7838255D01* +G01X1399782Y7838287D01* +G01X1402990Y7839468D01* +G01X1406200Y7840650D01* +G01X1418300Y7840679D01* +G01X1430400Y7840709D01* +G01X1433126Y7839498D01* +G01X1435852Y7838287D01* +G01X1437526Y7838276D01* +G01X1439199Y7838265D01* +G01X1441033Y7837220D01* +G01X1442867Y7836175D01* +G01X1445219Y7835081D01* +G01X1447571Y7833987D01* +G01X1450737Y7830821D01* +G01X1453903Y7827653D01* +G01X1455965Y7823987D01* +G01X1458027Y7820320D01* +G01X1458815Y7816653D01* +G01X1459602Y7812987D01* +G01X1459878Y7777508D01* +G01X1460154Y7742029D01* +G01X1457672Y7739288D01* +G01X1441129Y7739288D01* +G01X1439310Y7739979D01* +G01X1437492Y7740671D01* +G01X1437013Y7742179D01* +G01X1436534Y7743687D01* +G01X1434718Y7743687D01* +G01X1429748Y7740021D01* +G01X1427048Y7740021D01* +G01X1423133Y7737454D01* +G01X1414183Y7737197D01* +G37* +G36* +G01X1618133Y7740982D02* +G01X1612633Y7739218D01* +G01X1607133Y7737454D01* +G01X1592833Y7737457D01* +G01X1578533Y7737459D01* +G01X1576186Y7738740D01* +G01X1573839Y7740021D01* +G01X1572520Y7740006D01* +G01X1571199Y7739992D01* +G01X1566271Y7742370D01* +G01X1561342Y7744747D01* +G01X1559732Y7748636D01* +G01X1560187Y7751387D01* +G01X1568757Y7751387D01* +G01X1570434Y7749666D01* +G01X1572109Y7747945D01* +G01X1576787Y7746973D01* +G01X1581466Y7746003D01* +G01X1584400Y7745229D01* +G01X1587333Y7744456D01* +G01X1594873Y7744439D01* +G01X1594873Y7744439D01* +G01X1602413Y7744421D01* +G01X1607283Y7746455D01* +G01X1613724Y7747544D01* +G01X1617666Y7749768D01* +G01X1621608Y7751993D01* +G01X1627300Y7757916D01* +G01X1627349Y7759454D01* +G01X1628767Y7762387D01* +G01X1630183Y7765321D01* +G01X1630208Y7768478D01* +G01X1630233Y7771635D01* +G01X1628666Y7775078D01* +G01X1627099Y7778521D01* +G01X1625182Y7780849D01* +G01X1623265Y7783178D01* +G01X1618133Y7786601D01* +G01X1616300Y7787505D01* +G01X1614466Y7788410D01* +G01X1613367Y7789034D01* +G01X1612266Y7789657D01* +G01X1608966Y7791241D01* +G01X1605667Y7792825D01* +G01X1605013Y7792823D01* +G01X1604360Y7792821D01* +G01X1600980Y7794371D01* +G01X1597600Y7795921D01* +G01X1593698Y7797854D01* +G01X1589796Y7799787D01* +G01X1586548Y7802915D01* +G01X1583299Y7806042D01* +G01X1583299Y7816818D01* +G01X1585550Y7819650D01* +G01X1587800Y7822481D01* +G01X1594666Y7825972D01* +G01X1607133Y7826712D01* +G01X1610154Y7825897D01* +G01X1613175Y7825082D01* +G01X1614998Y7823648D01* +G01X1616822Y7822213D01* +G01X1617257Y7818538D01* +G01X1617692Y7814862D01* +G01X1618489Y7813375D01* +G01X1619285Y7811887D01* +G01X1624366Y7811887D01* +G01X1624366Y7827770D01* +G01X1620883Y7829299D01* +G01X1617399Y7830827D01* +G01X1611035Y7831990D01* +G01X1604670Y7833154D01* +G01X1601135Y7833056D01* +G01X1597600Y7832959D01* +G01X1591366Y7831744D01* +G01X1585133Y7830529D01* +G01X1579284Y7827653D01* +G01X1576158Y7824556D01* +G01X1573033Y7821459D01* +G01X1573024Y7819587D01* +G01X1571810Y7817387D01* +G01X1570596Y7815187D01* +G01X1570610Y7807120D01* +G01X1572160Y7803780D01* +G01X1573708Y7800439D01* +G01X1576815Y7797363D01* +G01X1579922Y7794287D01* +G01X1581635Y7794287D01* +G01X1583500Y7792821D01* +G01X1585364Y7791354D01* +G01X1587333Y7791345D01* +G01X1589533Y7790175D01* +G01X1591733Y7789005D01* +G01X1598637Y7786916D01* +G01X1599078Y7786202D01* +G01X1599520Y7785487D01* +G01X1602902Y7785487D01* +G01X1606399Y7782755D01* +G01X1607866Y7782269D01* +G01X1609333Y7781782D01* +G01X1611166Y7780139D01* +G01X1613000Y7778496D01* +G01X1615016Y7776068D01* +G01X1617033Y7773641D01* +G01X1617033Y7762241D01* +G01X1614816Y7759181D01* +G01X1612600Y7756121D01* +G01X1604200Y7752235D01* +G01X1596500Y7752254D01* +G01X1588800Y7752274D01* +G01X1585960Y7753481D01* +G01X1583120Y7754687D01* +G01X1579245Y7754687D01* +G01X1576431Y7756196D01* +G01X1573617Y7757704D01* +G01X1571683Y7757479D01* +G01X1569750Y7757254D01* +G01X1569254Y7754321D01* +G01X1568757Y7751387D01* +G01X1560187Y7751387D01* +G01X1560202Y7751478D01* +G01X1560672Y7754321D01* +G01X1561714Y7759087D01* +G01X1562756Y7763854D01* +G01X1563142Y7765871D01* +G01X1563527Y7767888D01* +G01X1568170Y7767888D01* +G01X1571151Y7766559D01* +G01X1574133Y7765231D01* +G01X1577800Y7763948D01* +G01X1581466Y7762665D01* +G01X1589406Y7761247D01* +G01X1597344Y7759828D01* +G01X1602422Y7760983D01* +G01X1607499Y7762138D01* +G01X1608599Y7763709D01* +G01X1609699Y7765280D01* +G01X1609677Y7767867D01* +G01X1609653Y7770454D01* +G01X1608026Y7772295D01* +G01X1606399Y7774137D01* +G01X1602969Y7776145D01* +G01X1599538Y7778154D01* +G01X1597578Y7778154D01* +G01X1594842Y7779620D01* +G01X1592105Y7781087D01* +G01X1589733Y7781087D01* +G01X1584400Y7783834D01* +G01X1580006Y7785937D01* +G01X1575613Y7788041D01* +G01X1574337Y7789147D01* +G01X1573061Y7790254D01* +G01X1570133Y7793042D01* +G01X1567205Y7795831D01* +G01X1563188Y7803454D01* +G01X1563160Y7810787D01* +G01X1563133Y7818120D01* +G01X1565159Y7822311D01* +G01X1567185Y7826503D01* +G01X1570780Y7830097D01* +G01X1574374Y7833691D01* +G01X1577774Y7835591D01* +G01X1581174Y7837492D01* +G01X1589533Y7839863D01* +G01X1592833Y7840494D01* +G01X1596133Y7841125D01* +G01X1604288Y7840808D01* +G01X1612443Y7840491D01* +G01X1615081Y7839389D01* +G01X1617719Y7838287D01* +G01X1620906Y7838287D01* +G01X1623919Y7836903D01* +G01X1626933Y7835520D01* +G01X1630995Y7833905D01* +G01X1631714Y7832014D01* +G01X1632433Y7830125D01* +G01X1632433Y7806104D01* +G01X1629173Y7803820D01* +G01X1615470Y7803820D01* +G01X1614068Y7804571D01* +G01X1612667Y7805321D01* +G01X1611786Y7806954D01* +G01X1610906Y7808587D01* +G01X1610115Y7812987D01* +G01X1609323Y7817387D01* +G01X1606761Y7818291D01* +G01X1604200Y7819195D01* +G01X1601148Y7818805D01* +G01X1598096Y7818417D01* +G01X1594915Y7816888D01* +G01X1591733Y7815360D01* +G01X1591194Y7814540D01* +G01X1590655Y7813720D01* +G01X1590644Y7811604D01* +G01X1590633Y7809489D01* +G01X1592350Y7807938D01* +G01X1594067Y7806387D01* +G01X1597300Y7804844D01* +G01X1600533Y7803301D01* +G01X1603833Y7801725D01* +G01X1607133Y7800150D01* +G01X1608324Y7800154D01* +G01X1612495Y7798276D01* +G01X1616666Y7796398D01* +G01X1617767Y7795707D01* +G01X1618866Y7795017D01* +G01X1621897Y7793693D01* +G01X1624781Y7791744D01* +G01X1627666Y7789796D01* +G01X1630769Y7786429D01* +G01X1633872Y7783063D01* +G01X1634807Y7779987D01* +G01X1637199Y7777268D01* +G01X1637199Y7760921D01* +G01X1635224Y7756888D01* +G01X1633248Y7752854D01* +G01X1630428Y7749921D01* +G01X1627607Y7746987D01* +G01X1621721Y7742954D01* +G01X1620449Y7742954D01* +G01X1619291Y7741968D01* +G01X1618133Y7740982D01* +G37* +G36* +G01X1533066Y7740864D02* +G01X1531600Y7740181D01* +G01X1525041Y7737454D01* +G01X1502266Y7737454D01* +G01X1500305Y7738786D01* +G01X1498343Y7740117D01* +G01X1495905Y7740114D01* +G01X1493467Y7740110D01* +G01X1486866Y7739279D01* +G01X1480266Y7738449D01* +G01X1477086Y7738785D01* +G01X1473905Y7739122D01* +G01X1472200Y7740827D01* +G01X1471833Y7794874D01* +G01X1471466Y7848920D01* +G01X1468362Y7849145D01* +G01X1465258Y7849369D01* +G01X1464145Y7850958D01* +G01X1463033Y7852546D01* +G01X1463033Y7860820D01* +G01X1470133Y7860820D01* +G01X1471615Y7858453D01* +G01X1474474Y7858221D01* +G01X1477333Y7857988D01* +G01X1478800Y7856547D01* +G01X1479166Y7802134D01* +G01X1479533Y7747721D01* +G01X1482792Y7747488D01* +G01X1486051Y7747256D01* +G01X1490653Y7752739D01* +G01X1491694Y7752238D01* +G01X1492733Y7751738D01* +G01X1494933Y7750288D01* +G01X1497133Y7748837D01* +G01X1497133Y7748837D01* +G01X1500800Y7747207D01* +G01X1507072Y7744421D01* +G01X1519866Y7744427D01* +G01X1524633Y7746124D01* +G01X1529400Y7747820D01* +G01X1531655Y7749237D01* +G01X1533912Y7750654D01* +G01X1536066Y7752488D01* +G01X1538220Y7754321D01* +G01X1539942Y7756749D01* +G01X1541664Y7759177D01* +G01X1545166Y7765765D01* +G01X1545166Y7767924D01* +G01X1546633Y7772097D01* +G01X1548099Y7776270D01* +G01X1548099Y7807904D01* +G01X1546633Y7812078D01* +G01X1545166Y7816250D01* +G01X1545166Y7817688D01* +G01X1543359Y7820471D01* +G01X1541551Y7823253D01* +G01X1540242Y7824938D01* +G01X1538933Y7826623D01* +G01X1535954Y7828671D01* +G01X1532975Y7830718D01* +G01X1526361Y7832003D01* +G01X1519747Y7833288D01* +G01X1513054Y7831837D01* +G01X1506360Y7830386D01* +G01X1504145Y7828387D01* +G01X1501923Y7826588D01* +G01X1499700Y7824789D01* +G01X1499700Y7822859D01* +G01X1501716Y7823327D01* +G01X1503733Y7823794D01* +G01X1507296Y7826026D01* +G01X1519866Y7826187D01* +G01X1527933Y7822279D01* +G01X1529413Y7820567D01* +G01X1530893Y7818854D01* +G01X1532546Y7816477D01* +G01X1534201Y7814101D01* +G01X1534622Y7811711D01* +G01X1535043Y7809320D01* +G01X1536102Y7806383D01* +G01X1537162Y7803445D01* +G01X1536937Y7789150D01* +G01X1536711Y7774854D01* +G01X1535363Y7770087D01* +G01X1534015Y7765321D01* +G01X1532991Y7764163D01* +G01X1531967Y7763005D01* +G01X1531967Y7761599D01* +G01X1528483Y7758288D01* +G01X1524999Y7754978D01* +G01X1518239Y7751754D01* +G01X1500896Y7751754D01* +G01X1497548Y7753273D01* +G01X1494200Y7754792D01* +G01X1493100Y7755361D01* +G01X1492000Y7755931D01* +G01X1491094Y7757693D01* +G01X1490188Y7759454D01* +G01X1490187Y7762074D01* +G01X1498844Y7762074D01* +G01X1503733Y7759093D01* +G01X1509446Y7759090D01* +G01X1509446Y7759090D01* +G01X1515158Y7759087D01* +G01X1521333Y7762182D01* +G01X1525366Y7765962D01* +G01X1525366Y7767765D01* +G01X1526169Y7768032D01* +G01X1526971Y7768300D01* +G01X1527603Y7771577D01* +G01X1528234Y7774854D01* +G01X1528738Y7784758D01* +G01X1529242Y7794663D01* +G01X1528309Y7802280D01* +G01X1527376Y7809896D01* +G01X1525320Y7812942D01* +G01X1523264Y7815988D01* +G01X1519301Y7817237D01* +G01X1515337Y7818487D01* +G01X1513569Y7818401D01* +G01X1511800Y7818316D01* +G01X1507903Y7817183D01* +G01X1504007Y7816050D01* +G01X1501670Y7812685D01* +G01X1499333Y7809320D01* +G01X1499088Y7785697D01* +G01X1498844Y7762074D01* +G01X1490187Y7762074D01* +G01X1490166Y7802046D01* +G01X1491266Y7806269D01* +G01X1492366Y7810492D01* +G01X1492366Y7814527D01* +G01X1491450Y7815442D01* +G01X1490533Y7816358D01* +G01X1490166Y7839606D01* +G01X1489799Y7862853D01* +G01X1480435Y7863059D01* +G01X1471071Y7863264D01* +G01X1470601Y7862042D01* +G01X1470133Y7860820D01* +G01X1463033Y7860820D01* +G01X1463033Y7868793D01* +G01X1463913Y7869673D01* +G01X1464793Y7870553D01* +G01X1497206Y7870553D01* +G01X1498086Y7869673D01* +G01X1498966Y7868793D01* +G01X1498966Y7836173D01* +G01X1499746Y7835692D01* +G01X1500525Y7835210D01* +G01X1501763Y7836260D01* +G01X1503000Y7837311D01* +G01X1507766Y7838828D01* +G01X1512533Y7840346D01* +G01X1516567Y7840821D01* +G01X1520599Y7841297D01* +G01X1524999Y7840605D01* +G01X1529400Y7839913D01* +G01X1531967Y7839005D01* +G01X1534533Y7838098D01* +G01X1538423Y7836176D01* +G01X1542313Y7834253D01* +G01X1545940Y7830381D01* +G01X1549566Y7826509D01* +G01X1549566Y7824951D01* +G01X1552500Y7821223D01* +G01X1552500Y7818080D01* +G01X1553629Y7816467D01* +G01X1554759Y7814854D01* +G01X1555588Y7806221D01* +G01X1556417Y7797587D01* +G01X1556410Y7792454D01* +G01X1556405Y7787320D01* +G01X1555592Y7778334D01* +G01X1554778Y7769348D01* +G01X1552500Y7766094D01* +G01X1552500Y7762961D01* +G01X1550446Y7759007D01* +G01X1548393Y7755054D01* +G01X1546813Y7752488D01* +G01X1545233Y7749921D01* +G01X1538049Y7743564D01* +G01X1534533Y7741546D01* +G01X1533066Y7740864D01* +G37* +G36* +G01X1423524Y7751754D02* +G01X1409452Y7751754D01* +G01X1404733Y7753732D01* +G01X1402334Y7755755D01* +G01X1399935Y7757777D01* +G01X1396299Y7765462D01* +G01X1396299Y7770252D01* +G01X1404224Y7770252D01* +G01X1405146Y7766136D01* +G01X1406066Y7762021D01* +G01X1407435Y7762021D01* +G01X1409300Y7760554D01* +G01X1411164Y7759087D01* +G01X1411164Y7759087D01* +G01X1420354Y7759087D01* +G01X1427524Y7762410D01* +G01X1429126Y7763902D01* +G01X1430728Y7765394D01* +G01X1431847Y7768566D01* +G01X1432966Y7771738D01* +G01X1432966Y7780860D01* +G01X1431625Y7782073D01* +G01X1430284Y7783288D01* +G01X1425576Y7783195D01* +G01X1420866Y7783103D01* +G01X1415064Y7781998D01* +G01X1409260Y7780894D01* +G01X1407228Y7778815D01* +G01X1405197Y7776736D01* +G01X1404224Y7770252D01* +G01X1396299Y7770252D01* +G01X1396299Y7775833D01* +G01X1398168Y7779554D01* +G01X1400037Y7783274D01* +G01X1406777Y7788421D01* +G01X1409596Y7788421D01* +G01X1411198Y7789309D01* +G01X1412800Y7790198D01* +G01X1416466Y7790700D01* +G01X1420133Y7791202D01* +G01X1438764Y7790987D01* +G01X1440666Y7789079D01* +G01X1440661Y7777933D01* +G01X1440655Y7766787D01* +G01X1438848Y7763854D01* +G01X1437040Y7760921D01* +G01X1434086Y7758139D01* +G01X1431133Y7755357D01* +G01X1427328Y7753555D01* +G01X1423524Y7751754D01* +G37* +G36* +G01X1211133Y7895551D02* +G01X1204959Y7895486D01* +G01X1194206Y7893887D01* +G01X1184855Y7895034D01* +G01X1175504Y7896181D01* +G01X1173905Y7897300D01* +G01X1172306Y7898420D01* +G01X1170145Y7898420D01* +G01X1167172Y7900411D01* +G01X1164199Y7902403D01* +G01X1160141Y7906461D01* +G01X1156083Y7910519D01* +G01X1154091Y7913492D01* +G01X1152099Y7916465D01* +G01X1152099Y7918224D01* +G01X1150633Y7920961D01* +G01X1149166Y7923697D01* +G01X1149166Y7928302D01* +G01X1148067Y7931419D01* +G01X1146966Y7934537D01* +G01X1146966Y7946085D01* +G01X1154751Y7946085D01* +G01X1156642Y7926749D01* +G01X1158037Y7924145D01* +G01X1159433Y7921541D01* +G01X1159433Y7919759D01* +G01X1161574Y7916606D01* +G01X1163715Y7913452D01* +G01X1166158Y7911236D01* +G01X1168600Y7909020D01* +G01X1170953Y7907386D01* +G01X1173307Y7905753D01* +G01X1173307Y7905753D01* +G01X1175222Y7905753D01* +G01X1181009Y7902651D01* +G01X1194337Y7902673D01* +G01X1207665Y7902695D01* +G01X1209936Y7903870D01* +G01X1212208Y7905044D01* +G01X1215520Y7905498D01* +G01X1218833Y7905952D01* +G01X1218833Y7907834D01* +G01X1216266Y7912344D01* +G01X1215497Y7912348D01* +G01X1214726Y7912353D01* +G01X1213315Y7910942D01* +G01X1206724Y7910117D01* +G01X1200133Y7909293D01* +G01X1192800Y7908547D01* +G01X1186612Y7909728D01* +G01X1180425Y7910907D01* +G01X1179221Y7911997D01* +G01X1178018Y7913086D01* +G01X1176414Y7913086D01* +G01X1173719Y7916203D01* +G01X1171024Y7919319D01* +G01X1167276Y7927386D01* +G01X1166937Y7934910D01* +G01X1166600Y7942434D01* +G01X1167506Y7943527D01* +G01X1168413Y7944619D01* +G01X1221971Y7944619D01* +G01X1222946Y7945903D01* +G01X1223920Y7947186D01* +G01X1223943Y7951007D01* +G01X1223966Y7954828D01* +G01X1223148Y7962351D01* +G01X1222329Y7969875D01* +G01X1220948Y7972453D01* +G01X1219566Y7975030D01* +G01X1219566Y7976912D01* +G01X1214813Y7981665D01* +G01X1210060Y7986419D01* +G01X1208178Y7986419D01* +G01X1202683Y7989364D01* +G01X1192974Y7989662D01* +G01X1183266Y7989960D01* +G01X1179966Y7989448D01* +G01X1176666Y7988935D01* +G01X1173280Y7987319D01* +G01X1169895Y7985703D01* +G01X1167016Y7982909D01* +G01X1164137Y7980116D01* +G01X1159433Y7973145D01* +G01X1159433Y7971672D01* +G01X1156642Y7965519D01* +G01X1154751Y7946085D01* +G01X1146966Y7946085D01* +G01X1146966Y7957724D01* +G01X1148568Y7961852D01* +G01X1149251Y7966581D01* +G01X1149935Y7971309D01* +G01X1151017Y7972505D01* +G01X1152099Y7973701D01* +G01X1152099Y7976688D01* +G01X1153566Y7978552D01* +G01X1155033Y7980417D01* +G01X1155033Y7981448D01* +G01X1158058Y7985061D01* +G01X1161083Y7988674D01* +G01X1164474Y7991024D01* +G01X1167866Y7993374D01* +G01X1171167Y7995007D01* +G01X1174466Y7996639D01* +G01X1176300Y7996694D01* +G01X1178133Y7996750D01* +G01X1181800Y7997768D01* +G01X1185466Y7998786D01* +G01X1189162Y7998836D01* +G01X1192858Y7998885D01* +G01X1197082Y7997785D01* +G01X1201304Y7996686D01* +G01X1205323Y7996686D01* +G01X1208043Y7995299D01* +G01X1210763Y7993912D01* +G01X1214589Y7992952D01* +G01X1220344Y7987196D01* +G01X1226099Y7981441D01* +G01X1226598Y7979347D01* +G01X1227097Y7977252D01* +G01X1228120Y7976070D01* +G01X1229143Y7974888D01* +G01X1229807Y7970937D01* +G01X1230470Y7966986D01* +G01X1231270Y7964755D01* +G01X1232070Y7962525D01* +G01X1231868Y7950121D01* +G01X1231666Y7937717D01* +G01X1228000Y7936699D01* +G01X1201050Y7936625D01* +G01X1174100Y7936552D01* +G01X1174100Y7933935D01* +G01X1175566Y7929762D01* +G01X1177033Y7925589D01* +G01X1177033Y7923650D01* +G01X1181479Y7920053D01* +G01X1183820Y7917928D01* +G01X1192800Y7916819D01* +G01X1200133Y7917254D01* +G01X1207466Y7917690D01* +G01X1211184Y7919560D01* +G01X1214092Y7920086D01* +G01X1217000Y7920611D01* +G01X1217997Y7921405D01* +G01X1218994Y7922199D01* +G01X1223966Y7916774D01* +G01X1223966Y7913999D01* +G01X1225066Y7913086D01* +G01X1226166Y7912173D01* +G01X1226166Y7910616D01* +G01X1229245Y7904256D01* +G01X1228865Y7903265D01* +G01X1228484Y7902274D01* +G01X1225080Y7900626D01* +G01X1221675Y7898978D01* +G01X1219337Y7898381D01* +G01X1217000Y7897786D01* +G01X1214067Y7896668D01* +G01X1211133Y7895551D01* +G37* +G36* +G01X1771358Y7894692D02* +G01X1766797Y7893897D01* +G01X1757857Y7895057D01* +G01X1748918Y7896217D01* +G01X1747346Y7897319D01* +G01X1745773Y7898420D01* +G01X1743684Y7898420D01* +G01X1739839Y7900972D01* +G01X1735993Y7903525D01* +G01X1733163Y7907026D01* +G01X1730333Y7910526D01* +G01X1729411Y7911989D01* +G01X1728489Y7913452D01* +G01X1727699Y7915286D01* +G01X1726909Y7917120D01* +G01X1725838Y7919252D01* +G01X1724767Y7921385D01* +G01X1724104Y7926623D01* +G01X1723439Y7931860D01* +G01X1721936Y7938385D01* +G01X1721917Y7946458D01* +G01X1721901Y7953785D01* +G01X1730562Y7953785D01* +G01X1730943Y7940482D01* +G01X1731324Y7927178D01* +G01X1732845Y7923839D01* +G01X1734366Y7920500D01* +G01X1734366Y7918443D01* +G01X1735833Y7916753D01* +G01X1737300Y7915062D01* +G01X1737300Y7913910D01* +G01X1741333Y7909515D01* +G01X1746898Y7905753D01* +G01X1748688Y7905753D01* +G01X1751505Y7904243D01* +G01X1754323Y7902733D01* +G01X1765921Y7902715D01* +G01X1765921Y7902715D01* +G01X1777519Y7902696D01* +G01X1779959Y7903842D01* +G01X1782400Y7904987D01* +G01X1785333Y7905584D01* +G01X1788267Y7906179D01* +G01X1788480Y7907643D01* +G01X1788694Y7909107D01* +G01X1786852Y7910837D01* +G01X1785009Y7912568D01* +G01X1784015Y7911742D01* +G01X1783020Y7910917D01* +G01X1777943Y7910174D01* +G01X1772867Y7909432D01* +G01X1770231Y7908981D01* +G01X1767595Y7908531D01* +G01X1756344Y7910858D01* +G01X1753992Y7912522D01* +G01X1751639Y7914186D01* +G01X1748666Y7917724D01* +G01X1746650Y7921455D01* +G01X1744633Y7925186D01* +G01X1744633Y7928302D01* +G01X1743533Y7931419D01* +G01X1742433Y7934537D01* +G01X1742433Y7959024D01* +G01X1743476Y7962271D01* +G01X1744519Y7965519D01* +G01X1744962Y7968195D01* +G01X1745405Y7970871D01* +G01X1746485Y7971768D01* +G01X1747566Y7972665D01* +G01X1747567Y7973492D01* +G01X1747568Y7974319D01* +G01X1749584Y7976352D01* +G01X1751600Y7978386D01* +G01X1753654Y7980202D01* +G01X1755709Y7982018D01* +G01X1758387Y7982018D01* +G01X1761020Y7983119D01* +G01X1763653Y7984219D01* +G01X1769837Y7984219D01* +G01X1774138Y7983012D01* +G01X1778439Y7981805D01* +G01X1779417Y7979895D01* +G01X1780394Y7977986D01* +G01X1780922Y7974096D01* +G01X1781448Y7970206D01* +G01X1784124Y7970429D01* +G01X1786800Y7970652D01* +G01X1786800Y7986023D01* +G01X1783733Y7987715D01* +G01X1780668Y7989406D01* +G01X1769800Y7989676D01* +G01X1758933Y7989945D01* +G01X1753067Y7989300D01* +G01X1748430Y7987055D01* +G01X1743794Y7984809D01* +G01X1740730Y7981682D01* +G01X1737667Y7978556D01* +G01X1736256Y7976070D01* +G01X1734845Y7973586D01* +G01X1733443Y7969919D01* +G01X1732040Y7966252D01* +G01X1731301Y7960019D01* +G01X1730562Y7953785D01* +G01X1721901Y7953785D01* +G01X1721900Y7954529D01* +G01X1722655Y7957091D01* +G01X1723410Y7959652D01* +G01X1724119Y7965095D01* +G01X1724829Y7970537D01* +G01X1725931Y7972219D01* +G01X1727033Y7973901D01* +G01X1727033Y7976688D01* +G01X1728500Y7978552D01* +G01X1729967Y7980417D01* +G01X1729967Y7981448D01* +G01X1735947Y7988592D01* +G01X1742466Y7992991D01* +G01X1746371Y7994838D01* +G01X1750275Y7996686D01* +G01X1752037Y7996716D01* +G01X1753799Y7996747D01* +G01X1757833Y7997754D01* +G01X1761866Y7998761D01* +G01X1769199Y7998860D01* +G01X1774333Y7997773D01* +G01X1779465Y7996686D01* +G01X1783923Y7996686D01* +G01X1789363Y7993912D01* +G01X1791015Y7993484D01* +G01X1792666Y7993056D01* +G01X1794316Y7990609D01* +G01X1795967Y7988161D01* +G01X1795967Y7965152D01* +G01X1793033Y7962219D01* +G01X1777226Y7962219D01* +G01X1775689Y7963296D01* +G01X1774152Y7964372D01* +G01X1773816Y7968418D01* +G01X1773481Y7972462D01* +G01X1772073Y7974023D01* +G01X1770666Y7975582D01* +G01X1765068Y7975260D01* +G01X1759470Y7974938D01* +G01X1757368Y7973183D01* +G01X1755266Y7971427D01* +G01X1753602Y7968207D01* +G01X1751938Y7964988D01* +G01X1750228Y7946839D01* +G01X1751132Y7937183D01* +G01X1752036Y7927528D01* +G01X1753810Y7924524D01* +G01X1755584Y7921519D01* +G01X1758285Y7919383D01* +G01X1760987Y7917247D01* +G01X1776811Y7917375D01* +G01X1781666Y7919528D01* +G01X1785266Y7920645D01* +G01X1788865Y7921761D01* +G01X1792259Y7920471D01* +G01X1792759Y7918429D01* +G01X1793258Y7916386D01* +G01X1794612Y7913830D01* +G01X1795967Y7911274D01* +G01X1795967Y7908866D01* +G01X1796985Y7908020D01* +G01X1798004Y7907175D01* +G01X1798341Y7905411D01* +G01X1798678Y7903648D01* +G01X1798239Y7903018D01* +G01X1797800Y7902387D01* +G01X1794992Y7900761D01* +G01X1792185Y7899135D01* +G01X1789492Y7898460D01* +G01X1786800Y7897787D01* +G01X1783866Y7896668D01* +G01X1780933Y7895551D01* +G01X1778427Y7895518D01* +G01X1775920Y7895486D01* +G01X1771358Y7894692D01* +G37* +G36* +G01X1849500Y7894375D02* +G01X1845466Y7893905D01* +G01X1836938Y7895046D01* +G01X1828409Y7896186D01* +G01X1826304Y7897241D01* +G01X1824200Y7898296D01* +G01X1822366Y7899127D01* +G01X1820533Y7899958D01* +G01X1818483Y7901078D01* +G01X1816433Y7902198D01* +G01X1807811Y7910847D01* +G01X1805622Y7915450D01* +G01X1803434Y7920053D01* +G01X1803049Y7921519D01* +G01X1802663Y7922986D01* +G01X1801398Y7926286D01* +G01X1800133Y7929586D01* +G01X1800149Y7959703D01* +G01X1807699Y7959703D01* +G01X1807699Y7932469D01* +G01X1809166Y7928295D01* +G01X1810633Y7924123D01* +G01X1810633Y7921751D01* +G01X1812099Y7919886D01* +G01X1813566Y7918021D01* +G01X1813571Y7917204D01* +G01X1813575Y7916386D01* +G01X1817054Y7912633D01* +G01X1820533Y7908879D01* +G01X1822116Y7908388D01* +G01X1823701Y7907896D01* +G01X1824590Y7906824D01* +G01X1825479Y7905753D01* +G01X1827888Y7905753D01* +G01X1827888Y7905753D01* +G01X1830775Y7904205D01* +G01X1833663Y7902658D01* +G01X1859400Y7902738D01* +G01X1863598Y7904245D01* +G01X1867796Y7905753D01* +G01X1870766Y7905753D01* +G01X1870766Y7909973D01* +G01X1869656Y7910894D01* +G01X1868546Y7911815D01* +G01X1864340Y7911028D01* +G01X1860133Y7910240D01* +G01X1853716Y7909345D01* +G01X1847299Y7908450D01* +G01X1840883Y7909418D01* +G01X1834467Y7910385D01* +G01X1831262Y7912224D01* +G01X1828058Y7914061D01* +G01X1824674Y7917445D01* +G01X1822861Y7920949D01* +G01X1821047Y7924452D01* +G01X1820120Y7928120D01* +G01X1819192Y7931786D01* +G01X1818746Y7936860D01* +G01X1818300Y7941935D01* +G01X1819416Y7943281D01* +G01X1820533Y7944627D01* +G01X1848400Y7944807D01* +G01X1876266Y7944986D01* +G01X1876475Y7953373D01* +G01X1876683Y7961760D01* +G01X1875192Y7966513D01* +G01X1873699Y7971266D01* +G01X1873699Y7973117D01* +G01X1872050Y7975876D01* +G01X1870399Y7978634D01* +G01X1867335Y7981731D01* +G01X1864271Y7984827D01* +G01X1854657Y7989416D01* +G01X1835199Y7989955D01* +G01X1832633Y7989632D01* +G01X1830066Y7989309D01* +G01X1826033Y7987339D01* +G01X1822000Y7985369D01* +G01X1818333Y7981648D01* +G01X1814666Y7977927D01* +G01X1812650Y7974039D01* +G01X1810633Y7970150D01* +G01X1810633Y7968049D01* +G01X1809166Y7963876D01* +G01X1807699Y7959703D01* +G01X1800149Y7959703D01* +G01X1800151Y7961852D01* +G01X1800927Y7964785D01* +G01X1801704Y7967719D01* +G01X1802616Y7970286D01* +G01X1803529Y7972852D01* +G01X1805660Y7977436D01* +G01X1807792Y7982018D01* +G01X1809166Y7982018D01* +G01X1809166Y7983892D01* +G01X1817970Y7992258D01* +G01X1822705Y7994472D01* +G01X1827438Y7996686D01* +G01X1829119Y7996696D01* +G01X1830799Y7996708D01* +G01X1834100Y7997747D01* +G01X1837400Y7998787D01* +G01X1841433Y7998827D01* +G01X1845466Y7998868D01* +G01X1853533Y7996703D01* +G01X1855677Y7996694D01* +G01X1857821Y7996686D01* +G01X1870161Y7990544D01* +G01X1874127Y7986098D01* +G01X1878093Y7981652D01* +G01X1878099Y7979999D01* +G01X1879180Y7979101D01* +G01X1880261Y7978205D01* +G01X1880729Y7975528D01* +G01X1881198Y7972852D01* +G01X1882398Y7971019D01* +G01X1883600Y7969185D01* +G01X1883849Y7953824D01* +G01X1884098Y7938463D01* +G01X1882792Y7937507D01* +G01X1881486Y7936552D01* +G01X1827329Y7936552D01* +G01X1828326Y7926653D01* +G01X1830899Y7922986D01* +G01X1831854Y7920420D01* +G01X1833426Y7920420D01* +G01X1835622Y7918795D01* +G01X1837819Y7917171D01* +G01X1858666Y7917351D01* +G01X1862461Y7918853D01* +G01X1866255Y7920354D01* +G01X1873602Y7921328D01* +G01X1877317Y7913625D01* +G01X1881033Y7905921D01* +G01X1881033Y7902193D01* +G01X1877045Y7900306D01* +G01X1873057Y7898420D01* +G01X1869626Y7898420D01* +G01X1868056Y7897320D01* +G01X1866486Y7896220D01* +G01X1853533Y7894845D01* +G01X1849500Y7894375D01* +G37* +G36* +G01X1434066Y7895716D02* +G01X1417933Y7893928D01* +G01X1413983Y7894707D01* +G01X1410033Y7895486D01* +G01X1405410Y7895486D01* +G01X1402533Y7896953D01* +G01X1399656Y7898420D01* +G01X1398284Y7898420D01* +G01X1390465Y7903610D01* +G01X1387491Y7907064D01* +G01X1384516Y7910519D01* +G01X1383488Y7912353D01* +G01X1382460Y7914186D01* +G01X1380550Y7917988D01* +G01X1378638Y7921791D01* +G01X1377996Y7925688D01* +G01X1377354Y7929586D01* +G01X1376453Y7931786D01* +G01X1375552Y7933986D01* +G01X1375547Y7946359D01* +G01X1382959Y7946359D01* +G01X1384185Y7936506D01* +G01X1385410Y7926653D01* +G01X1386821Y7923639D01* +G01X1388233Y7920625D01* +G01X1388233Y7919026D01* +G01X1390371Y7915873D01* +G01X1392509Y7912720D01* +G01X1394588Y7910871D01* +G01X1396666Y7909023D01* +G01X1399020Y7907388D01* +G01X1401374Y7905753D01* +G01X1401374Y7905753D01* +G01X1402247Y7905753D01* +G01X1408930Y7902708D01* +G01X1430607Y7902708D01* +G01X1433590Y7904230D01* +G01X1436574Y7905753D01* +G01X1438540Y7905753D01* +G01X1442783Y7909535D01* +G01X1447027Y7913317D01* +G01X1448949Y7916318D01* +G01X1450871Y7919319D01* +G01X1452251Y7922986D01* +G01X1453630Y7926653D01* +G01X1455815Y7944252D01* +G01X1454944Y7954855D01* +G01X1454072Y7965458D01* +G01X1451299Y7970630D01* +G01X1451299Y7973000D01* +G01X1447704Y7977693D01* +G01X1444108Y7982386D01* +G01X1438911Y7986419D01* +G01X1437173Y7986419D01* +G01X1434751Y7987916D01* +G01X1432329Y7989412D01* +G01X1422564Y7989703D01* +G01X1412800Y7989995D01* +G01X1409500Y7989424D01* +G01X1406200Y7988854D01* +G01X1403999Y7987641D01* +G01X1401800Y7986428D01* +G01X1401200Y7986423D01* +G01X1400602Y7986419D01* +G01X1397912Y7984402D01* +G01X1395221Y7982386D01* +G01X1393473Y7980343D01* +G01X1391726Y7978300D01* +G01X1388233Y7973154D01* +G01X1388233Y7971791D01* +G01X1385404Y7965519D01* +G01X1384181Y7955939D01* +G01X1382959Y7946359D01* +G01X1375547Y7946359D01* +G01X1375547Y7946452D01* +G01X1375543Y7958919D01* +G01X1376754Y7961758D01* +G01X1377966Y7964598D01* +G01X1377966Y7969025D01* +G01X1380732Y7975052D01* +G01X1381585Y7976885D01* +G01X1382438Y7978719D01* +G01X1383458Y7980561D01* +G01X1384479Y7982403D01* +G01X1387639Y7985832D01* +G01X1390800Y7989260D01* +G01X1395997Y7992769D01* +G01X1404276Y7996686D01* +G01X1405971Y7996716D01* +G01X1407667Y7996747D01* +G01X1411699Y7997754D01* +G01X1415733Y7998761D01* +G01X1419399Y7998814D01* +G01X1423067Y7998868D01* +G01X1427100Y7997785D01* +G01X1431133Y7996703D01* +G01X1432895Y7996694D01* +G01X1434658Y7996686D01* +G01X1439128Y7994443D01* +G01X1443599Y7992200D01* +G01X1445551Y7991134D01* +G01X1447501Y7990068D01* +G01X1454917Y7981954D01* +G01X1456006Y7979970D01* +G01X1457094Y7977986D01* +G01X1457935Y7976152D01* +G01X1458775Y7974319D01* +G01X1459838Y7972086D01* +G01X1460902Y7969853D01* +G01X1461558Y7965486D01* +G01X1462214Y7961119D01* +G01X1462990Y7958557D01* +G01X1463766Y7955995D01* +G01X1463766Y7936053D01* +G01X1462674Y7932452D01* +G01X1461582Y7928852D01* +G01X1461574Y7926624D01* +G01X1461566Y7924396D01* +G01X1460180Y7921676D01* +G01X1458793Y7918956D01* +G01X1457874Y7915295D01* +G01X1452053Y7906853D01* +G01X1446097Y7901820D01* +G01X1444481Y7900897D01* +G01X1442867Y7899973D01* +G01X1438466Y7897845D01* +G01X1434066Y7895716D01* +G37* +G36* +G01X1295763Y7896200D02* +G01X1287478Y7895114D01* +G01X1279194Y7894029D01* +G01X1271548Y7895033D01* +G01X1263901Y7896037D01* +G01X1258800Y7898802D01* +G01X1253896Y7902453D01* +G01X1249560Y7908867D01* +G01X1248872Y7912500D01* +G01X1248183Y7916133D01* +G01X1247624Y7916993D01* +G01X1247066Y7917853D01* +G01X1246700Y7946085D01* +G01X1246333Y7974319D01* +G01X1240039Y7974750D01* +G01X1233744Y7975181D01* +G01X1232033Y7976239D01* +G01X1232033Y7986303D01* +G01X1240703Y7986303D01* +G01X1241594Y7982752D01* +G01X1251466Y7982730D01* +G01X1253299Y7981804D01* +G01X1255133Y7980877D01* +G01X1255866Y7913316D01* +G01X1258601Y7909980D01* +G01X1261335Y7906643D01* +G01X1264693Y7904676D01* +G01X1268050Y7902708D01* +G01X1268050Y7902708D01* +G01X1289927Y7902708D01* +G01X1291453Y7903192D01* +G01X1292978Y7903677D01* +G01X1292756Y7906731D01* +G01X1292533Y7909786D01* +G01X1283671Y7909802D01* +G01X1274808Y7909819D01* +G01X1272304Y7911902D01* +G01X1269800Y7913986D01* +G01X1268149Y7917008D01* +G01X1266500Y7920030D01* +G01X1266500Y7980992D01* +G01X1267380Y7981872D01* +G01X1268259Y7982752D01* +G01X1289933Y7982752D01* +G01X1292432Y7986567D01* +G01X1291671Y7987776D01* +G01X1290909Y7988986D01* +G01X1279672Y7989188D01* +G01X1268435Y7989391D01* +G01X1266500Y7990998D01* +G01X1266500Y8012818D01* +G01X1265216Y8012764D01* +G01X1263933Y8012710D01* +G01X1257333Y8009111D01* +G01X1256417Y8007891D01* +G01X1255500Y8006671D01* +G01X1255500Y7990905D01* +G01X1254583Y7990312D01* +G01X1253666Y7989718D01* +G01X1241214Y7988986D01* +G01X1240959Y7987644D01* +G01X1240703Y7986303D01* +G01X1232033Y7986303D01* +G01X1232033Y7995132D01* +G01X1232950Y7995725D01* +G01X1233866Y7996319D01* +G01X1240100Y7996686D01* +G01X1246333Y7997052D01* +G01X1246700Y8004093D01* +G01X1247066Y8011135D01* +G01X1248077Y8012348D01* +G01X1249087Y8013562D01* +G01X1252933Y8015680D01* +G01X1254766Y8016528D01* +G01X1256599Y8017375D01* +G01X1257700Y8018035D01* +G01X1258800Y8018696D01* +G01X1262466Y8020460D01* +G01X1265964Y8023085D01* +G01X1268520Y8023085D01* +G01X1269433Y8024185D01* +G01X1270346Y8025285D01* +G01X1272942Y8025285D01* +G01X1273833Y8022965D01* +G01X1273833Y7996686D01* +G01X1297928Y7996686D01* +G01X1299154Y7995459D01* +G01X1300380Y7994233D01* +G01X1300123Y7985596D01* +G01X1299866Y7976959D01* +G01X1298915Y7976005D01* +G01X1297963Y7975052D01* +G01X1285898Y7974820D01* +G01X1273833Y7974587D01* +G01X1273833Y7922963D01* +G01X1275201Y7920408D01* +G01X1276570Y7917853D01* +G01X1289934Y7917431D01* +G01X1292114Y7918558D01* +G01X1294294Y7919686D01* +G01X1295638Y7919686D01* +G01X1297591Y7916735D01* +G01X1299543Y7913785D01* +G01X1300014Y7911431D01* +G01X1300485Y7909076D01* +G01X1303265Y7904364D01* +G01X1303033Y7901948D01* +G01X1302800Y7899531D01* +G01X1299281Y7897866D01* +G01X1295763Y7896200D01* +G37* +G36* +G01X1672766Y7895154D02* +G01X1665800Y7894666D01* +G01X1652599Y7896151D01* +G01X1649299Y7897792D01* +G01X1646000Y7899434D01* +G01X1642940Y7901736D01* +G01X1639880Y7904038D01* +G01X1636100Y7908531D01* +G01X1636100Y7909670D01* +G01X1635075Y7910828D01* +G01X1634051Y7911986D01* +G01X1632740Y7916753D01* +G01X1631429Y7921519D01* +G01X1631178Y7925776D01* +G01X1639572Y7925776D01* +G01X1640084Y7920987D01* +G01X1640597Y7916198D01* +G01X1643066Y7912851D01* +G01X1649666Y7905761D01* +G01X1650766Y7905732D01* +G01X1651866Y7905703D01* +G01X1654800Y7904286D01* +G01X1657733Y7902869D01* +G01X1657733Y7902869D01* +G01X1676840Y7902819D01* +G01X1679733Y7904811D01* +G01X1682399Y7905678D01* +G01X1685065Y7906544D01* +G01X1688815Y7910140D01* +G01X1692566Y7913737D01* +G01X1692566Y7915323D01* +G01X1694527Y7916067D01* +G01X1696487Y7916813D01* +G01X1697427Y7915866D01* +G01X1698366Y7914919D01* +G01X1698951Y7910153D01* +G01X1699535Y7905386D01* +G01X1706867Y7905386D01* +G01X1706867Y7973586D01* +G01X1704847Y7977182D01* +G01X1702829Y7980779D01* +G01X1699714Y7983589D01* +G01X1696600Y7986398D01* +G01X1695856Y7986408D01* +G01X1695111Y7986419D01* +G01X1692322Y7987914D01* +G01X1689532Y7989409D01* +G01X1677666Y7989682D01* +G01X1665800Y7989956D01* +G01X1660666Y7989434D01* +G01X1655533Y7988913D01* +G01X1647466Y7986280D01* +G01X1646524Y7985995D01* +G01X1645581Y7985712D01* +G01X1645790Y7978182D01* +G01X1646000Y7970652D01* +G01X1651074Y7970652D01* +G01X1654268Y7980886D01* +G01X1656267Y7981857D01* +G01X1668733Y7984226D01* +G01X1672491Y7984222D01* +G01X1676249Y7984219D01* +G01X1679367Y7983119D01* +G01X1682484Y7982018D01* +G01X1685755Y7982018D01* +G01X1689065Y7979492D01* +G01X1692375Y7976965D01* +G01X1694071Y7974175D01* +G01X1695767Y7971386D01* +G01X1696080Y7963969D01* +G01X1696392Y7956553D01* +G01X1695605Y7955081D01* +G01X1694817Y7953611D01* +G01X1676800Y7952643D01* +G01X1668366Y7951849D01* +G01X1659933Y7951054D01* +G01X1650451Y7947380D01* +G01X1648628Y7946184D01* +G01X1646804Y7944990D01* +G01X1643638Y7941825D01* +G01X1642013Y7939194D01* +G01X1640388Y7936564D01* +G01X1639979Y7931170D01* +G01X1639572Y7925776D01* +G01X1631178Y7925776D01* +G01X1630846Y7931422D01* +G01X1631955Y7934537D01* +G01X1633064Y7937653D01* +G01X1633475Y7939586D01* +G01X1633886Y7941520D01* +G01X1639440Y7948912D01* +G01X1643130Y7951849D01* +G01X1646820Y7954787D01* +G01X1648976Y7955320D01* +G01X1651133Y7955851D01* +G01X1652624Y7956815D01* +G01X1654115Y7957779D01* +G01X1659320Y7958517D01* +G01X1664525Y7959256D01* +G01X1666493Y7960004D01* +G01X1668462Y7960753D01* +G01X1676945Y7960753D01* +G01X1682556Y7961226D01* +G01X1688166Y7961701D01* +G01X1688166Y7967967D01* +G01X1686971Y7970049D01* +G01X1685776Y7972132D01* +G01X1683928Y7973525D01* +G01X1682081Y7974919D01* +G01X1673207Y7975239D01* +G01X1664333Y7975558D01* +G01X1660804Y7974202D01* +G01X1658947Y7966986D01* +G01X1657403Y7962952D01* +G01X1639871Y7962952D01* +G01X1638719Y7964105D01* +G01X1637566Y7965257D01* +G01X1637566Y7988692D01* +G01X1638637Y7990762D01* +G01X1639708Y7992832D01* +G01X1641387Y7993282D01* +G01X1643066Y7993732D01* +G01X1644533Y7993746D01* +G01X1646000Y7993761D01* +G01X1648134Y7994874D01* +G01X1650269Y7995987D01* +G01X1656934Y7996733D01* +G01X1663600Y7997479D01* +G01X1666533Y7998098D01* +G01X1669466Y7998716D01* +G01X1673500Y7998757D01* +G01X1677533Y7998798D01* +G01X1681200Y7998105D01* +G01X1684866Y7997413D01* +G01X1694083Y7996088D01* +G01X1695865Y7994920D01* +G01X1697648Y7993752D01* +G01X1699914Y7993752D01* +G01X1701170Y7992285D01* +G01X1702425Y7990819D01* +G01X1703799Y7990819D01* +G01X1707000Y7987335D01* +G01X1710201Y7983852D01* +G01X1712017Y7980382D01* +G01X1713833Y7976912D01* +G01X1713841Y7975249D01* +G01X1713849Y7973586D01* +G01X1714941Y7969985D01* +G01X1716033Y7966386D01* +G01X1716033Y7900084D01* +G01X1714513Y7898152D01* +G01X1712993Y7896219D01* +G01X1695607Y7896219D01* +G01X1693346Y7898961D01* +G01X1691086Y7901703D01* +G01X1689810Y7900805D01* +G01X1688533Y7899906D01* +G01X1684133Y7897774D01* +G01X1679733Y7895641D01* +G01X1672766Y7895154D01* +G37* +G36* +G01X1524958Y7896586D02* +G01X1503000Y7896166D01* +G01X1501431Y7896553D01* +G01X1499862Y7896940D01* +G01X1499230Y7898230D01* +G01X1498600Y7899519D01* +G01X1498233Y7951952D01* +G01X1497866Y8004386D01* +G01X1489309Y8004829D01* +G01X1488365Y8004045D01* +G01X1487421Y8003262D01* +G01X1487059Y8000055D01* +G01X1486698Y7996848D01* +G01X1483933Y7991185D01* +G01X1475754Y7990979D01* +G01X1467576Y7990772D01* +G01X1465988Y7992791D01* +G01X1464401Y7994809D01* +G01X1464633Y8010841D01* +G01X1464779Y8020885D01* +G01X1473260Y8020885D01* +G01X1473667Y7999252D01* +G01X1475133Y7999064D01* +G01X1476600Y7998877D01* +G01X1477510Y7999470D01* +G01X1478419Y8000063D01* +G01X1479903Y8005864D01* +G01X1481386Y8011665D01* +G01X1482905Y8013185D01* +G01X1501196Y8013703D01* +G01X1503001Y8013250D01* +G01X1504806Y8012797D01* +G01X1505920Y8010644D01* +G01X1507033Y8008491D01* +G01X1507033Y7905910D01* +G01X1509353Y7905020D01* +G01X1509353Y7905020D01* +G01X1518766Y7905020D01* +G01X1518766Y8009083D01* +G01X1519583Y8010876D01* +G01X1520400Y8012668D01* +G01X1522608Y8013110D01* +G01X1524816Y8013552D01* +G01X1541387Y8013552D01* +G01X1545817Y8009824D01* +G01X1546314Y8004784D01* +G01X1546810Y7999743D01* +G01X1548115Y7999402D01* +G01X1549420Y7999060D01* +G01X1553233Y7999789D01* +G01X1553233Y8019125D01* +G01X1552353Y8020005D01* +G01X1551473Y8020885D01* +G01X1473260Y8020885D01* +G01X1464779Y8020885D01* +G01X1464866Y8026872D01* +G01X1466290Y8027912D01* +G01X1467713Y8028952D01* +G01X1558366Y8028952D01* +G01X1559833Y8027485D01* +G01X1561300Y8026018D01* +G01X1561299Y8011169D01* +G01X1561298Y7996319D01* +G01X1575273Y7996560D01* +G01X1589247Y7996801D01* +G01X1591041Y7995626D01* +G01X1592833Y7994452D01* +G01X1592833Y7991639D01* +G01X1593574Y7991181D01* +G01X1594314Y7990724D01* +G01X1596239Y7992237D01* +G01X1598164Y7993752D01* +G01X1599568Y7993752D01* +G01X1601433Y7995219D01* +G01X1603297Y7996686D01* +G01X1606648Y7996686D01* +G01X1611208Y7997853D01* +G01X1615768Y7999022D01* +G01X1622533Y7998053D01* +G01X1627666Y7996752D01* +G01X1631673Y7995931D01* +G01X1632778Y7993794D01* +G01X1633882Y7991658D01* +G01X1633407Y7977998D01* +G01X1632932Y7964338D01* +G01X1631419Y7963279D01* +G01X1629906Y7962219D01* +G01X1614279Y7962219D01* +G01X1613582Y7963136D01* +G01X1612885Y7964052D01* +G01X1611556Y7967719D01* +G01X1610227Y7971386D01* +G01X1609552Y7972248D01* +G01X1608876Y7973111D01* +G01X1606538Y7972339D01* +G01X1604200Y7971567D01* +G01X1599488Y7966252D01* +G01X1599461Y7965431D01* +G01X1599433Y7964610D01* +G01X1597967Y7960019D01* +G01X1596500Y7955428D01* +G01X1596500Y7899056D01* +G01X1595740Y7897638D01* +G01X1594981Y7896219D01* +G01X1572626Y7896219D01* +G01X1569366Y7898503D01* +G01X1569366Y7973659D01* +G01X1568486Y7974539D01* +G01X1567607Y7975419D01* +G01X1563583Y7975419D01* +G01X1562442Y7977048D01* +G01X1561300Y7978678D01* +G01X1561283Y7986052D01* +G01X1569540Y7986052D01* +G01X1570884Y7983485D01* +G01X1574173Y7983485D01* +G01X1575803Y7982344D01* +G01X1577433Y7981203D01* +G01X1577433Y7906666D01* +G01X1578469Y7905806D01* +G01X1578469Y7905806D01* +G01X1579505Y7904946D01* +G01X1584152Y7905166D01* +G01X1588800Y7905386D01* +G01X1589166Y7933986D01* +G01X1589533Y7962586D01* +G01X1590740Y7964785D01* +G01X1591947Y7966986D01* +G01X1592206Y7969185D01* +G01X1592466Y7971386D01* +G01X1590166Y7971211D01* +G01X1587866Y7971036D01* +G01X1587401Y7972677D01* +G01X1587286Y7973083D01* +G01X1592674Y7973083D01* +G01X1593419Y7972339D01* +G01X1594164Y7971594D01* +G01X1595073Y7973293D01* +G01X1595982Y7974992D01* +G01X1597524Y7976315D01* +G01X1599066Y7977639D01* +G01X1603059Y7979583D01* +G01X1607052Y7981527D01* +G01X1611397Y7981589D01* +G01X1615742Y7981652D01* +G01X1616281Y7980552D01* +G01X1616281Y7980552D01* +G01X1616820Y7979452D01* +G01X1619708Y7970652D01* +G01X1624733Y7970652D01* +G01X1624939Y7979645D01* +G01X1625145Y7988638D01* +G01X1621338Y7990085D01* +G01X1616436Y7989993D01* +G01X1611533Y7989902D01* +G01X1605667Y7988908D01* +G01X1602733Y7987017D01* +G01X1599800Y7985127D01* +G01X1598234Y7983390D01* +G01X1596668Y7981652D01* +G01X1596168Y7980002D01* +G01X1595667Y7978352D01* +G01X1594413Y7978352D01* +G01X1593544Y7975718D01* +G01X1592674Y7973083D01* +G01X1587286Y7973083D01* +G01X1586936Y7974319D01* +G01X1586467Y7980486D01* +G01X1585999Y7986653D01* +G01X1584649Y7988003D01* +G01X1583299Y7989352D01* +G01X1570785Y7989352D01* +G01X1570162Y7987702D01* +G01X1569540Y7986052D01* +G01X1561283Y7986052D01* +G01X1561277Y7988986D01* +G01X1559979Y7991035D01* +G01X1551133Y7991110D01* +G01X1542287Y7991185D01* +G01X1541016Y7992455D01* +G01X1539745Y7993725D01* +G01X1538750Y8003347D01* +G01X1538352Y8003744D01* +G01X1537954Y8004142D01* +G01X1535007Y8004537D01* +G01X1532059Y8004932D01* +G01X1526833Y8003952D01* +G01X1526812Y7900253D01* +G01X1525885Y7898420D01* +G01X1524958Y7896586D01* +G37* +G36* +G01X1339100Y7949198D02* +G01X1339100Y7898524D01* +G01X1336795Y7896219D01* +G01X1314899Y7896219D01* +G01X1313433Y7897686D01* +G01X1311966Y7899153D01* +G01X1311966Y7973901D01* +G01X1310548Y7974660D01* +G01X1309129Y7975419D01* +G01X1305523Y7975419D01* +G01X1305078Y7976578D01* +G01X1304633Y7977739D01* +G01X1304633Y7987258D01* +G01X1311850Y7987258D01* +G01X1312091Y7985566D01* +G01X1312333Y7983872D01* +G01X1315044Y7983434D01* +G01X1317756Y7982996D01* +G01X1318894Y7982051D01* +G01X1320033Y7981106D01* +G01X1320033Y7907339D01* +G01X1320478Y7906179D01* +G01X1320923Y7905020D01* +G01X1320923Y7905020D01* +G01X1330886Y7905020D01* +G01X1331199Y7932336D01* +G01X1331512Y7959652D01* +G01X1332739Y7962379D01* +G01X1333967Y7965105D01* +G01X1333967Y7969325D01* +G01X1331094Y7971925D01* +G01X1330032Y7975143D01* +G01X1335433Y7975143D01* +G01X1335433Y7970199D01* +G01X1336900Y7971105D01* +G01X1336900Y7972983D01* +G01X1339650Y7975519D01* +G01X1342399Y7978055D01* +G01X1345699Y7979639D01* +G01X1349000Y7981223D01* +G01X1352082Y7981709D01* +G01X1355164Y7982195D01* +G01X1356913Y7981756D01* +G01X1358662Y7981317D01* +G01X1359832Y7978551D01* +G01X1361002Y7975785D01* +G01X1361458Y7972994D01* +G01X1361915Y7970202D01* +G01X1364624Y7970427D01* +G01X1367333Y7970652D01* +G01X1367539Y7979645D01* +G01X1367745Y7988638D01* +G01X1363937Y7990085D01* +G01X1359035Y7989993D01* +G01X1354133Y7989902D01* +G01X1348217Y7988929D01* +G01X1344987Y7986757D01* +G01X1341757Y7984585D01* +G01X1338594Y7979864D01* +G01X1335433Y7975143D01* +G01X1335433Y7975143D01* +G01X1330032Y7975143D01* +G01X1328852Y7978719D01* +G01X1328293Y7983852D01* +G01X1327733Y7988986D01* +G01X1312673Y7989403D01* +G01X1311850Y7987258D01* +G01X1304633Y7987258D01* +G01X1304633Y7995795D01* +G01X1306953Y7996686D01* +G01X1332500Y7996686D01* +G01X1333967Y7995219D01* +G01X1335433Y7993752D01* +G01X1335433Y7990085D01* +G01X1336720Y7990085D01* +G01X1338733Y7992512D01* +G01X1340933Y7993543D01* +G01X1343133Y7994573D01* +G01X1344966Y7995618D01* +G01X1346800Y7996663D01* +G01X1348266Y7996707D01* +G01X1349733Y7996750D01* +G01X1353400Y7997768D01* +G01X1357066Y7998786D01* +G01X1358605Y7998836D01* +G01X1360144Y7998885D01* +G01X1366976Y7997455D01* +G01X1373807Y7996025D01* +G01X1374875Y7994958D01* +G01X1375942Y7993891D01* +G01X1375894Y7978706D01* +G01X1375846Y7963521D01* +G01X1375379Y7963053D01* +G01X1374911Y7962586D01* +G01X1365989Y7962372D01* +G01X1357066Y7962160D01* +G01X1355039Y7963525D01* +G01X1354427Y7967397D01* +G01X1353815Y7971269D01* +G01X1351933Y7972539D01* +G01X1349484Y7972181D01* +G01X1347036Y7971823D01* +G01X1346089Y7971038D01* +G01X1345143Y7970253D01* +G01X1341390Y7964785D01* +G01X1339100Y7949198D01* +G37* +G36* +G01X1079500Y7944326D02* +G01X1079500Y7899153D01* +G01X1076566Y7896219D01* +G01X1053938Y7896219D01* +G01X1051633Y7898524D01* +G01X1051300Y7898786D01* +G01X1050916Y7952677D01* +G01X1050533Y8006567D01* +G01X1043482Y8007576D01* +G01X1042424Y8008453D01* +G01X1041366Y8009331D01* +G01X1041366Y8018682D01* +G01X1050008Y8018682D01* +G01X1050444Y8016946D01* +G01X1050879Y8015212D01* +G01X1054328Y8014823D01* +G01X1057777Y8014434D01* +G01X1058739Y8013119D01* +G01X1059700Y8011805D01* +G01X1059700Y8011805D01* +G01X1059700Y7904955D01* +G01X1065016Y7905171D01* +G01X1070333Y7905386D01* +G01X1070726Y7928486D01* +G01X1071119Y7951586D01* +G01X1071433Y7951895D01* +G01X1073038Y7953390D01* +G01X1074643Y7954886D01* +G01X1089647Y7954886D01* +G01X1091896Y7953602D01* +G01X1094144Y7952319D01* +G01X1094917Y7950486D01* +G01X1095690Y7948652D01* +G01X1099250Y7942786D01* +G01X1102175Y7937653D01* +G01X1103387Y7935086D01* +G01X1104598Y7932519D01* +G01X1105135Y7932152D01* +G01X1105673Y7931786D01* +G01X1106860Y7929586D01* +G01X1108047Y7927386D01* +G01X1109224Y7925186D01* +G01X1110400Y7922986D01* +G01X1112128Y7920053D01* +G01X1113855Y7917120D01* +G01X1116513Y7912041D01* +G01X1119171Y7906962D01* +G01X1121666Y7905066D01* +G01X1127716Y7905043D01* +G01X1133766Y7905020D01* +G01X1133766Y7906357D01* +G01X1127533Y7916820D01* +G01X1125897Y7919536D01* +G01X1124262Y7922253D01* +G01X1122413Y7925919D01* +G01X1119210Y7930727D01* +G01X1116035Y7937286D01* +G01X1114813Y7937286D01* +G01X1113119Y7942419D01* +G01X1111910Y7942419D01* +G01X1110215Y7946452D01* +G01X1108888Y7948827D01* +G01X1107561Y7951202D01* +G01X1106623Y7952332D01* +G01X1105684Y7953462D01* +G01X1107364Y7955250D01* +G01X1109044Y7957038D01* +G01X1112548Y7958202D01* +G01X1116054Y7959366D01* +G01X1117813Y7961485D01* +G01X1119123Y7961485D01* +G01X1121128Y7963757D01* +G01X1123133Y7966029D01* +G01X1125700Y7968411D01* +G01X1125700Y7970479D01* +G01X1128999Y7975785D01* +G01X1128999Y8001452D01* +G01X1126866Y8005118D01* +G01X1124733Y8008785D01* +G01X1119095Y8014121D01* +G01X1113599Y8016556D01* +G01X1112133Y8017390D01* +G01X1110666Y8018223D01* +G01X1104433Y8019265D01* +G01X1098199Y8020307D01* +G01X1074544Y8020642D01* +G01X1050889Y8020977D01* +G01X1050449Y8019829D01* +G01X1050008Y8018682D01* +G01X1041366Y8018682D01* +G01X1041366Y8027532D01* +G01X1043017Y8028232D01* +G01X1044666Y8028932D01* +G01X1102600Y8028419D01* +G01X1105533Y8027250D01* +G01X1108466Y8026083D01* +G01X1110529Y8026050D01* +G01X1112590Y8026018D01* +G01X1120848Y8022112D01* +G01X1123951Y8020018D01* +G01X1127052Y8017925D01* +G01X1129859Y8014455D01* +G01X1132667Y8010985D01* +G01X1133954Y8008418D01* +G01X1135241Y8005852D01* +G01X1136421Y8001819D01* +G01X1137599Y7997785D01* +G01X1137950Y7990263D01* +G01X1138300Y7982740D01* +G01X1137133Y7979315D01* +G01X1135967Y7975891D01* +G01X1135967Y7972621D01* +G01X1133984Y7968703D01* +G01X1132002Y7964785D01* +G01X1126667Y7957921D01* +G01X1124427Y7956036D01* +G01X1122188Y7954152D01* +G01X1120822Y7954152D01* +G01X1117494Y7950610D01* +G01X1118017Y7948898D01* +G01X1118540Y7947186D01* +G01X1119502Y7946084D01* +G01X1120464Y7944983D01* +G01X1121259Y7943151D01* +G01X1122054Y7941319D01* +G01X1128613Y7931053D01* +G01X1129773Y7928852D01* +G01X1130934Y7926653D01* +G01X1132689Y7923719D01* +G01X1134445Y7920786D01* +G01X1135929Y7918086D01* +G01X1137412Y7915385D01* +G01X1138156Y7914926D01* +G01X1138900Y7914466D01* +G01X1138900Y7911573D01* +G01X1139964Y7911165D01* +G01X1141029Y7910756D01* +G01X1142680Y7905753D01* +G01X1143687Y7905753D01* +G01X1145424Y7902095D01* +G01X1147160Y7898437D01* +G01X1145320Y7896219D01* +G01X1131660Y7896244D01* +G01X1118000Y7896268D01* +G01X1116466Y7897550D01* +G01X1114934Y7898832D01* +G01X1113743Y7901009D01* +G01X1112552Y7903186D01* +G01X1110199Y7907586D01* +G01X1108421Y7910519D01* +G01X1106644Y7913452D01* +G01X1104332Y7917853D01* +G01X1102555Y7920786D01* +G01X1100777Y7923719D01* +G01X1098465Y7928120D01* +G01X1096688Y7931053D01* +G01X1094910Y7933986D01* +G01X1093751Y7936476D01* +G01X1092590Y7938967D01* +G01X1091545Y7940012D01* +G01X1090499Y7941057D01* +G01X1090499Y7942691D01* +G01X1088905Y7944389D01* +G01X1087310Y7946085D01* +G01X1081259Y7946085D01* +G01X1080379Y7945206D01* +G01X1079500Y7944326D01* +G37* +G36* +G01X1424020Y7909381D02* +G01X1419841Y7908470D01* +G01X1415221Y7909387D01* +G01X1410600Y7910304D01* +G01X1409465Y7910598D01* +G01X1408330Y7910891D01* +G01X1405085Y7913916D01* +G01X1401840Y7916942D01* +G01X1400932Y7918497D01* +G01X1400024Y7920053D01* +G01X1399191Y7921886D01* +G01X1398358Y7923719D01* +G01X1395933Y7928738D01* +G01X1395933Y7957503D01* +G01X1402900Y7957503D01* +G01X1402900Y7934668D01* +G01X1404367Y7930496D01* +G01X1405833Y7926323D01* +G01X1405833Y7924327D01* +G01X1405833Y7924327D01* +G01X1412369Y7917698D01* +G01X1419927Y7916803D01* +G01X1426733Y7917693D01* +G01X1429357Y7920420D01* +G01X1430766Y7920420D01* +G01X1430766Y7922137D01* +G01X1431886Y7923374D01* +G01X1433004Y7924611D01* +G01X1434810Y7931865D01* +G01X1436616Y7939119D01* +G01X1436625Y7946249D01* +G01X1436633Y7953378D01* +G01X1434904Y7960182D01* +G01X1433175Y7966986D01* +G01X1431739Y7969340D01* +G01X1430304Y7971695D01* +G01X1428242Y7973317D01* +G01X1426179Y7974939D01* +G01X1420589Y7975121D01* +G01X1415000Y7975303D01* +G01X1413365Y7974945D01* +G01X1411730Y7974587D01* +G01X1405842Y7967719D01* +G01X1405838Y7966784D01* +G01X1405833Y7965849D01* +G01X1404367Y7961676D01* +G01X1402900Y7957503D01* +G01X1395933Y7957503D01* +G01X1395933Y7963433D01* +G01X1398424Y7968452D01* +G01X1399226Y7972346D01* +G01X1403446Y7976772D01* +G01X1407667Y7981199D01* +G01X1411699Y7982674D01* +G01X1415733Y7984149D01* +G01X1420133Y7983917D01* +G01X1424533Y7983685D01* +G01X1427927Y7982427D01* +G01X1431322Y7981170D01* +G01X1434161Y7978456D01* +G01X1437000Y7975743D01* +G01X1440334Y7971032D01* +G01X1440788Y7968642D01* +G01X1441242Y7966252D01* +G01X1442404Y7964052D01* +G01X1443564Y7961852D01* +G01X1443833Y7949019D01* +G01X1444101Y7936186D01* +G01X1443373Y7932519D01* +G01X1442645Y7928852D01* +G01X1440852Y7923719D01* +G01X1439292Y7920524D01* +G01X1437733Y7917329D01* +G01X1431133Y7911444D01* +G01X1429666Y7910869D01* +G01X1428199Y7910293D01* +G01X1424020Y7909381D01* +G37* +G36* +G01X1683377Y7910970D02* +G01X1677521Y7909745D01* +G01X1671667Y7908520D01* +G01X1662133Y7910317D01* +G01X1658881Y7912355D01* +G01X1656667Y7914519D01* +G01X1654454Y7916683D01* +G01X1652977Y7920568D01* +G01X1651500Y7924452D01* +G01X1651500Y7928542D01* +G01X1659594Y7928542D01* +G01X1661033Y7920952D01* +G01X1662899Y7919087D01* +G01X1662899Y7919087D01* +G01X1664765Y7917221D01* +G01X1671515Y7917253D01* +G01X1678266Y7917285D01* +G01X1681768Y7919649D01* +G01X1685268Y7922013D01* +G01X1688166Y7927694D01* +G01X1688166Y7939329D01* +G01X1685846Y7940219D01* +G01X1679123Y7940109D01* +G01X1672399Y7939999D01* +G01X1666533Y7939114D01* +G01X1663834Y7937425D01* +G01X1661136Y7935736D01* +G01X1660365Y7932138D01* +G01X1659594Y7928542D01* +G01X1651500Y7928542D01* +G01X1651500Y7928576D01* +G01X1651500Y7932699D01* +G01X1653028Y7936154D01* +G01X1654556Y7939609D01* +G01X1656138Y7941197D01* +G01X1657721Y7942786D01* +G01X1660155Y7944444D01* +G01X1662588Y7946101D01* +G01X1668961Y7947481D01* +G01X1675333Y7948860D01* +G01X1693019Y7949019D01* +G01X1695866Y7946940D01* +G01X1696105Y7936594D01* +G01X1696345Y7926246D01* +G01X1694717Y7922782D01* +G01X1693090Y7919319D01* +G01X1690108Y7916203D01* +G01X1687128Y7913086D01* +G01X1685715Y7913086D01* +G01X1684546Y7912028D01* +G01X1683377Y7910970D01* +G37* +G36* +G01X1214433Y7960491D02* +G01X1214433Y7950665D01* +G01X1212424Y7948998D01* +G01X1189778Y7949192D01* +G01X1167133Y7949385D01* +G01X1167148Y7957821D01* +G01X1167151Y7959652D01* +G01X1174119Y7959652D01* +G01X1174932Y7957085D01* +G01X1204743Y7957085D01* +G01X1205222Y7958334D01* +G01X1205701Y7959584D01* +G01X1204688Y7967699D01* +G01X1203143Y7969883D01* +G01X1201600Y7972068D01* +G01X1200133Y7973338D01* +G01X1198667Y7974609D01* +G01X1195147Y7975381D01* +G01X1191628Y7976152D01* +G01X1187666Y7976005D01* +G01X1184759Y7975324D01* +G01X1181853Y7974643D01* +G01X1179819Y7972563D01* +G01X1177786Y7970483D01* +G01X1175953Y7965068D01* +G01X1175953Y7965068D01* +G01X1174119Y7959652D01* +G01X1167151Y7959652D01* +G01X1167162Y7966255D01* +G01X1169700Y7969879D01* +G01X1169700Y7972040D01* +G01X1171716Y7974996D01* +G01X1173733Y7977953D01* +G01X1175566Y7979608D01* +G01X1177400Y7981263D01* +G01X1182838Y7982792D01* +G01X1183279Y7983506D01* +G01X1183719Y7984219D01* +G01X1195913Y7984219D01* +G01X1199489Y7982659D01* +G01X1203066Y7981099D01* +G01X1206183Y7978577D01* +G01X1209300Y7976054D01* +G01X1209300Y7974132D01* +G01X1210380Y7973235D01* +G01X1211461Y7972338D01* +G01X1211904Y7969662D01* +G01X1212347Y7966986D01* +G01X1213390Y7963738D01* +G01X1214433Y7960491D01* +G37* +G36* +G01X1866556Y7952809D02* +G01X1866078Y7950904D01* +G01X1865600Y7948999D01* +G01X1842333Y7949192D01* +G01X1819067Y7949385D01* +G01X1818848Y7954407D01* +G01X1818630Y7959403D01* +G01X1827501Y7959403D01* +G01X1828390Y7957085D01* +G01X1828390Y7957085D01* +G01X1858201Y7957085D01* +G01X1858625Y7958423D01* +G01X1859050Y7959761D01* +G01X1857311Y7965242D01* +G01X1855571Y7970722D01* +G01X1852066Y7974491D01* +G01X1844294Y7976152D01* +G01X1840333Y7976005D01* +G01X1837416Y7975322D01* +G01X1834498Y7974639D01* +G01X1832465Y7972692D01* +G01X1830433Y7970744D01* +G01X1830433Y7969447D01* +G01X1828448Y7967463D01* +G01X1827501Y7959403D01* +G01X1818630Y7959403D01* +G01X1818629Y7959429D01* +G01X1819703Y7962840D01* +G01X1820778Y7966252D01* +G01X1821225Y7968929D01* +G01X1821672Y7971605D01* +G01X1822752Y7972502D01* +G01X1823833Y7973398D01* +G01X1823833Y7975180D01* +G01X1830161Y7981111D01* +G01X1833414Y7982603D01* +G01X1836666Y7984095D01* +G01X1842920Y7984157D01* +G01X1849173Y7984219D01* +G01X1852066Y7982238D01* +G01X1854025Y7981762D01* +G01X1855982Y7981287D01* +G01X1862701Y7974568D01* +G01X1863154Y7972610D01* +G01X1863607Y7970652D01* +G01X1864740Y7968846D01* +G01X1865871Y7967040D01* +G01X1866214Y7959925D01* +G01X1866556Y7952809D01* +G37* +G36* +G01X1099666Y7961214D02* +G01X1087575Y7960947D01* +G01X1075484Y7960681D01* +G01X1072313Y7961477D01* +G01X1071506Y7963790D01* +G01X1070699Y7966104D01* +G01X1070699Y7970465D01* +G01X1079500Y7970465D01* +G01X1080621Y7969534D01* +G01X1081743Y7968603D01* +G01X1089972Y7969046D01* +G01X1098199Y7969489D01* +G01X1100828Y7970255D01* +G01X1103455Y7971020D01* +G01X1108197Y7976921D01* +G01X1108615Y7983376D01* +G01X1109034Y7989832D01* +G01X1108527Y7993887D01* +G01X1108020Y7997943D01* +G01X1102004Y8004018D01* +G01X1101202Y8004043D01* +G01X1100400Y8004068D01* +G01X1097467Y8005485D01* +G01X1094533Y8006902D01* +G01X1087505Y8006927D01* +G01X1080477Y8006952D01* +G01X1079500Y8005974D01* +G01X1079500Y7970465D01* +G01X1079500Y7970465D01* +G01X1070699Y7970465D01* +G01X1070699Y8012002D01* +G01X1072350Y8013183D01* +G01X1074000Y8014364D01* +G01X1099666Y8013795D01* +G01X1103514Y8011813D01* +G01X1107362Y8009830D01* +G01X1112867Y8004317D01* +G01X1114150Y8002552D01* +G01X1115433Y8000787D01* +G01X1115433Y7997597D01* +G01X1116533Y7994965D01* +G01X1117633Y7992333D01* +G01X1117633Y7982582D01* +G01X1116426Y7978817D01* +G01X1115221Y7975052D01* +G01X1114558Y7973586D01* +G01X1113895Y7972119D01* +G01X1112807Y7970136D01* +G01X1111719Y7968153D01* +G01X1106428Y7963792D01* +G01X1099666Y7961214D01* +G37* +G36* +G01X1473000Y8068918D02* +G01X1453827Y8068918D01* +G01X1450546Y8070281D01* +G01X1447266Y8071645D01* +G01X1444333Y8073023D01* +G01X1442447Y8074065D01* +G01X1440562Y8075106D01* +G01X1430766Y8084081D01* +G01X1430766Y8085825D01* +G01X1429300Y8087081D01* +G01X1427833Y8088337D01* +G01X1427833Y8090803D01* +G01X1426734Y8092016D01* +G01X1425636Y8093229D01* +G01X1424295Y8099718D01* +G01X1423346Y8103934D01* +G01X1422397Y8108151D01* +G01X1424295Y8116584D01* +G01X1424961Y8119806D01* +G01X1425628Y8123028D01* +G01X1426354Y8123902D01* +G01X1427079Y8124777D01* +G01X1429106Y8128474D01* +G01X1431133Y8132172D01* +G01X1432966Y8134288D01* +G01X1434800Y8136403D01* +G01X1437733Y8138746D01* +G01X1440666Y8141088D01* +G01X1443966Y8142949D01* +G01X1447266Y8144810D01* +G01X1449283Y8145618D01* +G01X1451299Y8146427D01* +G01X1451299Y8206199D01* +G01X1441203Y8206599D01* +G01X1431107Y8206998D01* +G01X1428519Y8208525D01* +G01X1425932Y8210052D01* +G01X1422333Y8214850D01* +G01X1422140Y8227317D01* +G01X1421946Y8239783D01* +G01X1421607Y8241308D01* +G01X1421268Y8242832D01* +G01X1419383Y8243691D01* +G01X1417497Y8244550D01* +G01X1414245Y8244550D01* +G01X1411689Y8245909D01* +G01X1409133Y8247268D01* +G01X1406457Y8247762D01* +G01X1403780Y8248255D01* +G01X1402114Y8250263D01* +G01X1397180Y8251189D01* +G01X1396284Y8252269D01* +G01X1395557Y8253145D01* +G01X1425673Y8253145D01* +G01X1426063Y8252514D01* +G01X1426453Y8251883D01* +G01X1430473Y8251883D01* +G01X1431353Y8251003D01* +G01X1432233Y8250123D01* +G01X1432256Y8220717D01* +G01X1432882Y8219729D01* +G01X1433508Y8218740D01* +G01X1435254Y8218866D01* +G01X1437000Y8218991D01* +G01X1460100Y8219689D01* +G01X1460100Y8216770D01* +G01X1460833Y8216317D01* +G01X1461566Y8215863D01* +G01X1461566Y8139231D01* +G01X1460605Y8137917D01* +G01X1459644Y8136601D01* +G01X1456143Y8136207D01* +G01X1452642Y8135813D01* +G01X1452276Y8134860D01* +G01X1451910Y8133907D01* +G01X1449645Y8133409D01* +G01X1447380Y8132912D01* +G01X1442859Y8128392D01* +G01X1438339Y8123872D01* +G01X1437804Y8121740D01* +G01X1437269Y8119608D01* +G01X1436035Y8118705D01* +G01X1434800Y8117802D01* +G01X1434800Y8098772D01* +G01X1435962Y8097412D01* +G01X1437125Y8096051D01* +G01X1438989Y8091337D01* +G01X1442155Y8088194D01* +G01X1445322Y8085051D01* +G01X1447945Y8083434D01* +G01X1450568Y8081817D01* +G01X1450568Y8081817D01* +G01X1456029Y8080792D01* +G01X1458004Y8078818D01* +G01X1468061Y8078818D01* +G01X1470085Y8080841D01* +G01X1473071Y8081346D01* +G01X1476057Y8081850D01* +G01X1477726Y8083084D01* +G01X1479394Y8084318D01* +G01X1486866Y8091791D01* +G01X1489334Y8095127D01* +G01X1490312Y8100917D01* +G01X1489531Y8101698D01* +G01X1488845Y8101274D01* +G01X1488159Y8100850D01* +G01X1487241Y8095111D01* +G01X1486137Y8094687D01* +G01X1485033Y8094264D01* +G01X1485033Y8092323D01* +G01X1481917Y8089341D01* +G01X1478800Y8086359D01* +G01X1477517Y8085911D01* +G01X1476233Y8085464D01* +G01X1476233Y8083969D01* +G01X1473237Y8083489D01* +G01X1470241Y8083010D01* +G01X1469476Y8081018D01* +G01X1457795Y8081018D01* +G01X1455798Y8083014D01* +G01X1452787Y8083496D01* +G01X1449777Y8083978D01* +G01X1449385Y8084998D01* +G01X1448994Y8086018D01* +G01X1447213Y8086465D01* +G01X1445433Y8086913D01* +G01X1445433Y8088913D01* +G01X1442500Y8089680D01* +G01X1442500Y8092018D01* +G01X1440958Y8092018D01* +G01X1439813Y8094767D01* +G01X1438668Y8097518D01* +G01X1437834Y8098041D01* +G01X1437000Y8098564D01* +G01X1437000Y8111451D01* +G01X1446896Y8111451D01* +G01X1446927Y8104118D01* +G01X1451216Y8097289D01* +G01X1451216Y8097289D01* +G01X1453952Y8095204D01* +G01X1456688Y8093118D01* +G01X1470059Y8093118D01* +G01X1472249Y8094931D01* +G01X1474439Y8096745D01* +G01X1476052Y8098694D01* +G01X1477666Y8100642D01* +G01X1478143Y8104697D01* +G01X1478620Y8108752D01* +G01X1478110Y8112149D01* +G01X1477866Y8113773D01* +G01X1490166Y8113773D01* +G01X1490166Y8102284D01* +G01X1491476Y8102284D01* +G01X1491921Y8103444D01* +G01X1492366Y8104604D01* +G01X1492315Y8108394D01* +G01X1492263Y8112184D01* +G01X1491221Y8114827D01* +G01X1491221Y8114827D01* +G01X1490166Y8113773D01* +G01X1477866Y8113773D01* +G01X1477600Y8115546D01* +G01X1475420Y8118030D01* +G01X1473239Y8120514D01* +G01X1470022Y8122399D01* +G01X1466805Y8124284D01* +G01X1462902Y8124204D01* +G01X1458999Y8124125D01* +G01X1456149Y8122555D01* +G01X1453299Y8120984D01* +G01X1451750Y8119439D01* +G01X1450200Y8117894D01* +G01X1448548Y8114673D01* +G01X1446896Y8111451D01* +G01X1437000Y8111451D01* +G01X1437000Y8117530D01* +G01X1438283Y8118948D01* +G01X1439566Y8120367D01* +G01X1439566Y8122003D01* +G01X1449181Y8131617D01* +G01X1450817Y8131617D01* +G01X1452235Y8132901D01* +G01X1453654Y8134184D01* +G01X1472620Y8134184D01* +G01X1473667Y8132515D01* +G01X1476416Y8131370D01* +G01X1479166Y8130225D01* +G01X1479166Y8128684D01* +G01X1480831Y8128684D01* +G01X1482382Y8126968D01* +G01X1483933Y8125252D01* +G01X1485526Y8123042D01* +G01X1487119Y8120831D01* +G01X1488756Y8114751D01* +G01X1490354Y8114751D01* +G01X1489869Y8117867D01* +G01X1489384Y8120984D01* +G01X1487233Y8122613D01* +G01X1487233Y8124083D01* +G01X1484971Y8126933D01* +G01X1482709Y8129784D01* +G01X1479900Y8130837D01* +G01X1479900Y8132237D01* +G01X1477150Y8133133D01* +G01X1474399Y8134030D01* +G01X1473942Y8134735D01* +G01X1473484Y8135439D01* +G01X1469909Y8136093D01* +G01X1466333Y8136746D01* +G01X1463766Y8139846D01* +G01X1463766Y8215362D01* +G01X1468426Y8219714D01* +G01X1479846Y8219376D01* +G01X1491266Y8219038D01* +G01X1494933Y8218516D01* +G01X1495300Y8234160D01* +G01X1495666Y8249804D01* +G01X1498514Y8251883D01* +G01X1501813Y8251883D01* +G01X1502235Y8252565D01* +G01X1502657Y8253248D01* +G01X1502017Y8253644D01* +G01X1501377Y8254039D01* +G01X1497605Y8253592D01* +G01X1493833Y8253145D01* +G01X1493833Y8222655D01* +G01X1492680Y8221502D01* +G01X1491529Y8220350D01* +G01X1437693Y8220350D01* +G01X1436063Y8221491D01* +G01X1434433Y8222633D01* +G01X1434433Y8252530D01* +G01X1433883Y8252846D01* +G01X1433333Y8253163D01* +G01X1429995Y8253646D01* +G01X1426657Y8254129D01* +G01X1425673Y8253145D01* +G01X1395557Y8253145D01* +G01X1395387Y8253350D01* +G01X1392830Y8253350D01* +G01X1390966Y8254816D01* +G01X1389102Y8256283D01* +G01X1386394Y8256283D01* +G01X1377597Y8247513D01* +G01X1368800Y8238742D01* +G01X1367973Y8238713D01* +G01X1367146Y8238683D01* +G01X1366233Y8237583D01* +G01X1365320Y8236483D01* +G01X1358346Y8236483D01* +G01X1357433Y8237583D01* +G01X1356520Y8238683D01* +G01X1355693Y8238699D01* +G01X1354866Y8238715D01* +G01X1351200Y8242044D01* +G01X1347533Y8245373D01* +G01X1327904Y8264864D01* +G01X1308276Y8284354D01* +G01X1307835Y8286112D01* +G01X1307394Y8287869D01* +G01X1307607Y8290817D01* +G01X1317713Y8290817D01* +G01X1319056Y8288973D01* +G01X1320400Y8287129D01* +G01X1320813Y8287106D01* +G01X1321226Y8287082D01* +G01X1340527Y8267958D01* +G01X1359829Y8248832D01* +G01X1361457Y8248708D01* +G01X1361457Y8248708D01* +G01X1363085Y8248583D01* +G01X1373892Y8259102D01* +G01X1384698Y8269621D01* +G01X1390066Y8268621D01* +G01X1390621Y8267642D01* +G01X1391175Y8266664D01* +G01X1393309Y8266196D01* +G01X1395443Y8265726D01* +G01X1395813Y8264764D01* +G01X1396183Y8263802D01* +G01X1398737Y8263322D01* +G01X1401291Y8262843D01* +G01X1401666Y8261867D01* +G01X1402041Y8260890D01* +G01X1404957Y8260424D01* +G01X1407873Y8259958D01* +G01X1408261Y8258946D01* +G01X1408650Y8257934D01* +G01X1415670Y8256881D01* +G01X1416435Y8255886D01* +G01X1417200Y8254892D01* +G01X1420500Y8254671D01* +G01X1423799Y8254449D01* +G01X1424166Y8255173D01* +G01X1424533Y8255896D01* +G01X1416725Y8257020D01* +G01X1415715Y8258029D01* +G01X1414706Y8259038D01* +G01X1411434Y8259529D01* +G01X1408163Y8260020D01* +G01X1407782Y8261011D01* +G01X1407402Y8262003D01* +G01X1404475Y8262498D01* +G01X1401548Y8262993D01* +G01X1401183Y8263945D01* +G01X1400817Y8264898D01* +G01X1398262Y8265377D01* +G01X1395708Y8265856D01* +G01X1395330Y8266842D01* +G01X1394951Y8267827D01* +G01X1392921Y8268337D01* +G01X1390891Y8268847D01* +G01X1389328Y8270983D01* +G01X1386764Y8271396D01* +G01X1384200Y8271809D01* +G01X1373651Y8261479D01* +G01X1363102Y8251149D01* +G01X1360348Y8251149D01* +G01X1333687Y8277183D01* +G01X1329108Y8281766D01* +G01X1324530Y8286349D01* +G01X1323137Y8286349D01* +G01X1322695Y8287999D01* +G01X1322253Y8289649D01* +G01X1322243Y8291181D01* +G01X1322233Y8292713D01* +G01X1332500Y8302668D01* +G01X1342766Y8312624D01* +G01X1342766Y8316189D01* +G01X1339833Y8318843D01* +G01X1339833Y8320862D01* +G01X1338753Y8321276D01* +G01X1337673Y8321691D01* +G01X1337194Y8324245D01* +G01X1336714Y8326799D01* +G01X1335727Y8327178D01* +G01X1334739Y8327557D01* +G01X1334269Y8330063D01* +G01X1333799Y8332570D01* +G01X1331813Y8333681D01* +G01X1331218Y8336545D01* +G01X1330623Y8339408D01* +G01X1328635Y8340071D01* +G01X1329146Y8337227D01* +G01X1329659Y8334382D01* +G01X1330710Y8333570D01* +G01X1331761Y8332757D01* +G01X1332235Y8330390D01* +G01X1332708Y8328023D01* +G01X1334660Y8327274D01* +G01X1335139Y8324720D01* +G01X1335618Y8322165D01* +G01X1336581Y8321796D01* +G01X1337544Y8321427D01* +G01X1338002Y8319338D01* +G01X1338460Y8317250D01* +G01X1340566Y8315503D01* +G01X1340566Y8313365D01* +G01X1329140Y8302091D01* +G01X1317713Y8290817D01* +G01X1307607Y8290817D01* +G01X1307709Y8292226D01* +G01X1308024Y8296583D01* +G01X1316778Y8305419D01* +G01X1325533Y8314254D01* +G01X1326176Y8315660D01* +G01X1326820Y8317066D01* +G01X1324527Y8321129D01* +G01X1322233Y8325193D01* +G01X1322233Y8327236D01* +G01X1320127Y8328984D01* +G01X1319616Y8331316D01* +G01X1319104Y8333649D01* +G01X1317735Y8336205D01* +G01X1316366Y8338760D01* +G01X1316366Y8341995D01* +G01X1315645Y8342442D01* +G01X1314923Y8342888D01* +G01X1313919Y8346335D01* +G01X1313788Y8346786D01* +G01X1325860Y8346786D01* +G01X1327043Y8341090D01* +G01X1327043Y8341090D01* +G01X1328017Y8340765D01* +G01X1328991Y8340440D01* +G01X1327935Y8346849D01* +G01X1327333Y8347948D01* +G01X1326731Y8349049D01* +G01X1326296Y8347917D01* +G01X1325860Y8346786D01* +G01X1313788Y8346786D01* +G01X1312916Y8349782D01* +G01X1283444Y8350515D01* +G01X1280992Y8352894D01* +G01X1278540Y8355272D01* +G01X1277653Y8358588D01* +G01X1276766Y8361903D01* +G01X1276774Y8391409D01* +G01X1276782Y8419178D01* +G01X1287767Y8419178D01* +G01X1287767Y8364999D01* +G01X1288224Y8362707D01* +G01X1288683Y8360415D01* +G01X1319007Y8360415D01* +G01X1322863Y8358595D01* +G01X1323338Y8354508D01* +G01X1323812Y8350420D01* +G01X1324398Y8349472D01* +G01X1324398Y8349472D01* +G01X1324983Y8348526D01* +G01X1325458Y8349295D01* +G01X1325933Y8350063D01* +G01X1325270Y8354294D01* +G01X1324607Y8358524D01* +G01X1323786Y8358797D01* +G01X1322966Y8359071D01* +G01X1322966Y8361725D01* +G01X1321806Y8362170D01* +G01X1320646Y8362615D01* +G01X1291484Y8362615D01* +G01X1290726Y8364033D01* +G01X1289966Y8365452D01* +G01X1289966Y8375633D01* +G01X1300204Y8375633D01* +G01X1301879Y8373615D01* +G01X1311873Y8373607D01* +G01X1321866Y8373599D01* +G01X1325299Y8372558D01* +G01X1328733Y8371516D01* +G01X1330219Y8370029D01* +G01X1331705Y8368543D01* +G01X1333216Y8365582D01* +G01X1334727Y8362620D01* +G01X1335168Y8359135D01* +G01X1335609Y8355648D01* +G01X1336568Y8354106D01* +G01X1337526Y8352563D01* +G01X1338048Y8349706D01* +G01X1338570Y8346849D01* +G01X1339866Y8344282D01* +G01X1341162Y8341715D01* +G01X1344323Y8334382D01* +G01X1345001Y8333282D01* +G01X1345679Y8332182D01* +G01X1347051Y8329616D01* +G01X1348425Y8327049D01* +G01X1349458Y8325216D01* +G01X1350492Y8323382D01* +G01X1351708Y8321549D01* +G01X1352925Y8319715D01* +G01X1353932Y8314206D01* +G01X1353438Y8310918D01* +G01X1352945Y8307630D01* +G01X1344453Y8299177D01* +G01X1335961Y8290725D01* +G01X1337347Y8289159D01* +G01X1338733Y8287594D01* +G01X1349145Y8277286D01* +G01X1359556Y8266977D01* +G01X1362293Y8265964D01* +G01X1376867Y8280127D01* +G01X1379658Y8281772D01* +G01X1382450Y8283416D01* +G01X1388599Y8283332D01* +G01X1392267Y8281248D01* +G01X1395933Y8279164D01* +G01X1411333Y8271530D01* +G01X1413533Y8270585D01* +G01X1415733Y8269639D01* +G01X1419767Y8268159D01* +G01X1423799Y8266678D01* +G01X1429447Y8265722D01* +G01X1434066Y8263697D01* +G01X1436633Y8263268D01* +G01X1439199Y8262837D01* +G01X1441252Y8261031D01* +G01X1443304Y8259226D01* +G01X1444552Y8256471D01* +G01X1445800Y8253716D01* +G01X1445800Y8253716D01* +G01X1446166Y8242717D01* +G01X1446533Y8231717D01* +G01X1482466Y8231717D01* +G01X1482876Y8243816D01* +G01X1483256Y8255019D01* +G01X1503178Y8255019D01* +G01X1503929Y8254555D01* +G01X1504681Y8254090D01* +G01X1508112Y8254561D01* +G01X1511542Y8255030D01* +G01X1513422Y8256910D01* +G01X1516278Y8257423D01* +G01X1519133Y8257936D01* +G01X1520233Y8258874D01* +G01X1521333Y8259813D01* +G01X1524449Y8260643D01* +G01X1527566Y8261472D01* +G01X1527566Y8262651D01* +G01X1530500Y8263530D01* +G01X1533433Y8264409D01* +G01X1533433Y8265702D01* +G01X1535941Y8266530D01* +G01X1538449Y8267358D01* +G01X1539377Y8268476D01* +G01X1540305Y8269595D01* +G01X1545032Y8268708D01* +G01X1554840Y8258929D01* +G01X1564647Y8249150D01* +G01X1564647Y8249150D01* +G01X1567828Y8248140D01* +G01X1580147Y8260197D01* +G01X1592466Y8272253D01* +G01X1601083Y8280606D01* +G01X1609699Y8288959D01* +G01X1609699Y8291978D01* +G01X1599983Y8301428D01* +G01X1590267Y8310877D01* +G01X1589407Y8312363D01* +G01X1588547Y8313849D01* +G01X1588955Y8316049D01* +G01X1589363Y8318249D01* +G01X1590677Y8319715D01* +G01X1591991Y8321182D01* +G01X1592478Y8323146D01* +G01X1592965Y8325110D01* +G01X1593906Y8325471D01* +G01X1594848Y8325832D01* +G01X1595327Y8328386D01* +G01X1595806Y8330941D01* +G01X1596794Y8331319D01* +G01X1597781Y8331698D01* +G01X1598294Y8334429D01* +G01X1598805Y8337159D01* +G01X1600696Y8339050D01* +G01X1601690Y8345262D01* +G01X1602673Y8346056D01* +G01X1603656Y8346849D01* +G01X1604492Y8353482D01* +G01X1603877Y8354479D01* +G01X1603260Y8355476D01* +G01X1602867Y8354096D01* +G01X1602473Y8352715D01* +G01X1601965Y8349458D01* +G01X1601457Y8346201D01* +G01X1599567Y8344311D01* +G01X1598585Y8338500D01* +G01X1597542Y8337634D01* +G01X1596500Y8336769D01* +G01X1596500Y8333480D01* +G01X1595033Y8331615D01* +G01X1593566Y8329751D01* +G01X1593566Y8327640D01* +G01X1592100Y8325949D01* +G01X1590633Y8324258D01* +G01X1590633Y8322268D01* +G01X1589166Y8321012D01* +G01X1587700Y8319757D01* +G01X1587700Y8318080D01* +G01X1586166Y8316131D01* +G01X1584633Y8314182D01* +G01X1596067Y8302718D01* +G01X1607500Y8291254D01* +G01X1607500Y8289857D01* +G01X1587966Y8270503D01* +G01X1568431Y8251149D01* +G01X1565509Y8251149D01* +G01X1555897Y8260500D01* +G01X1546285Y8269849D01* +G01X1544653Y8271910D01* +G01X1541795Y8271447D01* +G01X1538938Y8270983D01* +G01X1538199Y8269973D01* +G01X1537461Y8268963D01* +G01X1535630Y8268389D01* +G01X1533800Y8267814D01* +G01X1532051Y8266449D01* +G01X1530302Y8265083D01* +G01X1528164Y8265083D01* +G01X1524435Y8262149D01* +G01X1520920Y8262149D01* +G01X1520512Y8261084D01* +G01X1520103Y8260020D01* +G01X1516810Y8259526D01* +G01X1513516Y8259032D01* +G01X1512790Y8257139D01* +G01X1508995Y8256629D01* +G01X1505199Y8256119D01* +G01X1504189Y8255569D01* +G01X1503178Y8255019D01* +G01X1483256Y8255019D01* +G01X1483286Y8255916D01* +G01X1484143Y8257487D01* +G01X1485000Y8259058D01* +G01X1487273Y8260971D01* +G01X1489546Y8262883D01* +G01X1493467Y8263672D01* +G01X1498233Y8265121D01* +G01X1503000Y8266571D01* +G01X1503719Y8266560D01* +G01X1504438Y8266549D01* +G01X1512533Y8269663D01* +G01X1515547Y8271040D01* +G01X1518560Y8272416D01* +G01X1520787Y8272416D01* +G01X1521640Y8273444D01* +G01X1522493Y8274472D01* +G01X1524422Y8274957D01* +G01X1526351Y8275440D01* +G01X1529964Y8278283D01* +G01X1531862Y8278283D01* +G01X1532831Y8279238D01* +G01X1533800Y8280192D01* +G01X1537148Y8281804D01* +G01X1540496Y8283416D01* +G01X1546093Y8283416D01* +G01X1551399Y8280219D01* +G01X1558195Y8273428D01* +G01X1564991Y8266637D01* +G01X1566399Y8266410D01* +G01X1567807Y8266183D01* +G01X1579954Y8278175D01* +G01X1592100Y8290166D01* +G01X1592100Y8291212D01* +G01X1578370Y8304677D01* +G01X1574321Y8310519D01* +G01X1574634Y8314750D01* +G01X1574946Y8318983D01* +G01X1577561Y8322690D01* +G01X1580178Y8326399D01* +G01X1580667Y8327941D01* +G01X1581156Y8329483D01* +G01X1582228Y8330372D01* +G01X1583299Y8331262D01* +G01X1583299Y8333818D01* +G01X1586233Y8337547D01* +G01X1586237Y8338898D01* +G01X1586243Y8340249D01* +G01X1587700Y8342449D01* +G01X1589157Y8344649D01* +G01X1589166Y8346115D01* +G01X1589176Y8347582D01* +G01X1590353Y8349782D01* +G01X1591530Y8351982D01* +G01X1592499Y8356015D01* +G01X1592872Y8357564D01* +G01X1604378Y8357564D01* +G01X1604901Y8356240D01* +G01X1605424Y8354916D01* +G01X1606651Y8357482D01* +G01X1607879Y8360048D01* +G01X1623823Y8360246D01* +G01X1639766Y8360444D01* +G01X1639755Y8362813D01* +G01X1639744Y8365182D01* +G01X1639175Y8366078D01* +G01X1638605Y8366974D01* +G01X1637789Y8364809D01* +G01X1636971Y8362645D01* +G01X1621346Y8362447D01* +G01X1605720Y8362249D01* +G01X1605049Y8359907D01* +G01X1604378Y8357564D01* +G01X1604378Y8357564D01* +G01X1592872Y8357564D01* +G01X1593469Y8360048D01* +G01X1594434Y8363392D01* +G01X1595400Y8366735D01* +G01X1599422Y8371514D01* +G01X1601811Y8372324D01* +G01X1604200Y8373134D01* +G01X1615566Y8373558D01* +G01X1626933Y8373982D01* +G01X1627130Y8391322D01* +G01X1627326Y8408663D01* +G01X1603253Y8409182D01* +G01X1601835Y8410465D01* +G01X1600418Y8411748D01* +G01X1599197Y8411748D01* +G01X1597115Y8414080D01* +G01X1595033Y8416412D01* +G01X1595033Y8419154D01* +G01X1593995Y8421163D01* +G01X1592956Y8423171D01* +G01X1592631Y8424776D01* +G01X1604343Y8424776D01* +G01X1605020Y8422852D01* +G01X1605696Y8420929D01* +G01X1606965Y8420685D01* +G01X1606965Y8420685D01* +G01X1608233Y8420441D01* +G01X1608233Y8420589D01* +G01X1636039Y8420589D01* +G01X1638571Y8416725D01* +G01X1639529Y8418035D01* +G01X1640488Y8419345D01* +G01X1638073Y8422015D01* +G01X1636919Y8422015D01* +G01X1636479Y8421302D01* +G01X1636479Y8421302D01* +G01X1636039Y8420589D01* +G01X1608233Y8420589D01* +G01X1608233Y8422523D01* +G01X1605926Y8427148D01* +G01X1605254Y8427148D01* +G01X1604799Y8425962D01* +G01X1604343Y8424776D01* +G01X1592631Y8424776D01* +G01X1592219Y8426810D01* +G01X1591482Y8430448D01* +G01X1590208Y8434115D01* +G01X1589265Y8436827D01* +G01X1601563Y8436827D01* +G01X1602056Y8432904D01* +G01X1602549Y8428981D01* +G01X1602549Y8428981D01* +G01X1603167Y8428309D01* +G01X1603785Y8427636D01* +G01X1604176Y8428675D01* +G01X1604567Y8429715D01* +G01X1603445Y8436199D01* +G01X1601563Y8436827D01* +G01X1589265Y8436827D01* +G01X1588934Y8437781D01* +G01X1587584Y8440447D01* +G01X1586233Y8443114D01* +G01X1586233Y8445376D01* +G01X1584254Y8447355D01* +G01X1582452Y8452815D01* +G01X1581243Y8452815D01* +G01X1580409Y8454831D01* +G01X1579575Y8456847D01* +G01X1577788Y8459781D01* +G01X1576001Y8462714D01* +G01X1575250Y8464412D01* +G01X1574500Y8466109D01* +G01X1574500Y8473049D01* +G01X1577066Y8476521D01* +G01X1584583Y8484023D01* +G01X1592100Y8491525D01* +G01X1592100Y8493061D01* +G01X1581354Y8503554D01* +G01X1570608Y8514047D01* +G01X1569075Y8515510D01* +G01X1567541Y8516972D01* +G01X1566437Y8516720D01* +G01X1565333Y8516467D01* +G01X1558720Y8509962D01* +G01X1552108Y8503455D01* +G01X1549594Y8501601D01* +G01X1547081Y8499747D01* +G01X1538764Y8499747D01* +G01X1537015Y8501060D01* +G01X1535266Y8502372D01* +G01X1531600Y8504189D01* +G01X1526833Y8506719D01* +G01X1522066Y8509249D01* +G01X1520413Y8509281D01* +G01X1518586Y8511480D01* +G01X1516178Y8511480D01* +G01X1511066Y8514185D01* +G01X1508500Y8514669D01* +G01X1505933Y8515153D01* +G01X1503733Y8516179D01* +G01X1501533Y8517206D01* +G01X1494200Y8518665D01* +G01X1491139Y8519817D01* +G01X1488079Y8520968D01* +G01X1486047Y8523000D01* +G01X1484013Y8525033D01* +G01X1483933Y8525519D01* +G01X1509212Y8525519D01* +G01X1510505Y8525139D01* +G01X1511800Y8524759D01* +G01X1511800Y8524759D01* +G01X1514550Y8524271D01* +G01X1517299Y8523784D01* +G01X1517299Y8524145D01* +G01X1517845Y8524145D01* +G01X1518176Y8523152D01* +G01X1518508Y8522157D01* +G01X1524234Y8520967D01* +G01X1525345Y8518981D01* +G01X1527852Y8518510D01* +G01X1530358Y8518041D01* +G01X1530773Y8516960D01* +G01X1531187Y8515880D01* +G01X1533969Y8515880D01* +G01X1535718Y8514514D01* +G01X1537466Y8513149D01* +G01X1539116Y8512632D01* +G01X1540766Y8512115D01* +G01X1540766Y8510747D01* +G01X1544460Y8510747D01* +G01X1554238Y8520565D01* +G01X1564016Y8530383D01* +G01X1566173Y8530857D01* +G01X1568331Y8531330D01* +G01X1574899Y8525017D01* +G01X1581466Y8518703D01* +G01X1594117Y8506185D01* +G01X1606766Y8493666D01* +G01X1606766Y8492318D01* +G01X1605935Y8490765D01* +G01X1605105Y8489212D01* +G01X1595068Y8479249D01* +G01X1585030Y8469284D01* +G01X1588472Y8462777D01* +G01X1589127Y8462372D01* +G01X1589783Y8461966D01* +G01X1590303Y8459898D01* +G01X1590822Y8457829D01* +G01X1591807Y8457451D01* +G01X1592793Y8457073D01* +G01X1593272Y8454518D01* +G01X1593751Y8451964D01* +G01X1594739Y8451585D01* +G01X1595726Y8451206D01* +G01X1596195Y8448527D01* +G01X1596663Y8445848D01* +G01X1597705Y8445016D01* +G01X1598747Y8444185D01* +G01X1599284Y8441041D01* +G01X1599821Y8437897D01* +G01X1599821Y8437897D01* +G01X1600806Y8437568D01* +G01X1601791Y8437239D01* +G01X1600766Y8443648D01* +G01X1599793Y8444417D01* +G01X1598821Y8445187D01* +G01X1597781Y8450732D01* +G01X1596818Y8451101D01* +G01X1595856Y8451470D01* +G01X1595349Y8453792D01* +G01X1594842Y8456115D01* +G01X1592100Y8459612D01* +G01X1592100Y8461541D01* +G01X1589703Y8462882D01* +G01X1588990Y8470313D01* +G01X1609699Y8490873D01* +G01X1609699Y8493432D01* +G01X1587672Y8515175D01* +G01X1565644Y8536918D01* +G01X1565855Y8580326D01* +G01X1566066Y8623733D01* +G01X1566900Y8624257D01* +G01X1567735Y8624779D01* +G01X1570025Y8630280D01* +G01X1571566Y8630280D01* +G01X1571566Y8632617D01* +G01X1573033Y8633001D01* +G01X1574500Y8633384D01* +G01X1574500Y8634754D01* +G01X1580000Y8637044D01* +G01X1581045Y8638713D01* +G01X1615765Y8638929D01* +G01X1650484Y8639145D01* +G01X1652361Y8637670D01* +G01X1654238Y8636193D01* +G01X1654728Y8632497D01* +G01X1655218Y8628801D01* +G01X1656980Y8626057D01* +G01X1658742Y8623313D01* +G01X1661033Y8620746D01* +G01X1661033Y8619243D01* +G01X1664699Y8617849D01* +G01X1664699Y8616524D01* +G01X1667083Y8615553D01* +G01X1669466Y8614581D01* +G01X1670250Y8613548D01* +G01X1671034Y8612514D01* +G01X1678317Y8612204D01* +G01X1685600Y8611894D01* +G01X1689450Y8612340D01* +G01X1693300Y8612785D01* +G01X1694251Y8613735D01* +G01X1695202Y8614686D01* +G01X1696866Y8615214D01* +G01X1698531Y8615743D01* +G01X1706473Y8623685D01* +G01X1706919Y8625462D01* +G01X1707366Y8627240D01* +G01X1709227Y8627955D01* +G01X1709724Y8631700D01* +G01X1710221Y8635445D01* +G01X1709524Y8636690D01* +G01X1708827Y8637936D01* +G01X1708347Y8635025D01* +G01X1707867Y8632113D01* +G01X1707117Y8628079D01* +G01X1705865Y8628079D01* +G01X1705348Y8626451D01* +G01X1704831Y8624822D01* +G01X1700866Y8620951D01* +G01X1696901Y8617079D01* +G01X1695249Y8617079D01* +G01X1692682Y8614756D01* +G01X1687491Y8614105D01* +G01X1682300Y8613453D01* +G01X1677185Y8614095D01* +G01X1672070Y8614737D01* +G01X1670900Y8615908D01* +G01X1669728Y8617079D01* +G01X1667665Y8617079D01* +G01X1659566Y8625178D01* +G01X1659566Y8626672D01* +G01X1657955Y8628852D01* +G01X1656343Y8631031D01* +G01X1656323Y8645547D01* +G01X1666900Y8645547D01* +G01X1666900Y8634753D01* +G01X1669035Y8631589D01* +G01X1671171Y8628424D01* +G01X1674235Y8626419D01* +G01X1677298Y8624413D01* +G01X1677298Y8624413D01* +G01X1687359Y8624413D01* +G01X1690576Y8626584D01* +G01X1693794Y8628755D01* +G01X1695746Y8631573D01* +G01X1697700Y8634392D01* +G01X1697700Y8645606D01* +G01X1693384Y8651913D01* +G01X1688533Y8655098D01* +G01X1684500Y8655455D01* +G01X1680466Y8655813D01* +G01X1678266Y8655321D01* +G01X1676066Y8654829D01* +G01X1673452Y8653195D01* +G01X1670836Y8651560D01* +G01X1668868Y8648554D01* +G01X1666900Y8645547D01* +G01X1656323Y8645547D01* +G01X1656319Y8648246D01* +G01X1657538Y8650446D01* +G01X1658757Y8652646D01* +G01X1659516Y8654312D01* +G01X1660275Y8655977D01* +G01X1663655Y8659261D01* +G01X1667034Y8662546D01* +G01X1669146Y8662546D01* +G01X1669551Y8663601D01* +G01X1669955Y8664656D01* +G01X1672094Y8665068D01* +G01X1674233Y8665479D01* +G01X1676439Y8665905D01* +G01X1678574Y8666318D01* +G01X1686679Y8666318D01* +G01X1687972Y8665962D01* +G01X1689266Y8665607D01* +G01X1692055Y8665136D01* +G01X1694843Y8664665D01* +G01X1695656Y8662546D01* +G01X1697630Y8662546D01* +G01X1701331Y8658844D01* +G01X1705033Y8655143D01* +G01X1705033Y8652967D01* +G01X1706113Y8652552D01* +G01X1707193Y8652137D01* +G01X1707580Y8649642D01* +G01X1707966Y8647146D01* +G01X1708397Y8644418D01* +G01X1708397Y8644418D01* +G01X1708827Y8641689D01* +G01X1709546Y8642974D01* +G01X1710266Y8644260D01* +G01X1709765Y8648270D01* +G01X1709264Y8652279D01* +G01X1707986Y8652279D01* +G01X1706952Y8654663D01* +G01X1705917Y8657046D01* +G01X1702725Y8660434D01* +G01X1699533Y8663821D01* +G01X1697702Y8664390D01* +G01X1695872Y8664959D01* +G01X1695136Y8665903D01* +G01X1694400Y8666846D01* +G01X1691003Y8667333D01* +G01X1687606Y8667820D01* +G01X1687142Y8667069D01* +G01X1686679Y8666318D01* +G01X1678574Y8666318D01* +G01X1678646Y8666332D01* +G01X1678229Y8667006D01* +G01X1677813Y8667679D01* +G01X1673866Y8667479D01* +G01X1670200Y8666842D01* +G01X1669464Y8665901D01* +G01X1668727Y8664959D01* +G01X1666957Y8664397D01* +G01X1665186Y8663835D01* +G01X1658160Y8656810D01* +G01X1657697Y8654964D01* +G01X1657234Y8653118D01* +G01X1655283Y8652370D01* +G01X1654773Y8648285D01* +G01X1654263Y8644199D01* +G01X1652091Y8642373D01* +G01X1649920Y8640546D01* +G01X1581204Y8640546D01* +G01X1580105Y8639446D01* +G01X1579004Y8638346D01* +G01X1576920Y8638346D01* +G01X1573783Y8636239D01* +G01X1570646Y8634133D01* +G01X1568540Y8630996D01* +G01X1566433Y8627859D01* +G01X1566433Y8625775D01* +G01X1565333Y8624674D01* +G01X1564233Y8623575D01* +G01X1564233Y8534498D01* +G01X1562583Y8532316D01* +G01X1560933Y8530135D01* +G01X1545462Y8514647D01* +G01X1541673Y8513696D01* +G01X1539203Y8514540D01* +G01X1536733Y8515383D01* +G01X1536179Y8516308D01* +G01X1535624Y8517233D01* +G01X1531356Y8518170D01* +G01X1530617Y8520095D01* +G01X1527845Y8520615D01* +G01X1525072Y8521135D01* +G01X1523533Y8523122D01* +G01X1517845Y8524145D01* +G01X1517299Y8524145D01* +G01X1517299Y8525327D01* +G01X1516749Y8525652D01* +G01X1516200Y8525978D01* +G01X1513159Y8526481D01* +G01X1510117Y8526984D01* +G01X1509664Y8526252D01* +G01X1509212Y8525519D01* +G01X1483933Y8525519D01* +G01X1483467Y8528340D01* +G01X1482920Y8531647D01* +G01X1482877Y8541645D01* +G01X1482833Y8551643D01* +G01X1481183Y8552084D01* +G01X1479533Y8552527D01* +G01X1463609Y8552537D01* +G01X1447684Y8552547D01* +G01X1446925Y8551128D01* +G01X1446166Y8549710D01* +G01X1446166Y8530000D01* +G01X1444726Y8526744D01* +G01X1443286Y8523489D01* +G01X1440666Y8521175D01* +G01X1436986Y8519610D01* +G01X1433305Y8518046D01* +G01X1429652Y8517390D01* +G01X1426000Y8516735D01* +G01X1422333Y8515465D01* +G01X1418666Y8514194D01* +G01X1415652Y8512837D01* +G01X1412639Y8511480D01* +G01X1410890Y8511480D01* +G01X1407811Y8509888D01* +G01X1404733Y8508297D01* +G01X1403633Y8507664D01* +G01X1402533Y8507030D01* +G01X1397033Y8504658D01* +G01X1397033Y8503558D01* +G01X1392999Y8501902D01* +G01X1389333Y8499769D01* +G01X1385259Y8499758D01* +G01X1381185Y8499747D01* +G01X1378929Y8501411D01* +G01X1376673Y8503076D01* +G01X1369474Y8510159D01* +G01X1362274Y8517242D01* +G01X1361137Y8516630D01* +G01X1360000Y8516017D01* +G01X1335882Y8492591D01* +G01X1344088Y8484193D01* +G01X1352295Y8475794D01* +G01X1353266Y8472554D01* +G01X1354237Y8469314D01* +G01X1352481Y8462714D01* +G01X1350374Y8459159D01* +G01X1348266Y8455603D01* +G01X1346651Y8452925D01* +G01X1345037Y8450248D01* +G01X1344596Y8449147D01* +G01X1344156Y8448048D01* +G01X1342726Y8445115D01* +G01X1341296Y8442181D01* +G01X1341300Y8440875D01* +G01X1338586Y8434848D01* +G01X1337315Y8431181D01* +G01X1336045Y8427514D01* +G01X1335421Y8424057D01* +G01X1334796Y8420600D01* +G01X1331400Y8413150D01* +G01X1324800Y8409184D01* +G01X1312700Y8408816D01* +G01X1300600Y8408448D01* +G01X1300402Y8392041D01* +G01X1300204Y8375633D01* +G01X1289966Y8375633D01* +G01X1289966Y8416978D01* +G01X1290726Y8418396D01* +G01X1291484Y8419815D01* +G01X1293475Y8419900D01* +G01X1295467Y8419985D01* +G01X1294849Y8420133D01* +G01X1300600Y8420133D01* +G01X1310950Y8419974D01* +G01X1310950Y8419974D01* +G01X1321300Y8419815D01* +G01X1324998Y8425315D01* +G01X1325470Y8429649D01* +G01X1325940Y8433983D01* +G01X1326942Y8434782D01* +G01X1327944Y8435581D01* +G01X1328424Y8439000D01* +G01X1328903Y8442418D01* +G01X1329864Y8442787D01* +G01X1330825Y8443156D01* +G01X1331305Y8446152D01* +G01X1331783Y8449147D01* +G01X1333177Y8449147D01* +G01X1333967Y8452081D01* +G01X1334756Y8455014D01* +G01X1335944Y8455014D01* +G01X1338399Y8460515D01* +G01X1339593Y8462714D01* +G01X1340788Y8464914D01* +G01X1341777Y8465500D01* +G01X1342766Y8466087D01* +G01X1342766Y8469997D01* +G01X1332500Y8480024D01* +G01X1322233Y8490051D01* +G01X1322233Y8493896D01* +G01X1339092Y8510755D01* +G01X1355950Y8527614D01* +G01X1357433Y8527614D01* +G01X1357433Y8529727D01* +G01X1358533Y8530375D01* +G01X1363289Y8531394D01* +G01X1383940Y8511114D01* +G01X1384999Y8510520D01* +G01X1386058Y8509927D01* +G01X1389897Y8512947D01* +G01X1391827Y8512947D01* +G01X1392413Y8513944D01* +G01X1392999Y8514940D01* +G01X1395750Y8515834D01* +G01X1398500Y8516727D01* +G01X1398500Y8517848D01* +G01X1401433Y8518727D01* +G01X1404367Y8519606D01* +G01X1404367Y8520885D01* +G01X1407351Y8521389D01* +G01X1410335Y8521893D01* +G01X1410723Y8522905D01* +G01X1411111Y8523915D01* +G01X1414768Y8524401D01* +G01X1418425Y8524886D01* +G01X1419168Y8526823D01* +G01X1423548Y8527318D01* +G01X1427928Y8527814D01* +G01X1429928Y8529814D01* +G01X1432113Y8529814D01* +G01X1434433Y8530704D01* +G01X1434433Y8561112D01* +G01X1436301Y8561962D01* +G01X1438169Y8562813D01* +G01X1464718Y8562802D01* +G01X1491266Y8562791D01* +G01X1492366Y8562097D01* +G01X1493467Y8561403D01* +G01X1493833Y8545792D01* +G01X1494200Y8530180D01* +G01X1498966Y8529721D01* +G01X1498966Y8529940D01* +G01X1499535Y8529940D01* +G01X1499862Y8528960D01* +G01X1500187Y8527980D01* +G01X1500187Y8527980D01* +G01X1504420Y8527385D01* +G01X1508654Y8526790D01* +G01X1509078Y8527214D01* +G01X1509502Y8527638D01* +G01X1508818Y8528275D01* +G01X1508133Y8528913D01* +G01X1503834Y8529427D01* +G01X1499535Y8529940D01* +G01X1498966Y8529940D01* +G01X1498966Y8531112D01* +G01X1497133Y8532313D01* +G01X1495300Y8533514D01* +G01X1495300Y8564280D01* +G01X1468853Y8564280D01* +G01X1463766Y8566405D01* +G01X1463766Y8608757D01* +G01X1465416Y8610304D01* +G01X1467066Y8611851D01* +G01X1470979Y8612368D01* +G01X1474892Y8612885D01* +G01X1475257Y8613838D01* +G01X1475622Y8614790D01* +G01X1477767Y8615261D01* +G01X1479912Y8615732D01* +G01X1481418Y8618546D01* +G01X1483566Y8618546D01* +G01X1483566Y8620694D01* +G01X1485033Y8621480D01* +G01X1486500Y8622265D01* +G01X1486500Y8624186D01* +G01X1487913Y8625464D01* +G01X1489326Y8626743D01* +G01X1489836Y8629795D01* +G01X1490346Y8632846D01* +G01X1491156Y8633359D01* +G01X1491967Y8633872D01* +G01X1492240Y8639283D01* +G01X1492514Y8644694D01* +G01X1491428Y8645779D01* +G01X1490343Y8646865D01* +G01X1489827Y8649917D01* +G01X1489311Y8652969D01* +G01X1487905Y8654757D01* +G01X1486500Y8656544D01* +G01X1486500Y8657297D01* +G01X1483141Y8660655D01* +G01X1479784Y8664012D01* +G01X1478631Y8664012D01* +G01X1476882Y8665385D01* +G01X1475133Y8666758D01* +G01X1472055Y8667277D01* +G01X1468976Y8667795D01* +G01X1467705Y8667083D01* +G01X1466433Y8666372D01* +G01X1470783Y8665476D01* +G01X1475133Y8664581D01* +G01X1475720Y8663563D01* +G01X1476306Y8662546D01* +G01X1477186Y8662523D01* +G01X1478067Y8662499D01* +G01X1479900Y8660870D01* +G01X1481733Y8659241D01* +G01X1487090Y8652646D01* +G01X1488756Y8646413D01* +G01X1490166Y8646413D01* +G01X1490166Y8633369D01* +G01X1488174Y8632605D01* +G01X1487708Y8629689D01* +G01X1487241Y8626773D01* +G01X1486137Y8626349D01* +G01X1485033Y8625925D01* +G01X1485033Y8624243D01* +G01X1481278Y8620661D01* +G01X1477522Y8617079D01* +G01X1475572Y8617079D01* +G01X1474958Y8615981D01* +G01X1474344Y8614883D01* +G01X1468696Y8614167D01* +G01X1463049Y8613451D01* +G01X1452651Y8614756D01* +G01X1450084Y8617079D01* +G01X1448442Y8617079D01* +G01X1446388Y8618897D01* +G01X1444333Y8620713D01* +G01X1443710Y8621390D01* +G01X1443086Y8622066D01* +G01X1440337Y8625109D01* +G01X1439870Y8626970D01* +G01X1439403Y8628832D01* +G01X1438201Y8629504D01* +G01X1437000Y8630176D01* +G01X1437000Y8643585D01* +G01X1446899Y8643585D01* +G01X1446899Y8636925D01* +G01X1450105Y8630646D01* +G01X1451619Y8629133D01* +G01X1453133Y8627619D01* +G01X1455786Y8626016D01* +G01X1458439Y8624413D01* +G01X1458439Y8624413D01* +G01X1468101Y8624413D01* +G01X1470883Y8626301D01* +G01X1473665Y8628189D01* +G01X1475866Y8630858D01* +G01X1478067Y8633528D01* +G01X1478067Y8646865D01* +G01X1475951Y8649389D01* +G01X1473837Y8651913D01* +G01X1469266Y8655112D01* +G01X1465233Y8655449D01* +G01X1461200Y8655786D01* +G01X1458999Y8655434D01* +G01X1456800Y8655083D01* +G01X1453762Y8652596D01* +G01X1450723Y8650110D01* +G01X1446899Y8643585D01* +G01X1437000Y8643585D01* +G01X1437000Y8649192D01* +G01X1438196Y8650552D01* +G01X1439393Y8651913D01* +G01X1439940Y8653701D01* +G01X1440487Y8655489D01* +G01X1447731Y8662546D01* +G01X1449235Y8662546D01* +G01X1451099Y8664012D01* +G01X1452964Y8665479D01* +G01X1457046Y8665479D01* +G01X1458202Y8665922D01* +G01X1459358Y8666366D01* +G01X1458952Y8667023D01* +G01X1458547Y8667679D01* +G01X1454599Y8667479D01* +G01X1450933Y8666842D01* +G01X1450197Y8665901D01* +G01X1449460Y8664959D01* +G01X1447997Y8664491D01* +G01X1446533Y8664024D01* +G01X1443599Y8661129D01* +G01X1440666Y8658233D01* +G01X1439383Y8656723D01* +G01X1438100Y8655213D01* +G01X1438100Y8653210D01* +G01X1436725Y8651462D01* +G01X1435351Y8649712D01* +G01X1434819Y8645118D01* +G01X1434286Y8640524D01* +G01X1435320Y8630231D01* +G01X1436247Y8629304D01* +G01X1437173Y8628378D01* +G01X1437729Y8626579D01* +G01X1438286Y8624779D01* +G01X1439289Y8623679D01* +G01X1440292Y8622580D01* +G01X1442194Y8620196D01* +G01X1444097Y8617813D01* +G01X1446009Y8617813D01* +G01X1446854Y8615613D01* +G01X1448875Y8615613D01* +G01X1450514Y8614191D01* +G01X1452153Y8612770D01* +G01X1456042Y8612284D01* +G01X1459932Y8611798D01* +G01X1461566Y8608210D01* +G01X1461555Y8587529D01* +G01X1461544Y8566847D01* +G01X1460850Y8565746D01* +G01X1460156Y8564647D01* +G01X1446378Y8564280D01* +G01X1432600Y8563913D01* +G01X1432401Y8548520D01* +G01X1432202Y8533125D01* +G01X1430487Y8531535D01* +G01X1428772Y8529945D01* +G01X1424599Y8529423D01* +G01X1420426Y8528902D01* +G01X1418529Y8527005D01* +G01X1415056Y8526484D01* +G01X1411583Y8525963D01* +G01X1411217Y8525010D01* +G01X1410851Y8524056D01* +G01X1407961Y8523568D01* +G01X1405071Y8523080D01* +G01X1404095Y8522105D01* +G01X1403121Y8521130D01* +G01X1400076Y8520310D01* +G01X1397033Y8519491D01* +G01X1397033Y8518194D01* +G01X1391900Y8516500D01* +G01X1391900Y8515203D01* +G01X1385961Y8513604D01* +G01X1384647Y8514022D01* +G01X1383334Y8514438D01* +G01X1373133Y8524498D01* +G01X1362933Y8534557D01* +G01X1362549Y8576368D01* +G01X1362165Y8618180D01* +G01X1361999Y8577640D01* +G01X1361833Y8537101D01* +G01X1360733Y8536679D01* +G01X1359633Y8536257D01* +G01X1359633Y8534228D01* +G01X1322262Y8496814D01* +G01X1320766Y8496814D01* +G01X1320766Y8494713D01* +G01X1319299Y8494247D01* +G01X1317833Y8493782D01* +G01X1317833Y8491738D01* +G01X1328833Y8480951D01* +G01X1339833Y8470163D01* +G01X1339833Y8467240D01* +G01X1338592Y8464427D01* +G01X1337351Y8461614D01* +G01X1336280Y8461614D01* +G01X1335386Y8458864D01* +G01X1334492Y8456115D01* +G01X1333579Y8455575D01* +G01X1332667Y8455035D01* +G01X1332197Y8452529D01* +G01X1331726Y8450022D01* +G01X1329750Y8449264D01* +G01X1329256Y8445971D01* +G01X1328763Y8442678D01* +G01X1327790Y8442304D01* +G01X1326817Y8441931D01* +G01X1325776Y8434986D01* +G01X1323878Y8433088D01* +G01X1322874Y8425056D01* +G01X1321087Y8423886D01* +G01X1319299Y8422714D01* +G01X1319299Y8420592D01* +G01X1300600Y8420133D01* +G01X1294849Y8420133D01* +G01X1294000Y8420338D01* +G01X1292533Y8420690D01* +G01X1291140Y8422015D01* +G01X1289285Y8422015D01* +G01X1288525Y8420596D01* +G01X1287767Y8419178D01* +G01X1276782Y8419178D01* +G01X1276782Y8420915D01* +G01X1277816Y8424322D01* +G01X1278851Y8427729D01* +G01X1280171Y8429272D01* +G01X1281492Y8430815D01* +G01X1282884Y8430815D01* +G01X1284272Y8432071D01* +G01X1285660Y8433327D01* +G01X1313355Y8433923D01* +G01X1313854Y8436218D01* +G01X1314354Y8438515D01* +G01X1315360Y8439961D01* +G01X1316366Y8441408D01* +G01X1316366Y8444221D01* +G01X1317930Y8447601D01* +G01X1319495Y8450981D01* +G01X1322806Y8458314D01* +G01X1323262Y8459414D01* +G01X1323718Y8460515D01* +G01X1325525Y8463713D01* +G01X1327331Y8466912D01* +G01X1319110Y8475080D01* +G01X1310889Y8483247D01* +G01X1309228Y8485406D01* +G01X1307566Y8487566D01* +G01X1307571Y8492006D01* +G01X1307576Y8496448D01* +G01X1309021Y8498647D01* +G01X1310467Y8500847D01* +G01X1329733Y8519649D01* +G01X1349000Y8538450D01* +G01X1349000Y8621172D01* +G01X1347166Y8623393D01* +G01X1345333Y8625614D01* +G01X1342399Y8627019D01* +G01X1339466Y8628424D01* +G01X1311694Y8628652D01* +G01X1283922Y8628879D01* +G01X1282449Y8627563D01* +G01X1280976Y8626246D01* +G01X1279614Y8623313D01* +G01X1278252Y8620379D01* +G01X1277326Y8618916D01* +G01X1276399Y8617453D01* +G01X1273558Y8613939D01* +G01X1270717Y8610424D01* +G01X1267362Y8608116D01* +G01X1264007Y8605808D01* +G01X1260815Y8604111D01* +G01X1257622Y8602413D01* +G01X1254400Y8602361D01* +G01X1252567Y8601313D01* +G01X1250733Y8600265D01* +G01X1237852Y8600213D01* +G01X1232587Y8602413D01* +G01X1229910Y8602413D01* +G01X1226718Y8604111D01* +G01X1223525Y8605808D01* +G01X1220171Y8608116D01* +G01X1216816Y8610424D01* +G01X1213974Y8613939D01* +G01X1211133Y8617453D01* +G01X1210233Y8618916D01* +G01X1209333Y8620379D01* +G01X1207465Y8624046D01* +G01X1205597Y8627713D01* +G01X1204836Y8633681D01* +G01X1204075Y8639650D01* +G01X1204778Y8645782D01* +G01X1205007Y8647774D01* +G01X1215166Y8647774D01* +G01X1215166Y8632584D01* +G01X1217188Y8630563D01* +G01X1217731Y8628038D01* +G01X1218274Y8625513D01* +G01X1220196Y8623313D01* +G01X1227563Y8615613D01* +G01X1229635Y8615613D01* +G01X1229635Y8615613D01* +G01X1231733Y8613963D01* +G01X1233830Y8612313D01* +G01X1253879Y8612313D01* +G01X1255239Y8613509D01* +G01X1256599Y8614706D01* +G01X1258373Y8615248D01* +G01X1260147Y8615790D01* +G01X1263742Y8619551D01* +G01X1267337Y8623313D01* +G01X1268385Y8624474D01* +G01X1269433Y8625636D01* +G01X1269433Y8627735D01* +G01X1270900Y8630471D01* +G01X1272367Y8633208D01* +G01X1272367Y8636775D01* +G01X1274736Y8639145D01* +G01X1310270Y8638929D01* +G01X1345804Y8638713D01* +G01X1346521Y8637430D01* +G01X1347239Y8636146D01* +G01X1349216Y8636146D01* +G01X1355966Y8630105D01* +G01X1355966Y8628034D01* +G01X1358126Y8627204D01* +G01X1358577Y8624525D01* +G01X1359028Y8621846D01* +G01X1359380Y8620563D01* +G01X1359732Y8619280D01* +G01X1361301Y8619280D01* +G01X1360811Y8623457D01* +G01X1360320Y8627634D01* +G01X1358270Y8629913D01* +G01X1351072Y8637444D01* +G01X1346555Y8638435D01* +G01X1346161Y8639464D01* +G01X1345766Y8640492D01* +G01X1310106Y8640702D01* +G01X1274447Y8640913D01* +G01X1273407Y8642336D01* +G01X1272367Y8643760D01* +G01X1272367Y8647774D01* +G01X1270345Y8649795D01* +G01X1269814Y8652212D01* +G01X1269284Y8654628D01* +G01X1268075Y8655915D01* +G01X1266866Y8657201D01* +G01X1265041Y8659507D01* +G01X1263216Y8661813D01* +G01X1261366Y8661813D01* +G01X1261366Y8663019D01* +G01X1258399Y8664962D01* +G01X1255431Y8666904D01* +G01X1251799Y8667386D01* +G01X1248166Y8667868D01* +G01X1248166Y8666311D01* +G01X1250733Y8665607D01* +G01X1256233Y8664679D01* +G01X1256233Y8663203D01* +G01X1260664Y8661658D01* +G01X1261408Y8660268D01* +G01X1262151Y8658879D01* +G01X1264299Y8658879D01* +G01X1264299Y8657184D01* +G01X1266133Y8654781D01* +G01X1267967Y8652377D01* +G01X1267967Y8650184D01* +G01X1269214Y8648936D01* +G01X1270462Y8647689D01* +G01X1270497Y8640161D01* +G01X1270533Y8632633D01* +G01X1269250Y8631216D01* +G01X1267967Y8629797D01* +G01X1267967Y8627644D01* +G01X1266683Y8625866D01* +G01X1265400Y8624086D01* +G01X1261766Y8620583D01* +G01X1258132Y8617079D01* +G01X1256306Y8617079D01* +G01X1255691Y8615981D01* +G01X1255077Y8614883D01* +G01X1243766Y8613449D01* +G01X1238111Y8614166D01* +G01X1232456Y8614883D01* +G01X1231841Y8615981D01* +G01X1231227Y8617079D01* +G01X1229401Y8617079D01* +G01X1225767Y8620583D01* +G01X1222133Y8624086D01* +G01X1220850Y8625866D01* +G01X1219566Y8627644D01* +G01X1219566Y8630175D01* +G01X1217000Y8632741D01* +G01X1217035Y8640215D01* +G01X1217041Y8641449D01* +G01X1227633Y8641449D01* +G01X1227633Y8638989D01* +G01X1228842Y8635184D01* +G01X1230052Y8631379D01* +G01X1231213Y8630033D01* +G01X1232375Y8628686D01* +G01X1235541Y8626549D01* +G01X1238706Y8624413D01* +G01X1238706Y8624413D01* +G01X1248826Y8624413D01* +G01X1251992Y8626549D01* +G01X1255157Y8628686D01* +G01X1257451Y8631379D01* +G01X1258675Y8634704D01* +G01X1259900Y8638028D01* +G01X1259900Y8641449D01* +G01X1257333Y8648959D01* +G01X1255357Y8650802D01* +G01X1253380Y8652646D01* +G01X1252147Y8653678D01* +G01X1250914Y8654710D01* +G01X1244867Y8655882D01* +G01X1243400Y8655830D01* +G01X1241933Y8655777D01* +G01X1239295Y8655262D01* +G01X1236657Y8654747D01* +G01X1235405Y8653696D01* +G01X1234152Y8652646D01* +G01X1232176Y8650802D01* +G01X1230199Y8648959D01* +G01X1227633Y8641449D01* +G01X1217041Y8641449D01* +G01X1217071Y8647689D01* +G01X1218318Y8648936D01* +G01X1219566Y8650184D01* +G01X1219566Y8652414D01* +G01X1221216Y8654600D01* +G01X1222866Y8656785D01* +G01X1225799Y8659656D01* +G01X1228733Y8662528D01* +G01X1229673Y8662537D01* +G01X1230612Y8662546D01* +G01X1231422Y8664656D01* +G01X1235700Y8665479D01* +G01X1237906Y8665905D01* +G01X1240112Y8666332D01* +G01X1239696Y8667006D01* +G01X1239280Y8667679D01* +G01X1235333Y8667479D01* +G01X1233630Y8667155D01* +G01X1231927Y8666830D01* +G01X1227217Y8663633D01* +G01X1225935Y8662540D01* +G01X1224653Y8661446D01* +G01X1222476Y8659372D01* +G01X1220300Y8657300D01* +G01X1220300Y8655369D01* +G01X1219269Y8654974D01* +G01X1218238Y8654578D01* +G01X1217188Y8649795D01* +G01X1216177Y8648785D01* +G01X1215166Y8647774D01* +G01X1205007Y8647774D01* +G01X1205481Y8651913D01* +G01X1207430Y8655946D01* +G01X1209379Y8659979D01* +G01X1210439Y8661913D01* +G01X1211500Y8663847D01* +G01X1216351Y8668674D01* +G01X1221201Y8673500D01* +G01X1222767Y8673977D01* +G01X1224333Y8674452D01* +G01X1225433Y8675355D01* +G01X1226533Y8676256D01* +G01X1230199Y8677524D01* +G01X1233866Y8678791D01* +G01X1236433Y8679384D01* +G01X1239000Y8679977D01* +G01X1243400Y8680029D01* +G01X1247800Y8680082D01* +G01X1250733Y8679429D01* +G01X1253666Y8678777D01* +G01X1257333Y8677517D01* +G01X1260999Y8676256D01* +G01X1262100Y8675355D01* +G01X1263200Y8674452D01* +G01X1266306Y8673509D01* +G01X1271112Y8668795D01* +G01X1275919Y8664082D01* +G01X1278170Y8659979D01* +G01X1280976Y8654113D01* +G01X1282354Y8652884D01* +G01X1283733Y8651655D01* +G01X1315633Y8651417D01* +G01X1347533Y8651179D01* +G01X1352651Y8648612D01* +G01X1357771Y8646046D01* +G01X1362336Y8641775D01* +G01X1366902Y8637505D01* +G01X1367401Y8635909D01* +G01X1367902Y8634313D01* +G01X1369267Y8632564D01* +G01X1370633Y8630815D01* +G01X1370633Y8627672D01* +G01X1373199Y8624046D01* +G01X1373410Y8581880D01* +G01X1373621Y8539714D01* +G01X1386400Y8526782D01* +G01X1391189Y8527525D01* +G01X1395031Y8530547D01* +G01X1397109Y8530547D01* +G01X1399821Y8531945D01* +G01X1402533Y8533343D01* +G01X1409293Y8536413D01* +G01X1412107Y8536413D01* +G01X1415354Y8538688D01* +G01X1418477Y8539220D01* +G01X1421600Y8539752D01* +G01X1421966Y8553784D01* +G01X1422333Y8567816D01* +G01X1424604Y8570631D01* +G01X1426875Y8573446D01* +G01X1432600Y8575508D01* +G01X1441766Y8575944D01* +G01X1450933Y8576380D01* +G01X1451133Y8589397D01* +G01X1451334Y8602413D01* +G01X1448564Y8602413D01* +G01X1446699Y8603880D01* +G01X1444835Y8605347D01* +G01X1443135Y8605347D01* +G01X1440434Y8607335D01* +G01X1437733Y8609323D01* +G01X1434800Y8612339D01* +G01X1431866Y8615355D01* +G01X1430315Y8617521D01* +G01X1428764Y8619687D01* +G01X1426832Y8623770D01* +G01X1424900Y8627855D01* +G01X1424900Y8630421D01* +G01X1423717Y8634488D01* +G01X1422534Y8638555D01* +G01X1423338Y8643846D01* +G01X1424533Y8649340D01* +G01X1425727Y8654834D01* +G01X1426779Y8655997D01* +G01X1427833Y8657161D01* +G01X1427833Y8659436D01* +G01X1430978Y8663486D01* +G01X1434123Y8667536D01* +G01X1438131Y8670800D01* +G01X1442139Y8674066D01* +G01X1443786Y8674588D01* +G01X1445433Y8675111D01* +G01X1445433Y8676413D01* +G01X1448183Y8676894D01* +G01X1450933Y8677377D01* +G01X1454254Y8679460D01* +G01X1459926Y8679883D01* +G01X1465600Y8680307D01* +G01X1469266Y8679543D01* +G01X1472933Y8678779D01* +G01X1480266Y8676256D01* +G01X1481424Y8675268D01* +G01X1482582Y8674279D01* +G01X1483664Y8674279D01* +G01X1486365Y8672284D01* +G01X1489067Y8670288D01* +G01X1492237Y8666967D01* +G01X1495408Y8663646D01* +G01X1496783Y8661079D01* +G01X1498156Y8658513D01* +G01X1498999Y8656679D01* +G01X1499842Y8654846D01* +G01X1502266Y8649822D01* +G01X1502266Y8629846D01* +G01X1500983Y8627888D01* +G01X1499700Y8625931D01* +G01X1499700Y8623465D01* +G01X1497042Y8619461D01* +G01X1494384Y8615456D01* +G01X1492123Y8612881D01* +G01X1489862Y8610306D01* +G01X1486947Y8608376D01* +G01X1484033Y8606446D01* +G01X1479949Y8604143D01* +G01X1475866Y8601841D01* +G01X1475657Y8590577D01* +G01X1475447Y8579313D01* +G01X1475854Y8577663D01* +G01X1476261Y8576013D01* +G01X1484864Y8576005D01* +G01X1493467Y8575996D01* +G01X1497181Y8575006D01* +G01X1500895Y8574017D01* +G01X1503007Y8571906D01* +G01X1505119Y8569794D01* +G01X1505666Y8566487D01* +G01X1506212Y8563180D01* +G01X1506300Y8540108D01* +G01X1508316Y8539690D01* +G01X1510333Y8539272D01* +G01X1514000Y8537906D01* +G01X1517666Y8536540D01* +G01X1520406Y8535690D01* +G01X1523146Y8534840D01* +G01X1523515Y8534243D01* +G01X1523884Y8533647D01* +G01X1526384Y8533178D01* +G01X1528886Y8532708D01* +G01X1529782Y8531628D01* +G01X1530679Y8530547D01* +G01X1532622Y8530547D01* +G01X1539518Y8526880D01* +G01X1542196Y8526880D01* +G01X1546951Y8531519D01* +G01X1551706Y8536158D01* +G01X1552469Y8538167D01* +G01X1553233Y8540176D01* +G01X1553281Y8618913D01* +G01X1553926Y8623918D01* +G01X1554571Y8628922D01* +G01X1556900Y8631495D01* +G01X1556900Y8633961D01* +G01X1558366Y8635216D01* +G01X1559833Y8636472D01* +G01X1559852Y8637226D01* +G01X1559870Y8637979D01* +G01X1563424Y8641462D01* +G01X1566977Y8644946D01* +G01X1568307Y8644946D01* +G01X1569563Y8646413D01* +G01X1570818Y8647879D01* +G01X1573284Y8647879D01* +G01X1574549Y8649024D01* +G01X1575815Y8650169D01* +G01X1580474Y8650843D01* +G01X1585133Y8651516D01* +G01X1613367Y8651583D01* +G01X1641599Y8651649D01* +G01X1642896Y8652161D01* +G01X1644193Y8652675D01* +G01X1646208Y8656726D01* +G01X1648222Y8660779D01* +G01X1653968Y8668046D01* +G01X1661681Y8674279D01* +G01X1662751Y8674279D01* +G01X1663909Y8675268D01* +G01X1665066Y8676256D01* +G01X1672399Y8678779D01* +G01X1676066Y8679543D01* +G01X1679733Y8680307D01* +G01X1691277Y8679445D01* +G01X1692952Y8678054D01* +G01X1696404Y8677185D01* +G01X1699856Y8676316D01* +G01X1701546Y8674279D01* +G01X1702919Y8674279D01* +G01X1710657Y8668046D01* +G01X1713162Y8664811D01* +G01X1715666Y8661577D01* +G01X1717393Y8658578D01* +G01X1719120Y8655579D01* +G01X1720185Y8651913D01* +G01X1721251Y8648246D01* +G01X1722675Y8640405D01* +G01X1722002Y8635892D01* +G01X1721330Y8631379D01* +G01X1719485Y8626246D01* +G01X1717582Y8622219D01* +G01X1715679Y8618192D01* +G01X1714739Y8617086D01* +G01X1713798Y8615979D01* +G01X1706555Y8608647D01* +G01X1704878Y8607366D01* +G01X1703199Y8606086D01* +G01X1699678Y8604249D01* +G01X1696155Y8602413D01* +G01X1694544Y8602387D01* +G01X1692933Y8602361D01* +G01X1689266Y8600265D01* +G01X1675333Y8600265D01* +G01X1671667Y8602361D01* +G01X1670055Y8602387D01* +G01X1668444Y8602413D01* +G01X1664922Y8604249D01* +G01X1661400Y8606086D01* +G01X1659749Y8607366D01* +G01X1658098Y8608647D01* +G01X1650766Y8615444D01* +G01X1650766Y8617079D01* +G01X1649225Y8617079D01* +G01X1647122Y8622112D01* +G01X1646434Y8622538D01* +G01X1645746Y8622963D01* +G01X1644781Y8627359D01* +G01X1641940Y8628879D01* +G01X1614270Y8628662D01* +G01X1586599Y8628446D01* +G01X1580018Y8624761D01* +G01X1576333Y8618180D01* +G01X1576120Y8581513D01* +G01X1575907Y8544847D01* +G01X1576333Y8543134D01* +G01X1576759Y8541421D01* +G01X1595912Y8522601D01* +G01X1615064Y8503780D01* +G01X1617310Y8501350D01* +G01X1619555Y8498918D01* +G01X1620745Y8495785D01* +G01X1621935Y8492651D01* +G01X1620856Y8489271D01* +G01X1619778Y8485891D01* +G01X1610683Y8476718D01* +G01X1601589Y8467545D01* +G01X1602590Y8463448D01* +G01X1603945Y8461699D01* +G01X1605300Y8459950D01* +G01X1605300Y8457813D01* +G01X1606766Y8455948D01* +G01X1608233Y8454083D01* +G01X1608233Y8452076D01* +G01X1609699Y8449339D01* +G01X1611166Y8446603D01* +G01X1611166Y8443963D01* +G01X1612288Y8442251D01* +G01X1613410Y8440538D01* +G01X1614504Y8434115D01* +G01X1628418Y8433703D01* +G01X1642333Y8433292D01* +G01X1645343Y8431378D01* +G01X1648353Y8429465D01* +G01X1651500Y8424131D01* +G01X1651500Y8358872D01* +G01X1649891Y8356078D01* +G01X1648283Y8353282D01* +G01X1645995Y8351716D01* +G01X1643709Y8350149D01* +G01X1616404Y8350149D01* +G01X1614099Y8347844D01* +G01X1614099Y8343893D01* +G01X1612633Y8341157D01* +G01X1611166Y8338421D01* +G01X1611166Y8336049D01* +G01X1609793Y8333382D01* +G01X1608419Y8330715D01* +G01X1604566Y8322628D01* +G01X1604566Y8320816D01* +G01X1603128Y8320816D01* +G01X1602069Y8316782D01* +G01X1602464Y8314184D01* +G01X1619701Y8297303D01* +G01X1620825Y8293787D01* +G01X1621950Y8290271D01* +G01X1620610Y8286860D01* +G01X1619271Y8283450D01* +G01X1611289Y8275550D01* +G01X1603308Y8267650D01* +G01X1588991Y8253593D01* +G01X1574676Y8239536D01* +G01X1571684Y8238009D01* +G01X1568691Y8236483D01* +G01X1565087Y8236483D01* +G01X1561543Y8238302D01* +G01X1558000Y8240121D01* +G01X1549933Y8248197D01* +G01X1541866Y8256272D01* +G01X1538653Y8256283D01* +G01X1538231Y8255601D01* +G01X1537810Y8254919D01* +G01X1533305Y8252668D01* +G01X1528799Y8250417D01* +G01X1526582Y8250417D01* +G01X1524267Y8248439D01* +G01X1520599Y8247169D01* +G01X1516933Y8245898D01* +G01X1513512Y8244914D01* +G01X1510090Y8243931D01* +G01X1508275Y8242742D01* +G01X1506459Y8241552D01* +G01X1506194Y8228166D01* +G01X1505929Y8214779D01* +G01X1504629Y8212796D01* +G01X1503329Y8210811D01* +G01X1497251Y8206975D01* +G01X1475500Y8206204D01* +G01X1475531Y8176427D01* +G01X1475561Y8146650D01* +G01X1478148Y8145001D01* +G01X1480735Y8143351D01* +G01X1482605Y8143351D01* +G01X1483933Y8141884D01* +G01X1485260Y8140417D01* +G01X1486763Y8140417D01* +G01X1491370Y8135625D01* +G01X1495977Y8130834D01* +G01X1498161Y8126850D01* +G01X1498850Y8125384D01* +G01X1499540Y8123917D01* +G01X1500903Y8120638D01* +G01X1502266Y8117357D01* +G01X1502266Y8098184D01* +G01X1499700Y8094270D01* +G01X1499700Y8091482D01* +G01X1497133Y8087968D01* +G01X1495666Y8085623D01* +G01X1494200Y8083517D01* +G01X1492733Y8081409D01* +G01X1489067Y8078145D01* +G01X1486760Y8076281D01* +G01X1484455Y8074418D01* +G01X1483431Y8074418D01* +G01X1481567Y8072952D01* +G01X1479702Y8071485D01* +G01X1476915Y8071485D01* +G01X1474958Y8070201D01* +G01X1473000Y8068918D01* +G37* +G36* +G01X1469939Y8281129D02* +G01X1463278Y8280217D01* +G01X1455272Y8281414D01* +G01X1447266Y8282610D01* +G01X1442987Y8283027D01* +G01X1438707Y8283444D01* +G01X1436753Y8284428D01* +G01X1434800Y8285412D01* +G01X1431590Y8285904D01* +G01X1428380Y8286397D01* +G01X1425307Y8288549D01* +G01X1423227Y8288549D01* +G01X1420214Y8289932D01* +G01X1417200Y8291316D01* +G01X1415367Y8292147D01* +G01X1413533Y8292978D01* +G01X1412304Y8293726D01* +G01X1443906Y8293726D01* +G01X1445953Y8293186D01* +G01X1448000Y8292646D01* +G01X1463766Y8292640D01* +G01X1463766Y8292640D01* +G01X1479533Y8292633D01* +G01X1485183Y8293777D01* +G01X1484292Y8294668D01* +G01X1464425Y8294725D01* +G01X1444559Y8294782D01* +G01X1444233Y8294254D01* +G01X1443906Y8293726D01* +G01X1412304Y8293726D01* +G01X1407667Y8296546D01* +G01X1406566Y8297059D01* +G01X1405466Y8297573D01* +G01X1401983Y8299785D01* +G01X1398500Y8301996D01* +G01X1398500Y8303216D01* +G01X1396825Y8303216D01* +G01X1392712Y8306636D01* +G01X1388599Y8310057D01* +G01X1384194Y8314520D01* +G01X1379788Y8318983D01* +G01X1374661Y8325688D01* +G01X1369533Y8332394D01* +G01X1368131Y8334855D01* +G01X1366729Y8337315D01* +G01X1363548Y8343462D01* +G01X1360366Y8349609D01* +G01X1360366Y8351667D01* +G01X1359308Y8353291D01* +G01X1358248Y8354916D01* +G01X1357524Y8357849D01* +G01X1356800Y8360782D01* +G01X1355682Y8363715D01* +G01X1354564Y8366648D01* +G01X1354524Y8369582D01* +G01X1354484Y8372515D01* +G01X1352300Y8379715D01* +G01X1352307Y8391515D01* +G01X1352313Y8399648D01* +G01X1364041Y8399648D01* +G01X1364297Y8385200D01* +G01X1364553Y8370751D01* +G01X1365668Y8369049D01* +G01X1366783Y8367346D01* +G01X1367843Y8359644D01* +G01X1369859Y8357627D01* +G01X1370350Y8354559D01* +G01X1370840Y8351490D01* +G01X1371817Y8351115D01* +G01X1372793Y8350741D01* +G01X1373272Y8348186D01* +G01X1373751Y8345631D01* +G01X1374714Y8345262D01* +G01X1375677Y8344893D01* +G01X1376638Y8340516D01* +G01X1377641Y8340132D01* +G01X1378644Y8339747D01* +G01X1379631Y8336582D01* +G01X1382465Y8333180D01* +G01X1385299Y8329779D01* +G01X1385299Y8328149D01* +G01X1387500Y8328149D01* +G01X1387500Y8326794D01* +G01X1397756Y8316416D01* +G01X1398572Y8316416D01* +G01X1401069Y8313991D01* +G01X1403566Y8311566D01* +G01X1405616Y8310509D01* +G01X1407667Y8309451D01* +G01X1408117Y8308834D01* +G01X1408568Y8308216D01* +G01X1410317Y8307202D01* +G01X1412067Y8306188D01* +G01X1417200Y8303803D01* +G01X1419399Y8301946D01* +G01X1421505Y8301445D01* +G01X1423610Y8300944D01* +G01X1424572Y8299981D01* +G01X1425534Y8299019D01* +G01X1428590Y8298531D01* +G01X1431645Y8298042D01* +G01X1432650Y8297037D01* +G01X1433655Y8296032D01* +G01X1433655Y8296032D01* +G01X1438122Y8295513D01* +G01X1442590Y8294995D01* +G01X1443380Y8295785D01* +G01X1442962Y8296460D01* +G01X1442927Y8296517D01* +G01X1485033Y8296517D01* +G01X1485033Y8294979D01* +G01X1494933Y8295991D01* +G01X1495747Y8297037D01* +G01X1496562Y8298082D01* +G01X1500029Y8298558D01* +G01X1503496Y8299033D01* +G01X1504215Y8300906D01* +G01X1507033Y8301382D01* +G01X1509851Y8301859D01* +G01X1510601Y8303811D01* +G01X1512899Y8304315D01* +G01X1515199Y8304821D01* +G01X1515990Y8306882D01* +G01X1517666Y8306909D01* +G01X1523767Y8311045D01* +G01X1524915Y8312080D01* +G01X1526063Y8313116D01* +G01X1528034Y8314582D01* +G01X1530004Y8316049D01* +G01X1543096Y8329249D01* +G01X1544131Y8330411D01* +G01X1545166Y8331572D01* +G01X1545166Y8333231D01* +G01X1546633Y8334015D01* +G01X1548099Y8334800D01* +G01X1548099Y8336963D01* +G01X1549566Y8338219D01* +G01X1551033Y8339474D01* +G01X1551033Y8341151D01* +G01X1552454Y8342957D01* +G01X1553875Y8344765D01* +G01X1554367Y8346724D01* +G01X1554858Y8348682D01* +G01X1556110Y8348682D01* +G01X1556940Y8351798D01* +G01X1557769Y8354916D01* +G01X1558752Y8356019D01* +G01X1559734Y8357122D01* +G01X1560239Y8360924D01* +G01X1560744Y8364726D01* +G01X1562604Y8365440D01* +G01X1563134Y8371425D01* +G01X1563664Y8377411D01* +G01X1562135Y8378939D01* +G01X1561748Y8376460D01* +G01X1561361Y8373982D01* +G01X1560430Y8365308D01* +G01X1558544Y8363421D01* +G01X1558052Y8360145D01* +G01X1557561Y8356869D01* +G01X1556573Y8356049D01* +G01X1555587Y8355230D01* +G01X1554633Y8350149D01* +G01X1553289Y8350149D01* +G01X1552520Y8347291D01* +G01X1551751Y8344433D01* +G01X1550728Y8344040D01* +G01X1549705Y8343648D01* +G01X1548743Y8339271D01* +G01X1547688Y8338866D01* +G01X1546633Y8338462D01* +G01X1546633Y8336267D01* +G01X1543699Y8334697D01* +G01X1543699Y8332804D01* +G01X1541866Y8331082D01* +G01X1540033Y8329360D01* +G01X1540033Y8328259D01* +G01X1529837Y8318249D01* +G01X1528152Y8316959D01* +G01X1526466Y8315669D01* +G01X1521855Y8312015D01* +G01X1520233Y8312015D01* +G01X1520233Y8310561D01* +G01X1517483Y8309117D01* +G01X1514733Y8307673D01* +G01X1510067Y8305438D01* +G01X1509171Y8303989D01* +G01X1503366Y8302426D01* +G01X1503366Y8301106D01* +G01X1500090Y8300614D01* +G01X1496814Y8300123D01* +G01X1496020Y8299166D01* +G01X1495226Y8298210D01* +G01X1491413Y8297727D01* +G01X1487600Y8297243D01* +G01X1486316Y8296880D01* +G01X1485033Y8296517D01* +G01X1485033Y8296517D01* +G01X1442927Y8296517D01* +G01X1442545Y8297136D01* +G01X1438077Y8297602D01* +G01X1433608Y8298070D01* +G01X1432590Y8299088D01* +G01X1431572Y8300105D01* +G01X1428301Y8300596D01* +G01X1425029Y8301086D01* +G01X1424657Y8302058D01* +G01X1424283Y8303031D01* +G01X1421658Y8303523D01* +G01X1419033Y8304016D01* +G01X1419033Y8305302D01* +G01X1416415Y8306166D01* +G01X1413797Y8307030D01* +G01X1413009Y8309082D01* +G01X1410811Y8309082D01* +G01X1406200Y8312695D01* +G01X1404916Y8313822D01* +G01X1403633Y8314949D01* +G01X1402442Y8314949D01* +G01X1389299Y8327782D01* +G01X1384200Y8334203D01* +G01X1383068Y8335424D01* +G01X1381937Y8336645D01* +G01X1380962Y8338997D01* +G01X1379988Y8341349D01* +G01X1378798Y8341349D01* +G01X1378281Y8342999D01* +G01X1377764Y8344649D01* +G01X1375033Y8348147D01* +G01X1375033Y8350284D01* +G01X1373566Y8352148D01* +G01X1372100Y8354013D01* +G01X1372100Y8358261D01* +G01X1371045Y8358666D01* +G01X1369990Y8359071D01* +G01X1368988Y8367088D01* +G01X1367023Y8369053D01* +G01X1365378Y8391725D01* +G01X1366306Y8404224D01* +G01X1376500Y8404224D01* +G01X1376500Y8377968D01* +G01X1377550Y8375453D01* +G01X1378601Y8372938D01* +G01X1379121Y8369427D01* +G01X1379642Y8365915D01* +G01X1381004Y8363359D01* +G01X1382366Y8360804D01* +G01X1382366Y8357661D01* +G01X1383394Y8356809D01* +G01X1384422Y8355955D01* +G01X1384906Y8354027D01* +G01X1385391Y8352098D01* +G01X1388233Y8348484D01* +G01X1388233Y8347156D01* +G01X1389883Y8344802D01* +G01X1391533Y8342449D01* +G01X1394408Y8338782D01* +G01X1397282Y8335115D01* +G01X1402888Y8329616D01* +G01X1408493Y8324116D01* +G01X1413580Y8320745D01* +G01X1418666Y8317374D01* +G01X1422333Y8315474D01* +G01X1426000Y8313574D01* +G01X1428962Y8312154D01* +G01X1431925Y8310733D01* +G01X1436978Y8309623D01* +G01X1438456Y8308702D01* +G01X1439933Y8307781D01* +G01X1444333Y8307315D01* +G01X1448733Y8306850D01* +G01X1448733Y8306850D01* +G01X1452333Y8305766D01* +G01X1455933Y8304682D01* +G01X1472943Y8304682D01* +G01X1475504Y8305462D01* +G01X1478067Y8306241D01* +G01X1483566Y8307238D01* +G01X1489067Y8308235D01* +G01X1492733Y8309519D01* +G01X1496400Y8310804D01* +G01X1499333Y8312104D01* +G01X1502266Y8313405D01* +G01X1504466Y8314286D01* +G01X1507400Y8316055D01* +G01X1510333Y8317824D01* +G01X1512533Y8319045D01* +G01X1514733Y8320265D01* +G01X1521333Y8325451D01* +G01X1527820Y8332117D01* +G01X1534308Y8338782D01* +G01X1536366Y8341105D01* +G01X1536366Y8342588D01* +G01X1537833Y8343916D01* +G01X1539300Y8345243D01* +G01X1539300Y8346988D01* +G01X1542233Y8349643D01* +G01X1542233Y8352151D01* +G01X1543699Y8354015D01* +G01X1545166Y8355880D01* +G01X1545166Y8357870D01* +G01X1546525Y8360426D01* +G01X1547885Y8362982D01* +G01X1548422Y8365890D01* +G01X1548959Y8368798D01* +G01X1550166Y8371023D01* +G01X1551373Y8373249D01* +G01X1551373Y8401362D01* +G01X1563499Y8401362D01* +G01X1563522Y8381315D01* +G01X1563522Y8381315D01* +G01X1564763Y8379358D01* +G01X1565222Y8381070D01* +G01X1565679Y8382782D01* +G01X1565617Y8391581D01* +G01X1565554Y8400382D01* +G01X1565043Y8402215D01* +G01X1564532Y8404048D01* +G01X1564016Y8402705D01* +G01X1563499Y8401362D01* +G01X1551373Y8401362D01* +G01X1551373Y8409182D01* +G01X1548875Y8413794D01* +G01X1548390Y8416988D01* +G01X1547904Y8420182D01* +G01X1546960Y8421281D01* +G01X1546014Y8422381D01* +G01X1545022Y8426356D01* +G01X1542895Y8430235D01* +G01X1540768Y8434115D01* +G01X1538933Y8437847D01* +G01X1538028Y8438914D01* +G01X1537122Y8439981D01* +G01X1535277Y8442287D01* +G01X1533433Y8444593D01* +G01X1533433Y8445552D01* +G01X1528483Y8450497D01* +G01X1523533Y8455443D01* +G01X1519866Y8458379D01* +G01X1516200Y8461315D01* +G01X1514000Y8462739D01* +G01X1511800Y8464163D01* +G01X1510333Y8465039D01* +G01X1508867Y8465914D01* +G01X1503366Y8468580D01* +G01X1497866Y8471246D01* +G01X1496033Y8472198D01* +G01X1494200Y8473150D01* +G01X1490936Y8473647D01* +G01X1487672Y8474145D01* +G01X1485677Y8475801D01* +G01X1476005Y8476735D01* +G01X1466333Y8477669D01* +G01X1463766Y8477605D01* +G01X1461200Y8477540D01* +G01X1453133Y8476902D01* +G01X1445066Y8476265D01* +G01X1442863Y8475271D01* +G01X1440661Y8474277D01* +G01X1438096Y8473778D01* +G01X1435533Y8473278D01* +G01X1431866Y8471753D01* +G01X1428199Y8470227D01* +G01X1420521Y8466381D01* +G01X1418260Y8465165D01* +G01X1415998Y8463950D01* +G01X1413418Y8461614D01* +G01X1412189Y8461614D01* +G01X1411028Y8460532D01* +G01X1409866Y8459451D01* +G01X1405250Y8455453D01* +G01X1400635Y8451454D01* +G01X1396543Y8446451D01* +G01X1392451Y8441448D01* +G01X1391533Y8440715D01* +G01X1390624Y8439248D01* +G01X1389715Y8437781D01* +G01X1386751Y8432648D01* +G01X1386150Y8431548D01* +G01X1385550Y8430448D01* +G01X1383958Y8427369D01* +G01X1382366Y8424291D01* +G01X1382366Y8422360D01* +G01X1380899Y8419623D01* +G01X1379433Y8416887D01* +G01X1379433Y8413406D01* +G01X1376500Y8404224D01* +G01X1366306Y8404224D01* +G01X1366994Y8413496D01* +G01X1367982Y8414639D01* +G01X1368969Y8415782D01* +G01X1369438Y8419394D01* +G01X1369907Y8423007D01* +G01X1371914Y8425315D01* +G01X1372394Y8427994D01* +G01X1372873Y8430673D01* +G01X1374848Y8431431D01* +G01X1375340Y8434056D01* +G01X1375833Y8436681D01* +G01X1377055Y8436681D01* +G01X1378980Y8441448D01* +G01X1380899Y8442621D01* +G01X1380899Y8444113D01* +G01X1382733Y8446516D01* +G01X1384567Y8448920D01* +G01X1384567Y8449930D01* +G01X1389700Y8455063D01* +G01X1389700Y8455817D01* +G01X1393331Y8459449D01* +G01X1396963Y8463081D01* +G01X1398500Y8463081D01* +G01X1398500Y8465281D01* +G01X1399891Y8465281D01* +G01X1401869Y8467114D01* +G01X1403847Y8468948D01* +G01X1404995Y8468948D01* +G01X1405964Y8469864D01* +G01X1406933Y8470781D01* +G01X1409866Y8472633D01* +G01X1412800Y8474484D01* +G01X1414266Y8475357D01* +G01X1415733Y8476231D01* +G01X1424533Y8480577D01* +G01X1426183Y8481045D01* +G01X1427833Y8481513D01* +G01X1427833Y8482791D01* +G01X1434506Y8483791D01* +G01X1436393Y8485679D01* +G01X1440730Y8486144D01* +G01X1445066Y8486609D01* +G01X1447470Y8486982D01* +G01X1449874Y8487355D01* +G01X1449443Y8488051D01* +G01X1449013Y8488748D01* +G01X1446306Y8488649D01* +G01X1443599Y8488551D01* +G01X1436531Y8487568D01* +G01X1436032Y8486763D01* +G01X1435533Y8485958D01* +G01X1432013Y8485430D01* +G01X1428493Y8484903D01* +G01X1426577Y8482987D01* +G01X1423931Y8482490D01* +G01X1421285Y8481994D01* +G01X1419665Y8480042D01* +G01X1415375Y8479100D01* +G01X1414821Y8478240D01* +G01X1414266Y8477381D01* +G01X1411699Y8476102D01* +G01X1409133Y8474823D01* +G01X1406329Y8472981D01* +G01X1405164Y8472021D01* +G01X1403999Y8471061D01* +G01X1399558Y8467621D01* +G01X1395117Y8464181D01* +G01X1390864Y8459819D01* +G01X1386610Y8455457D01* +G01X1385440Y8453586D01* +G01X1384270Y8451714D01* +G01X1383352Y8450614D01* +G01X1382434Y8449515D01* +G01X1381117Y8447986D01* +G01X1379800Y8446458D01* +G01X1378533Y8444320D01* +G01X1377266Y8442181D01* +G01X1376444Y8440164D01* +G01X1375623Y8438148D01* +G01X1374414Y8438148D01* +G01X1373530Y8435398D01* +G01X1372648Y8432648D01* +G01X1370819Y8430448D01* +G01X1370340Y8427772D01* +G01X1369861Y8425095D01* +G01X1368862Y8424267D01* +G01X1367863Y8423437D01* +G01X1367347Y8419306D01* +G01X1366831Y8415175D01* +G01X1364946Y8413290D01* +G01X1364494Y8406469D01* +G01X1364041Y8399648D01* +G01X1352313Y8399648D01* +G01X1352316Y8403315D01* +G01X1354500Y8410514D01* +G01X1354532Y8413148D01* +G01X1354564Y8415782D01* +G01X1355687Y8418715D01* +G01X1356811Y8421648D01* +G01X1357464Y8424754D01* +G01X1358118Y8427859D01* +G01X1359170Y8429520D01* +G01X1360223Y8431181D01* +G01X1360708Y8433514D01* +G01X1361194Y8435846D01* +G01X1362247Y8436721D01* +G01X1363300Y8437594D01* +G01X1363300Y8440150D01* +G01X1365925Y8443648D01* +G01X1367689Y8447314D01* +G01X1368611Y8448759D01* +G01X1369533Y8450204D01* +G01X1377511Y8461248D01* +G01X1384155Y8467883D01* +G01X1390800Y8474518D01* +G01X1398133Y8480314D01* +G01X1400487Y8481964D01* +G01X1402840Y8483614D01* +G01X1404040Y8483614D01* +G01X1405296Y8485081D01* +G01X1406552Y8486547D01* +G01X1408542Y8486547D01* +G01X1410233Y8488014D01* +G01X1411924Y8489481D01* +G01X1414453Y8489481D01* +G01X1414975Y8490109D01* +G01X1449811Y8490109D01* +G01X1450653Y8488748D01* +G01X1450653Y8488748D01* +G01X1477613Y8488748D01* +G01X1479166Y8488748D01* +G01X1479166Y8487397D01* +G01X1483200Y8486639D01* +G01X1487536Y8486159D01* +G01X1491873Y8485679D01* +G01X1493761Y8483791D01* +G01X1497037Y8483300D01* +G01X1500313Y8482809D01* +G01X1501132Y8481822D01* +G01X1501952Y8480834D01* +G01X1504419Y8480371D01* +G01X1506885Y8479908D01* +G01X1507743Y8478875D01* +G01X1508601Y8477842D01* +G01X1510700Y8477381D01* +G01X1512798Y8476920D01* +G01X1513672Y8475867D01* +G01X1514546Y8474814D01* +G01X1515988Y8474814D01* +G01X1520345Y8471147D01* +G01X1522276Y8471147D01* +G01X1523120Y8468948D01* +G01X1524652Y8468948D01* +G01X1530734Y8463448D01* +G01X1534467Y8459715D01* +G01X1538200Y8455983D01* +G01X1540950Y8452941D01* +G01X1543699Y8449900D01* +G01X1543699Y8448487D01* +G01X1544700Y8447901D01* +G01X1545701Y8447314D01* +G01X1547083Y8444839D01* +G01X1548466Y8442363D01* +G01X1549423Y8440622D01* +G01X1550380Y8438881D01* +G01X1551700Y8438881D01* +G01X1552193Y8436256D01* +G01X1552685Y8433631D01* +G01X1553672Y8433252D01* +G01X1554660Y8432873D01* +G01X1555139Y8430194D01* +G01X1555619Y8427514D01* +G01X1556657Y8426322D01* +G01X1557696Y8425130D01* +G01X1558130Y8422289D01* +G01X1558565Y8419448D01* +G01X1560564Y8417136D01* +G01X1561034Y8411569D01* +G01X1561505Y8406003D01* +G01X1561505Y8406003D01* +G01X1562095Y8405047D01* +G01X1562687Y8404091D01* +G01X1563173Y8404577D01* +G01X1563660Y8405064D01* +G01X1563134Y8410999D01* +G01X1562609Y8416934D01* +G01X1561625Y8417918D01* +G01X1560641Y8418902D01* +G01X1559627Y8426540D01* +G01X1558702Y8426895D01* +G01X1557777Y8427250D01* +G01X1556779Y8432570D01* +G01X1553966Y8436146D01* +G01X1553966Y8437550D01* +G01X1552500Y8439414D01* +G01X1551033Y8441279D01* +G01X1551033Y8444014D01* +G01X1549711Y8444014D01* +G01X1547989Y8446719D01* +G01X1546266Y8449424D01* +G01X1545404Y8450877D01* +G01X1544541Y8452329D01* +G01X1543387Y8452975D01* +G01X1542233Y8453620D01* +G01X1542233Y8455748D01* +G01X1540033Y8455748D01* +G01X1540033Y8457055D01* +G01X1531807Y8465281D01* +G01X1530500Y8465281D01* +G01X1530500Y8467481D01* +G01X1528372Y8467481D01* +G01X1527786Y8468482D01* +G01X1527200Y8469482D01* +G01X1524816Y8470700D01* +G01X1522433Y8471918D01* +G01X1522433Y8473320D01* +G01X1520653Y8473766D01* +G01X1518872Y8474213D01* +G01X1518132Y8476142D01* +G01X1513755Y8477104D01* +G01X1512998Y8479076D01* +G01X1510800Y8479559D01* +G01X1508601Y8480042D01* +G01X1507775Y8481038D01* +G01X1506949Y8482033D01* +G01X1504115Y8482511D01* +G01X1501281Y8482990D01* +G01X1500920Y8483932D01* +G01X1500558Y8484875D01* +G01X1496659Y8485392D01* +G01X1492760Y8485910D01* +G01X1492261Y8486718D01* +G01X1491761Y8487527D01* +G01X1487847Y8488084D01* +G01X1483933Y8488640D01* +G01X1481549Y8488694D01* +G01X1479166Y8488748D01* +G01X1477613Y8488748D01* +G01X1478015Y8489397D01* +G01X1478416Y8490047D01* +G01X1476775Y8490488D01* +G01X1475133Y8490928D01* +G01X1464133Y8490837D01* +G01X1453133Y8490748D01* +G01X1449811Y8490109D01* +G01X1414975Y8490109D01* +G01X1415306Y8490508D01* +G01X1416160Y8491537D01* +G01X1418147Y8492006D01* +G01X1420133Y8492476D01* +G01X1423067Y8493829D01* +G01X1426000Y8495184D01* +G01X1428566Y8496077D01* +G01X1431133Y8496969D01* +G01X1434433Y8497667D01* +G01X1437733Y8498364D01* +G01X1441400Y8499410D01* +G01X1445066Y8500456D01* +G01X1446899Y8500767D01* +G01X1448733Y8501079D01* +G01X1483933Y8500797D01* +G01X1486772Y8499539D01* +G01X1489612Y8498281D01* +G01X1491906Y8498264D01* +G01X1494200Y8498248D01* +G01X1497397Y8496798D01* +G01X1500593Y8495347D01* +G01X1502839Y8495347D01* +G01X1508867Y8492567D01* +G01X1518892Y8487647D01* +G01X1520846Y8486618D01* +G01X1522800Y8485588D01* +G01X1523166Y8485077D01* +G01X1523533Y8484567D01* +G01X1525366Y8483609D01* +G01X1527200Y8482651D01* +G01X1538933Y8473464D01* +G01X1541902Y8470656D01* +G01X1544870Y8467847D01* +G01X1548501Y8463676D01* +G01X1552133Y8459504D01* +G01X1553385Y8457809D01* +G01X1554637Y8456115D01* +G01X1556384Y8453914D01* +G01X1558129Y8451714D01* +G01X1564233Y8441362D01* +G01X1564233Y8439794D01* +G01X1566338Y8438047D01* +G01X1566838Y8435775D01* +G01X1567337Y8433503D01* +G01X1568715Y8431243D01* +G01X1570094Y8428981D01* +G01X1570120Y8427148D01* +G01X1570147Y8425315D01* +G01X1572240Y8422550D01* +G01X1572695Y8419166D01* +G01X1573150Y8415782D01* +G01X1574375Y8412115D01* +G01X1575599Y8408448D01* +G01X1575599Y8373982D01* +G01X1574316Y8370850D01* +G01X1573033Y8367719D01* +G01X1573001Y8362982D01* +G01X1571550Y8359785D01* +G01X1570100Y8356588D01* +G01X1570100Y8354343D01* +G01X1568717Y8351329D01* +G01X1567333Y8348315D01* +G01X1566522Y8346482D01* +G01X1565710Y8344649D01* +G01X1565050Y8343549D01* +G01X1564390Y8342449D01* +G01X1562777Y8338782D01* +G01X1560970Y8335849D01* +G01X1559118Y8332916D01* +G01X1557266Y8329982D01* +G01X1556533Y8329109D01* +G01X1555799Y8328236D01* +G01X1552133Y8322822D01* +G01X1535826Y8306516D01* +G01X1530412Y8302849D01* +G01X1529539Y8302098D01* +G01X1528666Y8301347D01* +G01X1524999Y8299001D01* +G01X1521333Y8296654D01* +G01X1520599Y8296067D01* +G01X1519866Y8295479D01* +G01X1511066Y8291355D01* +G01X1508354Y8289952D01* +G01X1505643Y8288549D01* +G01X1503361Y8288549D01* +G01X1500624Y8287082D01* +G01X1497888Y8285616D01* +G01X1493760Y8285616D01* +G01X1491584Y8284491D01* +G01X1489408Y8283366D01* +G01X1483004Y8282703D01* +G01X1476600Y8282042D01* +G01X1469939Y8281129D01* +G37* +G36* +G01X1207694Y8288662D02* +G01X1202378Y8288163D01* +G01X1197062Y8287665D01* +G01X1172931Y8287950D01* +G01X1148799Y8288235D01* +G01X1145031Y8290259D01* +G01X1141263Y8292284D01* +G01X1138186Y8295665D01* +G01X1135109Y8299046D01* +G01X1133702Y8302116D01* +G01X1131567Y8305782D01* +G01X1129432Y8309449D01* +G01X1127126Y8313849D01* +G01X1124820Y8318249D01* +G01X1123070Y8321182D01* +G01X1121321Y8324116D01* +G01X1118415Y8329982D01* +G01X1115461Y8335115D01* +G01X1112508Y8340249D01* +G01X1111602Y8342082D01* +G01X1110695Y8343916D01* +G01X1106866Y8349314D01* +G01X1104733Y8351081D01* +G01X1102600Y8352847D01* +G01X1097682Y8354065D01* +G01X1092765Y8355282D01* +G01X1060397Y8355282D01* +G01X1059682Y8353401D01* +G01X1058967Y8351520D01* +G01X1058967Y8299648D01* +G01X1057292Y8296344D01* +G01X1055618Y8293042D01* +G01X1050103Y8288659D01* +G01X1045552Y8288176D01* +G01X1041000Y8287692D01* +G01X1018599Y8287937D01* +G01X996199Y8288183D01* +G01X994271Y8289446D01* +G01X992343Y8290711D01* +G01X990183Y8293022D01* +G01X988023Y8295333D01* +G01X987011Y8299458D01* +G01X986000Y8303583D01* +G01X986000Y8480314D01* +G01X986263Y8481134D01* +G01X997366Y8481134D01* +G01X997366Y8302578D01* +G01X998081Y8300697D01* +G01X998796Y8298816D01* +G01X1046343Y8298816D01* +G01X1046971Y8300099D01* +G01X1047599Y8301382D01* +G01X1047966Y8332792D01* +G01X1048333Y8364202D01* +G01X1051267Y8366379D01* +G01X1075100Y8366092D01* +G01X1098933Y8365805D01* +G01X1103333Y8364143D01* +G01X1107733Y8362481D01* +G01X1111033Y8359811D01* +G01X1114333Y8357141D01* +G01X1114591Y8356537D01* +G01X1114849Y8355933D01* +G01X1117317Y8353449D01* +G01X1119143Y8350515D01* +G01X1120969Y8347582D01* +G01X1121852Y8346115D01* +G01X1122734Y8344649D01* +G01X1128036Y8334382D01* +G01X1129772Y8331449D01* +G01X1131506Y8328516D01* +G01X1134309Y8323382D01* +G01X1139808Y8313116D01* +G01X1141539Y8310182D01* +G01X1143268Y8307249D01* +G01X1144451Y8305049D01* +G01X1144451Y8305049D01* +G01X1145633Y8302849D01* +G01X1151386Y8298816D01* +G01X1202699Y8298816D01* +G01X1202699Y8301267D01* +G01X1200427Y8305725D01* +G01X1198153Y8310182D01* +G01X1196398Y8313116D01* +G01X1194644Y8316049D01* +G01X1193484Y8318539D01* +G01X1192324Y8321029D01* +G01X1190233Y8323120D01* +G01X1190233Y8325862D01* +G01X1188616Y8326862D01* +G01X1187541Y8329155D01* +G01X1186466Y8331449D01* +G01X1184718Y8334382D01* +G01X1182970Y8337315D01* +G01X1180355Y8342554D01* +G01X1177739Y8347791D01* +G01X1176653Y8348693D01* +G01X1175566Y8349595D01* +G01X1175566Y8351388D01* +G01X1172633Y8354042D01* +G01X1172633Y8355689D01* +G01X1171349Y8356878D01* +G01X1170066Y8358067D01* +G01X1168338Y8360157D01* +G01X1166610Y8362249D01* +G01X1163063Y8366058D01* +G01X1159517Y8369868D01* +G01X1155400Y8372024D01* +G01X1153750Y8373581D01* +G01X1152099Y8375139D01* +G01X1152099Y8382358D01* +G01X1153724Y8383871D01* +G01X1155347Y8385384D01* +G01X1158307Y8386178D01* +G01X1161266Y8386973D01* +G01X1165300Y8388879D01* +G01X1169333Y8390785D01* +G01X1169700Y8391193D01* +G01X1170066Y8391601D01* +G01X1178659Y8397435D01* +G01X1181404Y8400742D01* +G01X1184149Y8404048D01* +G01X1185679Y8406981D01* +G01X1187210Y8409915D01* +G01X1190233Y8419552D01* +G01X1190233Y8432090D01* +G01X1187299Y8441272D01* +G01X1187299Y8443047D01* +G01X1182533Y8452185D01* +G01X1181568Y8453983D01* +G01X1180603Y8455782D01* +G01X1174816Y8461631D01* +G01X1169029Y8467481D01* +G01X1167727Y8467481D01* +G01X1166400Y8468948D01* +G01X1165072Y8470414D01* +G01X1163204Y8470414D01* +G01X1162235Y8471342D01* +G01X1161266Y8472269D01* +G01X1157348Y8474275D01* +G01X1153431Y8476281D01* +G01X1151894Y8476281D01* +G01X1145866Y8479018D01* +G01X1141100Y8480263D01* +G01X1136333Y8481510D01* +G01X1127533Y8482567D01* +G01X1118733Y8483624D01* +G01X1102600Y8484996D01* +G01X1052366Y8485016D01* +G01X1002133Y8485036D01* +G01X1000667Y8484234D01* +G01X999200Y8483432D01* +G01X998283Y8482283D01* +G01X997366Y8481134D01* +G01X986263Y8481134D01* +G01X987344Y8484508D01* +G01X988689Y8488703D01* +G01X993952Y8493325D01* +G01X996209Y8494330D01* +G01X998466Y8495337D01* +G01X1061900Y8495146D01* +G01X1125333Y8494954D01* +G01X1127533Y8493998D01* +G01X1129733Y8493042D01* +G01X1141965Y8491650D01* +G01X1146160Y8489481D01* +G01X1149555Y8489481D01* +G01X1155027Y8486547D01* +G01X1156561Y8486547D01* +G01X1161113Y8484294D01* +G01X1165666Y8482041D01* +G01X1168416Y8480622D01* +G01X1171167Y8479202D01* +G01X1171167Y8477748D01* +G01X1172712Y8477748D01* +G01X1177740Y8473684D01* +G01X1182769Y8469621D01* +G01X1186133Y8465434D01* +G01X1189497Y8461248D01* +G01X1190185Y8460412D01* +G01X1190872Y8459577D01* +G01X1197566Y8446885D01* +G01X1197566Y8443942D01* +G01X1198826Y8441595D01* +G01X1200085Y8439248D01* +G01X1200358Y8427514D01* +G01X1200631Y8415782D01* +G01X1199421Y8412482D01* +G01X1198210Y8409182D01* +G01X1196687Y8404048D01* +G01X1195660Y8402891D01* +G01X1194633Y8401732D01* +G01X1194633Y8400461D01* +G01X1190599Y8394536D01* +G01X1184472Y8388648D01* +G01X1182769Y8387359D01* +G01X1181066Y8386068D01* +G01X1178867Y8384367D01* +G01X1176666Y8382665D01* +G01X1175566Y8382138D01* +G01X1174466Y8381612D01* +G01X1168600Y8378283D01* +G01X1168600Y8375946D01* +G01X1172200Y8372143D01* +G01X1175800Y8368341D01* +G01X1180710Y8362249D01* +G01X1181800Y8360782D01* +G01X1185660Y8354916D01* +G01X1188566Y8349782D01* +G01X1191470Y8344649D01* +G01X1191987Y8343549D01* +G01X1192503Y8342449D01* +G01X1194291Y8339516D01* +G01X1196078Y8336582D01* +G01X1197531Y8333649D01* +G01X1198984Y8330715D01* +G01X1201928Y8325582D01* +G01X1204871Y8320449D01* +G01X1207757Y8315315D01* +G01X1208606Y8313482D01* +G01X1209456Y8311649D01* +G01X1210098Y8310549D01* +G01X1210739Y8309449D01* +G01X1212586Y8305712D01* +G01X1214433Y8301974D01* +G01X1214433Y8296062D01* +G01X1213333Y8295149D01* +G01X1212233Y8294236D01* +G01X1212233Y8292713D01* +G01X1209964Y8290687D01* +G01X1207694Y8288662D01* +G37* +G36* +G01X1849929Y8287957D02* +G01X1769933Y8287731D01* +G01X1765384Y8288195D01* +G01X1760834Y8288659D01* +G01X1757618Y8291114D01* +G01X1754403Y8293569D01* +G01X1752818Y8298261D01* +G01X1751233Y8302953D01* +G01X1751233Y8480370D01* +G01X1751375Y8480777D01* +G01X1762966Y8480777D01* +G01X1762966Y8302578D01* +G01X1763681Y8300697D01* +G01X1764397Y8298816D01* +G01X1764397Y8298816D01* +G01X1926393Y8298816D01* +G01X1927913Y8300748D01* +G01X1929433Y8302680D01* +G01X1929433Y8331141D01* +G01X1927828Y8333312D01* +G01X1926224Y8335482D01* +G01X1816403Y8335482D01* +G01X1814985Y8336241D01* +G01X1813566Y8337001D01* +G01X1813566Y8479261D01* +G01X1812549Y8481696D01* +G01X1811532Y8484131D01* +G01X1809157Y8484606D01* +G01X1806783Y8485081D01* +G01X1767733Y8484988D01* +G01X1766131Y8484342D01* +G01X1764529Y8483697D01* +G01X1763747Y8482237D01* +G01X1762966Y8480777D01* +G01X1751375Y8480777D01* +G01X1752636Y8484376D01* +G01X1754039Y8488381D01* +G01X1757526Y8491463D01* +G01X1761014Y8494544D01* +G01X1762540Y8494846D01* +G01X1764066Y8495148D01* +G01X1788267Y8495237D01* +G01X1812466Y8495326D01* +G01X1814300Y8494268D01* +G01X1816133Y8493210D01* +G01X1819067Y8491849D01* +G01X1820264Y8490482D01* +G01X1821462Y8489114D01* +G01X1823014Y8486027D01* +G01X1824566Y8482939D01* +G01X1824587Y8349049D01* +G01X1825029Y8347399D01* +G01X1825471Y8345749D01* +G01X1929955Y8345749D01* +G01X1936610Y8340668D01* +G01X1938155Y8337477D01* +G01X1939699Y8334286D01* +G01X1939678Y8299182D01* +G01X1938621Y8297349D01* +G01X1937563Y8295516D01* +G01X1936874Y8294018D01* +G01X1936185Y8292521D01* +G01X1929926Y8288183D01* +G01X1849929Y8287957D01* +G37* +G36* +G01X1083286Y8400155D02* +G01X1051507Y8399929D01* +G01X1049736Y8401089D01* +G01X1047966Y8402249D01* +G01X1047966Y8435327D01* +G01X1058836Y8435327D01* +G01X1059084Y8423572D01* +G01X1059333Y8411819D01* +G01X1059333Y8411819D01* +G01X1060157Y8410997D01* +G01X1060979Y8410175D01* +G01X1109933Y8410803D01* +G01X1114363Y8412193D01* +G01X1118792Y8413581D01* +G01X1120704Y8415095D01* +G01X1122617Y8416608D01* +G01X1124158Y8419484D01* +G01X1125700Y8422360D01* +G01X1125700Y8427987D01* +G01X1123877Y8431096D01* +G01X1122054Y8434207D01* +G01X1118927Y8436356D01* +G01X1115800Y8438506D01* +G01X1059755Y8438989D01* +G01X1059295Y8437158D01* +G01X1058836Y8435327D01* +G01X1047966Y8435327D01* +G01X1047966Y8446311D01* +G01X1048810Y8447912D01* +G01X1049652Y8449515D01* +G01X1050459Y8450053D01* +G01X1051267Y8450592D01* +G01X1080324Y8450603D01* +G01X1109382Y8450614D01* +G01X1115617Y8448415D01* +G01X1119126Y8448415D01* +G01X1126393Y8444615D01* +G01X1132373Y8438635D01* +G01X1134170Y8434837D01* +G01X1135967Y8431040D01* +G01X1135955Y8424877D01* +G01X1135944Y8418715D01* +G01X1133854Y8415048D01* +G01X1132801Y8412848D01* +G01X1131747Y8410648D01* +G01X1129504Y8408539D01* +G01X1127260Y8406430D01* +G01X1125563Y8405452D01* +G01X1123866Y8404473D01* +G01X1122033Y8403633D01* +G01X1120200Y8402794D01* +G01X1115066Y8400382D01* +G01X1083286Y8400155D01* +G37* +G04 Image End* + +G04 Text Start* +G54D10* +G01X1189334Y4066948D02* +G01X1189334Y4028848D01* +G01X1186794Y4021736D01* +G01X1184508Y4019450D01* +G01X1179682Y4017164D01* +G01X1175110Y4017164D01* +G01X1170284Y4019450D01* +G01X1167744Y4021736D01* +G01X1165458Y4028848D01* +G01X1165458Y4033674D01* +G01X1216004Y4057550D02* +G01X1220830Y4059836D01* +G01X1227942Y4066948D01* +G01X1227942Y4017164D01* +G54D11* +G01X-1361080Y6944260D02* +G01X-1275228Y6944260D01* +G01X-1258210Y6950102D01* +G01X-1246780Y6961532D01* +G01X-1240938Y6978550D01* +G01X-1240938Y6989980D01* +G01X-1246780Y7007252D01* +G01X-1258210Y7018682D01* +G01X-1275228Y7024270D01* +G01X-1361080Y7024270D01* +G01X-1361080Y7072022D02* +G01X-1240938Y7072022D01* +G01X-1361080Y7072022D02* +G01X-1361080Y7112154D01* +G01X-1355238Y7129172D01* +G01X-1343808Y7140602D01* +G01X-1332378Y7146444D01* +G01X-1315360Y7152032D01* +G01X-1286658Y7152032D01* +G01X-1269640Y7146444D01* +G01X-1258210Y7140602D01* +G01X-1246780Y7129172D01* +G01X-1240938Y7112154D01* +G01X-1240938Y7072022D01* +G01X-1361080Y7245504D02* +G01X-1240938Y7199784D01* +G01X-1361080Y7245504D02* +G01X-1240938Y7291224D01* +G01X-1281070Y7217056D02* +G01X-1281070Y7274206D01* +G01X-1338220Y7338976D02* +G01X-1343808Y7350406D01* +G01X-1361080Y7367678D01* +G01X-1240938Y7367678D01* +G01X-1361080Y7426860D02* +G01X-1361080Y7489852D01* +G01X-1315360Y7455562D01* +G01X-1315360Y7472580D01* +G01X-1309518Y7484010D01* +G01X-1303930Y7489852D01* +G01X-1286658Y7495440D01* +G01X-1275228Y7495440D01* +G01X-1258210Y7489852D01* +G01X-1246780Y7478422D01* +G01X-1240938Y7461150D01* +G01X-1240938Y7444132D01* +G01X-1246780Y7426860D01* +G01X-1252368Y7421272D01* +G01X-1263798Y7415430D01* +G01X-1361080Y7554622D02* +G01X-1361080Y7617614D01* +G01X-1315360Y7583324D01* +G01X-1315360Y7600342D01* +G01X-1309518Y7611772D01* +G01X-1303930Y7617614D01* +G01X-1286658Y7623202D01* +G01X-1275228Y7623202D01* +G01X-1258210Y7617614D01* +G01X-1246780Y7606184D01* +G01X-1240938Y7588912D01* +G01X-1240938Y7571894D01* +G01X-1246780Y7554622D01* +G01X-1252368Y7549034D01* +G01X-1263798Y7543192D01* +G01X-1361080Y7728104D02* +G01X-1281070Y7670954D01* +G01X-1281070Y7756806D01* +G01X-1361080Y7728104D02* +G01X-1240938Y7728104D01* +G01X-1361080Y7850278D02* +G01X-1240938Y7804558D01* +G01X-1361080Y7850278D02* +G01X-1240938Y7895998D01* +G01X-1281070Y7821830D02* +G01X-1281070Y7878980D01* +G54D12* +G01X-129688Y7373520D02* +G01X-74062Y7394602D01* +G01X-129688Y7415938D02* +G01X-74062Y7394602D01* +G01X-129688Y7443624D02* +G01X-74062Y7443624D01* +G01X-129688Y7471564D02* +G01X-74062Y7471564D01* +G01X-129688Y7471564D02* +G01X-74062Y7508648D01* +G01X-129688Y7508648D02* +G01X-74062Y7508648D01* +G01X-116480Y7895744D02* +G01X-121814Y7893204D01* +G01X-127148Y7887870D01* +G01X-129688Y7882536D01* +G01X-129688Y7871868D01* +G01X-127148Y7866534D01* +G01X-121814Y7861200D01* +G01X-116480Y7858660D01* +G01X-108606Y7856120D01* +G01X-95144Y7856120D01* +G01X-87270Y7858660D01* +G01X-81936Y7861200D01* +G01X-76602Y7866534D01* +G01X-74062Y7871868D01* +G01X-74062Y7882536D01* +G01X-76602Y7887870D01* +G01X-81936Y7893204D01* +G01X-87270Y7895744D01* +G01X-95144Y7895744D01* +G01X-95144Y7882536D02* +G01X-95144Y7895744D01* +G01X-129688Y7923430D02* +G01X-74062Y7923430D01* +G01X-129688Y7923430D02* +G01X-74062Y7960768D01* +G01X-129688Y7960768D02* +G01X-74062Y7960768D01* +G01X-129688Y7988454D02* +G01X-74062Y7988454D01* +G01X-129688Y7988454D02* +G01X-129688Y8006996D01* +G01X-127148Y8015124D01* +G01X-121814Y8020458D01* +G01X-116480Y8022998D01* +G01X-108606Y8025792D01* +G01X-95144Y8025792D01* +G01X-87270Y8022998D01* +G01X-81936Y8020458D01* +G01X-76602Y8015124D01* +G01X-74062Y8006996D01* +G01X-74062Y7988454D01* +G01X-129688Y8389520D02* +G01X-74062Y8389520D01* +G01X-129688Y8389520D02* +G01X-129688Y8408062D01* +G01X-127148Y8415936D01* +G01X-121814Y8421270D01* +G01X-116480Y8423810D01* +G01X-108606Y8426604D01* +G01X-95144Y8426604D01* +G01X-87270Y8423810D01* +G01X-81936Y8421270D01* +G01X-76602Y8415936D01* +G01X-74062Y8408062D01* +G01X-74062Y8389520D01* +G01X-129688Y8454290D02* +G01X-74062Y8454290D01* +G01X-129688Y8482230D02* +G01X-74062Y8482230D01* +G01X-129688Y8482230D02* +G01X-74062Y8519314D01* +G01X-129688Y8519314D02* +G01X-74062Y8519314D01* +G01X-129688Y8872120D02* +G01X-74062Y8872120D01* +G01X-74062Y8872120D02* +G01X-74062Y8903870D01* +G01X-111146Y8945018D02* +G01X-108606Y8939684D01* +G01X-103272Y8934350D01* +G01X-95144Y8931556D01* +G01X-89810Y8931556D01* +G01X-81936Y8934350D01* +G01X-76602Y8939684D01* +G01X-74062Y8945018D01* +G01X-74062Y8952892D01* +G01X-76602Y8958226D01* +G01X-81936Y8963560D01* +G01X-89810Y8966100D01* +G01X-95144Y8966100D01* +G01X-103272Y8963560D01* +G01X-108606Y8958226D01* +G01X-111146Y8952892D01* +G01X-111146Y8945018D01* +G01X-111146Y8993786D02* +G01X-84730Y8993786D01* +G01X-76602Y8996580D01* +G01X-74062Y9001914D01* +G01X-74062Y9009788D01* +G01X-76602Y9015122D01* +G01X-84730Y9022996D01* +G01X-111146Y9022996D02* +G01X-74062Y9022996D01* +G01X-129688Y9058810D02* +G01X-84730Y9058810D01* +G01X-76602Y9061350D01* +G01X-74062Y9066684D01* +G01X-74062Y9072018D01* +G01X-111146Y9050682D02* +G01X-111146Y9069224D01* +G01X-129688Y9354720D02* +G01X-74062Y9354720D01* +G01X-129688Y9354720D02* +G01X-129688Y9378596D01* +G01X-127148Y9386470D01* +G01X-124354Y9389010D01* +G01X-119274Y9391804D01* +G01X-113940Y9391804D01* +G01X-108606Y9389010D01* +G01X-105812Y9386470D01* +G01X-103272Y9378596D01* +G01X-103272Y9354720D01* +G01X-103272Y9373262D02* +G01X-74062Y9391804D01* +G01X-111146Y9432952D02* +G01X-108606Y9427618D01* +G01X-103272Y9422284D01* +G01X-95144Y9419490D01* +G01X-89810Y9419490D01* +G01X-81936Y9422284D01* +G01X-76602Y9427618D01* +G01X-74062Y9432952D01* +G01X-74062Y9440826D01* +G01X-76602Y9446160D01* +G01X-81936Y9451494D01* +G01X-89810Y9454034D01* +G01X-95144Y9454034D01* +G01X-103272Y9451494D01* +G01X-108606Y9446160D01* +G01X-111146Y9440826D01* +G01X-111146Y9432952D01* +G01X-111146Y9481720D02* +G01X-84730Y9481720D01* +G01X-76602Y9484514D01* +G01X-74062Y9489848D01* +G01X-74062Y9497722D01* +G01X-76602Y9503056D01* +G01X-84730Y9510930D01* +G01X-111146Y9510930D02* +G01X-74062Y9510930D01* +G01X-129688Y9546744D02* +G01X-84730Y9546744D01* +G01X-76602Y9549284D01* +G01X-74062Y9554618D01* +G01X-74062Y9559952D01* +G01X-111146Y9538616D02* +G01X-111146Y9557158D01* +G01X-510688Y7607200D02* +G01X-510688Y7636410D01* +G01X-489606Y7620662D01* +G01X-489606Y7628536D01* +G01X-486812Y7633870D01* +G01X-484272Y7636410D01* +G01X-476144Y7639204D01* +G01X-470810Y7639204D01* +G01X-462936Y7636410D01* +G01X-457602Y7631330D01* +G01X-455062Y7623202D01* +G01X-455062Y7615328D01* +G01X-457602Y7607200D01* +G01X-460396Y7604660D01* +G01X-465730Y7602120D01* +G01X-510688Y7666890D02* +G01X-455062Y7688226D01* +G01X-510688Y7709562D02* +G01X-455062Y7688226D01* +G01X-510688Y7753250D02* +G01X-508148Y7747916D01* +G01X-502814Y7742582D01* +G01X-497480Y7740042D01* +G01X-489606Y7737248D01* +G01X-476144Y7737248D01* +G01X-468270Y7740042D01* +G01X-462936Y7742582D01* +G01X-457602Y7747916D01* +G01X-455062Y7753250D01* +G01X-455062Y7763918D01* +G01X-457602Y7769252D01* +G01X-462936Y7774586D01* +G01X-468270Y7777126D01* +G01X-476144Y7779920D01* +G01X-489606Y7779920D01* +G01X-497480Y7777126D01* +G01X-502814Y7774586D01* +G01X-508148Y7769252D01* +G01X-510688Y7763918D01* +G01X-510688Y7753250D01* +G01X-510688Y8059320D02* +G01X-455062Y8072528D01* +G01X-510688Y8085736D02* +G01X-455062Y8072528D01* +G01X-510688Y8085736D02* +G01X-455062Y8098944D01* +G01X-510688Y8112406D02* +G01X-455062Y8098944D01* +G01X-502814Y8177430D02* +G01X-508148Y8172096D01* +G01X-510688Y8163968D01* +G01X-510688Y8153554D01* +G01X-508148Y8145426D01* +G01X-502814Y8140092D01* +G01X-497480Y8140092D01* +G01X-492146Y8142886D01* +G01X-489606Y8145426D01* +G01X-486812Y8150760D01* +G01X-481478Y8166762D01* +G01X-478938Y8172096D01* +G01X-476144Y8174636D01* +G01X-470810Y8177430D01* +G01X-462936Y8177430D01* +G01X-457602Y8172096D01* +G01X-455062Y8163968D01* +G01X-455062Y8153554D01* +G01X-457602Y8145426D01* +G01X-462936Y8140092D01* +G01X-510688Y8205116D02* +G01X-455062Y8205116D01* +G01X-510688Y8205116D02* +G01X-510688Y8239660D01* +G01X-484272Y8205116D02* +G01X-484272Y8226452D01* +G01X-455062Y8205116D02* +G01X-455062Y8239660D01* +G01X-510688Y8267346D02* +G01X-455062Y8267346D01* +G01X-455062Y8267346D02* +G01X-455062Y8299350D01* +G01X-510688Y8592720D02* +G01X-455062Y8592720D01* +G01X-510688Y8592720D02* +G01X-510688Y8616596D01* +G01X-508148Y8624470D01* +G01X-505354Y8627010D01* +G01X-500274Y8629804D01* +G01X-494940Y8629804D01* +G01X-489606Y8627010D01* +G01X-486812Y8624470D01* +G01X-484272Y8616596D01* +G01X-484272Y8592720D02* +G01X-484272Y8616596D01* +G01X-481478Y8624470D01* +G01X-478938Y8627010D01* +G01X-473604Y8629804D01* +G01X-465730Y8629804D01* +G01X-460396Y8627010D01* +G01X-457602Y8624470D01* +G01X-455062Y8616596D01* +G01X-455062Y8592720D01* +G01X-497480Y8697368D02* +G01X-502814Y8694828D01* +G01X-508148Y8689494D01* +G01X-510688Y8684160D01* +G01X-510688Y8673492D01* +G01X-508148Y8668158D01* +G01X-502814Y8662824D01* +G01X-497480Y8660284D01* +G01X-489606Y8657490D01* +G01X-476144Y8657490D01* +G01X-468270Y8660284D01* +G01X-462936Y8662824D01* +G01X-457602Y8668158D01* +G01X-455062Y8673492D01* +G01X-455062Y8684160D01* +G01X-457602Y8689494D01* +G01X-462936Y8694828D01* +G01X-468270Y8697368D01* +G01X-510688Y8725054D02* +G01X-455062Y8725054D01* +G01X-455062Y8725054D02* +G01X-455062Y8757058D01* +G01X-510688Y8784744D02* +G01X-455062Y8784744D01* +G01X-510688Y8822082D02* +G01X-473604Y8784744D01* +G01X-486812Y8798206D02* +G01X-455062Y8822082D01* +G01X-510688Y9121802D02* +G01X-455062Y9100720D01* +G01X-510688Y9121802D02* +G01X-455062Y9143138D01* +G01X-473604Y9108594D02* +G01X-473604Y9135010D01* +G01X-497480Y9210702D02* +G01X-502814Y9208162D01* +G01X-508148Y9202828D01* +G01X-510688Y9197494D01* +G01X-510688Y9186826D01* +G01X-508148Y9181492D01* +G01X-502814Y9176158D01* +G01X-497480Y9173618D01* +G01X-489606Y9170824D01* +G01X-476144Y9170824D01* +G01X-468270Y9173618D01* +G01X-462936Y9176158D01* +G01X-457602Y9181492D01* +G01X-455062Y9186826D01* +G01X-455062Y9197494D01* +G01X-457602Y9202828D01* +G01X-462936Y9208162D01* +G01X-468270Y9210702D01* +G01X-476144Y9210702D01* +G01X-476144Y9197494D02* +G01X-476144Y9210702D01* +G01X-510688Y9238388D02* +G01X-455062Y9238388D01* +G01X-510688Y9238388D02* +G01X-455062Y9275726D01* +G01X-510688Y9275726D02* +G01X-455062Y9275726D01* +G01X-510688Y9303412D02* +G01X-455062Y9303412D01* +G01X-510688Y9303412D02* +G01X-510688Y9321954D01* +G01X-508148Y9330082D01* +G01X-502814Y9335416D01* +G01X-497480Y9337956D01* +G01X-489606Y9340750D01* +G01X-476144Y9340750D01* +G01X-468270Y9337956D01* +G01X-462936Y9335416D01* +G01X-457602Y9330082D01* +G01X-455062Y9321954D01* +G01X-455062Y9303412D01* +G01X-2153814Y7918604D02* +G01X-2159148Y7913270D01* +G01X-2161688Y7905396D01* +G01X-2161688Y7894728D01* +G01X-2159148Y7886600D01* +G01X-2153814Y7881520D01* +G01X-2148480Y7881520D01* +G01X-2143146Y7884060D01* +G01X-2140606Y7886600D01* +G01X-2137812Y7891934D01* +G01X-2132478Y7907936D01* +G01X-2129938Y7913270D01* +G01X-2127144Y7915810D01* +G01X-2121810Y7918604D01* +G01X-2113936Y7918604D01* +G01X-2108602Y7913270D01* +G01X-2106062Y7905396D01* +G01X-2106062Y7894728D01* +G01X-2108602Y7886600D01* +G01X-2113936Y7881520D01* +G01X-2161688Y7946290D02* +G01X-2106062Y7946290D01* +G01X-2161688Y7946290D02* +G01X-2161688Y7980834D01* +G01X-2135272Y7946290D02* +G01X-2135272Y7967626D01* +G01X-2151274Y8008520D02* +G01X-2153814Y8013854D01* +G01X-2161688Y8021982D01* +G01X-2106062Y8021982D01* +G01X-2153814Y8426604D02* +G01X-2159148Y8421270D01* +G01X-2161688Y8413396D01* +G01X-2161688Y8402728D01* +G01X-2159148Y8394600D01* +G01X-2153814Y8389520D01* +G01X-2148480Y8389520D01* +G01X-2143146Y8392060D01* +G01X-2140606Y8394600D01* +G01X-2137812Y8399934D01* +G01X-2132478Y8415936D01* +G01X-2129938Y8421270D01* +G01X-2127144Y8423810D01* +G01X-2121810Y8426604D01* +G01X-2113936Y8426604D01* +G01X-2108602Y8421270D01* +G01X-2106062Y8413396D01* +G01X-2106062Y8402728D01* +G01X-2108602Y8394600D01* +G01X-2113936Y8389520D01* +G01X-2161688Y8454290D02* +G01X-2106062Y8454290D01* +G01X-2161688Y8454290D02* +G01X-2161688Y8488834D01* +G01X-2135272Y8454290D02* +G01X-2135272Y8475626D01* +G01X-2148480Y8519314D02* +G01X-2151274Y8519314D01* +G01X-2156354Y8521854D01* +G01X-2159148Y8524648D01* +G01X-2161688Y8529982D01* +G01X-2161688Y8540396D01* +G01X-2159148Y8545730D01* +G01X-2156354Y8548524D01* +G01X-2151274Y8551064D01* +G01X-2145940Y8551064D01* +G01X-2140606Y8548524D01* +G01X-2132478Y8543190D01* +G01X-2106062Y8516520D01* +G01X-2106062Y8553858D01* +G01X-2509414Y7613804D02* +G01X-2514748Y7608470D01* +G01X-2517288Y7600596D01* +G01X-2517288Y7589928D01* +G01X-2514748Y7581800D01* +G01X-2509414Y7576720D01* +G01X-2504080Y7576720D01* +G01X-2498746Y7579260D01* +G01X-2496206Y7581800D01* +G01X-2493412Y7587134D01* +G01X-2488078Y7603136D01* +G01X-2485538Y7608470D01* +G01X-2482744Y7611010D01* +G01X-2477410Y7613804D01* +G01X-2469536Y7613804D01* +G01X-2464202Y7608470D01* +G01X-2461662Y7600596D01* +G01X-2461662Y7589928D01* +G01X-2464202Y7581800D01* +G01X-2469536Y7576720D01* +G01X-2504080Y7681368D02* +G01X-2509414Y7678828D01* +G01X-2514748Y7673494D01* +G01X-2517288Y7668160D01* +G01X-2517288Y7657492D01* +G01X-2514748Y7652158D01* +G01X-2509414Y7646824D01* +G01X-2504080Y7644284D01* +G01X-2496206Y7641490D01* +G01X-2482744Y7641490D01* +G01X-2474870Y7644284D01* +G01X-2469536Y7646824D01* +G01X-2464202Y7652158D01* +G01X-2461662Y7657492D01* +G01X-2461662Y7668160D01* +G01X-2464202Y7673494D01* +G01X-2469536Y7678828D01* +G01X-2474870Y7681368D01* +G01X-2517288Y7709054D02* +G01X-2461662Y7709054D01* +G01X-2461662Y7709054D02* +G01X-2461662Y7741058D01* +G01X-2517288Y7768744D02* +G01X-2461662Y7768744D01* +G01X-2517288Y7806082D02* +G01X-2480204Y7768744D01* +G01X-2493412Y7782206D02* +G01X-2461662Y7806082D01* +G01X-2517288Y8084720D02* +G01X-2461662Y8084720D01* +G01X-2517288Y8084720D02* +G01X-2461662Y8105802D01* +G01X-2517288Y8127138D02* +G01X-2461662Y8105802D01* +G01X-2517288Y8127138D02* +G01X-2461662Y8127138D01* +G01X-2517288Y8154824D02* +G01X-2477410Y8154824D01* +G01X-2469536Y8157618D01* +G01X-2464202Y8162952D01* +G01X-2461662Y8170826D01* +G01X-2461662Y8176160D01* +G01X-2464202Y8184034D01* +G01X-2469536Y8189368D01* +G01X-2477410Y8192162D01* +G01X-2517288Y8192162D01* +G01X-2517288Y8238390D02* +G01X-2461662Y8238390D01* +G01X-2517288Y8219848D02* +G01X-2517288Y8257186D01* +G01X-2517288Y8284872D02* +G01X-2461662Y8284872D01* +G01X-2517288Y8284872D02* +G01X-2517288Y8319416D01* +G01X-2490872Y8284872D02* +G01X-2490872Y8306208D01* +G01X-2461662Y8284872D02* +G01X-2461662Y8319416D01* +G01X-2517288Y8643520D02* +G01X-2461662Y8643520D01* +G01X-2517288Y8643520D02* +G01X-2517288Y8667396D01* +G01X-2514748Y8675270D01* +G01X-2511954Y8677810D01* +G01X-2506874Y8680604D01* +G01X-2498746Y8680604D01* +G01X-2493412Y8677810D01* +G01X-2490872Y8675270D01* +G01X-2488078Y8667396D01* +G01X-2488078Y8643520D01* +G01X-2517288Y8708290D02* +G01X-2461662Y8708290D01* +G01X-2461662Y8708290D02* +G01X-2461662Y8740294D01* +G01X-2517288Y8767980D02* +G01X-2461662Y8767980D01* +G01X-2461662Y8767980D02* +G01X-2461662Y8799984D01* +G01X-2161688Y8872120D02* +G01X-2106062Y8872120D01* +G01X-2161688Y8872120D02* +G01X-2161688Y8890662D01* +G01X-2159148Y8898536D01* +G01X-2153814Y8903870D01* +G01X-2148480Y8906410D01* +G01X-2140606Y8909204D01* +G01X-2127144Y8909204D01* +G01X-2119270Y8906410D01* +G01X-2113936Y8903870D01* +G01X-2108602Y8898536D01* +G01X-2106062Y8890662D01* +G01X-2106062Y8872120D01* +G01X-2161688Y8936890D02* +G01X-2106062Y8936890D01* +G01X-2161688Y8936890D02* +G01X-2161688Y8971434D01* +G01X-2135272Y8936890D02* +G01X-2135272Y8958226D01* +G01X-2106062Y8936890D02* +G01X-2106062Y8971434D01* +G01X-2161688Y8999120D02* +G01X-2106062Y8999120D01* +G01X-2161688Y8999120D02* +G01X-2161688Y9033664D01* +G01X-2135272Y8999120D02* +G01X-2135272Y9020456D01* +G01X-2106062Y8999120D02* +G01X-2106062Y9033664D01* +G01X-2161688Y9061350D02* +G01X-2106062Y9061350D01* +G01X-2161688Y9061350D02* +G01X-2106062Y9082686D01* +G01X-2161688Y9104022D02* +G01X-2106062Y9082686D01* +G01X-2161688Y9104022D02* +G01X-2106062Y9104022D01* +G54D10* +G01X-1339109Y10645548D02* +G01X-1339109Y10609988D01* +G01X-1336823Y10602876D01* +G01X-1331997Y10598050D01* +G01X-1324885Y10595764D01* +G01X-1320059Y10595764D01* +G01X-1312947Y10598050D01* +G01X-1308121Y10602876D01* +G01X-1305835Y10609988D01* +G01X-1305835Y10645548D01* +G01X-1274339Y10645548D02* +G01X-1248177Y10645548D01* +G01X-1262401Y10626498D01* +G01X-1255289Y10626498D01* +G01X-1250463Y10624212D01* +G01X-1248177Y10621926D01* +G01X-1245891Y10614814D01* +G01X-1245891Y10609988D01* +G01X-1248177Y10602876D01* +G01X-1253003Y10598050D01* +G01X-1260115Y10595764D01* +G01X-1267227Y10595764D01* +G01X-1274339Y10598050D01* +G01X-1276879Y10600336D01* +G01X-1279165Y10605162D01* +G01X2024359Y358548D02* +G01X2057633Y308764D01* +G01X2057633Y358548D02* +G01X2024359Y308764D01* +G01X2084303Y349150D02* +G01X2089129Y351436D01* +G01X2096241Y358548D01* +G01X2096241Y308764D01* +G01X975720Y112168D02* +G01X1008994Y62384D01* +G01X1008994Y112168D02* +G01X975720Y62384D01* +G01X1037950Y100484D02* +G01X1037950Y102770D01* +G01X1040490Y107596D01* +G01X1042776Y109882D01* +G01X1047602Y112168D01* +G01X1057000Y112168D01* +G01X1061826Y109882D01* +G01X1064366Y107596D01* +G01X1066652Y102770D01* +G01X1066652Y97944D01* +G01X1064366Y93118D01* +G01X1059540Y86006D01* +G01X1035664Y62384D01* +G01X1068938Y62384D01* +G01X3655801Y8538364D02* +G01X3689075Y8488580D01* +G01X3689075Y8538364D02* +G01X3655801Y8488580D01* +G01X3720571Y8538364D02* +G01X3746733Y8538364D01* +G01X3732509Y8519314D01* +G01X3739621Y8519314D01* +G01X3744447Y8517028D01* +G01X3746733Y8514742D01* +G01X3749019Y8507630D01* +G01X3749019Y8502804D01* +G01X3746733Y8495692D01* +G01X3741907Y8490866D01* +G01X3734795Y8488580D01* +G01X3727683Y8488580D01* +G01X3720571Y8490866D01* +G01X3718031Y8493152D01* +G01X3715745Y8497978D01* +G01X3375121Y9050548D02* +G01X3408395Y9000764D01* +G01X3408395Y9050548D02* +G01X3375121Y9000764D01* +G01X3458941Y9050548D02* +G01X3435065Y9017274D01* +G01X3470879Y9017274D01* +G01X3458941Y9050548D02* +G01X3458941Y9000764D01* +G01X1531091Y10226448D02* +G01X1564365Y10176664D01* +G01X1564365Y10226448D02* +G01X1531091Y10176664D01* +G01X1619737Y10226448D02* +G01X1595861Y10226448D01* +G01X1593321Y10205112D01* +G01X1595861Y10207398D01* +G01X1602973Y10209938D01* +G01X1610085Y10209938D01* +G01X1617197Y10207398D01* +G01X1622023Y10202826D01* +G01X1624309Y10195714D01* +G01X1624309Y10190888D01* +G01X1622023Y10183776D01* +G01X1617197Y10178950D01* +G01X1610085Y10176664D01* +G01X1602973Y10176664D01* +G01X1595861Y10178950D01* +G01X1593321Y10181236D01* +G01X1591035Y10186062D01* +G01X4383638Y9051775D02* +G01X4416912Y9001991D01* +G01X4416912Y9051775D02* +G01X4383638Y9001991D01* +G01X4472284Y9044663D02* +G01X4469744Y9049489D01* +G01X4462632Y9051775D01* +G01X4457806Y9051775D01* +G01X4450694Y9049489D01* +G01X4445868Y9042377D01* +G01X4443582Y9030439D01* +G01X4443582Y9018501D01* +G01X4445868Y9009103D01* +G01X4450694Y9004277D01* +G01X4457806Y9001991D01* +G01X4460346Y9001991D01* +G01X4467458Y9004277D01* +G01X4472284Y9009103D01* +G01X4474570Y9016215D01* +G01X4474570Y9018501D01* +G01X4472284Y9025613D01* +G01X4467458Y9030439D01* +G01X4460346Y9032725D01* +G01X4457806Y9032725D01* +G01X4450694Y9030439D01* +G01X4445868Y9025613D01* +G01X4443582Y9018501D01* +G01X-1977009Y10620248D02* +G01X-1943735Y10570464D01* +G01X-1943735Y10620248D02* +G01X-1977009Y10570464D01* +G01X-1883791Y10620248D02* +G01X-1907413Y10570464D01* +G01X-1917065Y10620248D02* +G01X-1883791Y10620248D01* +G01X1803506Y6480964D02* +G01X1800966Y6485536D01* +G01X1796394Y6490362D01* +G01X1791568Y6492648D01* +G01X1781916Y6492648D01* +G01X1777344Y6490362D01* +G01X1772518Y6485536D01* +G01X1769978Y6480964D01* +G01X1767692Y6473598D01* +G01X1767692Y6461914D01* +G01X1769978Y6454548D01* +G01X1772518Y6449976D01* +G01X1777344Y6445150D01* +G01X1781916Y6442864D01* +G01X1791568Y6442864D01* +G01X1796394Y6445150D01* +G01X1800966Y6449976D01* +G01X1803506Y6454548D01* +G01X1858878Y6485536D02* +G01X1856338Y6490362D01* +G01X1849226Y6492648D01* +G01X1844400Y6492648D01* +G01X1837288Y6490362D01* +G01X1832462Y6483250D01* +G01X1830176Y6471312D01* +G01X1830176Y6459374D01* +G01X1832462Y6449976D01* +G01X1837288Y6445150D01* +G01X1844400Y6442864D01* +G01X1846940Y6442864D01* +G01X1854052Y6445150D01* +G01X1858878Y6449976D01* +G01X1861164Y6457088D01* +G01X1861164Y6459374D01* +G01X1858878Y6466486D01* +G01X1854052Y6471312D01* +G01X1846940Y6473598D01* +G01X1844400Y6473598D01* +G01X1837288Y6471312D01* +G01X1832462Y6466486D01* +G01X1830176Y6459374D01* +G01X1916536Y6492648D02* +G01X1892660Y6492648D01* +G01X1890120Y6471312D01* +G01X1892660Y6473598D01* +G01X1899772Y6476138D01* +G01X1906884Y6476138D01* +G01X1913996Y6473598D01* +G01X1918822Y6469026D01* +G01X1921108Y6461914D01* +G01X1921108Y6457088D01* +G01X1918822Y6449976D01* +G01X1913996Y6445150D01* +G01X1906884Y6442864D01* +G01X1899772Y6442864D01* +G01X1892660Y6445150D01* +G01X1890120Y6447436D01* +G01X1887834Y6452262D01* +G01X1509374Y4387750D02* +G01X1528424Y4337966D01* +G01X1547474Y4387750D02* +G01X1528424Y4337966D01* +G01X1574144Y4387750D02* +G01X1574144Y4337966D01* +G01X1574144Y4387750D02* +G01X1590908Y4387750D01* +G01X1598020Y4385464D01* +G01X1602846Y4380638D01* +G01X1605132Y4376066D01* +G01X1607418Y4368700D01* +G01X1607418Y4357016D01* +G01X1605132Y4349650D01* +G01X1602846Y4345078D01* +G01X1598020Y4340252D01* +G01X1590908Y4337966D01* +G01X1574144Y4337966D01* +G01X1634088Y4378352D02* +G01X1638914Y4380638D01* +G01X1646026Y4387750D01* +G01X1646026Y4337966D01* +G01X1720342Y6013450D02* +G01X1725168Y6015736D01* +G01X1732280Y6022848D01* +G01X1732280Y5973064D01* +G01X1773174Y6022848D02* +G01X1766062Y6020562D01* +G01X1761236Y6013450D01* +G01X1758950Y6001512D01* +G01X1758950Y5994400D01* +G01X1761236Y5982462D01* +G01X1766062Y5975350D01* +G01X1773174Y5973064D01* +G01X1778000Y5973064D01* +G01X1785112Y5975350D01* +G01X1789938Y5982462D01* +G01X1792224Y5994400D01* +G01X1792224Y6001512D01* +G01X1789938Y6013450D01* +G01X1785112Y6020562D01* +G01X1778000Y6022848D01* +G01X1773174Y6022848D01* +G01X1833118Y6022848D02* +G01X1826006Y6020562D01* +G01X1821180Y6013450D01* +G01X1818894Y6001512D01* +G01X1818894Y5994400D01* +G01X1821180Y5982462D01* +G01X1826006Y5975350D01* +G01X1833118Y5973064D01* +G01X1837944Y5973064D01* +G01X1845056Y5975350D01* +G01X1849882Y5982462D01* +G01X1852168Y5994400D01* +G01X1852168Y6001512D01* +G01X1849882Y6013450D01* +G01X1845056Y6020562D01* +G01X1837944Y6022848D01* +G01X1833118Y6022848D01* +G01X1878838Y6006338D02* +G01X1878838Y5982462D01* +G01X1881124Y5975350D01* +G01X1885950Y5973064D01* +G01X1893062Y5973064D01* +G01X1897888Y5975350D01* +G01X1905000Y5982462D01* +G01X1905000Y6006338D02* +G01X1905000Y5973064D01* +G01X1931670Y6022848D02* +G01X1931670Y5973064D01* +G01X1931670Y6022848D02* +G01X1962658Y6022848D01* +G01X1931670Y5999226D02* +G01X1950720Y5999226D01* +G01X3311504Y8924267D02* +G01X3305154Y8930363D01* +G01X3296010Y8933411D01* +G01X3283564Y8933411D01* +G01X3274166Y8930363D01* +G01X3268070Y8924267D01* +G01X3268070Y8917917D01* +G01X3271118Y8911821D01* +G01X3274166Y8908773D01* +G01X3280516Y8905725D01* +G01X3299058Y8899375D01* +G01X3305154Y8896327D01* +G01X3308202Y8893279D01* +G01X3311504Y8886929D01* +G01X3311504Y8877785D01* +G01X3305154Y8871435D01* +G01X3296010Y8868387D01* +G01X3283564Y8868387D01* +G01X3274166Y8871435D01* +G01X3268070Y8877785D01* +G01X3341730Y8933411D02* +G01X3341730Y8868387D01* +G01X3341730Y8933411D02* +G01X3381862Y8933411D01* +G01X3341730Y8902423D02* +G01X3366368Y8902423D01* +G01X3341730Y8868387D02* +G01X3381862Y8868387D01* +G01X3458316Y8917917D02* +G01X3455268Y8924267D01* +G01X3449172Y8930363D01* +G01X3442822Y8933411D01* +G01X3430630Y8933411D01* +G01X3424280Y8930363D01* +G01X3418184Y8924267D01* +G01X3415136Y8917917D01* +G01X3412088Y8908773D01* +G01X3412088Y8893279D01* +G01X3415136Y8883881D01* +G01X3418184Y8877785D01* +G01X3424280Y8871435D01* +G01X3430630Y8868387D01* +G01X3442822Y8868387D01* +G01X3449172Y8871435D01* +G01X3455268Y8877785D01* +G01X3458316Y8883881D01* +G01X3458316Y8893279D01* +G01X3442822Y8893279D02* +G01X3458316Y8893279D01* +G01X3513180Y8933411D02* +G01X3488542Y8868387D01* +G01X3513180Y8933411D02* +G01X3538072Y8868387D01* +G01X3497686Y8890231D02* +G01X3528674Y8890231D01* +G01X3568298Y8920965D02* +G01X3574394Y8924267D01* +G01X3583538Y8933411D01* +G01X3583538Y8868387D01* +G01X4300834Y8924267D02* +G01X4294484Y8930363D01* +G01X4285340Y8933411D01* +G01X4272894Y8933411D01* +G01X4263496Y8930363D01* +G01X4257400Y8924267D01* +G01X4257400Y8917917D01* +G01X4260448Y8911821D01* +G01X4263496Y8908773D01* +G01X4269846Y8905725D01* +G01X4288388Y8899375D01* +G01X4294484Y8896327D01* +G01X4297532Y8893279D01* +G01X4300834Y8886929D01* +G01X4300834Y8877785D01* +G01X4294484Y8871435D01* +G01X4285340Y8868387D01* +G01X4272894Y8868387D01* +G01X4263496Y8871435D01* +G01X4257400Y8877785D01* +G01X4331060Y8933411D02* +G01X4331060Y8868387D01* +G01X4331060Y8933411D02* +G01X4371192Y8933411D01* +G01X4331060Y8902423D02* +G01X4355698Y8902423D01* +G01X4331060Y8868387D02* +G01X4371192Y8868387D01* +G01X4447646Y8917917D02* +G01X4444598Y8924267D01* +G01X4438502Y8930363D01* +G01X4432152Y8933411D01* +G01X4419960Y8933411D01* +G01X4413610Y8930363D01* +G01X4407514Y8924267D01* +G01X4404466Y8917917D01* +G01X4401418Y8908773D01* +G01X4401418Y8893279D01* +G01X4404466Y8883881D01* +G01X4407514Y8877785D01* +G01X4413610Y8871435D01* +G01X4419960Y8868387D01* +G01X4432152Y8868387D01* +G01X4438502Y8871435D01* +G01X4444598Y8877785D01* +G01X4447646Y8883881D01* +G01X4447646Y8893279D01* +G01X4432152Y8893279D02* +G01X4447646Y8893279D01* +G01X4502510Y8933411D02* +G01X4477872Y8868387D01* +G01X4502510Y8933411D02* +G01X4527402Y8868387D01* +G01X4487016Y8890231D02* +G01X4518004Y8890231D01* +G01X4560676Y8917917D02* +G01X4560676Y8920965D01* +G01X4563724Y8927315D01* +G01X4566772Y8930363D01* +G01X4572868Y8933411D01* +G01X4585314Y8933411D01* +G01X4591664Y8930363D01* +G01X4594712Y8927315D01* +G01X4597760Y8920965D01* +G01X4597760Y8914869D01* +G01X4594712Y8908773D01* +G01X4588362Y8899375D01* +G01X4557628Y8868387D01* +G01X4600808Y8868387D01* +G01X272267Y6012411D02* +G01X272267Y5947387D01* +G01X302493Y6012411D02* +G01X302493Y5947387D01* +G01X302493Y6012411D02* +G01X324083Y6012411D01* +G01X333227Y6009363D01* +G01X339577Y6003267D01* +G01X342625Y5996917D01* +G01X345673Y5987773D01* +G01X345673Y5972279D01* +G01X342625Y5962881D01* +G01X339577Y5956785D01* +G01X333227Y5950435D01* +G01X324083Y5947387D01* +G01X302493Y5947387D01* +G01X375899Y6012411D02* +G01X375899Y5947387D01* +G01X375899Y6012411D02* +G01X416031Y6012411D01* +G01X375899Y5981423D02* +G01X400537Y5981423D01* +G01X375899Y5947387D02* +G01X416031Y5947387D01* +G01X534141Y6012411D02* +G01X527791Y6009363D01* +G01X521695Y6003267D01* +G01X518647Y5996917D01* +G01X515599Y5987773D01* +G01X515599Y5972279D01* +G01X518647Y5962881D01* +G01X521695Y5956785D01* +G01X527791Y5950435D01* +G01X534141Y5947387D01* +G01X546333Y5947387D01* +G01X552683Y5950435D01* +G01X558779Y5956785D01* +G01X561827Y5962881D01* +G01X565129Y5972279D01* +G01X565129Y5987773D01* +G01X561827Y5996917D01* +G01X558779Y6003267D01* +G01X552683Y6009363D01* +G01X546333Y6012411D01* +G01X534141Y6012411D01* +G01X595355Y6012411D02* +G01X595355Y5965929D01* +G01X598403Y5956785D01* +G01X604499Y5950435D01* +G01X613897Y5947387D01* +G01X619993Y5947387D01* +G01X629391Y5950435D01* +G01X635487Y5956785D01* +G01X638535Y5965929D01* +G01X638535Y6012411D01* +G01X690351Y6012411D02* +G01X690351Y5947387D01* +G01X668761Y6012411D02* +G01X711941Y6012411D01* +G01X205359Y12880848D02* +G01X205359Y12845288D01* +G01X207645Y12838176D01* +G01X212471Y12833350D01* +G01X219583Y12831064D01* +G01X224409Y12831064D01* +G01X231521Y12833350D01* +G01X236347Y12838176D01* +G01X238633Y12845288D01* +G01X238633Y12880848D01* +G01X265303Y12871450D02* +G01X270129Y12873736D01* +G01X277241Y12880848D01* +G01X277241Y12831064D01* +G36* +G01X1077717Y5625618D02* +G01X1077717Y5641527D01* +G01X1077784Y5645345D01* +G01X1122899Y5645345D01* +G01X1123217Y5643754D01* +G01X1137536Y5643436D01* +G01X1152490Y5644073D01* +G01X1153763Y5646936D01* +G01X1154399Y5650118D01* +G01X1155672Y5655846D01* +G01X1156308Y5659345D01* +G01X1157263Y5664118D01* +G01X1158218Y5667936D01* +G01X1158854Y5671118D01* +G01X1159490Y5673664D01* +G01X1160763Y5680027D01* +G01X1162036Y5685755D01* +G01X1162672Y5689254D01* +G01X1163626Y5694027D01* +G01X1164581Y5697845D01* +G01X1165218Y5701027D01* +G01X1165854Y5703573D01* +G01X1166490Y5707073D01* +G01X1167445Y5711845D01* +G01X1168399Y5715664D01* +G01X1169672Y5722027D01* +G01X1170308Y5724573D01* +G01X1170945Y5728073D01* +G01X1171899Y5732845D01* +G01X1172854Y5736664D01* +G01X1173490Y5739845D01* +G01X1174127Y5742391D01* +G01X1175399Y5748754D01* +G01X1175717Y5750982D01* +G01X1171979Y5751936D01* +G01X1160763Y5752255D01* +G01X1149467Y5751936D01* +G01X1145490Y5750982D01* +G01X1144536Y5747482D01* +G01X1143581Y5743664D01* +G01X1142308Y5737300D01* +G01X1141672Y5734754D01* +G01X1140399Y5728391D01* +G01X1139127Y5722664D01* +G01X1138490Y5719164D01* +G01X1137536Y5714391D01* +G01X1136581Y5710573D01* +G01X1135945Y5707391D01* +G01X1135308Y5704845D01* +G01X1134036Y5698482D01* +G01X1132763Y5692755D01* +G01X1132126Y5689254D01* +G01X1131172Y5684482D01* +G01X1130217Y5680664D01* +G01X1129581Y5677482D01* +G01X1128945Y5674936D01* +G01X1128308Y5671436D01* +G01X1127354Y5666664D01* +G01X1126399Y5662846D01* +G01X1125126Y5656482D01* +G01X1124490Y5653936D01* +G01X1123217Y5647573D01* +G01X1122899Y5645345D01* +G01X1122899Y5645345D01* +G01X1077784Y5645345D01* +G01X1078036Y5659664D01* +G01X1078672Y5662846D01* +G01X1079308Y5666345D01* +G01X1080263Y5671118D01* +G01X1081217Y5674936D01* +G01X1082490Y5681300D01* +G01X1083126Y5683846D01* +G01X1084399Y5690209D01* +G01X1085672Y5695936D01* +G01X1086308Y5699436D01* +G01X1087263Y5704209D01* +G01X1088217Y5708027D01* +G01X1089490Y5714391D01* +G01X1090126Y5716936D01* +G01X1091399Y5723300D01* +G01X1092672Y5729027D01* +G01X1093308Y5732527D01* +G01X1094263Y5737300D01* +G01X1095217Y5741118D01* +G01X1096490Y5747482D01* +G01X1097126Y5750027D01* +G01X1097763Y5753527D01* +G01X1098718Y5758300D01* +G01X1099672Y5762118D01* +G01X1101263Y5770073D01* +G01X1155036Y5770073D01* +G01X1211036Y5769436D01* +G01X1214854Y5768164D01* +G01X1217081Y5766891D01* +G01X1218672Y5765618D01* +G01X1220899Y5763391D01* +G01X1222808Y5759891D01* +G01X1223763Y5756391D01* +G01X1223763Y5753845D01* +G01X1223126Y5748754D01* +G01X1221854Y5742391D01* +G01X1220581Y5736664D01* +G01X1219308Y5730300D01* +G01X1218036Y5724573D01* +G01X1217399Y5721073D01* +G01X1216445Y5716300D01* +G01X1215490Y5712482D01* +G01X1214217Y5706118D01* +G01X1213581Y5703573D01* +G01X1212308Y5697209D01* +G01X1211036Y5691482D01* +G01X1209763Y5685118D01* +G01X1208490Y5679391D01* +G01X1207217Y5673027D01* +G01X1205945Y5667300D01* +G01X1205308Y5663800D01* +G01X1204354Y5659027D01* +G01X1203399Y5655209D01* +G01X1202763Y5652027D01* +G01X1202127Y5649482D01* +G01X1201490Y5646618D01* +G01X1200536Y5643436D01* +G01X1199263Y5640573D01* +G01X1197990Y5638345D01* +G01X1197036Y5636754D01* +G01X1195763Y5635164D01* +G01X1191945Y5631345D01* +G01X1188763Y5629118D01* +G01X1185899Y5627527D01* +G01X1183354Y5626573D01* +G01X1181127Y5625936D01* +G01X1128945Y5625618D01* +G01X1077717Y5625618D01* +G37* +G36* +G01X1280081Y5625618D02* +G01X1230445Y5626255D01* +G01X1227581Y5627527D01* +G01X1225354Y5628800D01* +G01X1223763Y5630073D01* +G01X1221854Y5632300D01* +G01X1220263Y5635164D01* +G01X1219308Y5638664D01* +G01X1219308Y5643754D01* +G01X1219945Y5647573D01* +G01X1221217Y5653936D01* +G01X1222490Y5659664D01* +G01X1223126Y5663164D01* +G01X1224081Y5667936D01* +G01X1225036Y5671755D01* +G01X1225672Y5674936D01* +G01X1225911Y5675891D01* +G01X1270218Y5675891D01* +G01X1270218Y5673664D01* +G01X1281672Y5673345D01* +G01X1293763Y5673982D01* +G01X1294558Y5675095D01* +G01X1295036Y5677164D01* +G01X1295990Y5681936D01* +G01X1297581Y5688300D01* +G01X1298217Y5691800D01* +G01X1299172Y5696573D01* +G01X1300127Y5700391D01* +G01X1300763Y5703573D01* +G01X1301399Y5706118D01* +G01X1302036Y5709618D01* +G01X1302990Y5714391D01* +G01X1304581Y5720754D01* +G01X1304899Y5723618D01* +G01X1304899Y5725527D01* +G01X1293445Y5725527D01* +G01X1281354Y5724891D01* +G01X1280399Y5723300D01* +G01X1278490Y5713755D01* +G01X1277536Y5709300D01* +G01X1276581Y5705482D01* +G01X1275945Y5702300D01* +G01X1275308Y5699755D01* +G01X1274672Y5696254D01* +G01X1273717Y5691482D01* +G01X1272127Y5685118D01* +G01X1270854Y5678755D01* +G01X1270218Y5675891D01* +G01X1270218Y5675891D01* +G01X1225911Y5675891D01* +G01X1226308Y5677482D01* +G01X1227581Y5683846D01* +G01X1228854Y5689573D01* +G01X1229490Y5693073D01* +G01X1230445Y5697845D01* +G01X1231399Y5701664D01* +G01X1232036Y5704845D01* +G01X1232672Y5707391D01* +G01X1233945Y5713755D01* +G01X1235217Y5719482D01* +G01X1235854Y5722664D01* +G01X1236808Y5726164D01* +G01X1238081Y5729027D01* +G01X1239354Y5731255D01* +G01X1240627Y5733164D01* +G01X1242217Y5735073D01* +G01X1244763Y5736982D01* +G01X1247945Y5738891D01* +G01X1250808Y5740164D01* +G01X1253354Y5740800D01* +G01X1255581Y5741118D01* +G01X1294717Y5741436D01* +G01X1335126Y5741118D01* +G01X1338945Y5740482D01* +G01X1342126Y5739527D01* +G01X1344354Y5738255D01* +G01X1345945Y5736982D01* +G01X1347536Y5735073D01* +G01X1348808Y5732527D01* +G01X1349445Y5728709D01* +G01X1349127Y5724573D01* +G01X1347217Y5715027D01* +G01X1346581Y5712482D01* +G01X1344036Y5699755D01* +G01X1342763Y5694027D01* +G01X1341490Y5687664D01* +G01X1340217Y5681936D01* +G01X1339581Y5678436D01* +G01X1338627Y5673664D01* +G01X1337672Y5669846D01* +G01X1336399Y5663482D01* +G01X1335763Y5660936D01* +G01X1335445Y5658709D01* +G01X1326854Y5657755D01* +G01X1275229Y5657118D01* +G01X1266399Y5656164D01* +G01X1265445Y5652664D01* +G01X1263854Y5646300D01* +G01X1263218Y5643118D01* +G01X1262899Y5640891D01* +G01X1297263Y5640891D01* +G01X1322956Y5640652D01* +G01X1331308Y5639936D01* +G01X1330672Y5637391D01* +G01X1330036Y5634209D01* +G01X1329399Y5631663D01* +G01X1328763Y5628164D01* +G01X1328445Y5625618D01* +G01X1280081Y5625618D01* +G37* +G36* +G01X1402899Y5625618D02* +G01X1362172Y5625936D01* +G01X1359945Y5626891D01* +G01X1357399Y5628164D01* +G01X1355490Y5629436D01* +G01X1353899Y5631027D01* +G01X1352627Y5632618D01* +G01X1351672Y5634527D01* +G01X1350718Y5637073D01* +G01X1350081Y5640573D01* +G01X1350399Y5643754D01* +G01X1350718Y5646300D01* +G01X1351354Y5650118D01* +G01X1352308Y5653300D01* +G01X1352945Y5656800D01* +G01X1353263Y5659345D01* +G01X1397808Y5659345D01* +G01X1396854Y5654573D01* +G01X1396218Y5652027D01* +G01X1394945Y5646300D01* +G01X1394308Y5643118D01* +G01X1393990Y5640891D01* +G01X1405445Y5640891D01* +G01X1417854Y5641527D01* +G01X1419127Y5644391D01* +G01X1420399Y5650755D01* +G01X1421354Y5655209D01* +G01X1422308Y5659027D01* +G01X1422945Y5662209D01* +G01X1423581Y5664755D01* +G01X1424854Y5671118D01* +G01X1425172Y5673664D01* +G01X1425172Y5675254D01* +G01X1403218Y5675254D01* +G01X1378399Y5675573D01* +G01X1373945Y5676209D01* +G01X1370763Y5677164D01* +G01X1368218Y5678436D01* +G01X1366309Y5679709D01* +G01X1364081Y5681936D01* +G01X1362172Y5685118D01* +G01X1361218Y5687664D01* +G01X1360899Y5690209D01* +G01X1361218Y5694664D01* +G01X1361854Y5698482D01* +G01X1362490Y5701982D01* +G01X1363445Y5706755D01* +G01X1364399Y5710573D01* +G01X1365672Y5716936D01* +G01X1366309Y5719482D01* +G01X1366945Y5722664D01* +G01X1367899Y5726164D01* +G01X1369172Y5729027D01* +G01X1370445Y5731255D01* +G01X1371399Y5732845D01* +G01X1373309Y5735073D01* +G01X1375854Y5736982D01* +G01X1377445Y5738255D01* +G01X1379354Y5739209D01* +G01X1381899Y5740164D01* +G01X1384445Y5740800D01* +G01X1386672Y5741118D01* +G01X1425809Y5741436D01* +G01X1466218Y5741118D01* +G01X1470036Y5740482D01* +G01X1473218Y5739527D01* +G01X1475445Y5738255D01* +G01X1477036Y5736982D01* +G01X1478627Y5735073D01* +G01X1479899Y5732527D01* +G01X1480536Y5728391D01* +G01X1480218Y5724573D01* +G01X1479581Y5721073D01* +G01X1478627Y5716300D01* +G01X1477672Y5712482D01* +G01X1476718Y5707709D01* +G01X1432172Y5707709D01* +G01X1432809Y5709618D01* +G01X1433763Y5713118D01* +G01X1434399Y5715664D01* +G01X1435672Y5721391D01* +G01X1435990Y5723936D01* +G01X1435990Y5725527D01* +G01X1424854Y5725527D01* +G01X1412763Y5725209D01* +G01X1411490Y5723300D01* +G01X1410854Y5720754D01* +G01X1408945Y5711209D01* +G01X1407990Y5706755D01* +G01X1407036Y5702936D01* +G01X1406399Y5699755D01* +G01X1405763Y5697209D01* +G01X1405127Y5693709D01* +G01X1404808Y5691164D01* +G01X1430581Y5691164D01* +G01X1459218Y5690845D01* +G01X1463354Y5689573D01* +G01X1465581Y5687982D01* +G01X1467808Y5685755D01* +G01X1469399Y5682573D01* +G01X1470036Y5680027D01* +G01X1470036Y5677482D01* +G01X1469399Y5673027D01* +G01X1468445Y5667936D01* +G01X1467490Y5664118D01* +G01X1465581Y5654573D01* +G01X1464945Y5652027D01* +G01X1464308Y5648527D01* +G01X1463354Y5644709D01* +G01X1460808Y5638982D01* +G01X1458263Y5635164D01* +G01X1456036Y5632618D01* +G01X1453490Y5630709D01* +G01X1451899Y5629436D01* +G01X1449672Y5628164D01* +G01X1446490Y5626891D01* +G01X1443945Y5625936D01* +G01X1402899Y5625618D01* +G37* +G36* +G01X1478627Y5625618D02* +G01X1478945Y5627209D01* +G01X1480218Y5633573D01* +G01X1480854Y5636118D01* +G01X1481490Y5639618D01* +G01X1482445Y5644391D01* +G01X1483400Y5648209D01* +G01X1484672Y5654573D01* +G01X1485309Y5657118D01* +G01X1486581Y5663482D01* +G01X1487854Y5669209D01* +G01X1488490Y5672709D01* +G01X1489445Y5677482D01* +G01X1490399Y5681300D01* +G01X1491672Y5687664D01* +G01X1492309Y5690209D01* +G01X1492945Y5693709D01* +G01X1493899Y5698482D01* +G01X1494854Y5702300D01* +G01X1496127Y5708664D01* +G01X1496763Y5711209D01* +G01X1498036Y5717573D01* +G01X1499309Y5723300D01* +G01X1500581Y5729664D01* +G01X1501854Y5735391D01* +G01X1502490Y5738891D01* +G01X1502808Y5741436D01* +G01X1547354Y5741436D01* +G01X1547036Y5739209D01* +G01X1546081Y5734754D01* +G01X1545127Y5730936D01* +G01X1543854Y5724573D01* +G01X1543218Y5722027D01* +G01X1541945Y5715664D01* +G01X1540672Y5709936D01* +G01X1540036Y5706436D01* +G01X1539081Y5701664D01* +G01X1538127Y5697845D01* +G01X1536854Y5691482D01* +G01X1536218Y5688936D01* +G01X1535581Y5685436D01* +G01X1534627Y5680664D01* +G01X1533672Y5676846D01* +G01X1532399Y5670482D01* +G01X1531763Y5667936D01* +G01X1530490Y5661573D01* +G01X1529218Y5655846D01* +G01X1527945Y5649482D01* +G01X1526672Y5643754D01* +G01X1525399Y5637391D01* +G01X1524127Y5631663D01* +G01X1523490Y5628164D01* +G01X1523172Y5625618D01* +G01X1478627Y5625618D01* +G37* +G36* +G01X1593172Y5596345D02* +G01X1557217Y5596664D01* +G01X1557854Y5598891D01* +G01X1560399Y5610346D01* +G01X1560718Y5612255D01* +G01X1582990Y5612255D01* +G01X1606218Y5612573D01* +G01X1607490Y5614482D01* +G01X1608127Y5617664D01* +G01X1608763Y5620209D01* +G01X1609400Y5623391D01* +G01X1609718Y5625618D01* +G01X1585218Y5625618D01* +G01X1558490Y5625936D01* +G01X1554672Y5626891D01* +G01X1552127Y5628164D01* +G01X1550218Y5629436D01* +G01X1548627Y5631027D01* +G01X1547354Y5632618D01* +G01X1546399Y5634527D01* +G01X1545445Y5637073D01* +G01X1544809Y5640573D01* +G01X1545074Y5643754D01* +G01X1589036Y5643754D01* +G01X1589036Y5641209D01* +G01X1600808Y5640891D01* +G01X1609559Y5641209D01* +G01X1612899Y5642164D01* +G01X1613854Y5644391D01* +G01X1614490Y5647891D01* +G01X1615445Y5652664D01* +G01X1616399Y5656482D01* +G01X1617672Y5662846D01* +G01X1618309Y5665391D01* +G01X1619581Y5671755D01* +G01X1620854Y5677482D01* +G01X1621490Y5680982D01* +G01X1622445Y5685755D01* +G01X1623399Y5689573D01* +G01X1624036Y5692755D01* +G01X1624672Y5695300D01* +G01X1625945Y5701664D01* +G01X1627218Y5707391D01* +G01X1628490Y5713755D01* +G01X1629763Y5719482D01* +G01X1630399Y5722982D01* +G01X1630718Y5725527D01* +G01X1606536Y5725527D01* +G01X1606218Y5723936D01* +G01X1605581Y5721391D01* +G01X1604309Y5715664D01* +G01X1603672Y5712164D01* +G01X1602718Y5707391D01* +G01X1601763Y5703573D01* +G01X1601127Y5700391D01* +G01X1600490Y5697845D01* +G01X1599218Y5691482D01* +G01X1597945Y5685755D01* +G01X1597309Y5682254D01* +G01X1596354Y5677482D01* +G01X1595400Y5673664D01* +G01X1594763Y5670482D01* +G01X1594127Y5667936D01* +G01X1593490Y5664436D01* +G01X1592536Y5659664D01* +G01X1591581Y5655846D01* +G01X1590309Y5649482D01* +G01X1589672Y5646936D01* +G01X1589036Y5643754D01* +G01X1589036Y5643754D01* +G01X1545074Y5643754D01* +G01X1545127Y5644391D01* +G01X1545763Y5648209D01* +G01X1546399Y5651391D01* +G01X1547672Y5657118D01* +G01X1548308Y5660618D01* +G01X1549263Y5665391D01* +G01X1550218Y5669209D01* +G01X1550854Y5672391D01* +G01X1551490Y5674936D01* +G01X1552127Y5678436D01* +G01X1553081Y5683209D01* +G01X1554036Y5687027D01* +G01X1555308Y5693391D01* +G01X1555945Y5695936D01* +G01X1557217Y5702300D01* +G01X1558490Y5708027D01* +G01X1560399Y5717573D01* +G01X1561354Y5722027D01* +G01X1562308Y5725209D01* +G01X1563263Y5728073D01* +G01X1565172Y5731573D01* +G01X1567081Y5734118D01* +G01X1568672Y5735709D01* +G01X1570263Y5736982D01* +G01X1572172Y5738255D01* +G01X1574718Y5739527D01* +G01X1577899Y5740482D01* +G01X1580763Y5741118D01* +G01X1629127Y5741436D01* +G01X1677490Y5741118D01* +G01X1678127Y5740641D01* +G01X1678127Y5739845D01* +G01X1676854Y5734118D01* +G01X1676218Y5730618D01* +G01X1675263Y5725845D01* +G01X1674308Y5722027D01* +G01X1673036Y5715664D01* +G01X1672399Y5713118D01* +G01X1671127Y5706755D01* +G01X1669854Y5701027D01* +G01X1668581Y5694664D01* +G01X1667308Y5688936D01* +G01X1666036Y5682573D01* +G01X1664763Y5676846D01* +G01X1664127Y5673345D01* +G01X1663172Y5668573D01* +G01X1662218Y5664755D01* +G01X1660945Y5658391D01* +G01X1660308Y5655846D01* +G01X1659036Y5649482D01* +G01X1657763Y5643754D01* +G01X1656490Y5637391D01* +G01X1655218Y5631663D01* +G01X1653945Y5625300D01* +G01X1652672Y5619573D01* +G01X1652036Y5617027D01* +G01X1651081Y5614164D01* +G01X1649809Y5611300D01* +G01X1648536Y5609073D01* +G01X1647263Y5607164D01* +G01X1645672Y5605255D01* +G01X1644081Y5603664D01* +G01X1641854Y5601754D01* +G01X1639627Y5600164D01* +G01X1637718Y5599209D01* +G01X1635490Y5598255D01* +G01X1632945Y5597300D01* +G01X1630399Y5596664D01* +G01X1593172Y5596345D01* +G37* +G36* +G01X1680990Y5625857D02* +G01X1675581Y5626573D01* +G01X1676536Y5629754D01* +G01X1677490Y5633573D01* +G01X1678127Y5636754D01* +G01X1678763Y5639300D01* +G01X1679399Y5642800D01* +G01X1680354Y5647573D01* +G01X1681309Y5651391D01* +G01X1682581Y5657755D01* +G01X1683218Y5660300D01* +G01X1683854Y5663800D01* +G01X1684809Y5668573D01* +G01X1685763Y5672391D01* +G01X1686399Y5675573D01* +G01X1687036Y5678118D01* +G01X1687672Y5681618D01* +G01X1688627Y5686391D01* +G01X1689581Y5690209D01* +G01X1690218Y5693391D01* +G01X1690854Y5695936D01* +G01X1691490Y5699436D01* +G01X1692445Y5704209D01* +G01X1693400Y5708027D01* +G01X1694036Y5711209D01* +G01X1694672Y5713755D01* +G01X1695309Y5717255D01* +G01X1696263Y5722027D01* +G01X1697218Y5725845D01* +G01X1697854Y5729027D01* +G01X1698491Y5731573D01* +G01X1699763Y5737936D01* +G01X1700081Y5740164D01* +G01X1711933Y5741118D01* +G01X1747490Y5741436D01* +G01X1795854Y5741118D01* +G01X1798400Y5740800D01* +G01X1801263Y5740164D01* +G01X1804127Y5738891D01* +G01X1806990Y5736664D01* +G01X1808581Y5734118D01* +G01X1809536Y5731891D01* +G01X1810172Y5728709D01* +G01X1809854Y5725845D01* +G01X1809536Y5723618D01* +G01X1808899Y5720118D01* +G01X1807945Y5716300D01* +G01X1806672Y5709936D01* +G01X1806036Y5707391D01* +G01X1804763Y5701027D01* +G01X1803491Y5695300D01* +G01X1802854Y5691800D01* +G01X1801899Y5687027D01* +G01X1800945Y5683209D01* +G01X1800309Y5680027D01* +G01X1799672Y5677482D01* +G01X1799036Y5673982D01* +G01X1798081Y5669209D01* +G01X1797127Y5665391D01* +G01X1795854Y5659027D01* +G01X1795218Y5656482D01* +G01X1794581Y5652982D01* +G01X1793627Y5648209D01* +G01X1792672Y5644391D01* +G01X1791399Y5638027D01* +G01X1790763Y5635482D01* +G01X1789490Y5629118D01* +G01X1789172Y5626891D01* +G01X1783604Y5625936D01* +G01X1766900Y5625618D01* +G01X1744627Y5625618D01* +G01X1744945Y5627209D01* +G01X1745581Y5629754D01* +G01X1746218Y5633255D01* +G01X1747172Y5638027D01* +G01X1748127Y5641845D01* +G01X1748763Y5645027D01* +G01X1749399Y5647573D01* +G01X1750036Y5651073D01* +G01X1750991Y5655846D01* +G01X1751945Y5659664D01* +G01X1752581Y5662846D01* +G01X1753218Y5665391D01* +G01X1753854Y5668891D01* +G01X1754809Y5673664D01* +G01X1755763Y5677482D01* +G01X1756399Y5680664D01* +G01X1757036Y5683209D01* +G01X1757672Y5686709D01* +G01X1758627Y5691482D01* +G01X1759581Y5695300D01* +G01X1760218Y5698482D01* +G01X1760854Y5701027D01* +G01X1761490Y5704527D01* +G01X1762445Y5709300D01* +G01X1764036Y5715664D01* +G01X1765309Y5722027D01* +G01X1765627Y5724255D01* +G01X1762684Y5725209D01* +G01X1753854Y5725527D01* +G01X1741763Y5724891D01* +G01X1740809Y5722027D01* +G01X1739854Y5718209D01* +G01X1739218Y5715027D01* +G01X1738581Y5712482D01* +G01X1737945Y5708982D01* +G01X1736990Y5704209D01* +G01X1736036Y5700391D01* +G01X1735400Y5697209D01* +G01X1734763Y5694664D01* +G01X1734127Y5691164D01* +G01X1733172Y5686391D01* +G01X1732218Y5682573D01* +G01X1731581Y5679391D01* +G01X1730945Y5676846D01* +G01X1730309Y5673345D01* +G01X1729354Y5668573D01* +G01X1728400Y5664755D01* +G01X1727763Y5661573D01* +G01X1727127Y5659027D01* +G01X1726490Y5655527D01* +G01X1725536Y5650755D01* +G01X1724581Y5646936D01* +G01X1723945Y5643754D01* +G01X1723309Y5641209D01* +G01X1722036Y5634845D01* +G01X1720763Y5629118D01* +G01X1720445Y5626891D01* +G01X1714797Y5625936D01* +G01X1697854Y5625618D01* +G01X1680990Y5625857D01* +G37* +G36* +G01X1868718Y5625618D02* +G01X1819718Y5625936D01* +G01X1817491Y5626891D01* +G01X1814945Y5628164D01* +G01X1813036Y5629436D01* +G01X1811445Y5631027D01* +G01X1810172Y5632618D01* +G01X1809218Y5634527D01* +G01X1808263Y5637073D01* +G01X1807627Y5639618D01* +G01X1807945Y5643754D01* +G01X1808581Y5647573D01* +G01X1809854Y5653936D01* +G01X1811127Y5659664D01* +G01X1811763Y5663164D01* +G01X1812718Y5667936D01* +G01X1813672Y5671755D01* +G01X1814309Y5674936D01* +G01X1814547Y5675891D01* +G01X1858854Y5675891D01* +G01X1858854Y5673664D01* +G01X1870627Y5673345D01* +G01X1879377Y5673584D01* +G01X1882718Y5674300D01* +G01X1883672Y5676846D01* +G01X1884309Y5680027D01* +G01X1884945Y5682573D01* +G01X1886854Y5692118D01* +G01X1887809Y5696573D01* +G01X1888763Y5700391D01* +G01X1889399Y5703573D01* +G01X1890036Y5706118D01* +G01X1890672Y5709618D01* +G01X1891627Y5714391D01* +G01X1893218Y5720754D01* +G01X1893536Y5723618D01* +G01X1893536Y5725527D01* +G01X1883036Y5725527D01* +G01X1870945Y5725209D01* +G01X1869672Y5724414D01* +G01X1869036Y5722664D01* +G01X1868081Y5718209D01* +G01X1867127Y5714391D01* +G01X1866490Y5711209D01* +G01X1865854Y5708664D01* +G01X1863945Y5699118D01* +G01X1862991Y5694664D01* +G01X1862036Y5690845D01* +G01X1861400Y5687664D01* +G01X1860763Y5685118D01* +G01X1859490Y5678755D01* +G01X1858854Y5675891D01* +G01X1858854Y5675891D01* +G01X1814547Y5675891D01* +G01X1814945Y5677482D01* +G01X1815581Y5680982D01* +G01X1816536Y5685755D01* +G01X1817491Y5689573D01* +G01X1818763Y5695936D01* +G01X1819400Y5698482D01* +G01X1820036Y5701982D01* +G01X1820990Y5706755D01* +G01X1821945Y5710573D01* +G01X1823218Y5716936D01* +G01X1823854Y5719482D01* +G01X1824491Y5722664D01* +G01X1825445Y5726164D01* +G01X1826718Y5729027D01* +G01X1827990Y5731255D01* +G01X1829263Y5733164D01* +G01X1830854Y5735073D01* +G01X1833400Y5736982D01* +G01X1836581Y5738891D01* +G01X1839445Y5740164D01* +G01X1841990Y5740800D01* +G01X1844218Y5741118D01* +G01X1883354Y5741436D01* +G01X1923763Y5741118D01* +G01X1927581Y5740482D01* +G01X1930763Y5739527D01* +G01X1932990Y5738255D01* +G01X1934581Y5736982D01* +G01X1936172Y5735073D01* +G01X1937445Y5732527D01* +G01X1938081Y5729027D01* +G01X1937763Y5724573D01* +G01X1935854Y5715027D01* +G01X1934581Y5709300D01* +G01X1933309Y5702936D01* +G01X1932036Y5697209D01* +G01X1930763Y5690845D01* +G01X1929491Y5685118D01* +G01X1928218Y5678755D01* +G01X1926945Y5673027D01* +G01X1925672Y5666664D01* +G01X1924400Y5660936D01* +G01X1924081Y5658709D01* +G01X1915491Y5657755D01* +G01X1863865Y5657118D01* +G01X1855036Y5656164D01* +G01X1854081Y5652664D01* +G01X1852490Y5646300D01* +G01X1851854Y5643118D01* +G01X1851536Y5640891D01* +G01X1885900Y5640891D01* +G01X1911593Y5640652D01* +G01X1919945Y5639936D01* +G01X1919309Y5637391D01* +G01X1918672Y5634209D01* +G01X1918036Y5631663D01* +G01X1917400Y5628164D01* +G01X1917081Y5625618D01* +G01X1868718Y5625618D01* +G37* +G36* +G01X2000445Y5625618D02* +G01X1951445Y5625936D01* +G01X1949218Y5626891D01* +G01X1946672Y5628164D01* +G01X1944763Y5629436D01* +G01X1943172Y5631027D01* +G01X1941899Y5632618D01* +G01X1940945Y5634527D01* +G01X1939990Y5637073D01* +G01X1939354Y5639618D01* +G01X1939623Y5643118D01* +G01X1983900Y5643118D01* +G01X1984218Y5641209D01* +G01X1995991Y5640891D01* +G01X2007445Y5640891D01* +G01X2008081Y5642800D01* +G01X2009036Y5646300D01* +G01X2010309Y5652664D01* +G01X2010945Y5655209D01* +G01X2012218Y5661573D01* +G01X2013491Y5667300D01* +G01X2014127Y5670800D01* +G01X2015081Y5675573D01* +G01X2016036Y5679391D01* +G01X2016672Y5682573D01* +G01X2017309Y5685118D01* +G01X2018581Y5691482D01* +G01X2019854Y5697209D01* +G01X2020491Y5700709D01* +G01X2021445Y5705482D01* +G01X2022400Y5709300D01* +G01X2023036Y5712482D01* +G01X2023672Y5715027D01* +G01X2024945Y5721391D01* +G01X2025263Y5723936D01* +G01X2025263Y5725527D01* +G01X2001081Y5725527D01* +G01X2000763Y5722982D01* +G01X1999809Y5718209D01* +G01X1998854Y5714391D01* +G01X1998218Y5711209D01* +G01X1997581Y5708664D01* +G01X1996945Y5705164D01* +G01X1995991Y5700391D01* +G01X1995036Y5696573D01* +G01X1993763Y5690209D01* +G01X1993127Y5687664D01* +G01X1991854Y5681300D01* +G01X1990581Y5675573D01* +G01X1989945Y5672073D01* +G01X1988991Y5667300D01* +G01X1988036Y5663482D01* +G01X1987400Y5660300D01* +G01X1986763Y5657755D01* +G01X1985490Y5651391D01* +G01X1984218Y5645664D01* +G01X1983900Y5643118D01* +G01X1983900Y5643118D01* +G01X1939623Y5643118D01* +G01X1939672Y5643754D01* +G01X1940309Y5648209D01* +G01X1940945Y5650755D01* +G01X1941581Y5654255D01* +G01X1942536Y5659027D01* +G01X1943491Y5662846D01* +G01X1944127Y5666027D01* +G01X1944763Y5668573D01* +G01X1945400Y5672073D01* +G01X1946354Y5676846D01* +G01X1947945Y5683209D01* +G01X1948581Y5686709D01* +G01X1949536Y5691482D01* +G01X1950491Y5695300D01* +G01X1951127Y5698482D01* +G01X1951763Y5701027D01* +G01X1952400Y5704527D01* +G01X1953354Y5709300D01* +G01X1954945Y5715664D01* +G01X1956218Y5722027D01* +G01X1956854Y5724573D01* +G01X1957809Y5727754D01* +G01X1959400Y5730618D01* +G01X1960672Y5732845D01* +G01X1961945Y5734118D01* +G01X1963536Y5735391D01* +G01X1965127Y5736982D01* +G01X1966718Y5738255D01* +G01X1968627Y5739209D01* +G01X1971172Y5740164D01* +G01X1973718Y5740800D01* +G01X1975945Y5741118D01* +G01X2002672Y5741436D01* +G01X2022161Y5741675D01* +G01X2029081Y5742391D01* +G01X2030036Y5745573D01* +G01X2030672Y5748754D01* +G01X2031945Y5754482D01* +G01X2033218Y5760846D01* +G01X2034491Y5766573D01* +G01X2034809Y5768800D01* +G01X2040377Y5769755D01* +G01X2057081Y5770073D01* +G01X2079354Y5770073D01* +G01X2079036Y5768164D01* +G01X2078082Y5764027D01* +G01X2077127Y5760209D01* +G01X2075854Y5753845D01* +G01X2075218Y5751300D01* +G01X2073945Y5744936D01* +G01X2072672Y5739209D01* +G01X2071400Y5732845D01* +G01X2070127Y5727118D01* +G01X2069491Y5723618D01* +G01X2068536Y5718845D01* +G01X2067581Y5715027D01* +G01X2066309Y5708664D01* +G01X2065672Y5706118D01* +G01X2064400Y5699755D01* +G01X2063127Y5694027D01* +G01X2062491Y5690527D01* +G01X2061536Y5685755D01* +G01X2060581Y5681936D01* +G01X2059309Y5675573D01* +G01X2058672Y5673027D01* +G01X2057400Y5666664D01* +G01X2056127Y5660936D01* +G01X2054854Y5654573D01* +G01X2053581Y5648845D01* +G01X2052945Y5645345D01* +G01X2051990Y5640573D01* +G01X2051036Y5636754D01* +G01X2050400Y5633573D01* +G01X2049763Y5631027D01* +G01X2049127Y5627845D01* +G01X2048809Y5625618D01* +G01X2000445Y5625618D01* +G37* +G36* +G01X2107354Y5625618D02* +G01X2107672Y5626891D01* +G01X2108309Y5629118D01* +G01X2108945Y5632618D01* +G01X2109900Y5637391D01* +G01X2110854Y5641209D01* +G01X2111172Y5642800D01* +G01X2155718Y5642800D01* +G01X2156036Y5641209D01* +G01X2167809Y5640891D01* +G01X2179263Y5640891D01* +G01X2179900Y5642482D01* +G01X2180854Y5645664D01* +G01X2181491Y5648845D01* +G01X2182127Y5651391D01* +G01X2183400Y5657755D01* +G01X2184672Y5663482D01* +G01X2185309Y5666982D01* +G01X2186263Y5671755D01* +G01X2187218Y5675573D01* +G01X2187854Y5678755D01* +G01X2188491Y5681300D01* +G01X2189127Y5684800D01* +G01X2190082Y5689573D01* +G01X2191036Y5693391D01* +G01X2192309Y5699755D01* +G01X2192945Y5702300D01* +G01X2194218Y5708664D01* +G01X2195491Y5714391D01* +G01X2196763Y5720754D01* +G01X2197400Y5723618D01* +G01X2197718Y5725527D01* +G01X2185627Y5725527D01* +G01X2176479Y5725289D01* +G01X2173218Y5724573D01* +G01X2172582Y5722664D01* +G01X2171945Y5719164D01* +G01X2170991Y5714391D01* +G01X2170036Y5710573D01* +G01X2169400Y5707391D01* +G01X2168763Y5704845D01* +G01X2167491Y5698482D01* +G01X2166218Y5692755D01* +G01X2165582Y5689254D01* +G01X2164627Y5684482D01* +G01X2163672Y5680664D01* +G01X2163036Y5677482D01* +G01X2162400Y5674936D01* +G01X2161127Y5668573D01* +G01X2159854Y5662846D01* +G01X2159218Y5659345D01* +G01X2158263Y5654573D01* +G01X2157309Y5650755D01* +G01X2156672Y5647573D01* +G01X2156036Y5645027D01* +G01X2155718Y5642800D01* +G01X2155718Y5642800D01* +G01X2111172Y5642800D01* +G01X2112127Y5647573D01* +G01X2112763Y5650118D01* +G01X2114036Y5656482D01* +G01X2115309Y5662209D01* +G01X2115945Y5665709D01* +G01X2116900Y5670482D01* +G01X2117854Y5674300D01* +G01X2119127Y5680664D01* +G01X2119763Y5683209D01* +G01X2121036Y5689573D01* +G01X2122309Y5695300D01* +G01X2122945Y5698800D01* +G01X2123900Y5703573D01* +G01X2124854Y5707391D01* +G01X2126127Y5713755D01* +G01X2126763Y5716300D01* +G01X2128036Y5722664D01* +G01X2129309Y5728391D01* +G01X2130582Y5734754D01* +G01X2131854Y5740482D01* +G01X2132491Y5743982D01* +G01X2133445Y5748754D01* +G01X2134400Y5752573D01* +G01X2135036Y5755755D01* +G01X2135672Y5758300D01* +G01X2137582Y5767846D01* +G01X2137900Y5770073D01* +G01X2159854Y5770073D01* +G01X2176400Y5769834D01* +G01X2182127Y5769118D01* +G01X2181809Y5765936D01* +G01X2180854Y5762118D01* +G01X2179581Y5755755D01* +G01X2178945Y5753209D01* +G01X2177036Y5743664D01* +G01X2176718Y5741436D01* +G01X2201854Y5741436D01* +G01X2227945Y5741118D01* +G01X2231127Y5740482D01* +G01X2234945Y5739527D01* +G01X2237172Y5737936D01* +G01X2238763Y5736346D01* +G01X2240354Y5734436D01* +G01X2241627Y5730936D01* +G01X2241945Y5727118D01* +G01X2241309Y5722664D01* +G01X2240354Y5717573D01* +G01X2239400Y5713755D01* +G01X2238763Y5710573D01* +G01X2238127Y5708027D01* +G01X2237491Y5704527D01* +G01X2236536Y5699755D01* +G01X2235582Y5695936D01* +G01X2234309Y5689573D01* +G01X2233672Y5687027D01* +G01X2233036Y5683527D01* +G01X2232082Y5678755D01* +G01X2231127Y5674936D01* +G01X2229854Y5668573D01* +G01X2229218Y5666027D01* +G01X2227945Y5659664D01* +G01X2226672Y5653936D01* +G01X2226036Y5650755D01* +G01X2225082Y5646618D01* +G01X2223809Y5642800D01* +G01X2222218Y5639300D01* +G01X2219036Y5634845D01* +G01X2217127Y5632618D01* +G01X2215536Y5631345D01* +G01X2213309Y5629754D01* +G01X2210763Y5628164D01* +G01X2207900Y5626891D01* +G01X2205036Y5625936D01* +G01X2155718Y5625618D01* +G01X2107354Y5625618D01* +G37* +G36* +G01X2264138Y5596584D02* +G01X2255309Y5597300D01* +G01X2255945Y5599209D01* +G01X2256582Y5602391D01* +G01X2257536Y5606845D01* +G01X2258491Y5610664D01* +G01X2258809Y5612255D01* +G01X2281400Y5612255D01* +G01X2304627Y5612891D01* +G01X2305581Y5614482D01* +G01X2306854Y5620845D01* +G01X2307173Y5623709D01* +G01X2307173Y5625618D01* +G01X2282991Y5625618D01* +G01X2256582Y5625936D01* +G01X2252763Y5626891D01* +G01X2250218Y5628164D01* +G01X2248309Y5629436D01* +G01X2246081Y5631663D01* +G01X2244172Y5634527D01* +G01X2243218Y5636754D01* +G01X2242900Y5641527D01* +G01X2243218Y5646300D01* +G01X2243854Y5649800D01* +G01X2244809Y5654573D01* +G01X2245763Y5658391D01* +G01X2246400Y5661573D01* +G01X2247036Y5664118D01* +G01X2247673Y5667618D01* +G01X2248627Y5672391D01* +G01X2249582Y5676209D01* +G01X2250218Y5679391D01* +G01X2250854Y5681936D01* +G01X2251491Y5685436D01* +G01X2252445Y5690209D01* +G01X2253400Y5694027D01* +G01X2254036Y5697209D01* +G01X2254673Y5699755D01* +G01X2255309Y5703255D01* +G01X2256263Y5708027D01* +G01X2257218Y5711845D01* +G01X2257854Y5715027D01* +G01X2258491Y5717573D01* +G01X2259127Y5721073D01* +G01X2260081Y5725845D01* +G01X2261036Y5729664D01* +G01X2261673Y5732845D01* +G01X2262309Y5735391D01* +G01X2262945Y5738891D01* +G01X2263263Y5741436D01* +G01X2285218Y5741436D01* +G01X2307491Y5740800D01* +G01X2307173Y5737936D01* +G01X2306218Y5734118D01* +G01X2304945Y5727754D01* +G01X2304309Y5725209D01* +G01X2303672Y5721709D01* +G01X2302718Y5716936D01* +G01X2301763Y5713118D01* +G01X2300491Y5706755D01* +G01X2299854Y5704209D01* +G01X2299218Y5700709D01* +G01X2298263Y5695936D01* +G01X2297309Y5692118D01* +G01X2296036Y5685755D01* +G01X2295400Y5683209D01* +G01X2294127Y5676846D01* +G01X2292854Y5671118D01* +G01X2292218Y5667618D01* +G01X2291263Y5662846D01* +G01X2290309Y5659027D01* +G01X2289672Y5655846D01* +G01X2289036Y5653300D01* +G01X2287763Y5646936D01* +G01X2287127Y5643436D01* +G01X2286809Y5640891D01* +G01X2310991Y5640891D01* +G01X2311309Y5642482D01* +G01X2311945Y5645027D01* +G01X2313218Y5650755D01* +G01X2313854Y5654255D01* +G01X2314809Y5659027D01* +G01X2315763Y5662846D01* +G01X2317036Y5669209D01* +G01X2317672Y5671755D01* +G01X2318309Y5675254D01* +G01X2319263Y5680027D01* +G01X2320218Y5683846D01* +G01X2321491Y5690209D01* +G01X2322127Y5692755D01* +G01X2322763Y5696254D01* +G01X2323718Y5701027D01* +G01X2324672Y5704845D01* +G01X2325945Y5711209D01* +G01X2326581Y5713755D01* +G01X2327854Y5720118D01* +G01X2329127Y5725845D01* +G01X2330400Y5732209D01* +G01X2331672Y5737936D01* +G01X2331991Y5740164D01* +G01X2337559Y5741118D01* +G01X2354263Y5741436D01* +G01X2370888Y5741198D01* +G01X2376218Y5740482D01* +G01X2374945Y5734118D01* +G01X2373673Y5728391D01* +G01X2372400Y5722027D01* +G01X2371127Y5716300D01* +G01X2369854Y5709936D01* +G01X2368582Y5704209D01* +G01X2367945Y5700709D01* +G01X2366991Y5695936D01* +G01X2366036Y5692118D01* +G01X2364763Y5685755D01* +G01X2364127Y5683209D01* +G01X2362854Y5676846D01* +G01X2361582Y5671118D01* +G01X2360309Y5664755D01* +G01X2359036Y5659027D01* +G01X2357764Y5652664D01* +G01X2356491Y5646936D01* +G01X2355218Y5640573D01* +G01X2353945Y5634845D01* +G01X2353309Y5631345D01* +G01X2352354Y5626573D01* +G01X2351400Y5622754D01* +G01X2350763Y5619573D01* +G01X2349809Y5616073D01* +G01X2348536Y5612573D01* +G01X2347263Y5610027D01* +G01X2345991Y5608118D01* +G01X2343445Y5604936D01* +G01X2341218Y5602709D01* +G01X2338036Y5600482D01* +G01X2335172Y5598891D01* +G01X2331672Y5597618D01* +G01X2328491Y5596664D01* +G01X2291263Y5596345D01* +G01X2264138Y5596584D01* +G37* +G36* +G01X2410900Y5625618D02* +G01X2411536Y5627845D01* +G01X2412491Y5631663D01* +G01X2413763Y5638027D01* +G01X2414400Y5640573D01* +G01X2415672Y5646936D01* +G01X2416945Y5652664D01* +G01X2418218Y5659027D01* +G01X2419491Y5664755D01* +G01X2420127Y5668254D01* +G01X2421082Y5673027D01* +G01X2422036Y5676846D01* +G01X2423309Y5683209D01* +G01X2423945Y5685755D01* +G01X2425091Y5691482D01* +G01X2472945Y5691482D01* +G01X2472945Y5688936D01* +G01X2487263Y5688618D01* +G01X2502218Y5688936D01* +G01X2503491Y5690845D01* +G01X2504127Y5693391D01* +G01X2505400Y5699755D01* +G01X2506673Y5705482D01* +G01X2507309Y5708982D01* +G01X2508263Y5713755D01* +G01X2509218Y5717573D01* +G01X2509854Y5720754D01* +G01X2510491Y5723300D01* +G01X2511763Y5729664D01* +G01X2513036Y5735391D01* +G01X2514309Y5741754D01* +G01X2515582Y5747482D01* +G01X2515900Y5750345D01* +G01X2515900Y5752255D01* +G01X2501263Y5752255D01* +G01X2490127Y5752016D01* +G01X2485991Y5751300D01* +G01X2485036Y5748436D01* +G01X2484400Y5745573D01* +G01X2483764Y5742073D01* +G01X2482809Y5737300D01* +G01X2481854Y5733482D01* +G01X2480582Y5727118D01* +G01X2479945Y5724573D01* +G01X2478673Y5718209D01* +G01X2477400Y5712482D01* +G01X2476764Y5708982D01* +G01X2475809Y5704209D01* +G01X2474854Y5700391D01* +G01X2474218Y5697209D01* +G01X2473582Y5694664D01* +G01X2472945Y5691482D01* +G01X2472945Y5691482D01* +G01X2425091Y5691482D01* +G01X2425218Y5692118D01* +G01X2426491Y5697845D01* +G01X2427127Y5701345D01* +G01X2428082Y5706118D01* +G01X2429036Y5709936D01* +G01X2430309Y5716300D01* +G01X2430945Y5718845D01* +G01X2431582Y5722346D01* +G01X2432536Y5727118D01* +G01X2433491Y5730936D01* +G01X2434763Y5737300D01* +G01X2435400Y5739845D01* +G01X2436672Y5746209D01* +G01X2437309Y5749073D01* +G01X2438263Y5751936D01* +G01X2440809Y5757027D01* +G01X2442082Y5758936D01* +G01X2444627Y5762118D01* +G01X2446218Y5763709D01* +G01X2448763Y5765618D01* +G01X2451945Y5767527D01* +G01X2455445Y5768800D01* +G01X2458309Y5769755D01* +G01X2504445Y5770073D01* +G01X2551536Y5769436D01* +G01X2555036Y5768164D01* +G01X2558218Y5766573D01* +G01X2560445Y5764664D01* +G01X2561718Y5762755D01* +G01X2562673Y5760846D01* +G01X2563627Y5758618D01* +G01X2564263Y5755436D01* +G01X2563945Y5751300D01* +G01X2563309Y5747482D01* +G01X2562036Y5741118D01* +G01X2561400Y5738573D01* +G01X2560127Y5732209D01* +G01X2558854Y5726482D01* +G01X2558218Y5722982D01* +G01X2557263Y5718209D01* +G01X2556309Y5714391D01* +G01X2555036Y5708027D01* +G01X2554400Y5705482D01* +G01X2553127Y5699118D01* +G01X2551854Y5693391D01* +G01X2550582Y5687027D01* +G01X2549309Y5681300D01* +G01X2548672Y5677800D01* +G01X2547718Y5673027D01* +G01X2546763Y5669209D01* +G01X2545491Y5662846D01* +G01X2544854Y5660300D01* +G01X2543582Y5653936D01* +G01X2542309Y5648209D01* +G01X2541036Y5641845D01* +G01X2539763Y5636118D01* +G01X2539127Y5632618D01* +G01X2538173Y5627845D01* +G01X2537536Y5625618D01* +G01X2513673Y5625618D01* +G01X2489809Y5625936D01* +G01X2490127Y5627209D01* +G01X2490764Y5630709D01* +G01X2491718Y5635482D01* +G01X2492673Y5639300D01* +G01X2493945Y5645664D01* +G01X2494582Y5648209D01* +G01X2495218Y5651709D01* +G01X2496172Y5656482D01* +G01X2497127Y5660300D01* +G01X2497763Y5663482D01* +G01X2498400Y5666027D01* +G01X2498718Y5668891D01* +G01X2498718Y5670800D01* +G01X2484718Y5670800D01* +G01X2469764Y5670482D01* +G01X2468889Y5669686D01* +G01X2468172Y5667936D01* +G01X2467218Y5664118D01* +G01X2466582Y5660936D01* +G01X2465945Y5658391D01* +G01X2465309Y5654891D01* +G01X2464354Y5650118D01* +G01X2463400Y5646300D01* +G01X2462127Y5639936D01* +G01X2461491Y5637391D01* +G01X2459582Y5627845D01* +G01X2459263Y5625618D01* +G01X2410900Y5625618D01* +G37* +G36* +G01X2561638Y5625857D02* +G01X2556309Y5626573D01* +G01X2556945Y5630073D01* +G01X2557900Y5634845D01* +G01X2558854Y5638664D01* +G01X2560127Y5645027D01* +G01X2560763Y5647573D01* +G01X2562036Y5653936D01* +G01X2563309Y5659664D01* +G01X2563945Y5663164D01* +G01X2564900Y5667936D01* +G01X2565854Y5671755D01* +G01X2567127Y5678118D01* +G01X2567764Y5680664D01* +G01X2569036Y5687027D01* +G01X2570309Y5692755D01* +G01X2570945Y5696254D01* +G01X2571900Y5701027D01* +G01X2572854Y5704845D01* +G01X2574127Y5711209D01* +G01X2574764Y5713755D01* +G01X2576036Y5720118D01* +G01X2577309Y5725845D01* +G01X2577945Y5729346D01* +G01X2578900Y5734118D01* +G01X2579855Y5737936D01* +G01X2581127Y5744300D01* +G01X2581764Y5746845D01* +G01X2583036Y5753209D01* +G01X2584309Y5758936D01* +G01X2585582Y5765300D01* +G01X2586218Y5768164D01* +G01X2586536Y5770073D01* +G01X2608809Y5770073D01* +G01X2625434Y5769834D01* +G01X2630763Y5769118D01* +G01X2629491Y5763391D01* +G01X2628854Y5759891D01* +G01X2627900Y5755118D01* +G01X2626945Y5751300D01* +G01X2625673Y5744936D01* +G01X2625036Y5742391D01* +G01X2623763Y5736027D01* +G01X2622491Y5730300D01* +G01X2621854Y5726800D01* +G01X2620900Y5722027D01* +G01X2619945Y5718209D01* +G01X2618673Y5711845D01* +G01X2618036Y5709300D01* +G01X2616764Y5702936D01* +G01X2615491Y5697209D01* +G01X2614854Y5693709D01* +G01X2613900Y5688936D01* +G01X2612945Y5685118D01* +G01X2611673Y5678755D01* +G01X2611036Y5676209D01* +G01X2609764Y5669846D01* +G01X2608491Y5664118D01* +G01X2607854Y5660618D01* +G01X2606900Y5655846D01* +G01X2605945Y5652027D01* +G01X2604673Y5645664D01* +G01X2604036Y5643118D01* +G01X2602764Y5636754D01* +G01X2601491Y5631027D01* +G01X2600854Y5627845D01* +G01X2600536Y5625618D01* +G01X2578263Y5625618D01* +G01X2561638Y5625857D01* +G37* +G36* +G01X2683263Y5625618D02* +G01X2634264Y5625936D01* +G01X2632036Y5626891D01* +G01X2629491Y5628164D01* +G01X2627582Y5629436D01* +G01X2625991Y5631027D01* +G01X2624718Y5632618D01* +G01X2623445Y5635164D01* +G01X2622491Y5638027D01* +G01X2622173Y5640255D01* +G01X2622491Y5643754D01* +G01X2623127Y5647573D01* +G01X2623763Y5650755D01* +G01X2624400Y5653300D01* +G01X2625036Y5656800D01* +G01X2625991Y5661573D01* +G01X2626945Y5665391D01* +G01X2628218Y5671755D01* +G01X2628854Y5674300D01* +G01X2629109Y5675573D01* +G01X2673400Y5675573D01* +G01X2673400Y5673664D01* +G01X2685173Y5673345D01* +G01X2693923Y5673584D01* +G01X2697263Y5674300D01* +G01X2698218Y5676846D01* +G01X2698855Y5679391D01* +G01X2700764Y5688936D01* +G01X2701718Y5693391D01* +G01X2702673Y5697209D01* +G01X2703309Y5700391D01* +G01X2703945Y5702936D01* +G01X2704582Y5706436D01* +G01X2705536Y5711209D01* +G01X2706491Y5715027D01* +G01X2707127Y5718209D01* +G01X2707764Y5720754D01* +G01X2708082Y5723618D01* +G01X2708082Y5725527D01* +G01X2696309Y5725527D01* +G01X2687400Y5725289D01* +G01X2684218Y5724573D01* +G01X2683582Y5722664D01* +G01X2682945Y5719482D01* +G01X2681991Y5715027D01* +G01X2681036Y5711209D01* +G01X2680400Y5708027D01* +G01X2679764Y5705482D01* +G01X2679127Y5701982D01* +G01X2678173Y5697209D01* +G01X2676582Y5690845D01* +G01X2675945Y5687345D01* +G01X2674991Y5682573D01* +G01X2674036Y5678755D01* +G01X2673400Y5675573D01* +G01X2673400Y5675573D01* +G01X2629109Y5675573D01* +G01X2630127Y5680664D01* +G01X2631400Y5686391D01* +G01X2632036Y5689891D01* +G01X2632991Y5694664D01* +G01X2633945Y5698482D01* +G01X2634582Y5701664D01* +G01X2635218Y5704209D01* +G01X2636491Y5710573D01* +G01X2637763Y5716300D01* +G01X2638400Y5719482D01* +G01X2639355Y5723936D01* +G01X2640627Y5727754D01* +G01X2641900Y5730300D01* +G01X2643173Y5732209D01* +G01X2645082Y5734436D01* +G01X2647945Y5736982D01* +G01X2650491Y5738573D01* +G01X2652400Y5739527D01* +G01X2655582Y5740482D01* +G01X2658763Y5741118D01* +G01X2698536Y5741436D01* +G01X2738309Y5741118D01* +G01X2740536Y5740800D01* +G01X2743718Y5740164D01* +G01X2746582Y5738891D01* +G01X2748491Y5737618D01* +G01X2750082Y5736027D01* +G01X2751673Y5733482D01* +G01X2752627Y5729664D01* +G01X2752309Y5724573D01* +G01X2751673Y5720754D01* +G01X2750400Y5715027D01* +G01X2749127Y5708664D01* +G01X2747854Y5702936D01* +G01X2746582Y5696573D01* +G01X2745309Y5690845D01* +G01X2744673Y5687345D01* +G01X2743718Y5682573D01* +G01X2742764Y5678755D01* +G01X2741491Y5672391D01* +G01X2740854Y5669846D01* +G01X2739582Y5663482D01* +G01X2738945Y5659982D01* +G01X2738627Y5657436D01* +G01X2704900Y5657436D01* +G01X2670218Y5656800D01* +G01X2668945Y5654255D01* +G01X2666400Y5642800D01* +G01X2666082Y5640891D01* +G01X2734809Y5640891D01* +G01X2734491Y5639618D01* +G01X2733854Y5637391D01* +G01X2731945Y5627845D01* +G01X2731627Y5625618D01* +G01X2683263Y5625618D01* +G37* +G36* +G01X2752866Y5625857D02* +G01X2751036Y5626573D01* +G01X2752945Y5628164D01* +G01X2755491Y5631345D01* +G01X2761854Y5637709D01* +G01X2764400Y5640891D01* +G01X2770763Y5647255D01* +G01X2773945Y5651073D01* +G01X2780309Y5657436D01* +G01X2783491Y5661254D01* +G01X2788900Y5666664D01* +G01X2790809Y5669209D01* +G01X2795582Y5673982D01* +G01X2796139Y5674936D01* +G01X2795900Y5676527D01* +G01X2791127Y5690845D01* +G01X2790491Y5693391D01* +G01X2781900Y5719164D01* +G01X2779991Y5725527D01* +G01X2775218Y5739845D01* +G01X2774900Y5741436D01* +G01X2796536Y5741436D01* +G01X2819127Y5740800D01* +G01X2820400Y5738573D01* +G01X2821354Y5735073D01* +G01X2830264Y5708346D01* +G01X2830900Y5706993D01* +G01X2831536Y5706755D01* +G01X2833127Y5707709D01* +G01X2837900Y5712482D01* +G01X2840445Y5715664D01* +G01X2845218Y5720436D01* +G01X2849036Y5724891D01* +G01X2853809Y5729664D01* +G01X2856355Y5732845D01* +G01X2861127Y5737618D01* +G01X2863036Y5739845D01* +G01X2863991Y5741436D01* +G01X2873854Y5741436D01* +G01X2883718Y5740800D01* +G01X2882764Y5739527D01* +G01X2880218Y5736346D01* +G01X2873854Y5729982D01* +G01X2871309Y5726800D01* +G01X2864945Y5720436D01* +G01X2862400Y5717255D01* +G01X2854446Y5709300D01* +G01X2851900Y5706118D01* +G01X2845536Y5699755D01* +G01X2842991Y5696573D01* +G01X2838218Y5691800D01* +G01X2836945Y5690209D01* +G01X2836945Y5688300D01* +G01X2837582Y5685755D01* +G01X2846173Y5659982D01* +G01X2848082Y5653618D01* +G01X2855718Y5630709D01* +G01X2856673Y5627527D01* +G01X2856991Y5625618D01* +G01X2812445Y5625618D01* +G01X2812127Y5627209D01* +G01X2810218Y5632936D01* +G01X2809263Y5636436D01* +G01X2803218Y5654573D01* +G01X2802582Y5657118D01* +G01X2802184Y5658232D01* +G01X2801627Y5658391D01* +G01X2800036Y5657436D01* +G01X2796855Y5653618D01* +G01X2790491Y5647255D01* +G01X2787945Y5644073D01* +G01X2779991Y5636118D01* +G01X2777445Y5632936D01* +G01X2771082Y5626573D01* +G01X2768059Y5625857D01* +G01X2760264Y5625618D01* +G01X2752866Y5625857D01* +G37* +G36* +G01X2936855Y5625618D02* +G01X2887854Y5625936D01* +G01X2883400Y5628164D01* +G01X2881173Y5629754D01* +G01X2879582Y5631345D01* +G01X2877991Y5633255D01* +G01X2876718Y5635800D01* +G01X2876082Y5641209D01* +G01X2876201Y5643118D01* +G01X2919673Y5643118D01* +G01X2919673Y5641209D01* +G01X2931764Y5640891D01* +G01X2943536Y5640891D01* +G01X2944173Y5643118D01* +G01X2945127Y5646936D01* +G01X2945764Y5650118D01* +G01X2946400Y5652664D01* +G01X2948309Y5662209D01* +G01X2949264Y5666664D01* +G01X2950218Y5670482D01* +G01X2950855Y5673664D01* +G01X2951491Y5676209D01* +G01X2952764Y5682573D01* +G01X2954036Y5688300D01* +G01X2954355Y5691164D01* +G01X2954355Y5693073D01* +G01X2942582Y5693073D01* +G01X2933673Y5692755D01* +G01X2930491Y5691800D01* +G01X2929536Y5688300D01* +G01X2928582Y5684482D01* +G01X2927946Y5681300D01* +G01X2927309Y5678755D01* +G01X2926673Y5675254D01* +G01X2925718Y5670482D01* +G01X2924127Y5664118D01* +G01X2922218Y5654573D01* +G01X2921264Y5650118D01* +G01X2920309Y5646300D01* +G01X2919673Y5643118D01* +G01X2919673Y5643118D01* +G01X2876201Y5643118D01* +G01X2876400Y5646300D01* +G01X2878945Y5659027D01* +G01X2880218Y5664755D01* +G01X2881491Y5671118D01* +G01X2882764Y5676846D01* +G01X2884673Y5686391D01* +G01X2885627Y5690845D01* +G01X2886582Y5694027D01* +G01X2887536Y5696573D01* +G01X2888809Y5698800D01* +G01X2890082Y5700709D01* +G01X2892309Y5703255D01* +G01X2894536Y5705164D01* +G01X2896127Y5706118D01* +G01X2898036Y5707073D01* +G01X2900264Y5708027D01* +G01X2902491Y5708664D01* +G01X2930809Y5708982D01* +G01X2958173Y5708982D01* +G01X2958491Y5710573D01* +G01X2961036Y5720754D01* +G01X2961355Y5723618D01* +G01X2961355Y5725527D01* +G01X2915536Y5725527D01* +G01X2915855Y5728073D01* +G01X2916809Y5732845D01* +G01X2917764Y5736664D01* +G01X2918718Y5741436D01* +G01X2954036Y5741436D01* +G01X2991582Y5741118D01* +G01X2995400Y5740482D01* +G01X2998582Y5739527D01* +G01X3000809Y5738255D01* +G01X3002400Y5736982D01* +G01X3003991Y5735073D01* +G01X3005264Y5732527D01* +G01X3005900Y5728709D01* +G01X3005582Y5724573D01* +G01X3003036Y5711845D01* +G01X3002400Y5709300D01* +G01X3000491Y5699755D01* +G01X2999536Y5695300D01* +G01X2998582Y5691482D01* +G01X2996673Y5681936D01* +G01X2996036Y5679391D01* +G01X2994764Y5673027D01* +G01X2993491Y5667300D01* +G01X2992854Y5663800D01* +G01X2991900Y5659027D01* +G01X2990945Y5655209D01* +G01X2990309Y5652027D01* +G01X2989673Y5649482D01* +G01X2988400Y5643118D01* +G01X2987127Y5637391D01* +G01X2985218Y5627845D01* +G01X2984900Y5625618D01* +G01X2936855Y5625618D01* +G37* +G36* +G01X3028809Y5625618D02* +G01X3006536Y5626255D01* +G01X3007173Y5629118D01* +G01X3008127Y5632936D01* +G01X3008764Y5636118D01* +G01X3009400Y5638664D01* +G01X3010036Y5642164D01* +G01X3010991Y5646936D01* +G01X3011946Y5650755D01* +G01X3013218Y5657118D01* +G01X3013855Y5659664D01* +G01X3014491Y5663164D01* +G01X3015445Y5667936D01* +G01X3016400Y5671755D01* +G01X3017037Y5674936D01* +G01X3017673Y5677482D01* +G01X3018309Y5680982D01* +G01X3019264Y5685755D01* +G01X3020218Y5689573D01* +G01X3020855Y5692755D01* +G01X3021491Y5695300D01* +G01X3022127Y5698800D01* +G01X3023082Y5703573D01* +G01X3024037Y5707391D01* +G01X3024673Y5710573D01* +G01X3025309Y5713118D01* +G01X3026582Y5719482D01* +G01X3027855Y5725209D01* +G01X3029764Y5734754D01* +G01X3030718Y5739209D01* +G01X3031354Y5741436D01* +G01X3077809Y5741436D01* +G01X3126491Y5741118D01* +G01X3130309Y5740482D01* +G01X3133491Y5739527D01* +G01X3135718Y5738255D01* +G01X3137309Y5736982D01* +G01X3138900Y5735073D01* +G01X3140173Y5732527D01* +G01X3140809Y5729027D01* +G01X3140491Y5724573D01* +G01X3139855Y5721391D01* +G01X3138582Y5715664D01* +G01X3137946Y5712164D01* +G01X3136991Y5707391D01* +G01X3136037Y5703573D01* +G01X3135400Y5700391D01* +G01X3134764Y5697845D01* +G01X3134127Y5694345D01* +G01X3133173Y5689573D01* +G01X3132218Y5685755D01* +G01X3130946Y5679391D01* +G01X3130309Y5676846D01* +G01X3129673Y5673345D01* +G01X3128718Y5668573D01* +G01X3127764Y5664755D01* +G01X3126491Y5658391D01* +G01X3125855Y5655846D01* +G01X3125218Y5652345D01* +G01X3124264Y5647573D01* +G01X3123309Y5643754D01* +G01X3122673Y5640573D01* +G01X3122037Y5638027D01* +G01X3120764Y5631663D01* +G01X3120127Y5628164D01* +G01X3119809Y5625618D01* +G01X3098491Y5625618D01* +G01X3076218Y5625936D01* +G01X3075661Y5626732D01* +G01X3075900Y5628482D01* +G01X3076855Y5632300D01* +G01X3077491Y5635482D01* +G01X3078127Y5638027D01* +G01X3078764Y5641527D01* +G01X3079718Y5646300D01* +G01X3080673Y5650118D01* +G01X3081309Y5653300D01* +G01X3081945Y5655846D01* +G01X3082582Y5659345D01* +G01X3083537Y5664118D01* +G01X3084491Y5667936D01* +G01X3085127Y5671118D01* +G01X3085764Y5673664D01* +G01X3086400Y5677164D01* +G01X3087355Y5681936D01* +G01X3088309Y5685755D01* +G01X3088945Y5688936D01* +G01X3089582Y5691482D01* +G01X3090218Y5694982D01* +G01X3091173Y5699755D01* +G01X3092127Y5703573D01* +G01X3092764Y5706755D01* +G01X3093400Y5709300D01* +G01X3094673Y5715664D01* +G01X3095945Y5721391D01* +G01X3096264Y5723936D01* +G01X3096264Y5725527D01* +G01X3085127Y5725527D01* +G01X3073036Y5725209D01* +G01X3071764Y5723300D01* +G01X3071127Y5720754D01* +G01X3070491Y5717255D01* +G01X3069537Y5712482D01* +G01X3068582Y5708664D01* +G01X3067945Y5705482D01* +G01X3067309Y5702936D01* +G01X3066673Y5699436D01* +G01X3065718Y5694664D01* +G01X3064764Y5690845D01* +G01X3064127Y5687664D01* +G01X3063491Y5685118D01* +G01X3062855Y5681618D01* +G01X3061900Y5676846D01* +G01X3060945Y5673027D01* +G01X3060309Y5669846D01* +G01X3059673Y5667300D01* +G01X3059036Y5663800D01* +G01X3058082Y5659027D01* +G01X3057127Y5655209D01* +G01X3056491Y5652027D01* +G01X3055855Y5649482D01* +G01X3055218Y5645982D01* +G01X3054264Y5641209D01* +G01X3053309Y5637391D01* +G01X3052673Y5634209D01* +G01X3052036Y5631663D01* +G01X3051400Y5628164D01* +G01X3051082Y5625618D01* +G01X3028809Y5625618D01* +G37* +G36* +G01X3199991Y5625618D02* +G01X3150991Y5625936D01* +G01X3148764Y5626891D01* +G01X3146218Y5628164D01* +G01X3144309Y5629436D01* +G01X3142082Y5631663D01* +G01X3140491Y5634209D01* +G01X3139536Y5636436D01* +G01X3138900Y5640891D01* +G01X3139091Y5643754D01* +G01X3183127Y5643754D01* +G01X3183127Y5641209D01* +G01X3194900Y5640891D01* +G01X3203650Y5641130D01* +G01X3206991Y5641845D01* +G01X3207945Y5644391D01* +G01X3209218Y5650755D01* +G01X3209855Y5653300D01* +G01X3211127Y5659664D01* +G01X3212400Y5665391D01* +G01X3213036Y5668891D01* +G01X3213991Y5673664D01* +G01X3214945Y5677482D01* +G01X3215582Y5680664D01* +G01X3216218Y5683209D01* +G01X3217491Y5689573D01* +G01X3218764Y5695300D01* +G01X3219400Y5698800D01* +G01X3220355Y5703573D01* +G01X3221309Y5707391D01* +G01X3221946Y5710573D01* +G01X3222582Y5713118D01* +G01X3223855Y5719482D01* +G01X3224491Y5722982D01* +G01X3224809Y5725527D01* +G01X3213036Y5725527D01* +G01X3204048Y5725289D01* +G01X3200627Y5724573D01* +G01X3199673Y5721073D01* +G01X3198718Y5716300D01* +G01X3197764Y5712482D01* +G01X3197127Y5709300D01* +G01X3196491Y5706755D01* +G01X3195218Y5700391D01* +G01X3193945Y5694664D01* +G01X3193309Y5691164D01* +G01X3192355Y5686391D01* +G01X3191400Y5682573D01* +G01X3190764Y5679391D01* +G01X3190127Y5676846D01* +G01X3188855Y5670482D01* +G01X3187582Y5664755D01* +G01X3186945Y5661254D01* +G01X3185991Y5656482D01* +G01X3185036Y5652664D01* +G01X3184400Y5649482D01* +G01X3183764Y5646936D01* +G01X3183127Y5643754D01* +G01X3183127Y5643754D01* +G01X3139091Y5643754D01* +G01X3139218Y5645664D01* +G01X3141127Y5655209D01* +G01X3141764Y5657755D01* +G01X3142400Y5661254D01* +G01X3143355Y5666027D01* +G01X3144309Y5669846D01* +G01X3144946Y5673027D01* +G01X3145582Y5675573D01* +G01X3146218Y5679073D01* +G01X3147173Y5683846D01* +G01X3148764Y5690209D01* +G01X3149400Y5693709D01* +G01X3150355Y5698482D01* +G01X3151309Y5702300D01* +G01X3151946Y5705482D01* +G01X3152582Y5708027D01* +G01X3153855Y5714391D01* +G01X3155127Y5720118D01* +G01X3155764Y5723300D01* +G01X3156718Y5726482D01* +G01X3157673Y5728709D01* +G01X3159264Y5731573D01* +G01X3161173Y5734118D01* +G01X3162764Y5735709D01* +G01X3164355Y5736982D01* +G01X3166264Y5738255D01* +G01X3168809Y5739527D01* +G01X3171991Y5740482D01* +G01X3174855Y5741118D01* +G01X3202218Y5741436D01* +G01X3228627Y5741436D01* +G01X3228946Y5743664D01* +G01X3229582Y5746845D01* +G01X3230855Y5752573D01* +G01X3232127Y5758936D01* +G01X3233400Y5764664D01* +G01X3234037Y5767846D01* +G01X3234355Y5770073D01* +G01X3256309Y5770073D01* +G01X3278264Y5769755D01* +G01X3277946Y5767209D01* +G01X3277309Y5764027D01* +G01X3276037Y5758300D01* +G01X3275400Y5754800D01* +G01X3274446Y5750027D01* +G01X3273491Y5746209D01* +G01X3272218Y5739845D01* +G01X3271582Y5737300D01* +G01X3270946Y5733800D01* +G01X3269991Y5729027D01* +G01X3269037Y5725209D01* +G01X3267764Y5718845D01* +G01X3267127Y5716300D01* +G01X3265855Y5709936D01* +G01X3264582Y5704209D01* +G01X3263946Y5700709D01* +G01X3262991Y5695936D01* +G01X3262037Y5692118D01* +G01X3260764Y5685755D01* +G01X3260127Y5683209D01* +G01X3258855Y5676846D01* +G01X3257582Y5671118D01* +G01X3256946Y5667618D01* +G01X3255991Y5662846D01* +G01X3255037Y5659027D01* +G01X3253764Y5652664D01* +G01X3253127Y5650118D01* +G01X3252491Y5646618D01* +G01X3251536Y5641845D01* +G01X3250582Y5638027D01* +G01X3249309Y5631663D01* +G01X3248673Y5629118D01* +G01X3248355Y5626891D01* +G01X3236264Y5625936D01* +G01X3199991Y5625618D01* +G37* +G36* +G01X3269355Y5625618D02* +G01X3269673Y5627209D01* +G01X3270309Y5629754D01* +G01X3271582Y5635482D01* +G01X3272218Y5638982D01* +G01X3273173Y5643754D01* +G01X3274127Y5647573D01* +G01X3274764Y5650755D01* +G01X3275400Y5653300D01* +G01X3276037Y5656800D01* +G01X3276991Y5661573D01* +G01X3277946Y5665391D01* +G01X3279218Y5671755D01* +G01X3279855Y5674300D01* +G01X3281127Y5680664D01* +G01X3282400Y5686391D01* +G01X3283036Y5689891D01* +G01X3283991Y5694664D01* +G01X3284946Y5698482D01* +G01X3285582Y5701664D01* +G01X3286218Y5704209D01* +G01X3287491Y5710573D01* +G01X3288764Y5716300D01* +G01X3289400Y5719482D01* +G01X3290355Y5723936D01* +G01X3291628Y5727754D01* +G01X3292900Y5730300D01* +G01X3294173Y5732209D01* +G01X3296082Y5734436D01* +G01X3298946Y5736982D01* +G01X3301491Y5738573D01* +G01X3303400Y5739527D01* +G01X3306582Y5740482D01* +G01X3309764Y5741118D01* +G01X3346355Y5741436D01* +G01X3381991Y5741436D01* +G01X3381673Y5739845D01* +G01X3381037Y5737300D01* +G01X3379127Y5727754D01* +G01X3378809Y5725527D01* +G01X3357491Y5725527D01* +G01X3335537Y5724891D01* +G01X3334582Y5722664D01* +G01X3333946Y5720118D01* +G01X3333309Y5716618D01* +G01X3332355Y5711845D01* +G01X3331400Y5708027D01* +G01X3330764Y5704845D01* +G01X3330127Y5702300D01* +G01X3329491Y5698800D01* +G01X3328537Y5694027D01* +G01X3327582Y5690209D01* +G01X3326946Y5687027D01* +G01X3326309Y5684482D01* +G01X3324400Y5674936D01* +G01X3323446Y5670482D01* +G01X3322491Y5666664D01* +G01X3321855Y5663482D01* +G01X3321218Y5660936D01* +G01X3320582Y5657436D01* +G01X3319627Y5652664D01* +G01X3318673Y5648845D01* +G01X3318036Y5645664D01* +G01X3317400Y5643118D01* +G01X3316127Y5636754D01* +G01X3314855Y5631027D01* +G01X3314218Y5627845D01* +G01X3313900Y5625618D01* +G01X3269355Y5625618D01* +G37* +G36* +G01X3409991Y5625618D02* +G01X3410309Y5626891D01* +G01X3410946Y5629118D01* +G01X3412218Y5635482D01* +G01X3413491Y5641209D01* +G01X3414764Y5647573D01* +G01X3416036Y5653300D01* +G01X3416673Y5656800D01* +G01X3417628Y5661573D01* +G01X3419218Y5667936D01* +G01X3420491Y5674300D01* +G01X3421127Y5677800D01* +G01X3422082Y5682573D01* +G01X3423036Y5686391D01* +G01X3424309Y5692755D01* +G01X3424946Y5695300D01* +G01X3426218Y5701664D01* +G01X3427491Y5707391D01* +G01X3428127Y5710891D01* +G01X3429082Y5715664D01* +G01X3430036Y5719482D01* +G01X3431309Y5725845D01* +G01X3431946Y5728391D01* +G01X3433218Y5734754D01* +G01X3434491Y5740482D01* +G01X3435764Y5746845D01* +G01X3437037Y5752573D01* +G01X3438309Y5758936D01* +G01X3439582Y5764664D01* +G01X3440218Y5767846D01* +G01X3440537Y5770073D01* +G01X3464400Y5770073D01* +G01X3488264Y5769755D01* +G01X3487946Y5767209D01* +G01X3487309Y5764027D01* +G01X3486037Y5758300D01* +G01X3484764Y5751936D01* +G01X3483491Y5746209D01* +G01X3482218Y5739845D01* +G01X3480946Y5734118D01* +G01X3479673Y5727754D01* +G01X3478400Y5722027D01* +G01X3477128Y5715664D01* +G01X3475855Y5709936D01* +G01X3475218Y5706436D01* +G01X3474264Y5701664D01* +G01X3473309Y5697845D01* +G01X3472673Y5694664D01* +G01X3472673Y5692118D01* +G01X3473071Y5691561D01* +G01X3473627Y5691800D01* +G01X3475218Y5693073D01* +G01X3477446Y5695300D01* +G01X3479355Y5697845D01* +G01X3485718Y5704209D01* +G01X3488264Y5707391D01* +G01X3493037Y5712164D01* +G01X3495582Y5715346D01* +G01X3501946Y5721709D01* +G01X3505764Y5726164D01* +G01X3511173Y5731573D01* +G01X3513082Y5734118D01* +G01X3519446Y5740482D01* +G01X3521991Y5743664D01* +G01X3526764Y5748436D01* +G01X3530582Y5752891D01* +G01X3535991Y5758300D01* +G01X3537900Y5760846D01* +G01X3544264Y5767209D01* +G01X3545855Y5769118D01* +G01X3548877Y5769834D01* +G01X3556037Y5770073D01* +G01X3566219Y5769755D01* +G01X3566696Y5769357D01* +G01X3566219Y5768800D01* +G01X3559855Y5762436D01* +G01X3556037Y5757982D01* +G01X3550628Y5752573D01* +G01X3548718Y5750027D01* +G01X3542355Y5743664D01* +G01X3539809Y5740482D01* +G01X3535036Y5735709D01* +G01X3531218Y5731255D01* +G01X3525809Y5725845D01* +G01X3523900Y5723300D01* +G01X3517537Y5716936D01* +G01X3514991Y5713755D01* +G01X3510218Y5708982D01* +G01X3509582Y5707709D01* +G01X3510218Y5705482D01* +G01X3527400Y5653936D01* +G01X3528355Y5650436D01* +G01X3536628Y5625618D01* +G01X3512446Y5625618D01* +G01X3494230Y5625936D01* +G01X3487946Y5626891D01* +G01X3486991Y5629436D01* +G01X3474582Y5666664D01* +G01X3474025Y5667698D01* +G01X3472991Y5667618D01* +G01X3470764Y5666345D01* +G01X3467582Y5663164D01* +G01X3465991Y5661254D01* +G01X3465037Y5659027D01* +G01X3463764Y5652664D01* +G01X3462491Y5646936D01* +G01X3461855Y5643436D01* +G01X3460900Y5638664D01* +G01X3459946Y5634845D01* +G01X3459309Y5631663D01* +G01X3458673Y5629118D01* +G01X3458355Y5626891D01* +G01X3452309Y5625936D01* +G01X3434173Y5625618D01* +G01X3409991Y5625618D01* +G37* +G36* +G01X3607582Y5625618D02* +G01X3567173Y5625936D01* +G01X3564946Y5626891D01* +G01X3562400Y5628164D01* +G01X3560491Y5629436D01* +G01X3558264Y5631663D01* +G01X3556673Y5634209D01* +G01X3555718Y5636436D01* +G01X3555082Y5640891D01* +G01X3555294Y5644073D01* +G01X3599309Y5644073D01* +G01X3599309Y5641209D01* +G01X3611082Y5640891D01* +G01X3622855Y5641527D01* +G01X3623809Y5644391D01* +G01X3624764Y5648209D01* +G01X3625400Y5651391D01* +G01X3626037Y5653936D01* +G01X3626673Y5657436D01* +G01X3627628Y5662209D01* +G01X3628582Y5666027D01* +G01X3629218Y5669209D01* +G01X3629855Y5671755D01* +G01X3630491Y5675254D01* +G01X3631446Y5680027D01* +G01X3633037Y5686391D01* +G01X3633673Y5689891D01* +G01X3634628Y5694664D01* +G01X3635582Y5698482D01* +G01X3636218Y5701664D01* +G01X3636855Y5704209D01* +G01X3637491Y5707709D01* +G01X3638446Y5712482D01* +G01X3639400Y5716300D01* +G01X3640037Y5719482D01* +G01X3640673Y5722027D01* +G01X3640991Y5724255D01* +G01X3638048Y5725209D01* +G01X3629218Y5725527D01* +G01X3620230Y5725209D01* +G01X3616809Y5724255D01* +G01X3615855Y5721391D01* +G01X3615218Y5718209D01* +G01X3614582Y5715664D01* +G01X3613946Y5712164D01* +G01X3612991Y5707391D01* +G01X3612037Y5703573D01* +G01X3611400Y5700391D01* +G01X3610764Y5697845D01* +G01X3610128Y5694345D01* +G01X3609173Y5689573D01* +G01X3607582Y5683209D01* +G01X3606946Y5679709D01* +G01X3605991Y5674936D01* +G01X3605037Y5671118D01* +G01X3604400Y5667936D01* +G01X3603764Y5665391D01* +G01X3603128Y5661891D01* +G01X3602173Y5657118D01* +G01X3601218Y5653300D01* +G01X3600582Y5650118D01* +G01X3599946Y5647573D01* +G01X3599309Y5644073D01* +G01X3599309Y5644073D01* +G01X3555294Y5644073D01* +G01X3555400Y5645664D01* +G01X3557309Y5655209D01* +G01X3557946Y5657755D01* +G01X3559219Y5664118D01* +G01X3560491Y5669846D01* +G01X3561128Y5673345D01* +G01X3562082Y5678118D01* +G01X3563037Y5681936D01* +G01X3563673Y5685118D01* +G01X3564309Y5687664D01* +G01X3564946Y5691164D01* +G01X3565900Y5695936D01* +G01X3566855Y5699755D01* +G01X3568128Y5706118D01* +G01X3568764Y5708664D01* +G01X3570673Y5718209D01* +G01X3571627Y5722664D01* +G01X3572900Y5726800D01* +G01X3574491Y5730300D01* +G01X3576082Y5732527D01* +G01X3577355Y5734118D01* +G01X3579582Y5736346D01* +G01X3582446Y5738255D01* +G01X3584991Y5739527D01* +G01X3588173Y5740482D01* +G01X3591037Y5741118D01* +G01X3630491Y5741436D01* +G01X3671219Y5741118D01* +G01X3675037Y5740482D01* +G01X3678219Y5739527D01* +G01X3680446Y5738255D01* +G01X3682037Y5736982D01* +G01X3683628Y5734754D01* +G01X3684900Y5731891D01* +G01X3685537Y5729346D01* +G01X3685219Y5726482D01* +G01X3684582Y5722664D01* +G01X3683946Y5719482D01* +G01X3683310Y5715982D01* +G01X3682355Y5711209D01* +G01X3681400Y5707391D01* +G01X3680128Y5701027D01* +G01X3679491Y5698482D01* +G01X3676946Y5685755D01* +G01X3675673Y5680027D01* +G01X3674400Y5673664D01* +G01X3673128Y5667936D01* +G01X3671855Y5661573D01* +G01X3670582Y5655846D01* +G01X3669309Y5649482D01* +G01X3668673Y5646618D01* +G01X3667718Y5643754D01* +G01X3665173Y5638664D01* +G01X3663900Y5636436D01* +G01X3662309Y5634527D01* +G01X3659128Y5631345D01* +G01X3656900Y5629754D01* +G01X3654673Y5628482D01* +G01X3652764Y5627527D01* +G01X3650537Y5626573D01* +G01X3648309Y5625936D01* +G01X3607582Y5625618D01* +G37* +G36* +G01X3685537Y5625618D02* +G01X3686173Y5626891D01* +G01X3687128Y5630391D01* +G01X3687764Y5633573D01* +G01X3689037Y5639300D01* +G01X3689673Y5642800D01* +G01X3690627Y5647573D01* +G01X3691582Y5651391D01* +G01X3692219Y5654573D01* +G01X3692855Y5657118D01* +G01X3693491Y5660618D01* +G01X3694446Y5665391D01* +G01X3695400Y5669209D01* +G01X3696673Y5675573D01* +G01X3697309Y5678118D01* +G01X3698582Y5684482D01* +G01X3699855Y5690209D01* +G01X3700491Y5693709D01* +G01X3701446Y5698482D01* +G01X3702400Y5702300D01* +G01X3703037Y5705482D01* +G01X3703673Y5708027D01* +G01X3704946Y5714391D01* +G01X3706855Y5722982D01* +G01X3707809Y5726800D01* +G01X3709082Y5729664D01* +G01X3710355Y5731573D01* +G01X3712900Y5734754D01* +G01X3715128Y5736664D01* +G01X3717355Y5738255D01* +G01X3719264Y5739209D01* +G01X3721809Y5740164D01* +G01X3724355Y5740800D01* +G01X3726582Y5741118D01* +G01X3763173Y5741436D01* +G01X3789821Y5741277D01* +G01X3798491Y5740800D01* +G01X3797855Y5737936D01* +G01X3797219Y5734754D01* +G01X3795946Y5729027D01* +G01X3795628Y5726800D01* +G01X3790378Y5725845D01* +G01X3774628Y5725527D01* +G01X3752673Y5725209D01* +G01X3751400Y5723936D01* +G01X3750764Y5720436D01* +G01X3749809Y5715664D01* +G01X3748855Y5711845D01* +G01X3748218Y5708664D01* +G01X3747582Y5706118D01* +G01X3746946Y5702618D01* +G01X3745991Y5697845D01* +G01X3745037Y5694027D01* +G01X3744400Y5690845D01* +G01X3743764Y5688300D01* +G01X3743128Y5684800D01* +G01X3742173Y5680027D01* +G01X3741218Y5676209D01* +G01X3740582Y5673027D01* +G01X3739946Y5670482D01* +G01X3738037Y5660936D01* +G01X3737082Y5656482D01* +G01X3736128Y5652664D01* +G01X3735491Y5649482D01* +G01X3734855Y5646936D01* +G01X3734218Y5643436D01* +G01X3733264Y5638664D01* +G01X3732309Y5634845D01* +G01X3731673Y5631663D01* +G01X3731037Y5629118D01* +G01X3730719Y5626891D01* +G01X3725071Y5625936D01* +G01X3708128Y5625618D01* +G01X3685537Y5625618D01* +G37* +G36* +G01X3842400Y5625618D02* +G01X3800718Y5626255D01* +G01X3797537Y5627845D01* +G01X3794991Y5629436D01* +G01X3792764Y5631663D01* +G01X3791173Y5634209D01* +G01X3790219Y5636754D01* +G01X3789582Y5639936D01* +G01X3789582Y5642482D01* +G01X3789673Y5643118D01* +G01X3833810Y5643118D01* +G01X3834128Y5641209D01* +G01X3845582Y5640891D01* +G01X3857355Y5641527D01* +G01X3858309Y5643754D01* +G01X3858946Y5646300D01* +G01X3860855Y5655846D01* +G01X3861810Y5660300D01* +G01X3862764Y5664118D01* +G01X3863400Y5667300D01* +G01X3864037Y5669846D01* +G01X3864673Y5673345D01* +G01X3865628Y5678118D01* +G01X3866582Y5681936D01* +G01X3867218Y5685118D01* +G01X3867855Y5687664D01* +G01X3868491Y5691164D01* +G01X3869446Y5695936D01* +G01X3870400Y5699755D01* +G01X3871037Y5702936D01* +G01X3871673Y5705482D01* +G01X3872309Y5708982D01* +G01X3873264Y5713755D01* +G01X3874855Y5720118D01* +G01X3875491Y5723300D01* +G01X3875809Y5725527D01* +G01X3864037Y5725527D01* +G01X3855048Y5725289D01* +G01X3851628Y5724573D01* +G01X3850673Y5722664D01* +G01X3850037Y5719164D01* +G01X3849082Y5714391D01* +G01X3847491Y5708027D01* +G01X3846855Y5704527D01* +G01X3845900Y5699755D01* +G01X3844946Y5695936D01* +G01X3844309Y5692755D01* +G01X3843673Y5690209D01* +G01X3843037Y5686709D01* +G01X3842082Y5681936D01* +G01X3841128Y5678118D01* +G01X3840491Y5674936D01* +G01X3839855Y5672391D01* +G01X3839219Y5668891D01* +G01X3838264Y5664118D01* +G01X3836673Y5657755D01* +G01X3835400Y5651391D01* +G01X3834128Y5645664D01* +G01X3833810Y5643118D01* +G01X3833810Y5643118D01* +G01X3789673Y5643118D01* +G01X3790219Y5646936D01* +G01X3791491Y5653300D01* +G01X3792764Y5659027D01* +G01X3793400Y5662527D01* +G01X3794355Y5667300D01* +G01X3795310Y5671118D01* +G01X3795946Y5674300D01* +G01X3796582Y5676846D01* +G01X3797219Y5680345D01* +G01X3798173Y5685118D01* +G01X3799128Y5688936D01* +G01X3800400Y5695300D01* +G01X3801037Y5697845D01* +G01X3802310Y5704209D01* +G01X3803582Y5709936D01* +G01X3804219Y5713436D01* +G01X3805173Y5718209D01* +G01X3807082Y5725845D01* +G01X3808355Y5729027D01* +G01X3809310Y5730936D01* +G01X3810582Y5732527D01* +G01X3814400Y5736346D01* +G01X3817264Y5738255D01* +G01X3819491Y5739527D01* +G01X3822673Y5740482D01* +G01X3825855Y5741118D01* +G01X3864991Y5741436D01* +G01X3906037Y5741118D01* +G01X3911128Y5740164D01* +G01X3913991Y5738891D01* +G01X3915582Y5737618D01* +G01X3917173Y5736027D01* +G01X3918764Y5733482D01* +G01X3919480Y5731414D01* +G01X3919718Y5728391D01* +G01X3919400Y5723936D01* +G01X3916855Y5711209D01* +G01X3915582Y5705482D01* +G01X3914310Y5699118D01* +G01X3913037Y5693391D01* +G01X3912400Y5689891D01* +G01X3911446Y5685118D01* +G01X3910491Y5681300D01* +G01X3909219Y5674936D01* +G01X3908582Y5672391D01* +G01X3907310Y5666027D01* +G01X3906673Y5662527D01* +G01X3905719Y5657755D01* +G01X3904764Y5653936D01* +G01X3904128Y5650755D01* +G01X3902855Y5645664D01* +G01X3901900Y5642482D01* +G01X3900310Y5639300D01* +G01X3897128Y5634845D01* +G01X3895219Y5632618D01* +G01X3893628Y5631345D01* +G01X3891400Y5629754D01* +G01X3888855Y5628164D01* +G01X3885991Y5626891D01* +G01X3883128Y5625936D01* +G01X3842400Y5625618D01* +G37* +G36* +G01X3969355Y5625618D02* +G01X3933082Y5625936D01* +G01X3930855Y5626891D01* +G01X3927673Y5628482D01* +G01X3925446Y5630391D01* +G01X3923855Y5632618D01* +G01X3922264Y5635800D01* +G01X3921310Y5638664D01* +G01X3920991Y5640891D01* +G01X3921946Y5647573D01* +G01X3923219Y5653300D01* +G01X3923855Y5656800D01* +G01X3924809Y5661573D01* +G01X3925764Y5665391D01* +G01X3926400Y5668573D01* +G01X3927037Y5671118D01* +G01X3927673Y5674618D01* +G01X3928628Y5679391D01* +G01X3929582Y5683209D01* +G01X3930855Y5689573D01* +G01X3931491Y5692118D01* +G01X3932128Y5695618D01* +G01X3933082Y5700391D01* +G01X3934037Y5704209D01* +G01X3935310Y5710573D01* +G01X3935946Y5713118D01* +G01X3937219Y5719482D01* +G01X3937855Y5722346D01* +G01X3938810Y5726164D01* +G01X3940082Y5729027D01* +G01X3941673Y5731573D01* +G01X3943264Y5733800D01* +G01X3944537Y5735073D01* +G01X3946764Y5736982D01* +G01X3949309Y5738573D01* +G01X3951219Y5739527D01* +G01X3954400Y5740482D01* +G01X3957582Y5741118D01* +G01X3994173Y5741436D01* +G01X4029809Y5741436D01* +G01X4029491Y5739527D01* +G01X4027582Y5730936D01* +G01X4026946Y5727754D01* +G01X4026628Y5725527D01* +G01X4005310Y5725527D01* +G01X3983355Y5724891D01* +G01X3982400Y5722664D01* +G01X3981764Y5720118D01* +G01X3981128Y5716618D01* +G01X3980173Y5711845D01* +G01X3979219Y5708027D01* +G01X3978582Y5704845D01* +G01X3977946Y5702300D01* +G01X3977309Y5698800D01* +G01X3976355Y5694027D01* +G01X3975400Y5690209D01* +G01X3974764Y5687027D01* +G01X3974128Y5684482D01* +G01X3973491Y5680982D01* +G01X3972537Y5676209D01* +G01X3970946Y5669846D01* +G01X3970309Y5666345D01* +G01X3969355Y5661573D01* +G01X3968400Y5657755D01* +G01X3967764Y5654573D01* +G01X3967128Y5652027D01* +G01X3965855Y5645664D01* +G01X3965219Y5642800D01* +G01X3964901Y5640891D01* +G01X3986537Y5640891D01* +G01X4008173Y5640573D01* +G01X4007855Y5638664D01* +G01X4007219Y5636118D01* +G01X4006582Y5632618D01* +G01X4005628Y5627845D01* +G01X4004991Y5625618D01* +G01X3969355Y5625618D01* +G37* +G36* +G01X4020264Y5625618D02* +G01X4020900Y5626891D01* +G01X4021855Y5630391D01* +G01X4022491Y5633573D01* +G01X4023764Y5639300D01* +G01X4024401Y5642800D01* +G01X4025355Y5647573D01* +G01X4026310Y5651391D01* +G01X4027582Y5657755D01* +G01X4028219Y5660300D01* +G01X4029491Y5666664D01* +G01X4030764Y5672391D01* +G01X4031401Y5675891D01* +G01X4032355Y5680664D01* +G01X4033310Y5684482D01* +G01X4034582Y5690845D01* +G01X4035219Y5693391D01* +G01X4036491Y5699755D01* +G01X4037764Y5705482D01* +G01X4038400Y5708982D01* +G01X4039355Y5713755D01* +G01X4040310Y5717573D01* +G01X4041582Y5723936D01* +G01X4042219Y5726482D01* +G01X4042855Y5729982D01* +G01X4043810Y5734754D01* +G01X4044764Y5738573D01* +G01X4046037Y5744936D01* +G01X4046673Y5747482D01* +G01X4047946Y5753845D01* +G01X4049219Y5759573D01* +G01X4049855Y5763073D01* +G01X4050810Y5767846D01* +G01X4051446Y5770073D01* +G01X4073400Y5770073D01* +G01X4089866Y5769834D01* +G01X4095355Y5769118D01* +G01X4095037Y5767209D01* +G01X4094400Y5763709D01* +G01X4093446Y5758936D01* +G01X4092491Y5755118D01* +G01X4091219Y5748754D01* +G01X4090582Y5746209D01* +G01X4090264Y5743346D01* +G01X4090264Y5741436D01* +G01X4115082Y5741436D01* +G01X4140855Y5741118D01* +G01X4143401Y5740800D01* +G01X4146264Y5740164D01* +G01X4149128Y5738891D01* +G01X4151991Y5736664D01* +G01X4153582Y5734118D01* +G01X4154537Y5731891D01* +G01X4155173Y5728709D01* +G01X4154855Y5725209D01* +G01X4152946Y5715664D01* +G01X4152310Y5713118D01* +G01X4151673Y5709618D01* +G01X4150719Y5704845D01* +G01X4149764Y5701027D01* +G01X4148491Y5694664D01* +G01X4147855Y5692118D01* +G01X4146582Y5685755D01* +G01X4145310Y5680027D01* +G01X4144673Y5676527D01* +G01X4143719Y5671755D01* +G01X4142764Y5667936D01* +G01X4142128Y5664755D01* +G01X4141491Y5662209D01* +G01X4140855Y5658709D01* +G01X4139900Y5653936D01* +G01X4138946Y5650118D01* +G01X4137673Y5643754D01* +G01X4137037Y5641209D01* +G01X4135764Y5634845D01* +G01X4134491Y5629118D01* +G01X4134173Y5626891D01* +G01X4128605Y5625936D01* +G01X4111900Y5625618D01* +G01X4089628Y5625618D01* +G01X4089946Y5627527D01* +G01X4090901Y5631663D01* +G01X4091855Y5635482D01* +G01X4093128Y5641845D01* +G01X4093764Y5644391D01* +G01X4094400Y5647891D01* +G01X4095355Y5652664D01* +G01X4096310Y5656482D01* +G01X4097582Y5662846D01* +G01X4098219Y5665391D01* +G01X4098855Y5668891D01* +G01X4099810Y5673664D01* +G01X4100764Y5677482D01* +G01X4102037Y5683846D01* +G01X4102673Y5686391D01* +G01X4103310Y5689891D01* +G01X4104264Y5694664D01* +G01X4105219Y5698482D01* +G01X4106491Y5704845D01* +G01X4107128Y5707391D01* +G01X4108401Y5713755D01* +G01X4109673Y5719482D01* +G01X4110310Y5722982D01* +G01X4110628Y5725527D01* +G01X4098855Y5725527D01* +G01X4089866Y5725209D01* +G01X4086446Y5724255D01* +G01X4085491Y5721391D01* +G01X4084855Y5718845D01* +G01X4083582Y5712482D01* +G01X4082309Y5706755D01* +G01X4081673Y5703255D01* +G01X4080719Y5698482D01* +G01X4079764Y5694664D01* +G01X4079128Y5691482D01* +G01X4078491Y5688936D01* +G01X4077855Y5685436D01* +G01X4076901Y5680664D01* +G01X4075946Y5676846D01* +G01X4074673Y5670482D01* +G01X4074037Y5667936D01* +G01X4072764Y5661573D01* +G01X4071491Y5655846D01* +G01X4070855Y5652345D01* +G01X4069901Y5647573D01* +G01X4068946Y5643754D01* +G01X4068309Y5640573D01* +G01X4067673Y5638027D01* +G01X4066400Y5631663D01* +G01X4065764Y5628164D01* +G01X4065446Y5625618D01* +G01X4020264Y5625618D01* +G37* +G36* +G01X4157639Y5625857D02* +G01X4152310Y5626573D01* +G01X4152946Y5628482D01* +G01X4153582Y5631982D01* +G01X4154537Y5636754D01* +G01X4155491Y5640573D01* +G01X4156764Y5646936D01* +G01X4157401Y5649482D01* +G01X4158037Y5652982D01* +G01X4158991Y5657755D01* +G01X4159946Y5661573D01* +G01X4161219Y5667936D01* +G01X4161855Y5670482D01* +G01X4162491Y5673982D01* +G01X4163446Y5678755D01* +G01X4164400Y5682573D01* +G01X4165673Y5688936D01* +G01X4166310Y5691482D01* +G01X4167582Y5697845D01* +G01X4168855Y5703573D01* +G01X4169491Y5707073D01* +G01X4170446Y5711845D01* +G01X4171400Y5715664D01* +G01X4172673Y5722027D01* +G01X4173310Y5724573D01* +G01X4173946Y5728073D01* +G01X4174901Y5732845D01* +G01X4175855Y5736664D01* +G01X4176810Y5741436D01* +G01X4221355Y5741436D01* +G01X4221037Y5739845D01* +G01X4219128Y5732209D01* +G01X4217855Y5725845D01* +G01X4217219Y5723300D01* +G01X4216582Y5719800D01* +G01X4215628Y5715027D01* +G01X4214673Y5711209D01* +G01X4213401Y5704845D01* +G01X4212764Y5702300D01* +G01X4211491Y5695936D01* +G01X4210219Y5690209D01* +G01X4209582Y5686709D01* +G01X4208628Y5681936D01* +G01X4207673Y5678118D01* +G01X4206400Y5671755D01* +G01X4205764Y5669209D01* +G01X4205128Y5665709D01* +G01X4204173Y5660936D01* +G01X4203219Y5657118D01* +G01X4201946Y5650755D01* +G01X4201310Y5648209D01* +G01X4200037Y5641845D01* +G01X4198764Y5636118D01* +G01X4198128Y5632618D01* +G01X4197173Y5627845D01* +G01X4196537Y5625618D01* +G01X4174264Y5625618D01* +G01X4157639Y5625857D01* +G37* +G36* +G01X4179355Y5754164D02* +G01X4179673Y5755436D01* +G01X4180310Y5757664D01* +G01X4181582Y5764027D01* +G01X4182219Y5767527D01* +G01X4182537Y5770073D01* +G01X4227082Y5770073D01* +G01X4226764Y5768164D01* +G01X4226128Y5765300D01* +G01X4224855Y5758936D01* +G01X4224219Y5756073D01* +G01X4223900Y5754164D01* +G01X4179355Y5754164D01* +G37* +G36* +G01X4217537Y5625618D02* +G01X4218173Y5627527D01* +G01X4219128Y5630391D01* +G01X4220401Y5636754D01* +G01X4221673Y5642482D01* +G01X4222310Y5645982D01* +G01X4223264Y5650755D01* +G01X4224219Y5654573D01* +G01X4224855Y5657755D01* +G01X4225492Y5660300D01* +G01X4226128Y5663800D01* +G01X4227082Y5668573D01* +G01X4228037Y5672391D01* +G01X4228673Y5675573D01* +G01X4229310Y5678118D01* +G01X4229946Y5681618D01* +G01X4230900Y5686391D01* +G01X4231855Y5690209D01* +G01X4232492Y5693391D01* +G01X4233128Y5695936D01* +G01X4234401Y5702300D01* +G01X4235673Y5708027D01* +G01X4236310Y5711527D01* +G01X4237264Y5716300D01* +G01X4238219Y5720118D01* +G01X4238855Y5723300D01* +G01X4239492Y5725845D01* +G01X4240764Y5732209D01* +G01X4242037Y5737936D01* +G01X4242355Y5740164D01* +G01X4254207Y5741118D01* +G01X4289764Y5741436D01* +G01X4338128Y5741118D01* +G01X4340673Y5740800D01* +G01X4343537Y5740164D01* +G01X4346401Y5738891D01* +G01X4349264Y5736664D01* +G01X4351173Y5733800D01* +G01X4352128Y5731573D01* +G01X4352446Y5729346D01* +G01X4352128Y5725845D01* +G01X4351492Y5722027D01* +G01X4350855Y5719482D01* +G01X4349582Y5713118D01* +G01X4348310Y5707391D01* +G01X4347673Y5703891D01* +G01X4346719Y5699118D01* +G01X4345764Y5695300D01* +G01X4345128Y5692118D01* +G01X4344492Y5689573D01* +G01X4343855Y5686073D01* +G01X4342901Y5681300D01* +G01X4341946Y5677482D01* +G01X4340673Y5671118D01* +G01X4340037Y5668573D01* +G01X4339401Y5665073D01* +G01X4338446Y5660300D01* +G01X4337492Y5656482D01* +G01X4336219Y5650118D01* +G01X4335583Y5647573D01* +G01X4334946Y5644073D01* +G01X4333991Y5639300D01* +G01X4333037Y5635482D01* +G01X4332401Y5632300D01* +G01X4331764Y5629754D01* +G01X4331446Y5627209D01* +G01X4331446Y5625618D01* +G01X4309491Y5625618D01* +G01X4287219Y5626255D01* +G01X4287537Y5629118D01* +G01X4288491Y5632936D01* +G01X4289128Y5636118D01* +G01X4289764Y5638664D01* +G01X4290400Y5642164D01* +G01X4291355Y5646936D01* +G01X4292310Y5650755D01* +G01X4292946Y5653936D01* +G01X4293582Y5656482D01* +G01X4294219Y5659982D01* +G01X4295173Y5664755D01* +G01X4296128Y5668573D01* +G01X4296764Y5671755D01* +G01X4297400Y5674300D01* +G01X4298037Y5677800D01* +G01X4298992Y5682573D01* +G01X4299946Y5686391D01* +G01X4300582Y5689573D01* +G01X4301219Y5692118D01* +G01X4301855Y5695618D01* +G01X4302810Y5700391D01* +G01X4303764Y5704209D01* +G01X4304400Y5707391D01* +G01X4305037Y5709936D01* +G01X4306310Y5716300D01* +G01X4307582Y5722027D01* +G01X4307901Y5724255D01* +G01X4304957Y5725209D01* +G01X4296128Y5725527D01* +G01X4287139Y5725209D01* +G01X4283719Y5724255D01* +G01X4282764Y5721391D01* +G01X4281491Y5715027D01* +G01X4280855Y5712482D01* +G01X4280219Y5708982D01* +G01X4279264Y5704209D01* +G01X4278310Y5700391D01* +G01X4277673Y5697209D01* +G01X4277037Y5694664D01* +G01X4276401Y5691164D01* +G01X4275446Y5686391D01* +G01X4274491Y5682573D01* +G01X4273855Y5679391D01* +G01X4273219Y5676846D01* +G01X4272582Y5673345D01* +G01X4271628Y5668573D01* +G01X4270673Y5664755D01* +G01X4270037Y5661573D01* +G01X4269401Y5659027D01* +G01X4268764Y5655527D01* +G01X4267810Y5650755D01* +G01X4266855Y5646936D01* +G01X4266219Y5643754D01* +G01X4265582Y5641209D01* +G01X4264310Y5634845D01* +G01X4263037Y5629118D01* +G01X4262719Y5626891D01* +G01X4257071Y5625936D01* +G01X4240128Y5625618D01* +G01X4217537Y5625618D01* +G37* +G36* +G01X4402401Y5625618D02* +G01X4361673Y5625936D01* +G01X4357219Y5628164D01* +G01X4354991Y5629754D01* +G01X4353401Y5631345D01* +G01X4351810Y5633255D01* +G01X4350537Y5635800D01* +G01X4349900Y5638664D01* +G01X4349582Y5641209D01* +G01X4349582Y5643118D01* +G01X4351492Y5652664D01* +G01X4352446Y5657118D01* +G01X4353082Y5659345D01* +G01X4375037Y5659345D01* +G01X4391503Y5659107D01* +G01X4396992Y5658391D01* +G01X4396673Y5656482D01* +G01X4394128Y5645027D01* +G01X4393810Y5642482D01* +G01X4393810Y5640891D01* +G01X4417992Y5640891D01* +G01X4418310Y5643436D01* +G01X4419264Y5648209D01* +G01X4420219Y5652027D01* +G01X4420855Y5655209D01* +G01X4421491Y5657755D01* +G01X4422764Y5664118D01* +G01X4424037Y5669846D01* +G01X4424673Y5673027D01* +G01X4424992Y5675254D01* +G01X4402719Y5675254D01* +G01X4378219Y5675573D01* +G01X4373764Y5676209D01* +G01X4369946Y5677164D01* +G01X4367401Y5678436D01* +G01X4365492Y5679709D01* +G01X4363900Y5681300D01* +G01X4362628Y5683209D01* +G01X4361355Y5685755D01* +G01X4360401Y5689573D01* +G01X4360401Y5693391D01* +G01X4361037Y5697209D01* +G01X4362946Y5706755D01* +G01X4364219Y5712482D01* +G01X4365492Y5718845D01* +G01X4366128Y5721709D01* +G01X4367082Y5725527D01* +G01X4368355Y5728709D01* +G01X4369310Y5730936D01* +G01X4370582Y5732527D01* +G01X4374401Y5736346D01* +G01X4377264Y5738255D01* +G01X4379491Y5739527D01* +G01X4382673Y5740482D01* +G01X4385855Y5741118D01* +G01X4424992Y5741436D01* +G01X4466037Y5741118D01* +G01X4469855Y5740482D01* +G01X4472401Y5739845D01* +G01X4474628Y5738573D01* +G01X4477810Y5735391D01* +G01X4479082Y5733164D01* +G01X4479719Y5728391D01* +G01X4479401Y5723300D01* +G01X4478764Y5720118D01* +G01X4478128Y5717573D01* +G01X4476855Y5711209D01* +G01X4476537Y5708982D01* +G01X4470969Y5708027D01* +G01X4454264Y5707709D01* +G01X4431992Y5707709D01* +G01X4432310Y5709618D01* +G01X4433264Y5713755D01* +G01X4434855Y5720118D01* +G01X4435492Y5723300D01* +G01X4435810Y5725527D01* +G01X4411628Y5725527D01* +G01X4411310Y5723936D01* +G01X4408764Y5713755D01* +G01X4407491Y5707391D01* +G01X4404310Y5693073D01* +G01X4403992Y5691164D01* +G01X4429764Y5691164D01* +G01X4458401Y5690845D01* +G01X4462219Y5689891D01* +G01X4464128Y5688936D01* +G01X4466355Y5687027D01* +G01X4467946Y5684482D01* +G01X4468901Y5682254D01* +G01X4469537Y5679709D01* +G01X4469219Y5675573D01* +G01X4468583Y5671755D01* +G01X4467310Y5666027D01* +G01X4464764Y5653300D01* +G01X4463492Y5647573D01* +G01X4462855Y5645027D01* +G01X4461901Y5642482D01* +G01X4460628Y5639936D01* +G01X4458719Y5636754D01* +G01X4456810Y5634209D01* +G01X4454583Y5631982D01* +G01X4452037Y5630073D01* +G01X4449492Y5628482D01* +G01X4445991Y5626891D01* +G01X4443128Y5625936D01* +G01X4402401Y5625618D01* +G37* +G36* +G01X4477173Y5625618D02* +G01X4477492Y5627209D01* +G01X4478128Y5630391D01* +G01X4478764Y5632936D01* +G01X4480037Y5639300D01* +G01X4481310Y5645027D01* +G01X4481946Y5648527D01* +G01X4482901Y5653300D01* +G01X4483855Y5657118D01* +G01X4485128Y5663482D01* +G01X4485764Y5666027D01* +G01X4487037Y5672391D01* +G01X4488310Y5678118D01* +G01X4488946Y5681618D01* +G01X4489901Y5686391D01* +G01X4490855Y5690209D01* +G01X4492128Y5696573D01* +G01X4492764Y5699118D01* +G01X4494037Y5705482D01* +G01X4495310Y5711209D01* +G01X4495946Y5714709D01* +G01X4496901Y5719482D01* +G01X4497855Y5723300D01* +G01X4499128Y5729664D01* +G01X4499764Y5732209D01* +G01X4501037Y5738573D01* +G01X4502310Y5744300D01* +G01X4503582Y5750664D01* +G01X4504855Y5756391D01* +G01X4505492Y5759891D01* +G01X4506446Y5764664D01* +G01X4507401Y5768482D01* +G01X4507719Y5770073D01* +G01X4551628Y5770073D01* +G01X4551310Y5767846D01* +G01X4550673Y5764664D01* +G01X4549401Y5758936D01* +G01X4548764Y5755436D01* +G01X4547810Y5750664D01* +G01X4546855Y5746845D01* +G01X4545583Y5740482D01* +G01X4544946Y5737936D01* +G01X4544310Y5734436D01* +G01X4543355Y5729664D01* +G01X4542401Y5725845D01* +G01X4541128Y5719482D01* +G01X4540492Y5716936D01* +G01X4539855Y5713436D01* +G01X4538901Y5708664D01* +G01X4537946Y5704845D01* +G01X4536673Y5698482D01* +G01X4536037Y5695936D01* +G01X4534764Y5689573D01* +G01X4534446Y5687345D01* +G01X4535083Y5685436D01* +G01X4535719Y5685198D01* +G01X4536355Y5685755D01* +G01X4557037Y5706436D01* +G01X4560219Y5710255D01* +G01X4590446Y5740482D01* +G01X4593071Y5741198D01* +G01X4599673Y5741436D01* +G01X4609219Y5741118D01* +G01X4609696Y5740720D01* +G01X4609219Y5740164D01* +G01X4586946Y5717891D01* +G01X4583764Y5714073D01* +G01X4567855Y5698164D01* +G01X4566901Y5696254D01* +G01X4567537Y5693709D01* +G01X4588537Y5630709D01* +G01X4589492Y5627527D01* +G01X4589810Y5625618D01* +G01X4567855Y5625618D01* +G01X4545583Y5626255D01* +G01X4544628Y5628164D01* +G01X4536992Y5651073D01* +G01X4534128Y5660618D01* +G01X4533651Y5661971D01* +G01X4532855Y5662209D01* +G01X4531264Y5660936D01* +G01X4529673Y5659345D01* +G01X4528083Y5656800D01* +G01X4527128Y5653300D01* +G01X4526491Y5650118D01* +G01X4525855Y5647573D01* +G01X4525219Y5644073D01* +G01X4524264Y5639300D01* +G01X4523310Y5635482D01* +G01X4522673Y5632300D01* +G01X4522037Y5629754D01* +G01X4521719Y5627209D01* +G01X4521719Y5625618D01* +G01X4477173Y5625618D01* +G37* +G36* +G01X4607628Y5625618D02* +G01X4607946Y5626891D01* +G01X4608901Y5630391D01* +G01X4609855Y5634209D01* +G01X4611128Y5640573D01* +G01X4611764Y5643118D01* +G01X4613037Y5649482D01* +G01X4614310Y5655209D01* +G01X4614946Y5658709D01* +G01X4615901Y5663482D01* +G01X4616855Y5667300D01* +G01X4618128Y5673664D01* +G01X4618764Y5676209D01* +G01X4619401Y5679709D01* +G01X4620355Y5684482D01* +G01X4621310Y5688300D01* +G01X4622582Y5694664D01* +G01X4623219Y5697209D01* +G01X4624492Y5703573D01* +G01X4625764Y5709300D01* +G01X4626401Y5712800D01* +G01X4627355Y5717573D01* +G01X4628310Y5721391D01* +G01X4629582Y5727754D01* +G01X4630219Y5730300D01* +G01X4631492Y5736664D01* +G01X4632128Y5739527D01* +G01X4632446Y5741436D01* +G01X4654719Y5741436D01* +G01X4671344Y5741198D01* +G01X4676674Y5740482D01* +G01X4676037Y5737936D01* +G01X4674764Y5731573D01* +G01X4674128Y5729027D01* +G01X4673492Y5725527D01* +G01X4672537Y5720754D01* +G01X4671583Y5716936D01* +G01X4670310Y5710573D01* +G01X4669674Y5708027D01* +G01X4669037Y5704527D01* +G01X4668082Y5699755D01* +G01X4667128Y5695936D01* +G01X4665855Y5689573D01* +G01X4665219Y5687027D01* +G01X4663946Y5680664D01* +G01X4662674Y5674936D01* +G01X4662037Y5671436D01* +G01X4661083Y5666664D01* +G01X4660128Y5662846D01* +G01X4658855Y5656482D01* +G01X4658219Y5653936D01* +G01X4656946Y5647573D01* +G01X4655673Y5641845D01* +G01X4654401Y5635482D01* +G01X4653128Y5629754D01* +G01X4652810Y5627209D01* +G01X4652810Y5625618D01* +G01X4607628Y5625618D01* +G37* +G36* +G01X4640639Y5754323D02* +G01X4635310Y5754800D01* +G01X4635946Y5757664D01* +G01X4636582Y5760846D01* +G01X4637855Y5766573D01* +G01X4638173Y5768800D01* +G01X4643662Y5769755D01* +G01X4660128Y5770073D01* +G01X4676674Y5769834D01* +G01X4682401Y5769118D01* +G01X4682082Y5765936D01* +G01X4681128Y5762118D01* +G01X4679537Y5754164D01* +G01X4657264Y5754164D01* +G01X4640639Y5754323D01* +G37* +G36* +G01X4695685Y5596505D02* +G01X4686855Y5596982D01* +G01X4687492Y5599209D01* +G01X4688128Y5601754D01* +G01X4690037Y5610346D01* +G01X4690355Y5612255D01* +G01X4712628Y5612255D01* +G01X4735855Y5612573D01* +G01X4737128Y5614482D01* +G01X4737764Y5617664D01* +G01X4738401Y5620209D01* +G01X4739037Y5623391D01* +G01X4739355Y5625618D01* +G01X4714855Y5625618D01* +G01X4688128Y5625936D01* +G01X4684310Y5626891D01* +G01X4681764Y5628164D01* +G01X4679855Y5629436D01* +G01X4677628Y5631663D01* +G01X4675719Y5634527D01* +G01X4674764Y5636754D01* +G01X4674446Y5640573D01* +G01X4674764Y5645664D01* +G01X4675401Y5649482D01* +G01X4676037Y5652027D01* +G01X4676674Y5655527D01* +G01X4677628Y5660300D01* +G01X4678583Y5664118D01* +G01X4679219Y5667300D01* +G01X4679855Y5669846D01* +G01X4680492Y5673345D01* +G01X4681446Y5678118D01* +G01X4682401Y5681936D01* +G01X4683037Y5685118D01* +G01X4683674Y5687664D01* +G01X4684310Y5691164D01* +G01X4685264Y5695936D01* +G01X4686219Y5699755D01* +G01X4686855Y5702936D01* +G01X4687492Y5705482D01* +G01X4688128Y5708982D01* +G01X4689082Y5713755D01* +G01X4690037Y5717573D01* +G01X4690674Y5720754D01* +G01X4691310Y5723300D01* +G01X4692583Y5729664D01* +G01X4693855Y5735391D01* +G01X4694492Y5738891D01* +G01X4694810Y5741436D01* +G01X4739355Y5741436D01* +G01X4739037Y5739209D01* +G01X4738083Y5734754D01* +G01X4737128Y5730936D01* +G01X4735855Y5724573D01* +G01X4735219Y5722027D01* +G01X4734582Y5718527D01* +G01X4733628Y5713755D01* +G01X4732673Y5709936D01* +G01X4731401Y5703573D01* +G01X4730764Y5701027D01* +G01X4730128Y5697527D01* +G01X4729174Y5692755D01* +G01X4728219Y5688936D01* +G01X4726946Y5682573D01* +G01X4726310Y5680027D01* +G01X4725673Y5676527D01* +G01X4724719Y5671755D01* +G01X4723764Y5667936D01* +G01X4722492Y5661573D01* +G01X4721855Y5659027D01* +G01X4720583Y5652664D01* +G01X4719310Y5646936D01* +G01X4718673Y5643436D01* +G01X4718355Y5640891D01* +G01X4729492Y5640891D01* +G01X4741582Y5641209D01* +G01X4742457Y5642005D01* +G01X4743174Y5643754D01* +G01X4744128Y5647573D01* +G01X4745401Y5653936D01* +G01X4746037Y5656482D01* +G01X4746673Y5659982D01* +G01X4747628Y5664755D01* +G01X4748582Y5668573D01* +G01X4749855Y5674936D01* +G01X4750492Y5677482D01* +G01X4751128Y5680982D01* +G01X4752083Y5685755D01* +G01X4753037Y5689573D01* +G01X4754310Y5695936D01* +G01X4754946Y5698482D01* +G01X4755583Y5701982D01* +G01X4756537Y5706755D01* +G01X4757492Y5710573D01* +G01X4758764Y5716936D01* +G01X4759401Y5719482D01* +G01X4760673Y5725845D01* +G01X4761946Y5731573D01* +G01X4763219Y5737936D01* +G01X4763537Y5740164D01* +G01X4769026Y5741118D01* +G01X4785492Y5741436D01* +G01X4807764Y5740800D01* +G01X4807446Y5737936D01* +G01X4806492Y5734118D01* +G01X4805219Y5727754D01* +G01X4804583Y5725209D01* +G01X4803310Y5718845D01* +G01X4802037Y5713118D01* +G01X4800764Y5706755D01* +G01X4799492Y5701027D01* +G01X4798219Y5694664D01* +G01X4796946Y5688936D01* +G01X4796310Y5685436D01* +G01X4795355Y5680664D01* +G01X4794401Y5676846D01* +G01X4793128Y5670482D01* +G01X4792492Y5667936D01* +G01X4791219Y5661573D01* +G01X4789946Y5655846D01* +G01X4788674Y5649482D01* +G01X4787401Y5643754D01* +G01X4786128Y5637391D01* +G01X4784855Y5631663D01* +G01X4783583Y5625300D01* +G01X4782310Y5619573D01* +G01X4781674Y5617027D01* +G01X4780719Y5614164D01* +G01X4779446Y5611300D01* +G01X4778173Y5609073D01* +G01X4776901Y5607164D01* +G01X4775310Y5605255D01* +G01X4773719Y5603664D01* +G01X4771492Y5601754D01* +G01X4769264Y5600164D01* +G01X4767355Y5599209D01* +G01X4765128Y5598255D01* +G01X4762583Y5597300D01* +G01X4760037Y5596664D01* +G01X4722810Y5596345D01* +G01X4695685Y5596505D01* +G37* +G36* +G01X1505354Y5754164D02* +G01X1505990Y5756391D01* +G01X1506945Y5759573D01* +G01X1507581Y5763073D01* +G01X1508536Y5767846D01* +G01X1509172Y5770073D01* +G01X1531445Y5770073D01* +G01X1548070Y5769914D01* +G01X1553399Y5769436D01* +G01X1552763Y5766891D01* +G01X1552127Y5764027D01* +G01X1550854Y5757664D01* +G01X1550536Y5755436D01* +G01X1544888Y5754482D01* +G01X1527945Y5754164D01* +G01X1505354Y5754164D01* +G37* +G36* +G01X4369866Y5930657D02* +G01X4364537Y5931373D01* +G01X4365810Y5936463D01* +G01X4367082Y5942827D01* +G01X4368355Y5948554D01* +G01X4368991Y5952055D01* +G01X4369946Y5956827D01* +G01X4370900Y5960646D01* +G01X4371537Y5963827D01* +G01X4372173Y5966373D01* +G01X4372810Y5969873D01* +G01X4373764Y5974646D01* +G01X4374719Y5978464D01* +G01X4375991Y5984827D01* +G01X4376628Y5987373D01* +G01X4377900Y5993736D01* +G01X4379173Y5999464D01* +G01X4379810Y6002964D01* +G01X4380764Y6007736D01* +G01X4381719Y6011555D01* +G01X4382355Y6014736D01* +G01X4382991Y6017282D01* +G01X4383628Y6020782D01* +G01X4384582Y6025554D01* +G01X4385537Y6028736D01* +G01X4386173Y6031282D01* +G01X4387128Y6033827D01* +G01X4388082Y6035736D01* +G01X4389355Y6037327D01* +G01X4393173Y6041146D01* +G01X4396037Y6043055D01* +G01X4398264Y6044327D01* +G01X4401446Y6045282D01* +G01X4404628Y6045918D01* +G01X4440901Y6046236D01* +G01X4467469Y6045998D01* +G01X4476537Y6045282D01* +G01X4476219Y6042100D01* +G01X4475264Y6038282D01* +G01X4473673Y6030327D01* +G01X4430400Y6030327D01* +G01X4430082Y6028736D01* +G01X4428173Y6021100D01* +G01X4427537Y6017918D01* +G01X4426901Y6015373D01* +G01X4426264Y6011873D01* +G01X4425310Y6007100D01* +G01X4424355Y6003282D01* +G01X4423719Y6000100D01* +G01X4423082Y5997555D01* +G01X4422446Y5994054D01* +G01X4421491Y5989282D01* +G01X4420537Y5985464D01* +G01X4419901Y5982282D01* +G01X4419264Y5979736D01* +G01X4418628Y5976236D01* +G01X4417673Y5971464D01* +G01X4416719Y5967646D01* +G01X4416082Y5964464D01* +G01X4415446Y5961918D01* +G01X4414810Y5958418D01* +G01X4413855Y5953645D01* +G01X4412901Y5949827D01* +G01X4412264Y5946645D01* +G01X4411628Y5944100D01* +G01X4410992Y5940600D01* +G01X4410037Y5935827D01* +G01X4409082Y5932009D01* +G01X4408764Y5930418D01* +G01X4386491Y5930418D01* +G01X4369866Y5930657D01* +G37* +G36* +G01X4718037Y5930418D02* +G01X4670628Y5930736D01* +G01X4666173Y5932964D01* +G01X4663946Y5934554D01* +G01X4662355Y5936145D01* +G01X4660764Y5938373D01* +G01X4659491Y5941236D01* +G01X4658855Y5944736D01* +G01X4659173Y5949827D01* +G01X4659280Y5950464D01* +G01X4706901Y5950464D01* +G01X4706901Y5948554D01* +G01X4721855Y5948236D01* +G01X4736810Y5948873D01* +G01X4737764Y5951736D01* +G01X4738719Y5955555D01* +G01X4739355Y5958736D01* +G01X4739992Y5961282D01* +G01X4740628Y5964782D01* +G01X4741582Y5969555D01* +G01X4742537Y5973373D01* +G01X4743810Y5979736D01* +G01X4744446Y5982282D01* +G01X4745719Y5988646D01* +G01X4746992Y5994373D01* +G01X4747628Y5997873D01* +G01X4748582Y6002645D01* +G01X4749537Y6006464D01* +G01X4750174Y6009645D01* +G01X4750810Y6012191D01* +G01X4751446Y6015691D01* +G01X4752401Y6020464D01* +G01X4753355Y6024282D01* +G01X4754628Y6030645D01* +G01X4755264Y6033191D01* +G01X4756537Y6039554D01* +G01X4757810Y6045282D01* +G01X4759719Y6054827D01* +G01X4760037Y6057055D01* +G01X4729492Y6057055D01* +G01X4729173Y6055145D01* +G01X4728537Y6052282D01* +G01X4727901Y6048782D01* +G01X4726946Y6044009D01* +G01X4725992Y6040191D01* +G01X4725355Y6037009D01* +G01X4724719Y6034464D01* +G01X4724082Y6030964D01* +G01X4723128Y6026191D01* +G01X4722173Y6022373D01* +G01X4720901Y6016009D01* +G01X4720264Y6013464D01* +G01X4718992Y6007100D01* +G01X4717719Y6001373D01* +G01X4717082Y5997873D01* +G01X4716128Y5993100D01* +G01X4715173Y5989282D01* +G01X4714537Y5986100D01* +G01X4713901Y5983555D01* +G01X4713264Y5980054D01* +G01X4712310Y5975282D01* +G01X4711355Y5971464D01* +G01X4710082Y5965100D01* +G01X4709446Y5962555D01* +G01X4708810Y5959055D01* +G01X4707855Y5954282D01* +G01X4706901Y5950464D01* +G01X4706901Y5950464D01* +G01X4659280Y5950464D01* +G01X4659810Y5953645D01* +G01X4661083Y5959373D01* +G01X4662355Y5965736D01* +G01X4663628Y5971464D01* +G01X4664901Y5977827D01* +G01X4666173Y5983555D01* +G01X4666810Y5987054D01* +G01X4667764Y5991827D01* +G01X4668719Y5995645D01* +G01X4669992Y6002009D01* +G01X4670628Y6004555D01* +G01X4671901Y6010918D01* +G01X4673173Y6016645D01* +G01X4674446Y6023009D01* +G01X4675719Y6028736D01* +G01X4676992Y6035100D01* +G01X4678264Y6040827D01* +G01X4679537Y6047191D01* +G01X4680173Y6050055D01* +G01X4681128Y6054191D01* +G01X4682401Y6058009D01* +G01X4683992Y6061191D01* +G01X4687173Y6065646D01* +G01X4689082Y6067873D01* +G01X4690674Y6069145D01* +G01X4692901Y6070736D01* +G01X4695764Y6072327D01* +G01X4698946Y6073600D01* +G01X4701810Y6074555D01* +G01X4747946Y6074873D01* +G01X4795355Y6074236D01* +G01X4798537Y6072964D01* +G01X4800764Y6072009D01* +G01X4802674Y6070736D01* +G01X4804264Y6069145D01* +G01X4805855Y6066918D01* +G01X4807128Y6064055D01* +G01X4807764Y6060236D01* +G01X4807446Y6054827D01* +G01X4806810Y6051009D01* +G01X4805537Y6045282D01* +G01X4804901Y6041782D01* +G01X4803946Y6037009D01* +G01X4802992Y6033191D01* +G01X4801719Y6026827D01* +G01X4801082Y6024282D01* +G01X4799810Y6017918D01* +G01X4798537Y6012191D01* +G01X4797264Y6005827D01* +G01X4795992Y6000100D01* +G01X4795355Y5996600D01* +G01X4794401Y5991827D01* +G01X4793446Y5988009D01* +G01X4792173Y5981646D01* +G01X4791537Y5979100D01* +G01X4790264Y5972736D01* +G01X4788992Y5967009D01* +G01X4788355Y5963509D01* +G01X4787401Y5958736D01* +G01X4785173Y5949827D01* +G01X4784219Y5947282D01* +G01X4782946Y5944736D01* +G01X4781673Y5942509D01* +G01X4780719Y5940918D01* +G01X4779446Y5939327D01* +G01X4776264Y5936145D01* +G01X4774037Y5934554D01* +G01X4771810Y5933282D01* +G01X4769901Y5932327D01* +G01X4767673Y5931373D01* +G01X4765446Y5930736D01* +G01X4718037Y5930418D01* +G37* +G36* +G01X4617651Y5930657D02* +G01X4613355Y5931373D01* +G01X4614628Y5936463D01* +G01X4617173Y5949191D01* +G01X4617810Y5952055D01* +G01X4618128Y5953964D01* +G01X4654401Y5953964D01* +G01X4653764Y5951736D01* +G01X4652810Y5947918D01* +G01X4650901Y5938373D01* +G01X4650264Y5935827D01* +G01X4649628Y5932645D01* +G01X4649310Y5930418D01* +G01X4631173Y5930418D01* +G01X4617651Y5930657D01* +G37* +G36* +G01X4476855Y5930418D02* +G01X4477492Y5931691D01* +G01X4478446Y5935191D01* +G01X4480355Y5944736D01* +G01X4481628Y5950464D01* +G01X4481946Y5952691D01* +G01X4486242Y5953645D01* +G01X4499128Y5953964D01* +G01X4517264Y5953645D01* +G01X4517901Y5953168D01* +G01X4517901Y5952373D01* +G01X4516628Y5946009D01* +G01X4515355Y5940282D01* +G01X4514082Y5933918D01* +G01X4513764Y5931691D01* +G01X4509151Y5930736D01* +G01X4495310Y5930418D01* +G01X4476855Y5930418D01* +G37* +G36* +G01X4558310Y5930418D02* +G01X4534128Y5931055D01* +G01X4534764Y5933918D01* +G01X4535719Y5937736D01* +G01X4536992Y5944100D01* +G01X4537628Y5946645D01* +G01X4538264Y5950145D01* +G01X4539219Y5954918D01* +G01X4540173Y5958736D01* +G01X4541446Y5965100D01* +G01X4542082Y5967646D01* +G01X4542719Y5971145D01* +G01X4543673Y5975918D01* +G01X4544628Y5979736D01* +G01X4545901Y5986100D01* +G01X4546537Y5988646D01* +G01X4547173Y5992145D01* +G01X4548128Y5996918D01* +G01X4549082Y6000736D01* +G01X4550355Y6007100D01* +G01X4550992Y6009645D01* +G01X4551628Y6013146D01* +G01X4552582Y6017918D01* +G01X4553537Y6021736D01* +G01X4554810Y6028100D01* +G01X4555446Y6030645D01* +G01X4556082Y6034146D01* +G01X4557037Y6038918D01* +G01X4557992Y6042736D01* +G01X4559264Y6049100D01* +G01X4559901Y6051645D01* +G01X4560537Y6054827D01* +G01X4560855Y6057055D01* +G01X4552264Y6057055D01* +G01X4543355Y6057691D01* +G01X4543355Y6059282D01* +G01X4544628Y6065009D01* +G01X4545901Y6071373D01* +G01X4546219Y6073600D01* +G01X4554491Y6074555D01* +G01X4579310Y6074873D01* +G01X4612401Y6074873D01* +G01X4612082Y6072327D01* +G01X4611128Y6067555D01* +G01X4610173Y6063736D01* +G01X4608901Y6057373D01* +G01X4608264Y6054827D01* +G01X4606991Y6048464D01* +G01X4605719Y6042736D01* +G01X4605082Y6039236D01* +G01X4604128Y6034464D01* +G01X4603173Y6030645D01* +G01X4601901Y6024282D01* +G01X4601264Y6021736D01* +G01X4600628Y6018236D01* +G01X4599673Y6013464D01* +G01X4598719Y6009645D01* +G01X4597446Y6003282D01* +G01X4596810Y6000736D01* +G01X4595537Y5994373D01* +G01X4594264Y5988646D01* +G01X4593628Y5985145D01* +G01X4592673Y5980373D01* +G01X4591719Y5976555D01* +G01X4590446Y5970191D01* +G01X4589810Y5967646D01* +G01X4588537Y5961282D01* +G01X4587264Y5955555D01* +G01X4586628Y5952055D01* +G01X4585673Y5947282D01* +G01X4584719Y5943464D01* +G01X4583446Y5937100D01* +G01X4582810Y5934554D01* +G01X4582492Y5932009D01* +G01X4582492Y5930418D01* +G01X4558310Y5930418D01* +G37* +G36* +G01X4133457Y5930657D02* +G01X4127173Y5931373D01* +G01X4125264Y5963827D01* +G01X4124628Y5974009D01* +G01X4121446Y6028100D01* +G01X4120810Y6038282D01* +G01X4118900Y6070736D01* +G01X4118582Y6073282D01* +G01X4118582Y6074873D01* +G01X4166946Y6074873D01* +G01X4166946Y6073282D01* +G01X4167264Y6070736D01* +G01X4169809Y6024918D01* +G01X4170446Y6014100D01* +G01X4172355Y5979736D01* +G01X4172673Y5973054D01* +G01X4172912Y5968918D01* +G01X4173628Y5967964D01* +G01X4175219Y5970191D01* +G01X4177764Y5975918D01* +G01X4185400Y5991191D01* +G01X4186673Y5994373D01* +G01X4194309Y6009645D01* +G01X4195582Y6012827D01* +G01X4203219Y6028100D01* +G01X4204491Y6031282D01* +G01X4212128Y6046554D01* +G01X4214673Y6052282D01* +G01X4221037Y6065009D01* +G01X4223582Y6070736D01* +G01X4224855Y6073282D01* +G01X4225491Y6074873D01* +G01X4235355Y6074873D01* +G01X4242594Y6074634D01* +G01X4244582Y6073918D01* +G01X4240764Y6066282D01* +G01X4239491Y6063100D01* +G01X4231855Y6047827D01* +G01X4230582Y6044645D01* +G01X4224219Y6031918D01* +G01X4221673Y6026191D01* +G01X4215309Y6013464D01* +G01X4212764Y6007736D01* +G01X4206400Y5995009D01* +G01X4203855Y5989282D01* +G01X4197491Y5976555D01* +G01X4194946Y5970827D01* +G01X4188582Y5958100D01* +G01X4186037Y5952373D01* +G01X4179673Y5939645D01* +G01X4178400Y5936463D01* +G01X4177128Y5933918D01* +G01X4176173Y5931691D01* +G01X4169889Y5930736D01* +G01X4151673Y5930418D01* +G01X4133457Y5930657D01* +G37* +G36* +G01X4294537Y5930418D02* +G01X4245855Y5930736D01* +G01X4243628Y5931691D01* +G01X4241082Y5932964D01* +G01X4239173Y5934236D01* +G01X4236946Y5936463D01* +G01X4235037Y5939327D01* +G01X4234082Y5941554D01* +G01X4233764Y5946009D01* +G01X4234082Y5951100D01* +G01X4235355Y5957464D01* +G01X4235991Y5960009D01* +G01X4236628Y5963509D01* +G01X4237582Y5968282D01* +G01X4238537Y5972100D01* +G01X4239810Y5978464D01* +G01X4240207Y5980054D01* +G01X4284673Y5980054D01* +G01X4284991Y5978464D01* +G01X4297082Y5978145D01* +G01X4308855Y5978145D01* +G01X4309173Y5980691D01* +G01X4310128Y5985464D01* +G01X4311719Y5991827D01* +G01X4312355Y5995327D01* +G01X4313310Y6000100D01* +G01X4314264Y6003918D01* +G01X4314901Y6007100D01* +G01X4315537Y6009645D01* +G01X4316173Y6013146D01* +G01X4317128Y6017918D01* +G01X4318719Y6024282D01* +G01X4319355Y6027782D01* +G01X4319673Y6030327D01* +G01X4307901Y6030327D01* +G01X4298912Y6030009D01* +G01X4295491Y6029055D01* +G01X4294537Y6026827D01* +G01X4292628Y6017282D01* +G01X4291673Y6012827D01* +G01X4290719Y6009009D01* +G01X4290082Y6005827D01* +G01X4289446Y6003282D01* +G01X4288810Y5999782D01* +G01X4287855Y5995009D01* +G01X4286264Y5988646D01* +G01X4284991Y5982282D01* +G01X4284673Y5980054D01* +G01X4284673Y5980054D01* +G01X4240207Y5980054D01* +G01X4240446Y5981009D01* +G01X4241082Y5984509D01* +G01X4242037Y5989282D01* +G01X4242991Y5993100D01* +G01X4244264Y5999464D01* +G01X4244900Y6002009D01* +G01X4245537Y6005509D01* +G01X4246492Y6010282D01* +G01X4247446Y6014100D01* +G01X4248082Y6017282D01* +G01X4248719Y6019827D01* +G01X4249355Y6023327D01* +G01X4250310Y6028100D01* +G01X4251582Y6031918D01* +G01X4253173Y6035100D01* +G01X4254764Y6037327D01* +G01X4256037Y6038918D01* +G01X4258264Y6041146D01* +G01X4261128Y6043055D01* +G01X4263355Y6044327D01* +G01X4266537Y6045282D01* +G01X4269719Y6045918D01* +G01X4309810Y6046236D01* +G01X4349900Y6045918D01* +G01X4352128Y6045600D01* +G01X4355310Y6044964D01* +G01X4358810Y6043373D01* +G01X4361355Y6040827D01* +G01X4362946Y6038282D01* +G01X4363900Y6035100D01* +G01X4363900Y6031918D01* +G01X4363264Y6027464D01* +G01X4361991Y6021736D01* +G01X4360719Y6015373D01* +G01X4359446Y6009645D01* +G01X4358173Y6003282D01* +G01X4356900Y5997555D01* +G01X4355628Y5991191D01* +G01X4354355Y5985464D01* +G01X4353082Y5979100D01* +G01X4351810Y5973373D01* +G01X4350537Y5967009D01* +G01X4349900Y5964145D01* +G01X4349582Y5962236D01* +G01X4280855Y5962236D01* +G01X4280537Y5960327D01* +G01X4279582Y5956191D01* +G01X4277991Y5949827D01* +G01X4277673Y5947282D01* +G01X4277673Y5945691D01* +G01X4310764Y5945691D01* +G01X4344810Y5945373D01* +G01X4345446Y5944896D01* +G01X4345446Y5944100D01* +G01X4344810Y5940600D01* +G01X4343855Y5935827D01* +G01X4342901Y5932009D01* +G01X4342582Y5930418D01* +G01X4294537Y5930418D01* +G37* +G36* +G01X-2333067Y10568136D02* +G01X-2308673Y10567985D01* +G01X-2290264Y10568136D01* +G01X-2284127Y10568591D01* +G01X-2283976Y10569652D01* +G01X-2283370Y10572379D01* +G01X-2282764Y10575409D01* +G01X-2282764Y10576167D01* +G01X-2295642Y10576470D01* +G01X-2308370Y10576470D01* +G01X-2308218Y10577530D01* +G01X-2307915Y10579046D01* +G01X-2307309Y10581773D01* +G01X-2306703Y10584803D01* +G01X-2306400Y10586015D01* +G01X-2305794Y10589046D01* +G01X-2305339Y10590864D01* +G01X-2304885Y10593136D01* +G01X-2304582Y10594803D01* +G01X-2304279Y10596015D01* +G01X-2303673Y10599045D01* +G01X-2303218Y10600864D01* +G01X-2302764Y10603136D01* +G01X-2302461Y10604803D01* +G01X-2302157Y10606015D01* +G01X-2301551Y10609045D01* +G01X-2301097Y10610864D01* +G01X-2300642Y10613136D01* +G01X-2300339Y10614803D01* +G01X-2300036Y10616015D01* +G01X-2299430Y10619045D01* +G01X-2298976Y10620864D01* +G01X-2298521Y10623136D01* +G01X-2298218Y10624803D01* +G01X-2297915Y10626015D01* +G01X-2297309Y10629045D01* +G01X-2296854Y10630864D01* +G01X-2296400Y10633136D01* +G01X-2296097Y10634803D01* +G01X-2295794Y10636015D01* +G01X-2295642Y10636773D01* +G01X-2318673Y10636773D01* +G01X-2318673Y10636015D01* +G01X-2318824Y10634803D01* +G01X-2319127Y10633591D01* +G01X-2319733Y10630561D01* +G01X-2320188Y10628742D01* +G01X-2320642Y10626470D01* +G01X-2320945Y10624803D01* +G01X-2321248Y10623591D01* +G01X-2321854Y10620561D01* +G01X-2322309Y10618742D01* +G01X-2322764Y10616470D01* +G01X-2323067Y10614803D01* +G01X-2323673Y10612076D01* +G01X-2324279Y10609045D01* +G01X-2324582Y10607833D01* +G01X-2325188Y10604803D01* +G01X-2325642Y10602985D01* +G01X-2326097Y10600712D01* +G01X-2326400Y10599045D01* +G01X-2327006Y10596318D01* +G01X-2327612Y10593288D01* +G01X-2327915Y10592076D01* +G01X-2328521Y10589046D01* +G01X-2328976Y10587227D01* +G01X-2329430Y10584955D01* +G01X-2329733Y10583288D01* +G01X-2330339Y10580561D01* +G01X-2330945Y10577530D01* +G01X-2331249Y10576318D01* +G01X-2331855Y10573288D01* +G01X-2332309Y10571470D01* +G01X-2332764Y10569349D01* +G01X-2333067Y10568136D01* +G37* +G36* +G01X-1578642Y10569046D02* +G01X-1578945Y10567985D01* +G01X-1555915Y10567985D01* +G01X-1555461Y10570258D01* +G01X-1555006Y10572076D01* +G01X-1554552Y10574349D01* +G01X-1554248Y10576015D01* +G01X-1553945Y10577227D01* +G01X-1553339Y10580258D01* +G01X-1552885Y10582076D01* +G01X-1552430Y10584349D01* +G01X-1552127Y10586015D01* +G01X-1551824Y10587227D01* +G01X-1551370Y10588742D01* +G01X-1551067Y10589500D01* +G01X-1547885Y10589500D01* +G01X-1545498Y10589349D01* +G01X-1544703Y10588894D01* +G01X-1544249Y10585712D01* +G01X-1543945Y10583894D01* +G01X-1543642Y10581773D01* +G01X-1543339Y10579955D01* +G01X-1542733Y10575712D01* +G01X-1542430Y10573894D01* +G01X-1542127Y10571773D01* +G01X-1541824Y10569955D01* +G01X-1541673Y10568894D01* +G01X-1541483Y10568401D01* +G01X-1540915Y10568136D01* +G01X-1529400Y10567985D01* +G01X-1518643Y10567985D01* +G01X-1518643Y10568894D01* +G01X-1518794Y10570258D01* +G01X-1519097Y10572379D01* +G01X-1519400Y10574197D01* +G01X-1519703Y10576318D01* +G01X-1520309Y10579955D01* +G01X-1520612Y10582076D01* +G01X-1520915Y10583894D01* +G01X-1521218Y10586015D01* +G01X-1521521Y10587833D01* +G01X-1521824Y10589500D01* +G01X-1521711Y10589765D01* +G01X-1521067Y10589955D01* +G01X-1519703Y10590409D01* +G01X-1518491Y10591015D01* +G01X-1516976Y10591924D01* +G01X-1515764Y10592833D01* +G01X-1514855Y10593894D01* +G01X-1513339Y10596015D01* +G01X-1512582Y10597530D01* +G01X-1511976Y10599349D01* +G01X-1511521Y10601470D01* +G01X-1511218Y10602985D01* +G01X-1510612Y10605712D01* +G01X-1510006Y10608742D01* +G01X-1509400Y10611470D01* +G01X-1508794Y10614500D01* +G01X-1508188Y10617227D01* +G01X-1506976Y10623288D01* +G01X-1506673Y10624500D01* +G01X-1506370Y10626015D01* +G01X-1506067Y10628136D01* +G01X-1505915Y10630106D01* +G01X-1506218Y10631318D01* +G01X-1506673Y10632530D01* +G01X-1507127Y10633439D01* +G01X-1507733Y10634197D01* +G01X-1508794Y10635106D01* +G01X-1510309Y10635864D01* +G01X-1511521Y10636318D01* +G01X-1512733Y10636621D01* +G01X-1538945Y10636773D01* +G01X-1564400Y10636773D01* +G01X-1564400Y10636015D01* +G01X-1564551Y10634803D01* +G01X-1564855Y10633591D01* +G01X-1565764Y10629045D01* +G01X-1566218Y10627227D01* +G01X-1566673Y10625106D01* +G01X-1567582Y10620561D01* +G01X-1568188Y10617833D01* +G01X-1568794Y10614803D01* +G01X-1569400Y10612076D01* +G01X-1570006Y10609045D01* +G01X-1570309Y10607833D01* +G01X-1570915Y10604803D01* +G01X-1571370Y10602985D01* +G01X-1571824Y10600712D01* +G01X-1572127Y10599045D01* +G01X-1549248Y10599045D01* +G01X-1549097Y10600258D01* +G01X-1548491Y10603288D01* +G01X-1548188Y10604500D01* +G01X-1547885Y10606015D01* +G01X-1547430Y10607833D01* +G01X-1546976Y10610106D01* +G01X-1546673Y10611773D01* +G01X-1546067Y10614500D01* +G01X-1545461Y10617530D01* +G01X-1545158Y10618742D01* +G01X-1544552Y10621773D01* +G01X-1544097Y10623591D01* +G01X-1543642Y10625864D01* +G01X-1543339Y10627530D01* +G01X-1542733Y10628136D01* +G01X-1535612Y10628288D01* +G01X-1528946Y10628288D01* +G01X-1528946Y10627379D01* +G01X-1529097Y10626015D01* +G01X-1529703Y10623288D01* +G01X-1530309Y10620258D01* +G01X-1530612Y10619045D01* +G01X-1530915Y10617530D01* +G01X-1531370Y10615712D01* +G01X-1531824Y10613439D01* +G01X-1532127Y10611773D01* +G01X-1532733Y10609045D01* +G01X-1533339Y10606015D01* +G01X-1533642Y10604803D01* +G01X-1534249Y10601773D01* +G01X-1534703Y10599955D01* +G01X-1535158Y10598439D01* +G01X-1536976Y10598099D01* +G01X-1542127Y10597985D01* +G01X-1549097Y10598136D01* +G01X-1549097Y10598136D01* +G01X-1549248Y10599045D01* +G01X-1572127Y10599045D01* +G01X-1572733Y10596318D01* +G01X-1573339Y10593288D01* +G01X-1573642Y10592076D01* +G01X-1574248Y10589046D01* +G01X-1574703Y10587227D01* +G01X-1575158Y10584955D01* +G01X-1575461Y10583288D01* +G01X-1575764Y10582076D01* +G01X-1576370Y10579046D01* +G01X-1576824Y10577227D01* +G01X-1577279Y10574955D01* +G01X-1577582Y10573288D01* +G01X-1578188Y10570561D01* +G01X-1578642Y10569046D01* +G37* +G36* +G01X222716Y6612406D02* +G01X162079Y6612845D01* +G01X155928Y6615921D01* +G01X152852Y6618118D01* +G01X150655Y6620315D01* +G01X148458Y6623391D01* +G01X146700Y6627346D01* +G01X145822Y6633058D01* +G01X146261Y6639209D01* +G01X147140Y6644482D01* +G01X148019Y6648876D01* +G01X149776Y6656785D01* +G01X150655Y6661618D01* +G01X151973Y6668209D01* +G01X153291Y6673482D01* +G01X155049Y6682270D01* +G01X155928Y6685785D01* +G01X157685Y6694573D01* +G01X159443Y6702482D01* +G01X161200Y6711270D01* +G01X162958Y6719179D01* +G01X163837Y6724012D01* +G01X165155Y6730603D01* +G01X166473Y6735876D01* +G01X168231Y6744664D01* +G01X169109Y6748179D01* +G01X170867Y6756967D01* +G01X172625Y6764876D01* +G01X174382Y6773664D01* +G01X175261Y6777618D01* +G01X176579Y6783330D01* +G01X178337Y6788603D01* +G01X180534Y6792997D01* +G01X184928Y6799148D01* +G01X187564Y6802224D01* +G01X189761Y6803982D01* +G01X192837Y6806179D01* +G01X196791Y6808376D01* +G01X201185Y6810133D01* +G01X205140Y6811451D01* +G01X264897Y6811891D01* +G01X323337Y6811451D01* +G01X322897Y6807936D01* +G01X322018Y6803542D01* +G01X320261Y6795633D01* +G01X319382Y6790800D01* +G01X318943Y6787285D01* +G01X244246Y6787285D01* +G01X243367Y6785088D01* +G01X242049Y6780694D01* +G01X241170Y6776300D01* +G01X240291Y6772785D01* +G01X238534Y6763997D01* +G01X236776Y6756088D01* +G01X235897Y6751254D01* +G01X234579Y6744664D01* +G01X233261Y6739391D01* +G01X232382Y6734997D01* +G01X231504Y6731482D01* +G01X230625Y6727088D01* +G01X230185Y6724012D01* +G01X289064Y6724012D01* +G01X288185Y6721815D01* +G01X286867Y6717421D01* +G01X285109Y6708633D01* +G01X284231Y6705118D01* +G01X283791Y6701603D01* +G01X283791Y6699406D01* +G01X254791Y6699406D01* +G01X232822Y6699076D01* +G01X224912Y6698088D01* +G01X223594Y6693255D01* +G01X222276Y6686664D01* +G01X220958Y6681391D01* +G01X220079Y6676997D01* +G01X219200Y6673482D01* +G01X218322Y6668649D01* +G01X217003Y6662057D01* +G01X215685Y6656785D01* +G01X213928Y6647997D01* +G01X213049Y6644482D01* +G01X212170Y6640088D01* +G01X211731Y6637012D01* +G01X248640Y6637012D01* +G01X285988Y6636133D01* +G01X285988Y6633936D01* +G01X284231Y6625148D01* +G01X282473Y6617239D01* +G01X282034Y6614164D01* +G01X267204Y6612845D01* +G01X222716Y6612406D01* +G37* +G36* +G01X390124Y6612406D02* +G01X324655Y6612845D01* +G01X318503Y6615921D01* +G01X315428Y6618118D01* +G01X313231Y6620315D01* +G01X311034Y6623391D01* +G01X309276Y6627346D01* +G01X308397Y6633058D01* +G01X308837Y6640088D01* +G01X309715Y6645361D01* +G01X312352Y6658542D01* +G01X313231Y6662057D01* +G01X314109Y6666891D01* +G01X314549Y6670406D01* +G01X347943Y6670406D01* +G01X372878Y6670187D01* +G01X380897Y6669527D01* +G01X380019Y6666012D01* +G01X379140Y6662057D01* +G01X377382Y6653270D01* +G01X375625Y6645361D01* +G01X374746Y6640527D01* +G01X374306Y6637012D01* +G01X394958Y6637012D01* +G01X410556Y6637342D01* +G01X416049Y6638330D01* +G01X417367Y6642724D01* +G01X418685Y6647997D01* +G01X419564Y6652391D01* +G01X420443Y6655906D01* +G01X421322Y6660739D01* +G01X422640Y6667330D01* +G01X423958Y6672603D01* +G01X425715Y6681391D01* +G01X426594Y6684906D01* +G01X428352Y6693694D01* +G01X428791Y6697209D01* +G01X428791Y6699406D01* +G01X390564Y6699406D01* +G01X351019Y6699846D01* +G01X347503Y6700285D01* +G01X342231Y6701164D01* +G01X337397Y6703361D01* +G01X334321Y6705558D01* +G01X331246Y6708633D01* +G01X328609Y6712588D01* +G01X327291Y6715664D01* +G01X326852Y6720936D01* +G01X327291Y6727088D01* +G01X328170Y6732361D01* +G01X329049Y6736755D01* +G01X330806Y6744664D01* +G01X331685Y6749497D01* +G01X333003Y6756088D01* +G01X334321Y6761361D01* +G01X336958Y6774542D01* +G01X337837Y6778058D01* +G01X338715Y6782012D01* +G01X340034Y6786406D01* +G01X341791Y6790361D01* +G01X343549Y6793876D01* +G01X345306Y6796512D01* +G01X348822Y6800906D01* +G01X351019Y6803103D01* +G01X354534Y6805739D01* +G01X358928Y6808376D01* +G01X363761Y6810133D01* +G01X367716Y6811451D01* +G01X431428Y6811891D01* +G01X496458Y6811012D01* +G01X501291Y6809255D01* +G01X505685Y6807057D01* +G01X508761Y6804421D01* +G01X510518Y6802224D01* +G01X511837Y6799588D01* +G01X513155Y6796073D01* +G01X514034Y6791239D01* +G01X513594Y6785967D01* +G01X512716Y6780694D01* +G01X508322Y6758724D01* +G01X507882Y6755648D01* +G01X499534Y6754330D01* +G01X474488Y6753891D01* +G01X449553Y6754220D01* +G01X441534Y6755209D01* +G01X443291Y6763997D01* +G01X445049Y6771906D01* +G01X446806Y6780694D01* +G01X447685Y6784649D01* +G01X448125Y6787285D01* +G01X427473Y6787285D01* +G01X411765Y6786955D01* +G01X405943Y6785967D01* +G01X404625Y6781133D01* +G01X403306Y6774542D01* +G01X401988Y6769270D01* +G01X400231Y6760482D01* +G01X399352Y6756967D01* +G01X398473Y6752133D01* +G01X397155Y6745542D01* +G01X395837Y6740270D01* +G01X394958Y6735876D01* +G01X394079Y6732361D01* +G01X393200Y6727527D01* +G01X392761Y6724012D01* +G01X434943Y6724012D01* +G01X478882Y6723133D01* +G01X482397Y6721815D01* +G01X485034Y6720497D01* +G01X487670Y6718739D01* +G01X490306Y6716543D01* +G01X492064Y6714345D01* +G01X493382Y6711709D01* +G01X494700Y6708194D01* +G01X495579Y6703361D01* +G01X495140Y6698967D01* +G01X494261Y6692815D01* +G01X492503Y6684906D01* +G01X490746Y6676118D01* +G01X488988Y6668209D01* +G01X488109Y6663376D01* +G01X486791Y6656785D01* +G01X485473Y6651512D01* +G01X484594Y6647118D01* +G01X482837Y6640088D01* +G01X481519Y6635694D01* +G01X479321Y6631300D01* +G01X474927Y6625148D01* +G01X472291Y6622073D01* +G01X470094Y6620315D01* +G01X467018Y6618118D01* +G01X463503Y6615921D01* +G01X459549Y6614164D01* +G01X455594Y6612845D01* +G01X390124Y6612406D01* +G37* +G36* +G01X536003Y6612406D02* +G01X502609Y6612845D01* +G01X504806Y6621633D01* +G01X506564Y6630421D01* +G01X507443Y6633936D01* +G01X508322Y6638770D01* +G01X509640Y6645361D01* +G01X510958Y6650633D01* +G01X512716Y6659421D01* +G01X513594Y6662936D01* +G01X515352Y6671724D01* +G01X517109Y6679633D01* +G01X517988Y6684467D01* +G01X519306Y6691058D01* +G01X520625Y6696330D01* +G01X522118Y6703800D01* +G01X588291Y6703800D01* +G01X588291Y6699846D01* +G01X608943Y6699406D01* +G01X629155Y6699406D01* +G01X630034Y6702042D01* +G01X631352Y6706876D01* +G01X633109Y6715664D01* +G01X633988Y6719179D01* +G01X634867Y6724012D01* +G01X636185Y6730603D01* +G01X637503Y6735876D01* +G01X639261Y6744664D01* +G01X640140Y6748179D01* +G01X641897Y6756967D01* +G01X643655Y6764876D01* +G01X645412Y6773664D01* +G01X647170Y6781573D01* +G01X647609Y6785088D01* +G01X647609Y6787285D01* +G01X606306Y6787285D01* +G01X605867Y6785088D01* +G01X603230Y6774542D01* +G01X601473Y6765755D01* +G01X600594Y6762239D01* +G01X599715Y6757406D01* +G01X598397Y6750815D01* +G01X597079Y6745542D01* +G01X595321Y6736755D01* +G01X594443Y6733239D01* +G01X593564Y6728406D01* +G01X592246Y6721815D01* +G01X590927Y6716543D01* +G01X590049Y6712149D01* +G01X589170Y6708633D01* +G01X588291Y6703800D01* +G01X588291Y6703800D01* +G01X522118Y6703800D01* +G01X522382Y6705118D01* +G01X523261Y6708633D01* +G01X525019Y6717421D01* +G01X526776Y6725330D01* +G01X527655Y6730164D01* +G01X528973Y6736755D01* +G01X530291Y6742027D01* +G01X532049Y6750815D01* +G01X532928Y6754330D01* +G01X534685Y6763118D01* +G01X536443Y6771027D01* +G01X538200Y6779815D01* +G01X539958Y6787724D01* +G01X541715Y6796512D01* +G01X543473Y6804421D01* +G01X544352Y6808815D01* +G01X544791Y6811891D01* +G01X619488Y6811891D01* +G01X696821Y6811012D01* +G01X701655Y6809255D01* +G01X706049Y6807057D01* +G01X709564Y6803542D01* +G01X711761Y6800027D01* +G01X713079Y6796512D01* +G01X713958Y6792997D01* +G01X713958Y6787724D01* +G01X713079Y6781573D01* +G01X711321Y6772785D01* +G01X710443Y6769270D01* +G01X708685Y6760482D01* +G01X706928Y6752573D01* +G01X706049Y6747739D01* +G01X704731Y6741149D01* +G01X703412Y6735876D01* +G01X702534Y6731482D01* +G01X701655Y6727967D01* +G01X700776Y6723133D01* +G01X699458Y6716543D01* +G01X698140Y6711270D01* +G01X697261Y6706876D01* +G01X695943Y6702042D01* +G01X694185Y6697209D01* +G01X692427Y6693694D01* +G01X690670Y6690618D01* +G01X688473Y6687982D01* +G01X683200Y6682709D01* +G01X678806Y6679633D01* +G01X674852Y6677436D01* +G01X671337Y6676118D01* +G01X668261Y6675239D01* +G01X625200Y6674800D01* +G01X593674Y6674470D01* +G01X582579Y6673482D01* +G01X581261Y6670845D01* +G01X580382Y6666012D01* +G01X579064Y6659421D01* +G01X577746Y6654148D01* +G01X575988Y6645361D01* +G01X575109Y6641845D01* +G01X574231Y6637012D01* +G01X572912Y6630421D01* +G01X571594Y6625148D01* +G01X570715Y6620755D01* +G01X569837Y6617239D01* +G01X569397Y6614164D01* +G01X561049Y6612845D01* +G01X536003Y6612406D01* +G37* +G36* +G01X1651624Y6612406D02* +G01X1591427Y6612845D01* +G01X1588351Y6614164D01* +G01X1584836Y6615921D01* +G01X1582200Y6617679D01* +G01X1579124Y6620755D01* +G01X1576927Y6624270D01* +G01X1575609Y6627346D01* +G01X1574730Y6633497D01* +G01X1575170Y6640088D01* +G01X1578685Y6657664D01* +G01X1579564Y6661179D01* +G01X1581321Y6669967D01* +G01X1583079Y6677876D01* +G01X1584836Y6686664D01* +G01X1586594Y6694573D01* +G01X1587473Y6699406D01* +G01X1588791Y6705997D01* +G01X1590109Y6711270D01* +G01X1591867Y6720058D01* +G01X1592745Y6723573D01* +G01X1594503Y6732361D01* +G01X1596261Y6740270D01* +G01X1598018Y6749058D01* +G01X1599776Y6756967D01* +G01X1601533Y6765755D01* +G01X1603291Y6773664D01* +G01X1604170Y6778058D01* +G01X1605488Y6783770D01* +G01X1607245Y6788603D01* +G01X1609442Y6792997D01* +G01X1612079Y6796952D01* +G01X1614276Y6800027D01* +G01X1617352Y6803103D01* +G01X1621746Y6806179D01* +G01X1625700Y6808376D01* +G01X1630094Y6810133D01* +G01X1634049Y6811451D01* +G01X1693806Y6811891D01* +G01X1752245Y6811451D01* +G01X1751806Y6808376D01* +G01X1750927Y6804421D01* +G01X1749170Y6795633D01* +G01X1748291Y6790800D01* +G01X1747852Y6787285D01* +G01X1672276Y6787285D01* +G01X1671836Y6784209D01* +G01X1670518Y6778058D01* +G01X1669200Y6772785D01* +G01X1668321Y6768391D01* +G01X1667442Y6764876D01* +G01X1665685Y6756088D01* +G01X1663927Y6748179D01* +G01X1662170Y6739391D01* +G01X1660412Y6731482D01* +G01X1659533Y6727088D01* +G01X1659094Y6724012D01* +G01X1717094Y6724012D01* +G01X1715776Y6717421D01* +G01X1714897Y6713906D01* +G01X1714018Y6709073D01* +G01X1712700Y6702482D01* +G01X1711821Y6699406D01* +G01X1653821Y6699406D01* +G01X1653382Y6696770D01* +G01X1652064Y6691058D01* +G01X1650746Y6685785D01* +G01X1649867Y6681391D01* +G01X1648988Y6677876D01* +G01X1648109Y6673042D01* +G01X1646791Y6666451D01* +G01X1645473Y6661179D01* +G01X1644594Y6656785D01* +G01X1643715Y6653270D01* +G01X1641079Y6640088D01* +G01X1640639Y6637012D01* +G01X1677548Y6637012D01* +G01X1714897Y6636133D01* +G01X1714897Y6633936D01* +G01X1713139Y6626027D01* +G01X1711382Y6617239D01* +G01X1710943Y6614164D01* +G01X1696113Y6612845D01* +G01X1651624Y6612406D01* +G37* +G36* +G01X1154670Y6612406D02* +G01X1155109Y6614603D01* +G01X1157746Y6625148D01* +G01X1159503Y6633936D01* +G01X1160821Y6637891D01* +G01X1162579Y6640527D01* +G01X1177958Y6662057D01* +G01X1184109Y6670845D01* +G01X1210473Y6707755D01* +G01X1216624Y6716543D01* +G01X1238594Y6747300D01* +G01X1244746Y6756088D01* +G01X1264518Y6783770D01* +G01X1265836Y6785967D01* +G01X1256939Y6786955D01* +G01X1229367Y6787285D01* +G01X1192458Y6788164D01* +G01X1192897Y6791239D01* +G01X1193776Y6794754D01* +G01X1195533Y6803542D01* +G01X1196412Y6808376D01* +G01X1196852Y6811891D01* +G01X1338336Y6811891D01* +G01X1337897Y6809255D01* +G01X1336579Y6803542D01* +G01X1335261Y6798270D01* +G01X1333503Y6789482D01* +G01X1331746Y6785088D01* +G01X1318564Y6766633D01* +G01X1312412Y6757845D01* +G01X1272867Y6702482D01* +G01X1266715Y6693694D01* +G01X1229367Y6641406D01* +G01X1228049Y6638770D01* +G01X1227609Y6637012D01* +G01X1264518Y6637012D01* +G01X1292090Y6636683D01* +G01X1300988Y6635694D01* +G01X1299230Y6628664D01* +G01X1296594Y6615482D01* +G01X1296155Y6612406D01* +G01X1154670Y6612406D01* +G37* +G36* +G01X1314774Y6613148D02* +G01X1314609Y6613724D01* +G01X1319442Y6618558D01* +G01X1322958Y6622952D01* +G01X1331746Y6631740D01* +G01X1337018Y6637891D01* +G01X1344488Y6645361D01* +G01X1347124Y6648876D01* +G01X1356791Y6658542D01* +G01X1359427Y6662057D01* +G01X1369094Y6671724D01* +G01X1371730Y6675239D01* +G01X1380518Y6684027D01* +G01X1384033Y6688421D01* +G01X1390624Y6695012D01* +G01X1392382Y6697648D01* +G01X1391942Y6701164D01* +G01X1368215Y6772346D01* +G01X1365579Y6781133D01* +G01X1357670Y6804861D01* +G01X1356352Y6809255D01* +G01X1355912Y6811891D01* +G01X1388427Y6811891D01* +G01X1413143Y6811451D01* +G01X1422261Y6810133D01* +G01X1424018Y6806179D01* +G01X1435882Y6770588D01* +G01X1438518Y6761800D01* +G01X1441155Y6753891D01* +G01X1442473Y6749497D01* +G01X1442912Y6746861D01* +G01X1444670Y6747739D01* +G01X1447306Y6749936D01* +G01X1453897Y6756527D01* +G01X1459170Y6762679D01* +G01X1466639Y6770148D01* +G01X1469276Y6773664D01* +G01X1478942Y6783330D01* +G01X1481579Y6786845D01* +G01X1490367Y6795633D01* +G01X1493882Y6800027D01* +G01X1500473Y6806618D01* +G01X1503109Y6809694D01* +G01X1504427Y6811891D01* +G01X1519367Y6811891D01* +G01X1530352Y6811671D01* +G01X1533427Y6811012D01* +G01X1531670Y6808815D01* +G01X1522882Y6800027D01* +G01X1519367Y6795633D01* +G01X1510579Y6786845D01* +G01X1507064Y6782451D01* +G01X1500473Y6775861D01* +G01X1496958Y6771467D01* +G01X1488170Y6762679D01* +G01X1483776Y6757406D01* +G01X1474988Y6748618D01* +G01X1469715Y6742467D01* +G01X1463124Y6735876D01* +G01X1459609Y6731482D01* +G01X1453018Y6724891D01* +G01X1452139Y6723463D01* +G01X1452139Y6720936D01* +G01X1453458Y6716103D01* +G01X1478503Y6640967D01* +G01X1479821Y6636133D01* +G01X1487730Y6612406D01* +G01X1454776Y6612406D01* +G01X1429840Y6612736D01* +G01X1420943Y6613724D01* +G01X1419185Y6617679D01* +G01X1412155Y6638770D01* +G01X1408640Y6650194D01* +G01X1401609Y6671285D01* +G01X1400621Y6673152D01* +G01X1399412Y6673482D01* +G01X1397655Y6671724D01* +G01X1395897Y6669527D01* +G01X1387109Y6660739D01* +G01X1383594Y6656346D01* +G01X1374806Y6647558D01* +G01X1371291Y6643164D01* +G01X1362503Y6634376D01* +G01X1358988Y6629982D01* +G01X1350200Y6621194D01* +G01X1345806Y6615921D01* +G01X1343609Y6613724D01* +G01X1339215Y6612736D01* +G01X1327791Y6612406D01* +G01X1317026Y6612736D01* +G01X1314774Y6613148D01* +G37* +G36* +G01X789973Y6612406D02* +G01X724943Y6612845D01* +G01X721867Y6614164D01* +G01X718352Y6615921D01* +G01X715715Y6617679D01* +G01X713519Y6619876D01* +G01X711761Y6622512D01* +G01X710003Y6626027D01* +G01X708685Y6629542D01* +G01X708246Y6632618D01* +G01X708685Y6637451D01* +G01X709564Y6643603D01* +G01X710443Y6647997D01* +G01X710882Y6651512D01* +G01X710882Y6653709D01* +G01X744276Y6653709D01* +G01X769212Y6653380D01* +G01X777231Y6652391D01* +G01X775473Y6643603D01* +G01X775034Y6639649D01* +G01X775034Y6637012D01* +G01X794367Y6637012D01* +G01X815018Y6637451D01* +G01X816227Y6638550D01* +G01X817215Y6640967D01* +G01X818534Y6646239D01* +G01X820291Y6655027D01* +G01X821170Y6658542D01* +G01X822049Y6663376D01* +G01X823367Y6669967D01* +G01X824685Y6675239D01* +G01X825564Y6679633D01* +G01X826443Y6683148D01* +G01X829079Y6696330D01* +G01X829518Y6699406D01* +G01X809306Y6699406D01* +G01X788655Y6700285D01* +G01X788655Y6702482D01* +G01X790412Y6710391D01* +G01X792170Y6719179D01* +G01X792609Y6722254D01* +G01X797772Y6723573D01* +G01X813261Y6724012D01* +G01X828969Y6724452D01* +G01X834791Y6725770D01* +G01X836109Y6728846D01* +G01X836988Y6733679D01* +G01X838306Y6740270D01* +G01X839624Y6745542D01* +G01X841382Y6754330D01* +G01X842261Y6757845D01* +G01X843140Y6762679D01* +G01X844458Y6769270D01* +G01X845776Y6774542D01* +G01X846655Y6778936D01* +G01X847534Y6782451D01* +G01X847973Y6785527D01* +G01X842920Y6786845D01* +G01X827761Y6787285D01* +G01X806670Y6786406D01* +G01X805352Y6784209D01* +G01X803594Y6775421D01* +G01X801837Y6767512D01* +G01X800079Y6758724D01* +G01X799640Y6755648D01* +G01X791291Y6754330D01* +G01X766246Y6753891D01* +G01X732852Y6753891D01* +G01X733291Y6756088D01* +G01X734170Y6759603D01* +G01X737685Y6777179D01* +G01X738564Y6781133D01* +G01X739882Y6785527D01* +G01X741640Y6789482D01* +G01X743837Y6793876D01* +G01X746912Y6798270D01* +G01X752185Y6803542D01* +G01X755261Y6806179D01* +G01X759215Y6808376D01* +G01X763609Y6810133D01* +G01X767564Y6811451D01* +G01X830837Y6811891D01* +G01X894109Y6811451D01* +G01X898064Y6810573D01* +G01X902018Y6809255D01* +G01X905533Y6807057D01* +G01X909488Y6803542D01* +G01X912124Y6799588D01* +G01X913443Y6796512D01* +G01X913882Y6791239D01* +G01X913443Y6783330D01* +G01X912564Y6778058D01* +G01X910806Y6770148D01* +G01X909927Y6765315D01* +G01X908609Y6758724D01* +G01X907291Y6753452D01* +G01X904655Y6740270D01* +G01X903776Y6736755D01* +G01X902897Y6732361D01* +G01X901579Y6727527D01* +G01X899382Y6723573D01* +G01X897185Y6720497D01* +G01X895428Y6718300D01* +G01X892352Y6715664D01* +G01X888397Y6713027D01* +G01X887408Y6711819D01* +G01X887958Y6710830D01* +G01X891034Y6707755D01* +G01X893670Y6703800D01* +G01X894988Y6700724D01* +G01X894988Y6696330D01* +G01X892352Y6683148D01* +G01X891473Y6678315D01* +G01X890155Y6671724D01* +G01X888836Y6666451D01* +G01X887079Y6657664D01* +G01X886200Y6654148D01* +G01X884443Y6645361D01* +G01X883564Y6641406D01* +G01X882246Y6637451D01* +G01X880488Y6633497D01* +G01X878731Y6629982D01* +G01X876973Y6627346D01* +G01X874776Y6624709D01* +G01X870382Y6620315D01* +G01X867306Y6618118D01* +G01X864230Y6616361D01* +G01X861594Y6615042D01* +G01X858519Y6613724D01* +G01X855443Y6612845D01* +G01X789973Y6612406D01* +G37* +G36* +G01X990337Y6612406D02* +G01X902897Y6612845D01* +G01X903776Y6615921D01* +G01X904655Y6619876D01* +G01X905533Y6624709D01* +G01X906852Y6631300D01* +G01X908170Y6636573D01* +G01X909927Y6645361D01* +G01X910806Y6648876D01* +G01X911685Y6653709D01* +G01X913003Y6660300D01* +G01X916079Y6672603D01* +G01X917397Y6676118D01* +G01X919155Y6679633D01* +G01X920912Y6682709D01* +G01X922231Y6684906D01* +G01X923988Y6687103D01* +G01X926185Y6689300D01* +G01X929261Y6691936D01* +G01X932337Y6694133D01* +G01X935412Y6695891D01* +G01X940246Y6697648D01* +G01X944200Y6698967D01* +G01X987261Y6699406D01* +G01X1029003Y6699406D01* +G01X1029882Y6701603D01* +G01X1031200Y6705118D01* +G01X1032079Y6709951D01* +G01X1033397Y6716543D01* +G01X1034715Y6721815D01* +G01X1036473Y6730603D01* +G01X1037352Y6734118D01* +G01X1038230Y6738951D01* +G01X1039549Y6745542D01* +G01X1040867Y6750815D01* +G01X1042624Y6759603D01* +G01X1043503Y6763118D01* +G01X1045261Y6771906D01* +G01X1047018Y6779815D01* +G01X1047897Y6784209D01* +G01X1048337Y6787285D01* +G01X1006155Y6787285D01* +G01X1005715Y6784649D01* +G01X1003079Y6772785D01* +G01X1002200Y6767952D01* +G01X1000882Y6761361D01* +G01X999564Y6756088D01* +G01X999125Y6753891D01* +G01X933215Y6753891D01* +G01X933655Y6756967D01* +G01X936291Y6770148D01* +G01X938928Y6782012D01* +G01X940246Y6786406D01* +G01X942003Y6790361D01* +G01X943761Y6793876D01* +G01X945518Y6796512D01* +G01X949033Y6800906D01* +G01X951231Y6803103D01* +G01X954746Y6805739D01* +G01X959140Y6808376D01* +G01X963973Y6810133D01* +G01X967927Y6811451D01* +G01X1031640Y6811891D01* +G01X1096670Y6811012D01* +G01X1101503Y6809255D01* +G01X1105897Y6807057D01* +G01X1108973Y6804421D01* +G01X1110730Y6802224D01* +G01X1112488Y6799148D01* +G01X1113806Y6795633D01* +G01X1114246Y6791679D01* +G01X1113806Y6785088D01* +G01X1112927Y6779815D01* +G01X1111170Y6771027D01* +G01X1109412Y6763118D01* +G01X1108534Y6758285D01* +G01X1107215Y6751694D01* +G01X1105897Y6746421D01* +G01X1104140Y6737633D01* +G01X1103261Y6734118D01* +G01X1101503Y6725330D01* +G01X1100624Y6720497D01* +G01X1099306Y6713906D01* +G01X1096231Y6701603D01* +G01X1094912Y6698088D01* +G01X1093155Y6694573D01* +G01X1091397Y6691497D01* +G01X1090079Y6689300D01* +G01X1088321Y6687103D01* +G01X1086124Y6684906D01* +G01X1083049Y6682270D01* +G01X1079973Y6680073D01* +G01X1076897Y6678315D01* +G01X1072064Y6676558D01* +G01X1068109Y6675239D01* +G01X1025049Y6674800D01* +G01X982867Y6673921D01* +G01X981549Y6669967D01* +G01X979352Y6661179D01* +G01X977594Y6652391D01* +G01X975837Y6644482D01* +G01X974958Y6640088D01* +G01X974518Y6637012D01* +G01X1082609Y6637012D01* +G01X1079534Y6621633D01* +G01X1078655Y6618118D01* +G01X1078215Y6614603D01* +G01X1078215Y6612406D01* +G01X990337Y6612406D01* +G37* +G36* +G01X2133639Y6612406D02* +G01X2134079Y6614603D01* +G01X2134957Y6618118D01* +G01X2136715Y6626027D01* +G01X2137594Y6630861D01* +G01X2138912Y6637451D01* +G01X2140230Y6642724D01* +G01X2141988Y6651512D01* +G01X2142866Y6655027D01* +G01X2144624Y6663815D01* +G01X2146382Y6671724D01* +G01X2147260Y6676558D01* +G01X2148579Y6683148D01* +G01X2149897Y6688421D01* +G01X2151654Y6697209D01* +G01X2152533Y6700724D01* +G01X2153148Y6703800D01* +G01X2219321Y6703800D01* +G01X2219321Y6699846D01* +G01X2238654Y6699406D01* +G01X2258866Y6699846D01* +G01X2260075Y6700944D01* +G01X2261064Y6703361D01* +G01X2262382Y6708633D01* +G01X2264139Y6717421D01* +G01X2265018Y6720936D01* +G01X2266776Y6729724D01* +G01X2268533Y6737633D01* +G01X2269412Y6742467D01* +G01X2270730Y6749058D01* +G01X2272048Y6754330D01* +G01X2272927Y6758724D01* +G01X2273806Y6762239D01* +G01X2275563Y6771027D01* +G01X2277321Y6778936D01* +G01X2278200Y6783770D01* +G01X2278639Y6787285D01* +G01X2258866Y6787285D01* +G01X2237776Y6786406D01* +G01X2236018Y6782451D01* +G01X2234700Y6776300D01* +G01X2233382Y6771027D01* +G01X2230745Y6757845D01* +G01X2229867Y6754330D01* +G01X2228988Y6749497D01* +G01X2227669Y6742906D01* +G01X2226351Y6737633D01* +G01X2224594Y6728846D01* +G01X2223715Y6725330D01* +G01X2221957Y6716543D01* +G01X2220200Y6708633D01* +G01X2219321Y6703800D01* +G01X2219321Y6703800D01* +G01X2153148Y6703800D01* +G01X2154291Y6709512D01* +G01X2156048Y6717421D01* +G01X2157806Y6726209D01* +G01X2159563Y6734118D01* +G01X2160442Y6738951D01* +G01X2161761Y6745542D01* +G01X2163079Y6750815D01* +G01X2163957Y6755209D01* +G01X2164836Y6758724D01* +G01X2165715Y6763558D01* +G01X2167033Y6770148D01* +G01X2168351Y6775421D01* +G01X2170109Y6784209D01* +G01X2170988Y6787724D01* +G01X2172745Y6796512D01* +G01X2174503Y6804421D01* +G01X2175382Y6808815D01* +G01X2175821Y6811891D01* +G01X2248321Y6811891D01* +G01X2324776Y6811451D01* +G01X2330488Y6810133D01* +G01X2334003Y6808815D01* +G01X2336639Y6807057D01* +G01X2338836Y6804861D01* +G01X2341473Y6801785D01* +G01X2343669Y6797830D01* +G01X2344548Y6791239D01* +G01X2344109Y6783330D01* +G01X2343230Y6778936D01* +G01X2341473Y6771027D01* +G01X2339715Y6762239D01* +G01X2338836Y6757406D01* +G01X2337518Y6750815D01* +G01X2336200Y6745542D01* +G01X2334442Y6736755D01* +G01X2333564Y6733239D01* +G01X2329170Y6711270D01* +G01X2327851Y6705118D01* +G01X2326094Y6699406D01* +G01X2323897Y6694573D01* +G01X2321261Y6690179D01* +G01X2318624Y6687103D01* +G01X2314230Y6682709D01* +G01X2312033Y6680952D01* +G01X2308957Y6679194D01* +G01X2305442Y6677436D01* +G01X2301488Y6676118D01* +G01X2298851Y6675679D01* +G01X2299291Y6672164D01* +G01X2300169Y6666451D01* +G01X2301927Y6655906D01* +G01X2302806Y6649754D01* +G01X2303685Y6644482D01* +G01X2304563Y6638330D01* +G01X2305442Y6633058D01* +G01X2306321Y6626906D01* +G01X2307200Y6621633D01* +G01X2308518Y6612406D01* +G01X2241730Y6612406D01* +G01X2241291Y6615482D01* +G01X2239533Y6626027D01* +G01X2238654Y6632179D01* +G01X2237776Y6637451D01* +G01X2236897Y6643603D01* +G01X2236018Y6648876D01* +G01X2235139Y6655027D01* +G01X2234260Y6660300D01* +G01X2233382Y6666451D01* +G01X2232503Y6671724D01* +G01X2232063Y6674800D01* +G01X2223276Y6674800D01* +G01X2213609Y6673921D01* +G01X2212291Y6670845D01* +G01X2211412Y6666451D01* +G01X2210533Y6662936D01* +G01X2209655Y6658103D01* +G01X2208336Y6651512D01* +G01X2207018Y6646239D01* +G01X2205261Y6637451D01* +G01X2204382Y6633936D01* +G01X2202624Y6625148D01* +G01X2200867Y6617239D01* +G01X2200427Y6614164D01* +G01X2192079Y6612845D01* +G01X2167033Y6612406D01* +G01X2133639Y6612406D01* +G37* +G36* +G01X1782014Y6612736D02* +G01X1774215Y6613724D01* +G01X1773776Y6616361D01* +G01X1772018Y6647997D01* +G01X1771140Y6662936D01* +G01X1766746Y6742027D01* +G01X1765867Y6756967D01* +G01X1765427Y6765315D01* +G01X1765427Y6772346D01* +G01X1826942Y6772346D01* +G01X1826942Y6768391D01* +G01X1827382Y6763118D01* +G01X1829139Y6731482D01* +G01X1830018Y6714785D01* +G01X1831776Y6683148D01* +G01X1832215Y6676118D01* +G01X1832654Y6667330D01* +G01X1833204Y6665133D01* +G01X1833973Y6664694D01* +G01X1835730Y6666451D01* +G01X1842761Y6680512D01* +G01X1846276Y6688421D01* +G01X1858579Y6713027D01* +G01X1862094Y6720936D01* +G01X1874397Y6745542D01* +G01X1877912Y6753452D01* +G01X1884942Y6767512D01* +G01X1886261Y6770588D01* +G01X1889886Y6771906D01* +G01X1899882Y6772346D01* +G01X1909658Y6772126D01* +G01X1912624Y6771467D01* +G01X1911306Y6768391D01* +G01X1909548Y6763997D01* +G01X1897245Y6739391D01* +G01X1893730Y6731482D01* +G01X1883185Y6710391D01* +G01X1880548Y6704240D01* +G01X1868245Y6679633D01* +G01X1864730Y6671724D01* +G01X1854185Y6650633D01* +G01X1850670Y6642724D01* +G01X1838367Y6618118D01* +G01X1837048Y6614603D01* +G01X1836609Y6612406D01* +G01X1805412Y6612406D01* +G01X1782014Y6612736D01* +G37* +G36* +G01X1973261Y6612406D02* +G01X1917457Y6612845D01* +G01X1914382Y6614164D01* +G01X1910867Y6615921D01* +G01X1908230Y6617679D01* +G01X1906033Y6619876D01* +G01X1904276Y6622073D01* +G01X1902518Y6625148D01* +G01X1901200Y6628664D01* +G01X1900761Y6632179D01* +G01X1901137Y6637451D01* +G01X1961836Y6637451D01* +G01X1961836Y6633936D01* +G01X1977215Y6633497D01* +G01X1993473Y6633936D01* +G01X1994681Y6635035D01* +G01X1995670Y6637451D01* +G01X1996988Y6642724D01* +G01X1997867Y6647118D01* +G01X1998745Y6650633D01* +G01X1999624Y6655467D01* +G01X2000942Y6662057D01* +G01X2002260Y6667330D01* +G01X2003139Y6671724D01* +G01X2004018Y6675239D01* +G01X2004897Y6680073D01* +G01X2006215Y6686664D01* +G01X2008412Y6695452D01* +G01X2009291Y6700285D01* +G01X2010609Y6706876D01* +G01X2011927Y6712149D01* +G01X2012806Y6716543D01* +G01X2013685Y6720058D01* +G01X2014563Y6724891D01* +G01X2015882Y6731482D01* +G01X2017200Y6736755D01* +G01X2018079Y6741149D01* +G01X2018957Y6744664D01* +G01X2019397Y6748179D01* +G01X2019397Y6750376D01* +G01X1986882Y6750376D01* +G01X1986003Y6748179D01* +G01X1984685Y6743785D01* +G01X1983806Y6739391D01* +G01X1982927Y6735876D01* +G01X1982048Y6731042D01* +G01X1980730Y6724452D01* +G01X1979412Y6719179D01* +G01X1978533Y6714785D01* +G01X1977654Y6711270D01* +G01X1976776Y6706436D01* +G01X1975458Y6699846D01* +G01X1973261Y6691058D01* +G01X1972382Y6686224D01* +G01X1971064Y6679633D01* +G01X1969745Y6674361D01* +G01X1968867Y6669967D01* +G01X1967988Y6666451D01* +G01X1967109Y6661618D01* +G01X1965791Y6655027D01* +G01X1964473Y6649754D01* +G01X1963594Y6645361D01* +G01X1962715Y6641845D01* +G01X1961836Y6637451D01* +G01X1961836Y6637451D01* +G01X1901137Y6637451D01* +G01X1901200Y6638330D01* +G01X1902079Y6643603D01* +G01X1902958Y6648436D01* +G01X1904276Y6655027D01* +G01X1905594Y6660300D01* +G01X1906473Y6664694D01* +G01X1907352Y6668209D01* +G01X1908230Y6673042D01* +G01X1909548Y6679633D01* +G01X1910867Y6684906D01* +G01X1912624Y6693694D01* +G01X1913503Y6697209D01* +G01X1914382Y6702042D01* +G01X1915700Y6708633D01* +G01X1917018Y6713906D01* +G01X1918776Y6722694D01* +G01X1919655Y6726209D01* +G01X1922291Y6739391D01* +G01X1923609Y6745542D01* +G01X1924927Y6749936D01* +G01X1925806Y6753012D01* +G01X1927124Y6756088D01* +G01X1928882Y6758724D01* +G01X1932397Y6763118D01* +G01X1935473Y6765755D01* +G01X1938548Y6767952D01* +G01X1941185Y6769270D01* +G01X1944700Y6770588D01* +G01X1948215Y6771467D01* +G01X1951291Y6771906D01* +G01X2006215Y6772346D01* +G01X2061139Y6771906D01* +G01X2064655Y6771467D01* +G01X2068609Y6770588D01* +G01X2072564Y6768830D01* +G01X2076518Y6765755D01* +G01X2079154Y6761800D01* +G01X2080473Y6758724D01* +G01X2080912Y6754330D01* +G01X2080473Y6749936D01* +G01X2078715Y6741149D01* +G01X2077836Y6736315D01* +G01X2076518Y6729724D01* +G01X2075200Y6724452D01* +G01X2073442Y6715664D01* +G01X2072564Y6712149D01* +G01X2069048Y6694573D01* +G01X2067291Y6686664D01* +G01X2065533Y6677876D01* +G01X2063776Y6669967D01* +G01X2062897Y6665133D01* +G01X2061579Y6658542D01* +G01X2060261Y6653270D01* +G01X2059382Y6648876D01* +G01X2058503Y6645361D01* +G01X2057624Y6641406D01* +G01X2056306Y6637012D01* +G01X2054548Y6633058D01* +G01X2052791Y6629982D01* +G01X2051473Y6627785D01* +G01X2049715Y6625588D01* +G01X2044442Y6620315D01* +G01X2040048Y6617239D01* +G01X2036094Y6615042D01* +G01X2032579Y6613724D01* +G01X2029503Y6612845D01* +G01X1973261Y6612406D01* +G37* +G36* +G01X3197851Y6612406D02* +G01X3198291Y6614164D01* +G01X3199609Y6618997D01* +G01X3200927Y6624270D01* +G01X3202685Y6633058D01* +G01X3203563Y6636573D01* +G01X3204442Y6641406D01* +G01X3205760Y6647997D01* +G01X3207078Y6653270D01* +G01X3208836Y6662057D01* +G01X3209715Y6665573D01* +G01X3210594Y6670406D01* +G01X3211912Y6676997D01* +G01X3213230Y6682270D01* +G01X3214988Y6691058D01* +G01X3215866Y6694573D01* +G01X3216745Y6699406D01* +G01X3218063Y6705997D01* +G01X3219381Y6711270D01* +G01X3221139Y6720058D01* +G01X3222018Y6723573D01* +G01X3222897Y6728406D01* +G01X3224215Y6734997D01* +G01X3225533Y6740270D01* +G01X3227291Y6749058D01* +G01X3228169Y6752573D01* +G01X3229048Y6757406D01* +G01X3230366Y6763997D01* +G01X3231684Y6769270D01* +G01X3233442Y6778058D01* +G01X3234321Y6781573D01* +G01X3234760Y6785088D01* +G01X3234760Y6787285D01* +G01X3185548Y6787285D01* +G01X3186866Y6793876D01* +G01X3187745Y6797391D01* +G01X3188624Y6802224D01* +G01X3189942Y6808815D01* +G01X3190821Y6811891D01* +G01X3273866Y6811891D01* +G01X3336041Y6811561D01* +G01X3356472Y6810573D01* +G01X3354715Y6803542D01* +G01X3352078Y6790361D01* +G01X3351639Y6787285D01* +G01X3302427Y6787285D01* +G01X3301548Y6785088D01* +G01X3300230Y6781573D01* +G01X3299351Y6776740D01* +G01X3298033Y6770148D01* +G01X3296715Y6764876D01* +G01X3294957Y6756088D01* +G01X3294078Y6752573D01* +G01X3292321Y6743785D01* +G01X3290563Y6735876D01* +G01X3289684Y6731042D01* +G01X3288366Y6724452D01* +G01X3287048Y6719179D01* +G01X3285290Y6710391D01* +G01X3284412Y6706876D01* +G01X3283533Y6702042D01* +G01X3282215Y6695452D01* +G01X3280897Y6690179D01* +G01X3279139Y6681391D01* +G01X3278260Y6677876D01* +G01X3277381Y6673042D01* +G01X3276063Y6666451D01* +G01X3274745Y6661179D01* +G01X3272987Y6652391D01* +G01X3272109Y6648876D01* +G01X3271230Y6644043D01* +G01X3269912Y6637451D01* +G01X3268593Y6632179D01* +G01X3266836Y6623391D01* +G01X3265957Y6619876D01* +G01X3265078Y6615482D01* +G01X3264639Y6612406D01* +G01X3197851Y6612406D01* +G37* +G36* +G01X2752306Y6612406D02* +G01X2752745Y6614603D01* +G01X2753624Y6618118D01* +G01X2754503Y6622952D01* +G01X2755821Y6629542D01* +G01X2757139Y6634815D01* +G01X2758897Y6643603D01* +G01X2759776Y6647118D01* +G01X2761533Y6655906D01* +G01X2763291Y6663815D01* +G01X2764170Y6668649D01* +G01X2765488Y6675239D01* +G01X2766806Y6680512D01* +G01X2768563Y6689300D01* +G01X2769442Y6692815D01* +G01X2771200Y6701603D01* +G01X2772957Y6709512D01* +G01X2773836Y6714345D01* +G01X2775154Y6720936D01* +G01X2776473Y6726209D01* +G01X2778230Y6734997D01* +G01X2779109Y6738512D01* +G01X2780866Y6747300D01* +G01X2782624Y6755209D01* +G01X2783503Y6760042D01* +G01X2784821Y6766633D01* +G01X2786139Y6771906D01* +G01X2787897Y6780694D01* +G01X2788776Y6784209D01* +G01X2789654Y6789043D01* +G01X2790972Y6795633D01* +G01X2792291Y6800906D01* +G01X2794488Y6811891D01* +G01X2860397Y6811891D01* +G01X2859957Y6808815D01* +G01X2859078Y6804421D01* +G01X2857321Y6796512D01* +G01X2855563Y6787724D01* +G01X2853806Y6779815D01* +G01X2852927Y6774982D01* +G01X2851609Y6768391D01* +G01X2850291Y6763118D01* +G01X2848533Y6754330D01* +G01X2847654Y6750815D01* +G01X2845897Y6742027D01* +G01X2844139Y6734118D01* +G01X2843260Y6729285D01* +G01X2841942Y6722694D01* +G01X2840624Y6717421D01* +G01X2838866Y6708633D01* +G01X2837988Y6705118D01* +G01X2837548Y6701603D01* +G01X2837548Y6699406D01* +G01X2857321Y6699406D01* +G01X2878412Y6700285D01* +G01X2880169Y6703800D01* +G01X2881048Y6707755D01* +G01X2881927Y6712588D01* +G01X2883245Y6719179D01* +G01X2884563Y6724452D01* +G01X2886321Y6733239D01* +G01X2887200Y6736755D01* +G01X2888957Y6745542D01* +G01X2890715Y6753452D01* +G01X2892473Y6762239D01* +G01X2894230Y6770148D01* +G01X2895109Y6774982D01* +G01X2896427Y6781573D01* +G01X2897745Y6786845D01* +G01X2898624Y6791239D01* +G01X2899503Y6794754D01* +G01X2901260Y6803542D01* +G01X2902139Y6808376D01* +G01X2902578Y6811891D01* +G01X2935972Y6811891D01* +G01X2960908Y6811671D01* +G01X2968927Y6811012D01* +G01X2968048Y6807057D01* +G01X2967169Y6802664D01* +G01X2965412Y6794754D01* +G01X2964533Y6789921D01* +G01X2963215Y6783330D01* +G01X2961897Y6778058D01* +G01X2960139Y6769270D01* +G01X2959260Y6765755D01* +G01X2957503Y6756967D01* +G01X2955745Y6749058D01* +G01X2954866Y6744224D01* +G01X2953548Y6737633D01* +G01X2952230Y6732361D01* +G01X2950472Y6723573D01* +G01X2949594Y6720058D01* +G01X2947836Y6711270D01* +G01X2946078Y6703361D01* +G01X2945200Y6698527D01* +G01X2943882Y6691936D01* +G01X2942563Y6686664D01* +G01X2940806Y6677876D01* +G01X2939927Y6674361D01* +G01X2938169Y6665573D01* +G01X2936412Y6657664D01* +G01X2935533Y6652830D01* +G01X2934215Y6646239D01* +G01X2932897Y6640967D01* +G01X2931139Y6632179D01* +G01X2930260Y6628664D01* +G01X2927624Y6615482D01* +G01X2927184Y6612406D01* +G01X2894230Y6612406D01* +G01X2861275Y6613285D01* +G01X2861715Y6616361D01* +G01X2863472Y6625148D01* +G01X2864351Y6628664D01* +G01X2865230Y6633497D01* +G01X2866548Y6640088D01* +G01X2867866Y6645361D01* +G01X2868745Y6649754D01* +G01X2869624Y6653270D01* +G01X2871382Y6662057D01* +G01X2873139Y6669967D01* +G01X2873578Y6673042D01* +G01X2868855Y6674361D01* +G01X2854684Y6674800D01* +G01X2833594Y6674361D01* +G01X2831836Y6673372D01* +G01X2830957Y6671285D01* +G01X2830078Y6667330D01* +G01X2829200Y6662497D01* +G01X2827882Y6655906D01* +G01X2826563Y6650633D01* +G01X2825685Y6646239D01* +G01X2824806Y6642724D01* +G01X2823927Y6637891D01* +G01X2822609Y6631300D01* +G01X2821291Y6626027D01* +G01X2820412Y6621633D01* +G01X2819533Y6618118D01* +G01X2819094Y6614603D01* +G01X2819094Y6612406D01* +G01X2752306Y6612406D01* +G37* +G36* +G01X2985185Y6612406D02* +G01X2952230Y6612845D01* +G01X2953109Y6616361D01* +G01X2954427Y6622512D01* +G01X2955745Y6627785D01* +G01X2957503Y6636573D01* +G01X2958381Y6640088D01* +G01X2960139Y6648876D01* +G01X2961897Y6656785D01* +G01X2963654Y6665573D01* +G01X2965412Y6673482D01* +G01X2966291Y6678315D01* +G01X2967609Y6684906D01* +G01X2968927Y6690179D01* +G01X2970684Y6698967D01* +G01X2971563Y6702482D01* +G01X3037912Y6702482D01* +G01X3038351Y6699846D01* +G01X3058563Y6699406D01* +G01X3073613Y6699736D01* +G01X3079215Y6700724D01* +G01X3080533Y6705558D01* +G01X3081851Y6712149D01* +G01X3083169Y6717421D01* +G01X3084048Y6721815D01* +G01X3084927Y6725330D01* +G01X3085806Y6730164D01* +G01X3087124Y6736755D01* +G01X3088442Y6742027D01* +G01X3090200Y6750815D01* +G01X3091078Y6754330D01* +G01X3092836Y6763118D01* +G01X3094594Y6771027D01* +G01X3097230Y6784209D01* +G01X3097669Y6787285D01* +G01X3055487Y6787285D01* +G01X3055048Y6784649D01* +G01X3054169Y6780694D01* +G01X3053291Y6775861D01* +G01X3051972Y6769270D01* +G01X3050654Y6763997D01* +G01X3049776Y6759603D01* +G01X3048897Y6756088D01* +G01X3047139Y6747300D01* +G01X3045382Y6739391D01* +G01X3044503Y6734557D01* +G01X3043184Y6727967D01* +G01X3041866Y6722694D01* +G01X3040988Y6718300D01* +G01X3040109Y6714785D01* +G01X3038351Y6705997D01* +G01X3037912Y6702482D01* +G01X3037912Y6702482D01* +G01X2971563Y6702482D01* +G01X2973321Y6711270D01* +G01X2975078Y6719179D01* +G01X2975957Y6724012D01* +G01X2977276Y6730603D01* +G01X2978594Y6735876D01* +G01X2980351Y6744664D01* +G01X2981230Y6748179D01* +G01X2982987Y6756967D01* +G01X2984745Y6764876D01* +G01X2986503Y6773664D01* +G01X2987381Y6777618D01* +G01X2988700Y6783330D01* +G01X2990457Y6788603D01* +G01X2992654Y6792997D01* +G01X2997048Y6799148D01* +G01X2999684Y6802224D01* +G01X3001882Y6803982D01* +G01X3004957Y6806179D01* +G01X3008912Y6808376D01* +G01X3013306Y6810133D01* +G01X3017260Y6811451D01* +G01X3080972Y6811891D01* +G01X3146442Y6811012D01* +G01X3150836Y6809255D01* +G01X3153912Y6807936D01* +G01X3156548Y6806179D01* +G01X3158745Y6803982D01* +G01X3160942Y6800906D01* +G01X3162700Y6796952D01* +G01X3163578Y6791239D01* +G01X3163139Y6784209D01* +G01X3162260Y6778936D01* +G01X3161382Y6775421D01* +G01X3159624Y6766633D01* +G01X3157866Y6758724D01* +G01X3156988Y6753891D01* +G01X3155669Y6747300D01* +G01X3154351Y6742027D01* +G01X3152594Y6733239D01* +G01X3151715Y6729724D01* +G01X3149957Y6720936D01* +G01X3148200Y6713027D01* +G01X3146442Y6704240D01* +G01X3144684Y6696330D01* +G01X3143806Y6691497D01* +G01X3142488Y6684906D01* +G01X3141169Y6679633D01* +G01X3139412Y6670845D01* +G01X3138533Y6667330D01* +G01X3136775Y6658542D01* +G01X3135018Y6650633D01* +G01X3133260Y6641845D01* +G01X3131503Y6633936D01* +G01X3129745Y6625148D01* +G01X3127987Y6617239D01* +G01X3127548Y6614164D01* +G01X3119200Y6612845D01* +G01X3094154Y6612406D01* +G01X3060760Y6612406D01* +G01X3061200Y6615042D01* +G01X3062518Y6620755D01* +G01X3063836Y6626027D01* +G01X3064715Y6630421D01* +G01X3065594Y6633936D01* +G01X3067351Y6642724D01* +G01X3069109Y6650633D01* +G01X3070866Y6659421D01* +G01X3072624Y6667330D01* +G01X3073503Y6671724D01* +G01X3073942Y6674800D01* +G01X3031760Y6674800D01* +G01X3031321Y6672164D01* +G01X3028685Y6660300D01* +G01X3027806Y6655467D01* +G01X3026488Y6648876D01* +G01X3025169Y6643603D01* +G01X3024291Y6639209D01* +G01X3023412Y6635694D01* +G01X3022533Y6630861D01* +G01X3021215Y6624270D01* +G01X3019897Y6618997D01* +G01X3018578Y6612406D01* +G01X2985185Y6612406D01* +G37* +G36* +G01X2416169Y6612406D02* +G01X2355972Y6612845D01* +G01X2352897Y6614164D01* +G01X2349382Y6615921D01* +G01X2346745Y6617679D01* +G01X2343669Y6620755D01* +G01X2341033Y6625148D01* +G01X2339715Y6628664D01* +G01X2339276Y6633497D01* +G01X2339715Y6639209D01* +G01X2341473Y6647997D01* +G01X2342351Y6651512D01* +G01X2345867Y6669088D01* +G01X2347624Y6676997D01* +G01X2349382Y6685785D01* +G01X2351139Y6693694D01* +G01X2352018Y6698527D01* +G01X2353336Y6705118D01* +G01X2354654Y6710391D01* +G01X2356412Y6719179D01* +G01X2357291Y6722694D01* +G01X2359048Y6731482D01* +G01X2360806Y6739391D01* +G01X2362564Y6748179D01* +G01X2364321Y6756088D01* +G01X2365200Y6760921D01* +G01X2366518Y6767512D01* +G01X2367836Y6772785D01* +G01X2368715Y6777179D01* +G01X2370473Y6784209D01* +G01X2371791Y6787724D01* +G01X2373548Y6791239D01* +G01X2375745Y6795194D01* +G01X2377503Y6798270D01* +G01X2380139Y6800906D01* +G01X2386291Y6806179D01* +G01X2390245Y6808376D01* +G01X2394639Y6810133D01* +G01X2398594Y6811451D01* +G01X2458351Y6811891D01* +G01X2516791Y6811451D01* +G01X2516351Y6807936D01* +G01X2512836Y6790361D01* +G01X2512397Y6787285D01* +G01X2436821Y6787285D01* +G01X2436382Y6783770D01* +G01X2435063Y6777179D01* +G01X2433745Y6771906D01* +G01X2432866Y6767512D01* +G01X2431988Y6763997D01* +G01X2431109Y6759164D01* +G01X2429791Y6752573D01* +G01X2428472Y6747300D01* +G01X2427594Y6742906D01* +G01X2426715Y6739391D01* +G01X2424957Y6730603D01* +G01X2424518Y6726648D01* +G01X2424518Y6724012D01* +G01X2453079Y6724012D01* +G01X2481639Y6723573D01* +G01X2481200Y6720936D01* +G01X2480321Y6716543D01* +G01X2479442Y6713027D01* +G01X2477685Y6704240D01* +G01X2477245Y6701164D01* +G01X2469885Y6699846D01* +G01X2447806Y6699406D01* +G01X2418367Y6699406D01* +G01X2417927Y6696330D01* +G01X2416609Y6690179D01* +G01X2415291Y6684906D01* +G01X2414412Y6680512D01* +G01X2413533Y6676997D01* +G01X2412654Y6672164D01* +G01X2411336Y6665573D01* +G01X2410018Y6660300D01* +G01X2409139Y6655906D01* +G01X2408260Y6652391D01* +G01X2406503Y6643603D01* +G01X2405624Y6639649D01* +G01X2405185Y6637012D01* +G01X2442533Y6637012D01* +G01X2479882Y6636133D01* +G01X2479442Y6633058D01* +G01X2478564Y6629542D01* +G01X2476806Y6620755D01* +G01X2475927Y6615921D01* +G01X2475488Y6612406D01* +G01X2416169Y6612406D01* +G37* +G36* +G01X2495700Y6612406D02* +G01X2496578Y6615042D01* +G01X2497897Y6619876D01* +G01X2499654Y6628664D01* +G01X2500533Y6632179D01* +G01X2502115Y6640088D01* +G01X2568200Y6640088D01* +G01X2568200Y6637451D01* +G01X2587973Y6637012D01* +G01X2608624Y6637451D01* +G01X2610382Y6639209D01* +G01X2611261Y6644043D01* +G01X2612579Y6650633D01* +G01X2613897Y6655906D01* +G01X2614776Y6660300D01* +G01X2615654Y6663815D01* +G01X2617412Y6672603D01* +G01X2619170Y6680512D01* +G01X2620048Y6685345D01* +G01X2621366Y6691936D01* +G01X2622685Y6697209D01* +G01X2623564Y6701603D01* +G01X2624442Y6705118D01* +G01X2625321Y6709951D01* +G01X2626639Y6716543D01* +G01X2627957Y6721815D01* +G01X2629715Y6730603D01* +G01X2630594Y6734118D01* +G01X2631473Y6738951D01* +G01X2632791Y6745542D01* +G01X2634109Y6750815D01* +G01X2635867Y6759603D01* +G01X2636745Y6763118D01* +G01X2638503Y6771906D01* +G01X2640260Y6779815D01* +G01X2641139Y6784209D01* +G01X2641578Y6787285D01* +G01X2600276Y6787285D01* +G01X2599397Y6785088D01* +G01X2598079Y6780694D01* +G01X2597200Y6777179D01* +G01X2595442Y6768391D01* +G01X2593685Y6760482D01* +G01X2592806Y6755648D01* +G01X2591488Y6749058D01* +G01X2590169Y6743785D01* +G01X2589291Y6739391D01* +G01X2588412Y6735876D01* +G01X2586654Y6727088D01* +G01X2584897Y6719179D01* +G01X2584018Y6714345D01* +G01X2582700Y6707755D01* +G01X2581382Y6702482D01* +G01X2580503Y6698088D01* +G01X2579624Y6694573D01* +G01X2578745Y6689739D01* +G01X2577427Y6683148D01* +G01X2576109Y6677876D01* +G01X2574351Y6669088D01* +G01X2573472Y6665573D01* +G01X2572594Y6660739D01* +G01X2571276Y6654148D01* +G01X2569957Y6648876D01* +G01X2568200Y6640088D01* +G01X2568200Y6640088D01* +G01X2502115Y6640088D01* +G01X2502291Y6640967D01* +G01X2504048Y6648876D01* +G01X2504927Y6653709D01* +G01X2506245Y6660300D01* +G01X2507563Y6665573D01* +G01X2509321Y6674361D01* +G01X2510200Y6677876D01* +G01X2511957Y6686664D01* +G01X2513715Y6694573D01* +G01X2514594Y6699406D01* +G01X2515912Y6705997D01* +G01X2517230Y6711270D01* +G01X2518988Y6720058D01* +G01X2519866Y6723573D01* +G01X2521624Y6732361D01* +G01X2523382Y6740270D01* +G01X2524260Y6745103D01* +G01X2525579Y6751694D01* +G01X2526897Y6756967D01* +G01X2528654Y6765755D01* +G01X2529533Y6769270D01* +G01X2530412Y6774103D01* +G01X2531730Y6780694D01* +G01X2533048Y6785967D01* +G01X2534806Y6794754D01* +G01X2535685Y6798270D01* +G01X2537442Y6807057D01* +G01X2537882Y6810133D01* +G01X2556556Y6811451D01* +G01X2612579Y6811891D01* +G01X2689912Y6811012D01* +G01X2694745Y6809255D01* +G01X2699139Y6807057D01* +G01X2702215Y6804421D01* +G01X2703973Y6802224D01* +G01X2705730Y6799148D01* +G01X2707048Y6795633D01* +G01X2707488Y6791679D01* +G01X2707048Y6785088D01* +G01X2706169Y6779815D01* +G01X2705291Y6774982D01* +G01X2703973Y6768391D01* +G01X2702654Y6763118D01* +G01X2700897Y6754330D01* +G01X2700018Y6750815D01* +G01X2698260Y6742027D01* +G01X2696503Y6734118D01* +G01X2694745Y6725330D01* +G01X2692988Y6717421D01* +G01X2692109Y6712588D01* +G01X2690791Y6705997D01* +G01X2689472Y6700724D01* +G01X2687715Y6691936D01* +G01X2686836Y6688421D01* +G01X2685957Y6683588D01* +G01X2684639Y6676997D01* +G01X2683321Y6671724D01* +G01X2681563Y6662936D01* +G01X2680685Y6659421D01* +G01X2678048Y6646239D01* +G01X2676730Y6640527D01* +G01X2674973Y6635694D01* +G01X2673215Y6632179D01* +G01X2671018Y6628664D01* +G01X2668821Y6625588D01* +G01X2667063Y6623391D01* +G01X2664866Y6621194D01* +G01X2661791Y6618997D01* +G01X2657836Y6616361D01* +G01X2653003Y6614164D01* +G01X2649048Y6612845D01* +G01X2571715Y6612406D01* +G01X2495700Y6612406D01* +G37* +G01X994664Y3410458D02* +G01X994664Y3353816D01* +G01X1022858Y3410458D02* +G01X1022858Y3353816D01* +G01X1022858Y3410458D02* +G01X1041654Y3410458D01* +G01X1049782Y3407918D01* +G01X1055370Y3402584D01* +G01X1057910Y3396996D01* +G01X1060704Y3388868D01* +G01X1060704Y3375406D01* +G01X1057910Y3367278D01* +G01X1055370Y3361944D01* +G01X1049782Y3356610D01* +G01X1041654Y3353816D01* +G01X1022858Y3353816D01* +G01X1088898Y3410458D02* +G01X1088898Y3353816D01* +G01X1088898Y3410458D02* +G01X1123950Y3410458D01* +G01X1088898Y3383534D02* +G01X1110488Y3383534D01* +G01X1088898Y3353816D02* +G01X1123950Y3353816D01* +G01X1212596Y3410458D02* +G01X1234186Y3353816D01* +G01X1255776Y3410458D02* +G01X1234186Y3353816D01* +G01X1324356Y3396996D02* +G01X1321816Y3402584D01* +G01X1316482Y3407918D01* +G01X1310894Y3410458D01* +G01X1300226Y3410458D01* +G01X1294892Y3407918D01* +G01X1289304Y3402584D01* +G01X1286764Y3396996D01* +G01X1283970Y3388868D01* +G01X1283970Y3375406D01* +G01X1286764Y3367278D01* +G01X1289304Y3361944D01* +G01X1294892Y3356610D01* +G01X1300226Y3353816D01* +G01X1310894Y3353816D01* +G01X1316482Y3356610D01* +G01X1321816Y3361944D01* +G01X1324356Y3367278D01* +G01X1392936Y3396996D02* +G01X1390396Y3402584D01* +G01X1385062Y3407918D01* +G01X1379474Y3410458D01* +G01X1368806Y3410458D01* +G01X1363472Y3407918D01* +G01X1357884Y3402584D01* +G01X1355344Y3396996D01* +G01X1352550Y3388868D01* +G01X1352550Y3375406D01* +G01X1355344Y3367278D01* +G01X1357884Y3361944D01* +G01X1363472Y3356610D01* +G01X1368806Y3353816D01* +G01X1379474Y3353816D01* +G01X1385062Y3356610D01* +G01X1390396Y3361944D01* +G01X1392936Y3367278D01* +G04 Text End* + +G04 PolygonModel Start* +G54D13* +G01X1323700Y3975000D02* +G01X1323700Y3467000D01* +G01X1069700Y3467000D01* +G01X1069700Y3975000D01* +G01X1323700Y3975000D01* +G01X447405Y13387224D02* +G01X447405Y12763400D01* +G01X2479400Y13387224D02* +G01X2479400Y12763400D01* +G01X447400Y13387300D02* +G01X2479400Y13387224D01* +G01X66400Y7048400D02* +G01X2860400Y7048400D01* +G01X2860400Y12763400D02* +G01X2860400Y7048400D01* +G01X66400Y12763400D02* +G01X66400Y7048400D01* +G01X66400Y12763400D02* +G01X2860400Y12763400D01* +G01X-22500Y10286900D02* +G01X-22500Y6984900D01* +G01X-2308500Y6730900D02* +G01X-276500Y6730900D01* +G01X-2308500Y10540900D02* +G01X-276500Y10540900D01* +G01X-2562500Y6984900D02* +G01X-2562500Y10286900D01* +G01X-2562500Y6984900D02* +G03X-2308500Y6730900I254000J0D01* +G01X-2308500Y10540900D02* +G03X-2562500Y10286900I0J-254000D01* +G01X-22500Y10286900D02* +G03X-276500Y10540900I-254000J0D01* +G01X-22500Y6984900D02* +G02X-276500Y6730900I-254000J0D01* +G01X917300Y2705000D02* +G01X739500Y2705000D01* +G01X739500Y2705000D02* +G01X739500Y3213000D01* +G01X739500Y3213000D02* +G01X917300Y3213000D01* +G01X930000Y25300D02* +G01X41000Y25300D01* +G01X41000Y25300D02* +G01X41000Y5892700D01* +G01X41000Y5892700D02* +G01X930000Y5892700D01* +G01X930000Y5892700D02* +G01X930000Y25300D01* +G01X3781104Y9911100D02* +G01X3781104Y9199900D01* +G01X3781104Y9199900D02* +G01X3067400Y9199900D01* +G01X3067400Y9199900D02* +G01X3067400Y11054100D01* +G01X3067400Y11054100D02* +G01X3778600Y11054100D01* +G01X3778600Y11054100D02* +G01X3778600Y10363555D01* +G01X3719601Y9911100D02* +G01X3719601Y10363555D01* +G01X3719601Y10363555D02* +G01X3862999Y10363555D01* +G01X3854800Y9911100D02* +G01X3719601Y9911100D01* +G01X2983001Y9112006D02* +G01X2983001Y11141999D01* +G01X2983001Y11141994D02* +G01X3862999Y11141994D01* +G01X3862999Y9112006D02* +G01X3862999Y11141999D01* +G01X2983001Y9112006D02* +G01X3862999Y9112006D01* +G36* +G01X3702400Y9619000D02* +G01X3791300Y9669800D01* +G01X3791300Y9555500D01* +G01X3702400Y9619000D01* +G37* +G01X4781104Y9911100D02* +G01X4781104Y9199900D01* +G01X4781104Y9199900D02* +G01X4067400Y9199900D01* +G01X4067400Y9199900D02* +G01X4067400Y11054100D01* +G01X4067400Y11054100D02* +G01X4778600Y11054100D01* +G01X4778600Y11054100D02* +G01X4778600Y10363555D01* +G01X4719601Y9911100D02* +G01X4719601Y10363555D01* +G01X4719601Y10363555D02* +G01X4862999Y10363555D01* +G01X4854800Y9911100D02* +G01X4719601Y9911100D01* +G01X3983001Y9112006D02* +G01X3983001Y11141999D01* +G01X3983001Y11141994D02* +G01X4862999Y11141994D01* +G01X4862999Y9112006D02* +G01X4862999Y11141999D01* +G01X3983001Y9112006D02* +G01X4862999Y9112006D01* +G36* +G01X4702400Y9619000D02* +G01X4791300Y9669800D01* +G01X4791300Y9555500D01* +G01X4702400Y9619000D01* +G37* +G01X-2179148Y10909200D02* +G01X-1419500Y10909200D01* +G01X-1419500Y10909200D02* +G01X-1419500Y10655200D01* +G01X-1419500Y10655200D02* +G01X-2435500Y10655200D01* +G01X-2435500Y10655200D02* +G01X-2435500Y10909200D01* +G01X-2435500Y10909200D02* +G01X-2179148Y10909200D01* +G01X-2179148Y10909200D02* +G01X-2179148Y10655200D01* +G54D10* +G01X1693938Y6067531D02* +G01X1693938Y6402765D01* +G01X2162017Y6067983D02* +G01X1526783Y6067983D01* +G01X2162017Y6403217D02* +G01X1526783Y6403217D01* +G01X2162017Y6067983D02* +G01X2162017Y6096477D01* +G01X2162017Y6403217D02* +G01X2162017Y6374723D01* +G54D13* +G01X1606500Y5931400D02* +G01X1606500Y6039300D01* +G01X1660450Y5985350D02* +G01X1552550Y5985350D01* +G36* +G01X1534401Y6060360D02* +G01X1488681Y6060360D01* +G01X1488681Y6101559D01* +G01X1534401Y6101559D01* +G01X1534401Y6060360D01* +G37* +G36* +G01X1534401Y6410840D02* +G01X1534401Y6369641D01* +G01X1488681Y6369641D01* +G01X1488681Y6410840D01* +G01X1534401Y6410840D01* +G37* +G01X1717700Y4035101D02* +G01X1717700Y3515102D01* +G01X1717700Y3515102D02* +G01X1437700Y3515102D01* +G01X1437700Y4035101D02* +G01X1437700Y3515102D01* +G01X1717700Y4035101D02* +G01X1437700Y4035101D01* +G01X1717700Y3939176D02* +G01X1437700Y3939176D01* + +G04 Rect Start* +G01X-1038500Y9270900D02* +G01X-1521100Y9270900D01* +G01X-1521100Y10540900D01* +G01X-1038500Y10540900D01* +G01X-1038500Y9270900D01* +G04 Rect End* + +M02* + diff --git a/hardware/gerber/Gerber_TopSolderMaskLayer.GTS b/hardware/gerber/Gerber_TopSolderMaskLayer.GTS new file mode 100644 index 0000000..ab8c9e3 --- /dev/null +++ b/hardware/gerber/Gerber_TopSolderMaskLayer.GTS @@ -0,0 +1,258 @@ +G04 Layer: TopSolderMaskLayer* +G04 EasyEDA Pro v3.2.148, 2026-08-18 14:30:59* +G04 Gerber Generator version 0.3* +G04 Scale: 100 percent, Rotated: No, Reflected: No* +G04 Dimensions in millimeters* +G04 Leading zeros omitted, absolute positions, 4 integers and 5 decimals* +G04 Generated by one-click* +G04 Object Configs: Pad,Via,Track,Text,Image,Dimension,BoardOutline,BoardCutout,CopperFilled,SolidRegion,FPCStiffener,Line,PlaneZone,ComponentProperty,ComponentSilkscreen,TearDrop* +G04 Layer Configs: 1,2,3,4,5,6,7,8,9,10,11,13,14,56* +G04 Copper Areas: 0* +%FSLAX45Y45*% +%MOMM*% +%AMRoundRect*1,1,$1,$2,$3*1,1,$1,$4,$5*1,1,$1,0-$2,0-$3*1,1,$1,0-$4,0-$5*20,1,$1,$2,$3,$4,$5,0*20,1,$1,$4,$5,0-$2,0-$3,0*20,1,$1,0-$2,0-$3,0-$4,0-$5,0*20,1,$1,0-$4,0-$5,$2,$3,0*4,1,4,$2,$3,$4,$5,0-$2,0-$3,0-$4,0-$5,$2,$3,0*% +%ADD10C,1.7526*% +%ADD11RoundRect,0.1016X-0.8255X-0.8255X-0.8255X0.8255*% +%ADD12O,2.0066X1.4986*% +%ADD13RoundRect,0.1016X-0.9525X0.6985X0.9525X0.6985*% +%ADD14C,1.8542*% +%ADD15C,1.7037*% +%ADD16C,1.7016*% +%ADD17RoundRect,0.1016X-0.8X-0.8X-0.8X0.8*% +%ADD18C,1.4986*% +%ADD19RoundRect,0.1016X-0.762X-0.762X-0.762X0.762*% +%ADD20C,1.6256*% +%ADD21RoundRect,0.1016X-0.8255X0.8255X0.8255X0.8255*% +%ADD22RoundRect,0.1016X-0.95X1.188X0.95X1.188*% +%ADD23C,1.9016*% +G75* + + +G04 Pad Start* +G54D10* +G01X1196700Y3594000D03* +G54D11* +G01X1196700Y3848000D03* +G54D12* +G01X2733400Y12572900D03* +G01X2733400Y12318900D03* +G01X2733400Y12064900D03* +G01X2733400Y11810900D03* +G01X2733400Y11556900D03* +G01X2733400Y11302900D03* +G01X2733400Y11048900D03* +G01X2733400Y10794900D03* +G01X2733400Y10540900D03* +G01X2733400Y10286900D03* +G01X2733400Y10032900D03* +G01X2733400Y9778900D03* +G01X2733400Y9524900D03* +G01X2733400Y9270900D03* +G01X2733400Y9016900D03* +G01X2733400Y8762900D03* +G01X2733400Y8508900D03* +G01X2733400Y8254900D03* +G01X2733400Y8000900D03* +G01X2733400Y7746900D03* +G01X2733400Y7492900D03* +G01X2733400Y7238900D03* +G01X193400Y7238900D03* +G01X193400Y7492900D03* +G01X193400Y7746900D03* +G01X193400Y8000900D03* +G01X193400Y8254900D03* +G01X193400Y8508900D03* +G01X193400Y8762900D03* +G01X193400Y9016900D03* +G01X193400Y9270900D03* +G01X193400Y9524900D03* +G01X193400Y9778900D03* +G01X193400Y10032900D03* +G01X193400Y10286900D03* +G01X193400Y10540900D03* +G01X193400Y10794900D03* +G01X193400Y11048900D03* +G01X193400Y11302900D03* +G01X193400Y11556900D03* +G01X193400Y11810900D03* +G01X193400Y12064900D03* +G01X193400Y12318900D03* +G54D13* +G01X193400Y12572900D03* +G54D14* +G01X-276500Y7492900D03* +G01X-276500Y7746900D03* +G01X-276500Y8000900D03* +G01X-276500Y8254900D03* +G01X-276500Y8508900D03* +G01X-276500Y8762900D03* +G01X-276500Y9016900D03* +G01X-276500Y9270900D03* +G01X-276500Y9524900D03* +G01X-2308500Y9016900D03* +G01X-2308500Y8762900D03* +G01X-2308500Y8508900D03* +G01X-2308500Y8254900D03* +G01X-2308500Y8000900D03* +G01X-2308500Y7746900D03* +G54D16* +G01X1946000Y5372000D03* +G01X2200000Y5372000D03* +G01X1946000Y5118000D03* +G01X2200000Y5118000D03* +G01X1946000Y4864000D03* +G01X2200000Y4864000D03* +G01X1946000Y4610000D03* +G01X2200000Y4610000D03* +G01X1946000Y4356000D03* +G01X2200000Y4356000D03* +G01X1946000Y4102000D03* +G01X2200000Y4102000D03* +G01X1946000Y3848000D03* +G01X2200000Y3848000D03* +G01X1946000Y3594000D03* +G01X2200000Y3594000D03* +G01X1946000Y3340000D03* +G01X2200000Y3340000D03* +G01X1946000Y3086000D03* +G01X2200000Y3086000D03* +G01X1946000Y2832000D03* +G01X2200000Y2832000D03* +G01X1946000Y2578000D03* +G01X2200000Y2578000D03* +G01X1946000Y2324000D03* +G01X2200000Y2324000D03* +G01X1946000Y2070000D03* +G01X2200000Y2070000D03* +G01X1946000Y1816000D03* +G01X2200000Y1816000D03* +G01X1946000Y1562000D03* +G01X2200000Y1562000D03* +G01X1946000Y1308000D03* +G01X2200000Y1308000D03* +G01X1946000Y1054000D03* +G01X2200000Y1054000D03* +G01X1946000Y800000D03* +G01X2200000Y800000D03* +G01X1946000Y546000D03* +G54D17* +G01X2200000Y546000D03* +G01X612500Y546000D03* +G54D16* +G01X358500Y546000D03* +G01X612500Y800000D03* +G01X358500Y800000D03* +G01X612500Y1054000D03* +G01X358500Y1054000D03* +G01X612500Y1308000D03* +G01X358500Y1308000D03* +G01X612500Y1562000D03* +G01X358500Y1562000D03* +G01X612500Y1816000D03* +G01X358500Y1816000D03* +G01X612500Y2070000D03* +G01X358500Y2070000D03* +G01X612500Y2324000D03* +G01X358500Y2324000D03* +G01X612500Y2578000D03* +G01X358500Y2578000D03* +G54D18* +G01X612500Y2832000D03* +G54D16* +G01X358500Y2832000D03* +G54D18* +G01X612500Y3086000D03* +G54D16* +G01X358500Y3086000D03* +G01X612500Y3340000D03* +G01X358500Y3340000D03* +G01X612500Y3594000D03* +G01X358500Y3594000D03* +G01X612500Y3848000D03* +G01X358500Y3848000D03* +G01X612500Y4102000D03* +G01X358500Y4102000D03* +G01X612500Y4356000D03* +G01X358500Y4356000D03* +G01X612500Y4610000D03* +G01X358500Y4610000D03* +G01X612500Y4864000D03* +G01X358500Y4864000D03* +G01X612500Y5118000D03* +G01X358500Y5118000D03* +G01X612500Y5372000D03* +G01X358500Y5372000D03* +G54D10* +G01X3829410Y6008016D03* +G01X3575410Y6008016D03* +G01X3829410Y6262016D03* +G01X3575410Y6262016D03* +G01X3829410Y6516016D03* +G01X3575410Y6516016D03* +G01X3829410Y6770016D03* +G01X3575410Y6770016D03* +G01X3829410Y7024016D03* +G01X3575410Y7024016D03* +G01X3829410Y7278016D03* +G01X3575410Y7278016D03* +G01X3829410Y7532016D03* +G01X3575410Y7532016D03* +G01X3829410Y7786016D03* +G01X3575410Y7786016D03* +G01X3829410Y8040016D03* +G01X3575410Y8040016D03* +G01X3829410Y8294016D03* +G54D11* +G01X3575410Y8294016D03* +G54D19* +G01X3550000Y9619000D03* +G54D20* +G01X3296000Y9619000D03* +G01X3550000Y9873000D03* +G01X3296000Y9873000D03* +G01X3550000Y10127000D03* +G01X3296000Y10127000D03* +G01X3550000Y10381000D03* +G01X3296000Y10381000D03* +G01X3550000Y10635000D03* +G01X3296000Y10635000D03* +G54D10* +G01X2091542Y10008008D03* +G01X2091542Y9754008D03* +G01X1837542Y10008008D03* +G01X1837542Y9754008D03* +G01X1583542Y10008008D03* +G01X1583542Y9754008D03* +G01X1329542Y10008008D03* +G01X1329542Y9754008D03* +G01X1075542Y10008008D03* +G54D21* +G01X1075542Y9754008D03* +G54D19* +G01X4550000Y9619000D03* +G54D20* +G01X4296000Y9619000D03* +G01X4550000Y9873000D03* +G01X4296000Y9873000D03* +G01X4550000Y10127000D03* +G01X4296000Y10127000D03* +G01X4550000Y10381000D03* +G01X4296000Y10381000D03* +G01X4550000Y10635000D03* +G01X4296000Y10635000D03* +G54D21* +G01X-2308500Y10782200D03* +G54D10* +G01X-2054500Y10782200D03* +G01X-1800500Y10782200D03* +G01X-1546500Y10782200D03* +G54D22* +G01X1584406Y6235600D03* +G01X2104394Y6235600D03* +G54D23* +G01X1577700Y4210102D03* +G01X1577700Y3340102D03* +G04 Pad End* + +M02* + diff --git a/hardware/gerber/How-to-order-PCB.txt b/hardware/gerber/How-to-order-PCB.txt new file mode 100644 index 0000000..1ae4417 --- /dev/null +++ b/hardware/gerber/How-to-order-PCB.txt @@ -0,0 +1,4 @@ +How to Order PCB + +Please refer to: +https://prodocs.easyeda.com/en/pcb/order-order-pcb/index.html \ No newline at end of file diff --git a/hardware/pcb_photo.jpg b/hardware/pcb_photo.jpg new file mode 100644 index 0000000..6b1b92f Binary files /dev/null and b/hardware/pcb_photo.jpg differ diff --git a/spi_gpio_probe/CMakeLists.txt b/spi_gpio_probe/CMakeLists.txt new file mode 100644 index 0000000..50ff3a7 --- /dev/null +++ b/spi_gpio_probe/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(spi_gpio_probe) diff --git a/spi_gpio_probe/main/CMakeLists.txt b/spi_gpio_probe/main/CMakeLists.txt new file mode 100644 index 0000000..52a3b94 --- /dev/null +++ b/spi_gpio_probe/main/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "main.c" INCLUDE_DIRS ".") diff --git a/spi_gpio_probe/main/main.c b/spi_gpio_probe/main/main.c new file mode 100644 index 0000000..4bcbded --- /dev/null +++ b/spi_gpio_probe/main/main.c @@ -0,0 +1,103 @@ +// Standalone diagnostic firmware - NOT part of the real esp-spi project. +// Purpose: bypass the SPI slave peripheral entirely and watch the raw GPIO +// pins (plain digital input, interrupt on every edge) that our real +// firmware's spi_slave.cpp configures for SPI slave use on ESP32-S3: +// CS=GPIO10, SCLK=GPIO12, MOSI=GPIO13, MISO=GPIO11 +// Logs every CS/SCLK edge with a microsecond timestamp and the +// MOSI/MISO/CS level sampled at that instant, so a real transaction +// attempt from the CH341A bridge can be visually reconstructed from the +// console log - answers directly whether the ESP32 sees anything at all +// on these pins, and if so, whether it looks like a sane SPI waveform +// (CS low, some number of SCLK edges, CS high) or not. +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "driver/gpio.h" +#include "esp_timer.h" + +#define PIN_CS 10 +#define PIN_SCLK 12 +#define PIN_MOSI 13 +#define PIN_MISO 11 + +typedef struct +{ + int64_t us; + uint8_t pin; // which pin's edge triggered this event (PIN_CS or PIN_SCLK) + uint8_t level; // level that pin transitioned TO + uint8_t cs; + uint8_t sclk; + uint8_t mosi; + uint8_t miso; +} event_t; + +#define EVQ_LEN 4096 +static QueueHandle_t evq; + +static void IRAM_ATTR gpio_isr(void *arg) +{ + uint32_t pin = (uint32_t)(uintptr_t)arg; + event_t ev; + ev.us = esp_timer_get_time(); + ev.pin = (uint8_t)pin; + ev.level = (uint8_t)gpio_get_level((gpio_num_t)pin); + ev.cs = (uint8_t)gpio_get_level(PIN_CS); + ev.sclk = (uint8_t)gpio_get_level(PIN_SCLK); + ev.mosi = (uint8_t)gpio_get_level(PIN_MOSI); + ev.miso = (uint8_t)gpio_get_level(PIN_MISO); + + BaseType_t hpw = pdFALSE; + xQueueSendFromISR(evq, &ev, &hpw); + if (hpw) portYIELD_FROM_ISR(); +} + +void app_main(void) +{ + printf("\n\n=== spi_gpio_probe starting ===\n"); + printf("Pins: CS=GPIO%d SCLK=GPIO%d MOSI=GPIO%d MISO=GPIO%d\n", PIN_CS, PIN_SCLK, PIN_MOSI, PIN_MISO); + printf("Watching CS + SCLK edges only (plain digital input, no SPI peripheral involved).\n\n"); + + evq = xQueueCreate(EVQ_LEN, sizeof(event_t)); + + gpio_config_t io = { 0 }; + io.pin_bit_mask = (1ULL << PIN_CS) | (1ULL << PIN_SCLK) | (1ULL << PIN_MOSI) | (1ULL << PIN_MISO); + io.mode = GPIO_MODE_INPUT; + io.pull_up_en = GPIO_PULLUP_DISABLE; + io.pull_down_en = GPIO_PULLDOWN_DISABLE; + io.intr_type = GPIO_INTR_ANYEDGE; + gpio_config(&io); + + gpio_install_isr_service(0); + gpio_isr_handler_add((gpio_num_t)PIN_CS, gpio_isr, (void*)(uintptr_t)PIN_CS); + gpio_isr_handler_add((gpio_num_t)PIN_SCLK, gpio_isr, (void*)(uintptr_t)PIN_SCLK); + + printf("Idle levels right now: CS=%d SCLK=%d MOSI=%d MISO=%d\n\n", + gpio_get_level(PIN_CS), gpio_get_level(PIN_SCLK), + gpio_get_level(PIN_MOSI), gpio_get_level(PIN_MISO)); + + int64_t last_us = 0; + unsigned long total_events = 0; + unsigned long cs_high_count = 0; + + for (;;) + { + event_t ev; + if (xQueueReceive(evq, &ev, pdMS_TO_TICKS(3000))) + { + const char *pin_name = (ev.pin == PIN_CS) ? "CS " : "SCLK"; + long long delta = last_us ? (long long)(ev.us - last_us) : 0; + printf("[t=%10lld us d=%6lld us] %s -> %d | CS=%d SCLK=%d MOSI=%d MISO=%d\n", + (long long)ev.us, delta, pin_name, ev.level, + ev.cs, ev.sclk, ev.mosi, ev.miso); + last_us = ev.us; + total_events++; + if (ev.pin == PIN_CS && ev.level == 1) cs_high_count++; + } + else + { + printf("--- idle (no CS/SCLK edges in last 3s) --- total_events=%lu cs_high_transitions=%lu\n", + total_events, cs_high_count); + } + } +} diff --git a/spi_gpio_probe/sdkconfig b/spi_gpio_probe/sdkconfig new file mode 100644 index 0000000..5107663 --- /dev/null +++ b/spi_gpio_probe/sdkconfig @@ -0,0 +1,4051 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) 6.1.0 Project Configuration +# +# default: +CONFIG_SOC_ADC_SUPPORTED=y +# default: +CONFIG_SOC_UART_SUPPORTED=y +# default: +CONFIG_SOC_PCNT_SUPPORTED=y +# default: +CONFIG_SOC_PHY_SUPPORTED=y +# default: +CONFIG_SOC_WIFI_SUPPORTED=y +# default: +CONFIG_SOC_TWAI_SUPPORTED=y +# default: +CONFIG_SOC_GDMA_SUPPORTED=y +# default: +CONFIG_SOC_UHCI_SUPPORTED=y +# default: +CONFIG_SOC_AHB_GDMA_SUPPORTED=y +# default: +CONFIG_SOC_GPTIMER_SUPPORTED=y +# default: +CONFIG_SOC_LCDCAM_CAM_SUPPORTED=y +# default: +CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y +# default: +CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y +# default: +CONFIG_SOC_LCD_I80_SUPPORTED=y +# default: +CONFIG_SOC_LCD_RGB_SUPPORTED=y +# default: +CONFIG_SOC_MCPWM_SUPPORTED=y +# default: +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +# default: +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +# default: +CONFIG_SOC_ULP_SUPPORTED=y +# default: +CONFIG_SOC_ULP_FSM_SUPPORTED=y +# default: +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +# default: +CONFIG_SOC_BT_SUPPORTED=y +# default: +CONFIG_SOC_USB_OTG_SUPPORTED=y +# default: +CONFIG_SOC_USB_DFU_SUPPORTED=y +# default: +CONFIG_SOC_USB_OTG_CONSOLE_SUPPORTED=y +# default: +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +# default: +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +# default: +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +# default: +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +# default: +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +# default: +CONFIG_SOC_EFUSE_SUPPORTED=y +# default: +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +# default: +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +# default: +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +# default: +CONFIG_SOC_RTC_MEM_SUPPORTED=y +# default: +CONFIG_SOC_RTC_TIMER_SUPPORTED=y +# default: +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +# default: +CONFIG_SOC_XT_WDT_SUPPORTED=y +# default: +CONFIG_SOC_I2S_SUPPORTED=y +# default: +CONFIG_SOC_RMT_SUPPORTED=y +# default: +CONFIG_SOC_SDM_SUPPORTED=y +# default: +CONFIG_SOC_GPSPI_SUPPORTED=y +# default: +CONFIG_SOC_LEDC_SUPPORTED=y +# default: +CONFIG_SOC_I2C_SUPPORTED=y +# default: +CONFIG_SOC_SYSTIMER_SUPPORTED=y +# default: +CONFIG_SOC_SUPPORT_COEXISTENCE=y +# default: +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +# default: +CONFIG_SOC_AES_SUPPORTED=y +# default: +CONFIG_SOC_MPI_SUPPORTED=y +# default: +CONFIG_SOC_SHA_SUPPORTED=y +# default: +CONFIG_SOC_HMAC_SUPPORTED=y +# default: +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +# default: +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +# default: +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +# default: +CONFIG_SOC_MEMPROT_SUPPORTED=y +# default: +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +# default: +CONFIG_SOC_BOD_SUPPORTED=y +# default: +CONFIG_SOC_CLK_TREE_SUPPORTED=y +# default: +CONFIG_SOC_REGI2C_SUPPORTED=y +# default: +CONFIG_SOC_MPU_SUPPORTED=y +# default: +CONFIG_SOC_WDT_SUPPORTED=y +# default: +CONFIG_SOC_RTC_WDT_SUPPORTED=y +# default: +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +# default: +CONFIG_SOC_RNG_SUPPORTED=y +# default: +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +# default: +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +# default: +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +# default: +CONFIG_SOC_PM_SUPPORTED=y +# default: +CONFIG_SOC_SIMD_INSTRUCTION_SUPPORTED=y +# default: +CONFIG_SOC_SPI_EXTERNAL_NOR_FLASH_SUPPORTED=y +# default: +CONFIG_SOC_XTAL_SUPPORT_40M=y +# default: +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +# default: +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +# default: +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +# default: +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +# default: +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +# default: +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +# default: +CONFIG_SOC_ADC_DMA_SUPPORTED=y +# default: +CONFIG_SOC_ADC_PERIPH_NUM=2 +# default: +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +# default: +CONFIG_SOC_ADC_ATTEN_NUM=4 +# default: +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +# default: +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +# default: +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +# default: +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +# default: +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +# default: +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +# default: +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +# default: +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=2 +# default: +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +# default: +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +# default: +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +# default: +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +# default: +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +# default: +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +# default: +CONFIG_SOC_ADC_SHARED_POWER=y +# default: +CONFIG_SOC_APB_BACKUP_DMA=y +# default: +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +# default: +CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED=y +# default: +CONFIG_SOC_CACHE_FREEZE_SUPPORTED=y +# default: +CONFIG_SOC_CACHE_ACS_INVALID_STATE_ON_PANIC=y +# default: +CONFIG_SOC_CPU_CORES_NUM=2 +# default: +CONFIG_SOC_CPU_INTR_NUM=32 +# default: +CONFIG_SOC_CPU_HAS_FPU=y +# default: +CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y +# default: +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +# default: +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +# default: +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +# default: +CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 +# default: +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +# default: +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +# default: +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +# default: +CONFIG_SOC_AHB_GDMA_VERSION=1 +# default: +CONFIG_SOC_GPIO_PORT=1 +# default: +CONFIG_SOC_GPIO_PIN_COUNT=49 +# default: +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +# default: +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +# default: +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +# default: +CONFIG_SOC_GPIO_IN_RANGE_MAX=48 +# default: +CONFIG_SOC_GPIO_OUT_RANGE_MAX=48 +# default: +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000 +# default: +CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y +# default: +CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +# default: +CONFIG_SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP=y +# default: +CONFIG_SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK=0 +# default: +CONFIG_SOC_I2C_NUM=2 +# default: +CONFIG_SOC_HP_I2C_NUM=2 +# default: +CONFIG_SOC_I2C_SUPPORT_XTAL=y +# default: +CONFIG_SOC_I2C_SUPPORT_RTC=y +# default: +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +# default: +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +# default: +CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST=y +# default: +CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE=y +# default: +CONFIG_SOC_I2S_HW_VERSION_2=y +# default: +CONFIG_SOC_I2S_SUPPORTS_PCM=y +# default: +CONFIG_SOC_I2S_SUPPORTS_PDM=y +# default: +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +# default: +CONFIG_SOC_I2S_SUPPORTS_PCM2PDM=y +# default: +CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +# default: +CONFIG_SOC_I2S_SUPPORTS_PDM2PCM=y +# default: +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2 +# default: +CONFIG_SOC_I2S_PDM_MAX_RX_LINES=4 +# default: +CONFIG_SOC_I2S_SUPPORTS_TDM=y +# default: +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +# default: +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +# default: +CONFIG_SOC_LEDC_TIMER_NUM=4 +# default: +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +# default: +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +# default: +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +# default: +CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y +# default: +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +# default: +CONFIG_SOC_MMU_PERIPH_NUM=1 +# default: +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +# default: +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +# default: +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +# default: +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +# default: +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +# default: +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y +# default: +CONFIG_SOC_RMT_SUPPORT_DMA=y +# default: +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +# default: +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +# default: +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +# default: +CONFIG_SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS=y +# default: +CONFIG_SOC_RTCIO_PIN_COUNT=22 +# default: +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +# default: +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +# default: +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +# default: +CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y +# default: +CONFIG_SOC_SPI_PERIPH_NUM=3 +# default: +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +# default: +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +# default: +CONFIG_SOC_SPI_SUPPORT_OCT=y +# default: +CONFIG_SOC_SPIRAM_SUPPORTED=y +# default: +CONFIG_SOC_SPIRAM_XIP_SUPPORTED=y +# default: +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +# default: +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 +# default: +CONFIG_SOC_RTC_TIMER_V1=y +# default: +CONFIG_SOC_TOUCH_SENSOR_VERSION=2 +# default: +CONFIG_SOC_TOUCH_MIN_CHAN_ID=1 +# default: +CONFIG_SOC_TOUCH_MAX_CHAN_ID=14 +# default: +CONFIG_SOC_TOUCH_SUPPORT_BENCHMARK=y +# default: +CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y +# default: +CONFIG_SOC_TOUCH_SUPPORT_WATERPROOF=y +# default: +CONFIG_SOC_TOUCH_SUPPORT_PROX_SENSING=y +# default: +CONFIG_SOC_TOUCH_SUPPORT_DENOISE_CHAN=y +# default: +CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3 +# default: +CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 +# default: +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 +# default: +CONFIG_SOC_TWAI_MASK_FILTER_NUM=1 +# default: +CONFIG_SOC_UART_NUM=3 +# default: +CONFIG_SOC_UART_HP_NUM=3 +# default: +CONFIG_SOC_UART_FIFO_LEN=128 +# default: +CONFIG_SOC_UART_BITRATE_MAX=5000000 +# default: +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +# default: +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +# default: +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +# default: +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +# default: +CONFIG_SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE=y +# default: +CONFIG_SOC_USB_OTG_PERIPH_NUM=1 +# default: +CONFIG_SOC_USB_FSLS_PHY_NUM=1 +# default: +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +# default: +CONFIG_SOC_SHA_SUPPORT_DMA=y +# default: +CONFIG_SOC_SHA_SUPPORT_RESUME=y +# default: +CONFIG_SOC_SHA_GDMA=y +# default: +CONFIG_SOC_SHA_SUPPORT_SHA1=y +# default: +CONFIG_SOC_SHA_SUPPORT_SHA224=y +# default: +CONFIG_SOC_SHA_SUPPORT_SHA256=y +# default: +CONFIG_SOC_SHA_SUPPORT_SHA384=y +# default: +CONFIG_SOC_SHA_SUPPORT_SHA512=y +# default: +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +# default: +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +# default: +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +# default: +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +# default: +CONFIG_SOC_MPI_OPERATIONS_NUM=3 +# default: +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +# default: +CONFIG_SOC_AES_SUPPORT_DMA=y +# default: +CONFIG_SOC_AES_GDMA=y +# default: +CONFIG_SOC_AES_SUPPORT_AES_128=y +# default: +CONFIG_SOC_AES_SUPPORT_AES_256=y +# default: +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +# default: +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y +# default: +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +# default: +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +# default: +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +# default: +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +# default: +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +# default: +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +# default: +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +# default: +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +# default: +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +# default: +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +# default: +CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +# default: +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +# default: +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +# default: +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +# default: +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +# default: +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +# default: +CONFIG_SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP=y +# default: +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +# default: +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +# default: +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +# default: +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y +# default: +CONFIG_SOC_CLK_LP_FAST_SUPPORT_XTAL_D2=y +# default: +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y +# default: +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_DCACHE=y +# default: +CONFIG_SOC_EFUSE_HARD_DIS_JTAG=y +# default: +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +# default: +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +# default: +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +# default: +CONFIG_SOC_EFUSE_DIS_ICACHE=y +# default: +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +# default: +CONFIG_SOC_EFUSE_XTS_AES_KEY_128=y +# default: +CONFIG_SOC_EFUSE_XTS_AES_KEY_256=y +# default: +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +# default: +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +# default: +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +# default: +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +# default: +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +# default: +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +# default: +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +# default: +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +# default: +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +# default: +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +# default: +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +# default: +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +# default: +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +# default: +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE=y +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING=y +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +# default: +CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY=y +# default: +CONFIG_SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM=y +# default: +CONFIG_SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP=y +# default: +CONFIG_SOC_SPI_MEM_FLASH_SUPPORT_HPM=y +# default: +CONFIG_SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT=y +# default: +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +# default: +CONFIG_SOC_MEMSPI_ENCRYPTION_ALIGNMENT=16 +# default: +CONFIG_SOC_COEX_HW_PTI=y +# default: +CONFIG_SOC_EXTERNAL_COEX_LEADER_TX_LINE=y +# default: +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +# default: +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +# default: +CONFIG_SOC_SDMMC_DATA_WIDTH_MAX=8 +# default: +CONFIG_SOC_SDMMC_DELAY_PHASE_NUM=4 +# default: +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +# default: +CONFIG_SOC_WIFI_HW_TSF=y +# default: +CONFIG_SOC_WIFI_FTM_SUPPORT=y +# default: +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +# default: +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +# default: +CONFIG_SOC_WIFI_TXOP_SUPPORT=y +# default: +CONFIG_SOC_WIFI_CSI_SUPPORT=y +# default: +CONFIG_SOC_WIFI_MESH_SUPPORT=y +# default: +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +# default: +CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND=y +# default: +CONFIG_SOC_BLE_SUPPORTED=y +# default: +CONFIG_SOC_BLE_MESH_SUPPORTED=y +# default: +CONFIG_SOC_BLE_50_SUPPORTED=y +# default: +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +# default: +CONFIG_SOC_BLUFI_SUPPORTED=y +# default: +CONFIG_SOC_ULP_HAS_ADC=y +# default: +CONFIG_SOC_PHY_COMBO_MODULE=y +# default: +CONFIG_SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV=y +# default: +CONFIG_IDF_CMAKE=y +# default: +CONFIG_IDF_TOOLCHAIN="gcc" +# default: +CONFIG_IDF_TOOLCHAIN_GCC=y +# default: +CONFIG_IDF_TARGET_ARCH_XTENSA=y +# default: +CONFIG_IDF_TARGET_ARCH="xtensa" +# default: +CONFIG_IDF_TARGET="esp32s3" +# default: +CONFIG_IDF_INIT_VERSION="6.1.0" +# default: +CONFIG_IDF_TARGET_ESP32S3=y +# default: +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# Build type +# +# default: +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# default: +# CONFIG_APP_BUILD_TYPE_RAM is not set +# default: +CONFIG_APP_BUILD_GENERATE_BINARIES=y +# default: +CONFIG_APP_BUILD_BOOTLOADER=y +# default: +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y + +# +# Minimize binary changes between builds +# +# default: +# CONFIG_APP_BUILD_MINIMIZE_BINARY_CHANGES is not set +# end of Minimize binary changes between builds + +# default: +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# default: +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# App Update config +# +# end of App Update config + +# +# Bootloader config +# + +# +# Bootloader manager +# +# default: +CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y +# default: +CONFIG_BOOTLOADER_PROJECT_VER=1 +# end of Bootloader manager + +# +# Application Rollback +# +# default: +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# end of Application Rollback + +# +# Recovery Bootloader and Rollback +# +# end of Recovery Bootloader and Rollback + +# default: +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +# default: +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# default: +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# default: +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set + +# +# Log +# +# default: +CONFIG_BOOTLOADER_LOG_VERSION_1=y +# default: +CONFIG_BOOTLOADER_LOG_VERSION=1 +# default: +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# default: +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# default: +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +# default: +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# default: +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# default: +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +# default: +CONFIG_BOOTLOADER_LOG_LEVEL=3 + +# +# Format +# +# default: +# CONFIG_BOOTLOADER_LOG_COLORS is not set +# default: +CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y +# end of Format + +# +# Settings +# +# default: +CONFIG_BOOTLOADER_LOG_MODE_TEXT_EN=y +# default: +CONFIG_BOOTLOADER_LOG_MODE_TEXT=y +# end of Settings +# end of Log + +# default: +CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ=80 + +# +# Serial Flash Configurations +# +# default: +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +# default: +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations + +# default: +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# default: +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# default: +# CONFIG_BOOTLOADER_APP_TEST is not set +# default: +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +# default: +CONFIG_BOOTLOADER_WDT_ENABLE=y +# default: +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +# default: +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# default: +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# default: +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# default: +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +# default: +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# default: +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +# default: +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +# default: +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# default: +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# default: +CONFIG_SECURE_BOOT_IMAGE_DIGEST_LEN=32 +# default: +CONFIG_SECURE_BOOT_ROM_FAST_WAKE_RESERVE_SIZE=0 +# default: +# CONFIG_SECURE_BOOT is not set +# default: +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# default: +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +# default: +CONFIG_APP_COMPILE_TIME_DATE=y +# default: +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# default: +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# default: +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +# default: +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 +# end of Application manager + +# default: +CONFIG_ESP_ROM_HAS_CRC_LE=y +# default: +CONFIG_ESP_ROM_HAS_CRC_BE=y +# default: +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +# default: +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +# default: +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +# default: +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +# default: +CONFIG_ESP_ROM_USB_OTG_NUM=3 +# default: +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +# default: +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +# default: +CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV=y +# default: +CONFIG_ESP_ROM_GET_CLK_FREQ=y +# default: +CONFIG_ESP_ROM_HAS_HAL_WDT=y +# default: +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +# default: +CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y +# default: +CONFIG_ESP_ROM_HAS_SPI_FLASH=y +# default: +CONFIG_ESP_ROM_HAS_SPI_FLASH_MMAP=y +# default: +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y +# default: +CONFIG_ESP_ROM_HAS_NEWLIB=y +# default: +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +# default: +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +# default: +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +# default: +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +# default: +CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y +# default: +CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y +# default: +CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG=y +# default: +CONFIG_ESP_ROM_HAS_SW_FLOAT=y +# default: +CONFIG_ESP_ROM_HAS_VERSION=y +# default: +CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y +# default: +CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC=y +# default: +CONFIG_ESP_ROM_CONSOLE_OUTPUT_SECONDARY=y +# default: +CONFIG_ESP_ROM_HAS_REGI2C_IMPL=y +# default: +CONFIG_ESP_ROM_BOOTLOADER_OFFSET_FLASH=0x0 + +# +# Boot ROM Behavior +# +# default: +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# default: +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# default: +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# default: +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# default: +# CONFIG_ESPTOOLPY_NO_STUB is not set +# default: +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +# default: +CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y +# default: +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# default: +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +# default: +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# default: +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +# default: +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +# default: +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# default: +CONFIG_ESPTOOLPY_FLASHMODE_VAL=3 +# default: +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +# default: +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# default: +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# default: +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +# default: +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# default: +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# default: +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# default: +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# default: +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# default: +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# default: +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# default: +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# default: +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +# default: +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +# default: +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +# default: +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# default: +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +# default: +CONFIG_ESPTOOLPY_BEFORE="default-reset" +# default: +CONFIG_ESPTOOLPY_AFTER_RESET=y +# default: +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +# default: +CONFIG_ESPTOOLPY_AFTER="hard-reset" +# default: +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# default: +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# default: +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# default: +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# default: +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +# default: +# CONFIG_PARTITION_TABLE_CUSTOM is not set +# default: +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +# default: +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +# default: +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +# default: +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +# default: +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y +# default: +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# default: +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# default: +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +# default: +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# default: +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# default: +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +# default: +# CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE is not set +# default: +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +# default: +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# default: +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +# default: +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# default: +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# default: +# CONFIG_COMPILER_CXX_RTTI is not set +# default: +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# default: +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# default: +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# default: +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# default: +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set +# default: +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# default: +# CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS is not set +# default: +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# default: +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# default: +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set +# default: +# CONFIG_COMPILER_DISABLE_GCC15_WARNINGS is not set +# default: +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# default: +CONFIG_COMPILER_RT_LIB_GCCLIB=y +# default: +CONFIG_COMPILER_RT_LIB_NAME="gcc" +# default: +CONFIG_COMPILER_ORPHAN_SECTIONS_ERROR=y +# default: +# CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING is not set +# default: +# CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE is not set +# default: +# CONFIG_COMPILER_STATIC_ANALYZER is not set +# default: +CONFIG_COMPILER_CXX_GLIBCXX_CONSTEXPR_NO_CHANGE=y +# default: +# CONFIG_COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD_CONSTEXPR is not set +# default: +# CONFIG_COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD is not set +# end of Compiler options + +# +# Component config +# + +# +# Bluetooth +# +# default: +# CONFIG_BT_ENABLED is not set + +# +# Common Options +# + +# +# BT Logs +# + +# +# Log Sources +# +# end of Log Sources + +# default: +# CONFIG_BT_LOG_CRITICAL_ONLY is not set +# default: +# CONFIG_BLE_LOG_ENABLED is not set + +# +# Legacy SPI Log Output (Deprecated - use BT Log Async Output instead) +# +# default: +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# end of Legacy SPI Log Output (Deprecated - use BT Log Async Output instead) +# end of BT Logs + +# default: +# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set +# end of Common Options +# end of Bluetooth + +# +# Console Library +# +# default: +# CONFIG_CONSOLE_SORTED_HELP is not set +# end of Console Library + +# +# Legacy Driver Configurations +# + +# +# Legacy TWAI Driver Configurations +# +# default: +# CONFIG_TWAI_ISR_IN_IRAM_LEGACY is not set +# default: +# CONFIG_TWAI_SUPPRESS_DEPRECATE_WARN is not set +# default: +# CONFIG_TWAI_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy TWAI Driver Configurations + +# +# Legacy I2C Driver Configurations +# +# default: +# CONFIG_I2C_SUPPRESS_DEPRECATE_WARN is not set +# default: +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations + +# +# Legacy Touch Sensor Driver Configurations +# +# default: +# CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN is not set +# default: +# CONFIG_TOUCH_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Touch Sensor Driver Configurations +# end of Legacy Driver Configurations + +# +# eFuse Bit Manager +# +# default: +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# default: +# CONFIG_EFUSE_VIRTUAL is not set +# default: +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +# default: +CONFIG_ESP_TLS_USING_MBEDTLS=y +# default: +# CONFIG_ESP_TLS_CUSTOM_STACK is not set +# default: +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# default: +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# default: +# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set +# default: +# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set +# default: +# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set +# default: +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# default: +# CONFIG_ESP_TLS_INSECURE is not set +# default: +CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y +# end of ESP-TLS + +# +# ADC and ADC Calibration +# +# default: +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# default: +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# default: +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# default: +# CONFIG_ADC_ENABLE_DEBUG_LOG is not set +# end of ADC and ADC Calibration + +# +# Wireless Coexistence +# +# default: +CONFIG_ESP_COEX_ENABLED=y +# default: +# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set +# default: +# CONFIG_ESP_COEX_GPIO_DEBUG is not set +# end of Wireless Coexistence + +# +# Common ESP-related +# +# default: +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# ESP-Driver:Camera Controller Configurations +# +# default: +# CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE is not set +# end of ESP-Driver:Camera Controller Configurations + +# +# GDMA Configurations +# +# default: +CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y +# default: +CONFIG_GDMA_ISR_HANDLER_IN_IRAM=y +# default: +CONFIG_GDMA_OBJ_DRAM_SAFE=y +# default: +# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set +# end of GDMA Configurations + +# +# ESP-Driver:GPIO Configurations +# +# default: +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations + +# +# ESP-Driver:GPTimer Configurations +# +# default: +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# default: +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# default: +# CONFIG_GPTIMER_ISR_CACHE_SAFE is not set +# default: +CONFIG_GPTIMER_OBJ_CACHE_SAFE=y +# default: +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations + +# +# ESP-Driver:I2C Configurations +# +# default: +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# default: +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# default: +CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM=y +# end of ESP-Driver:I2C Configurations + +# +# ESP-Driver:I2S Configurations +# +# default: +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# default: +# CONFIG_I2S_CTRL_FUNC_IN_IRAM is not set +# default: +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations + +# +# ESP-Driver:I3C Master Configurations +# +# default: +# CONFIG_I3C_MASTER_ISR_CACHE_SAFE is not set +# default: +# CONFIG_I3C_MASTER_ENABLE_DEBUG_LOG is not set +# default: +# CONFIG_I3C_MASTER_ISR_HANDLER_IN_IRAM is not set +# end of ESP-Driver:I3C Master Configurations + +# +# ESP-Driver:LEDC Configurations +# +# default: +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations + +# +# ESP-Driver:MCPWM Configurations +# +# default: +CONFIG_MCPWM_ISR_HANDLER_IN_IRAM=y +# default: +# CONFIG_MCPWM_ISR_CACHE_SAFE is not set +# default: +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +# default: +CONFIG_MCPWM_OBJ_CACHE_SAFE=y +# default: +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:MCPWM Configurations + +# +# ESP-Driver:PCNT Configurations +# +# default: +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# default: +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# default: +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:PCNT Configurations + +# +# ESP-Driver:RMT Configurations +# +# default: +CONFIG_RMT_ENCODER_FUNC_IN_IRAM=y +# default: +CONFIG_RMT_TX_ISR_HANDLER_IN_IRAM=y +# default: +CONFIG_RMT_RX_ISR_HANDLER_IN_IRAM=y +# default: +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# default: +# CONFIG_RMT_TX_ISR_CACHE_SAFE is not set +# default: +# CONFIG_RMT_RX_ISR_CACHE_SAFE is not set +# default: +CONFIG_RMT_OBJ_CACHE_SAFE=y +# default: +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# default: +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# end of ESP-Driver:RMT Configurations + +# +# ESP-Driver:Sigma Delta Modulator Configurations +# +# default: +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# default: +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations + +# +# ESP-Driver:SD Host SDMMC Controller Configurations +# +# default: +# CONFIG_SD_HOST_SDMMC_ISR_CACHE_SAFE is not set +# end of ESP-Driver:SD Host SDMMC Controller Configurations + +# +# ESP-Driver:SPI Configurations +# +# default: +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# default: +# CONFIG_SPI_SLAVE_IN_IRAM is not set +# default: +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations + +# +# ESP-Driver:Touch Sensor Configurations +# +# default: +# CONFIG_TOUCH_CTRL_FUNC_IN_IRAM is not set +# default: +# CONFIG_TOUCH_ISR_IRAM_SAFE is not set +# default: +# CONFIG_TOUCH_ENABLE_DEBUG_LOG is not set +# default: +# CONFIG_TOUCH_SKIP_FSM_CHECK is not set +# end of ESP-Driver:Touch Sensor Configurations + +# +# ESP-Driver:Temperature Sensor Configurations +# +# default: +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Temperature Sensor Configurations + +# +# ESP-Driver:TWAI Configurations +# +# default: +# CONFIG_TWAI_ISR_IN_IRAM is not set +# default: +# CONFIG_TWAI_IO_FUNC_IN_IRAM is not set +# default: +# CONFIG_TWAI_ISR_CACHE_SAFE is not set +# default: +# CONFIG_TWAI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:TWAI Configurations + +# +# ESP-Driver:UART Configurations +# +# default: +# CONFIG_UART_ISR_IN_IRAM is not set +# end of ESP-Driver:UART Configurations + +# +# ESP-Driver:UHCI Configurations +# +# default: +# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set +# default: +# CONFIG_UHCI_ISR_CACHE_SAFE is not set +# default: +# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:UHCI Configurations + +# +# ESP-Driver:USB Serial/JTAG Configuration +# +# default: +CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y +# end of ESP-Driver:USB Serial/JTAG Configuration + +# +# Ethernet +# +# default: +CONFIG_ETH_ENABLED=y +# default: +CONFIG_ETH_USE_SPI_ETHERNET=y +# default: +# CONFIG_ETH_USE_OPENETH is not set +# default: +# CONFIG_ETH_TRANSMIT_MUTEX is not set +# end of Ethernet + +# +# Event Loop Library +# +# default: +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +# default: +CONFIG_ESP_EVENT_POST_FROM_ISR=y +# default: +CONFIG_ESP_EVENT_POST_FROM_ISR_SIZE=4 +# default: +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# default: +CONFIG_ESP_GDBSTUB_ENABLED=y +# default: +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +# default: +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +# default: +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 +# end of GDB Stub + +# +# ESP HID +# +# default: +CONFIG_ESPHID_TASK_SIZE_BT=2048 +# default: +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID + +# +# ESP HTTP client +# +# default: +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# default: +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# default: +# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set +# default: +# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set +# default: +# CONFIG_ESP_HTTP_CLIENT_ENABLE_GET_CONTENT_RANGE is not set +# default: +CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT=2000 +# default: +# CONFIG_ESP_HTTP_CLIENT_SAVE_RESPONSE_HEADERS is not set +# default: +CONFIG_ESP_HTTP_CLIENT_STRICT_HEADER_BUFFER=y +# end of ESP HTTP client + +# +# HTTP Server +# +# default: +CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 +# default: +CONFIG_HTTPD_MAX_URI_LEN=512 +# default: +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +# default: +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# default: +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# default: +# CONFIG_HTTPD_WS_SUPPORT is not set +# default: +# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +# default: +CONFIG_HTTPD_ENABLE_EVENTS=y +# default: +CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000 +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# default: +# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set +# default: +# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set +# default: +CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000 +# default: +# CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD is not set +# default: +CONFIG_ESP_HTTPS_OTA_VERIFY_SPI_MODE=y +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# default: +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# default: +# CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# +# default: +CONFIG_ESP_HW_SUPPORT_FUNC_IN_IRAM=y + +# +# Chip revision +# +# default: +CONFIG_ESP32S3_REV_MIN_0=y +# default: +# CONFIG_ESP32S3_REV_MIN_1 is not set +# default: +# CONFIG_ESP32S3_REV_MIN_2 is not set +# default: +CONFIG_ESP32S3_REV_MIN_FULL=0 +# default: +CONFIG_ESP_REV_MIN_FULL=0 + +# +# Maximum Supported ESP32-S3 Revision (Rev v0.99) +# +# default: +CONFIG_ESP32S3_REV_MAX_FULL=99 +# default: +CONFIG_ESP_REV_MAX_FULL=99 +# default: +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +# default: +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199 + +# +# Maximum Supported ESP32-S3 eFuse Block Revision (eFuse Block Rev v1.99) +# +# end of Chip revision + +# +# MAC Config +# +# default: +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +# default: +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +# default: +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +# default: +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# default: +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +# default: +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 +# default: +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +# default: +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +# default: +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# default: +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set +# end of MAC Config + +# +# Sleep Config +# +# default: +# CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set +# default: +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +# default: +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +# default: +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +# default: +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +# default: +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 +# default: +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# default: +# CONFIG_ESP_SLEEP_DEBUG is not set +# default: +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# default: +# CONFIG_ESP_SLEEP_SET_FLASH_DPD is not set +# end of Sleep Config + +# +# RTC Clock Config +# +# default: +CONFIG_RTC_CLK_SRC_INT_RC=y +# default: +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# default: +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# default: +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +# default: +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# default: +CONFIG_RTC_CLK_FUNC_IN_IRAM=y +# default: +CONFIG_RTC_TIME_FUNC_IN_IRAM=y +# end of RTC Clock Config + +# +# Peripheral Control +# +# default: +CONFIG_ESP_PERIPH_CTRL_FUNC_IN_IRAM=y +# default: +CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control + +# +# Main XTAL Config +# +# default: +CONFIG_XTAL_FREQ_40=y +# default: +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config + +# +# Power Supplier +# + +# +# Brownout Detector +# +# default: +CONFIG_ESP_BROWNOUT_DET=y +# default: +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# default: +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# default: +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# default: +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# default: +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# default: +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +# default: +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set +# default: +CONFIG_ESP_BROWNOUT_DET_LVL=7 +# default: +CONFIG_ESP_BROWNOUT_USE_INTR=y +# end of Brownout Detector +# end of Power Supplier + +# default: +CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y +# default: +CONFIG_ESP_INTR_IN_IRAM=y +# end of Hardware Settings + +# +# ESP-Driver:LCD Controller Configurations +# +# default: +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# default: +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set +# default: +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:LCD Controller Configurations + +# +# LibC +# +# default: +# CONFIG_LIBC_NEWLIB is not set +# default: +CONFIG_LIBC_PICOLIBC=y +# default: +CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY=y +# default: +CONFIG_LIBC_MISC_IN_IRAM=y +# default: +CONFIG_LIBC_LOCKS_PLACE_IN_IRAM=y +# default: +CONFIG_LIBC_STDOUT_LINE_ENDING_CRLF=y +# default: +# CONFIG_LIBC_STDOUT_LINE_ENDING_LF is not set +# default: +# CONFIG_LIBC_STDOUT_LINE_ENDING_CR is not set +# default: +# CONFIG_LIBC_STDIN_LINE_ENDING_CRLF is not set +# default: +# CONFIG_LIBC_STDIN_LINE_ENDING_LF is not set +# default: +CONFIG_LIBC_STDIN_LINE_ENDING_CR=y +# default: +CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y +# default: +# CONFIG_LIBC_TIME_SYSCALL_USE_RTC is not set +# default: +# CONFIG_LIBC_TIME_SYSCALL_USE_HRT is not set +# default: +# CONFIG_LIBC_TIME_SYSCALL_USE_NONE is not set +# default: +CONFIG_LIBC_ASSERT_BUFFER_SIZE=200 +# end of LibC + +# +# ESP-MM: Memory Management Configurations +# +# default: +# CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS is not set +# end of ESP-MM: Memory Management Configurations + +# +# ESP NETIF Adapter +# +# default: +CONFIG_ESP_NETIF_LOST_IP_TIMER_ENABLE=y +# default: +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# default: +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set +# default: +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# default: +# CONFIG_ESP_NETIF_LOOPBACK is not set +# default: +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +# default: +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y +# default: +CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS=y +# default: +# CONFIG_ESP_NETIF_L2_TAP is not set +# default: +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# default: +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set +# end of ESP NETIF Adapter + +# +# Partition API Configuration +# +# end of Partition API Configuration + +# +# PHY +# +# default: +CONFIG_ESP_PHY_ENABLED=y +# default: +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# default: +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +# default: +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +# default: +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# default: +# CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +# default: +CONFIG_ESP_PHY_ENABLE_USB=y +# default: +# CONFIG_ESP_PHY_ENABLE_CERT_TEST is not set +# default: +CONFIG_ESP_PHY_RF_CAL_PARTIAL=y +# default: +# CONFIG_ESP_PHY_RF_CAL_NONE is not set +# default: +# CONFIG_ESP_PHY_RF_CAL_FULL is not set +# default: +CONFIG_ESP_PHY_CALIBRATION_MODE=0 +# default: +CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 +# default: +# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set +# default: +# CONFIG_ESP_PHY_RECORD_USED_TIME is not set +# default: +CONFIG_ESP_PHY_IRAM_OPT=y +# default: +# CONFIG_ESP_PHY_DEBUG is not set +# default: +CONFIG_ESP_PHY_ENABLE_VERSION_PRINT=y +# end of PHY + +# +# Power Management +# +# default: +# CONFIG_PM_SLEEP_FUNC_IN_IRAM is not set +# default: +# CONFIG_PM_ENABLE is not set +# default: +# CONFIG_PM_SLP_IRAM_OPT is not set +# default: +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +# default: +CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y +# default: +CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU=y +# end of Power Management + +# +# ESP PSRAM +# +# default: +# CONFIG_SPIRAM is not set +# end of ESP PSRAM + +# +# ESP Ringbuf +# +# default: +# CONFIG_RINGBUF_IN_IRAM is not set +# default: +# CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP-ROM +# +# default: +CONFIG_ESP_ROM_PRINT_IN_IRAM=y +# end of ESP-ROM + +# +# ESP Security Specific +# +# end of ESP Security Specific + +# +# ESP-STDIO +# +# default: +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# default: +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# default: +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# default: +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# default: +# CONFIG_ESP_CONSOLE_NONE is not set +# default: +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +# default: +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +# default: +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +# default: +CONFIG_ESP_CONSOLE_UART=y +# default: +CONFIG_ESP_CONSOLE_UART_NUM=0 +# default: +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 +# default: +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +# default: +CONFIG_ESP_STDIO_MAX_VFS_ENTRIES=2 +# end of ESP-STDIO + +# +# ESP System Settings +# +# default: +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +# default: +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160=y +# default: +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240 is not set +# default: +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=160 + +# +# Cache config +# +# default: +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# default: +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +# default: +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# default: +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +# default: +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +# default: +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# default: +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +# default: +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +# default: +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# default: +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +# default: +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# default: +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +# default: +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# default: +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +# default: +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +# default: +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# default: +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +# default: +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# default: +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +# default: +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config + +# +# Memory +# +# default: +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# default: +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory + +# +# Trace memory +# +# default: +# CONFIG_ESP32S3_TRAX is not set +# default: +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# end of Trace memory + +# default: +CONFIG_ESP_SYSTEM_IN_IRAM=y +# default: +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +# default: +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# default: +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# default: +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# default: +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +# default: +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +# default: +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y +# default: +CONFIG_ESP_SYSTEM_MEMPROT=y +# default: +CONFIG_ESP_SYSTEM_MEMPROT_PMS=y +# default: +CONFIG_ESP_SYSTEM_MEMPROT_PMS_LOCK=y +# default: +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +# default: +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +# default: +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +# default: +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# default: +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# default: +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +# default: +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +# default: +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +# default: +CONFIG_ESP_INT_WDT=y +# default: +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +# default: +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +# default: +CONFIG_ESP_TASK_WDT_EN=y +# default: +CONFIG_ESP_TASK_WDT_INIT=y +# default: +# CONFIG_ESP_TASK_WDT_PANIC is not set +# default: +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +# default: +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# default: +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# default: +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# default: +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +# default: +CONFIG_ESP_DEBUG_OCDAWARE=y +# default: +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +# default: +CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y +# end of ESP System Settings + +# +# IPC (Inter-Processor Call) +# +# default: +CONFIG_ESP_IPC_ENABLE=y +# default: +CONFIG_ESP_IPC_TASK_STACK_SIZE=1280 +# default: +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +# default: +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# ESP Timer (High Resolution Timer) +# +# default: +CONFIG_ESP_TIMER_IN_IRAM=y +# default: +# CONFIG_ESP_TIMER_PROFILING is not set +# default: +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +# default: +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +# default: +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +# default: +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# default: +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +# default: +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +# default: +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +# default: +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# default: +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +# default: +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of ESP Timer (High Resolution Timer) + +# +# ESP Trace Configuration +# +# default: +# CONFIG_ESP_TRACE_LIB_EXTERNAL is not set +# default: +CONFIG_ESP_TRACE_LIB_NONE=y +# default: +CONFIG_ESP_TRACE_LIB_NAME="none" +# default: +# CONFIG_ESP_TRACE_TRANSPORT_APPTRACE is not set +# default: +CONFIG_ESP_TRACE_TRANSPORT_NONE=y +# default: +CONFIG_ESP_TRACE_TRANSPORT_NAME="none" +# end of ESP Trace Configuration + +# +# Wi-Fi +# +# default: +CONFIG_ESP_WIFI_ENABLED=y +# default: +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10 +# default: +CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# default: +# CONFIG_ESP_WIFI_STATIC_TX_BUFFER is not set +# default: +CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER=y +# default: +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=1 +# default: +CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# default: +CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y +# default: +# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set +# default: +CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 +# default: +CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5 +# default: +# CONFIG_ESP_WIFI_CSI_ENABLED is not set +# default: +CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y +# default: +CONFIG_ESP_WIFI_TX_BA_WIN=6 +# default: +CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y +# default: +CONFIG_ESP_WIFI_RX_BA_WIN=6 +# default: +CONFIG_ESP_WIFI_NVS_ENABLED=y +# default: +CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y +# default: +# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set +# default: +CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752 +# default: +CONFIG_ESP_WIFI_MGMT_SBUF_NUM=32 +# default: +CONFIG_ESP_WIFI_IRAM_OPT=y +# default: +# CONFIG_ESP_WIFI_EXTRA_IRAM_OPT is not set +# default: +CONFIG_ESP_WIFI_RX_IRAM_OPT=y +# default: +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +# default: +CONFIG_ESP_WIFI_ENABLE_SAE_H2E=y +# default: +CONFIG_ESP_WIFI_ENABLE_SAE_PK=y +# default: +CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y +# default: +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y +# default: +CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT=y +# default: +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP=y +# default: +# CONFIG_ESP_WIFI_PASN_SUPPORT is not set +# default: +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# default: +CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +# default: +# CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT is not set +# default: +CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +# default: +CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 +# default: +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +# default: +CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y +# default: +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +# default: +CONFIG_ESP_WIFI_GMAC_SUPPORT=y +# default: +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# default: +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +# default: +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +# default: +CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y +# default: +CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y +# default: +# CONFIG_ESP_WIFI_WAPI_PSK is not set +# default: +# CONFIG_ESP_WIFI_SUITE_B_192 is not set +# default: +# CONFIG_ESP_WIFI_11KV_SUPPORT is not set +# default: +# CONFIG_ESP_WIFI_MBO_SUPPORT is not set +# default: +# CONFIG_ESP_WIFI_ENABLE_ROAMING_APP is not set +# default: +# CONFIG_ESP_WIFI_DPP_SUPPORT is not set +# default: +# CONFIG_ESP_WIFI_11R_SUPPORT is not set +# default: +# CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR is not set + +# +# WPS Configuration Options +# +# default: +# CONFIG_ESP_WIFI_WPS_STRICT is not set +# default: +# CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# default: +# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set +# end of WPS Configuration Options + +# default: +# CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# default: +CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y +# default: +# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set +# default: +# CONFIG_ESP_WIFI_PASSIVE_HIDDEN_AP_SUPPORT is not set +# default: +# CONFIG_ESP_WIFI_PRIVACY_ENHANCEMENTS_ENABLED is not set +# end of Wi-Fi + +# +# Wi-Fi Remote +# +# default: +CONFIG_ESP_WIFI_REMOTE_IN_IDF=y +# default: +CONFIG_ESP_WIFI_REMOTE_ENABLED=y +# default: +CONFIG_SLAVE_IDF_TARGET_ESP32=y +# default: +# CONFIG_SLAVE_IDF_TARGET_ESP32S2 is not set +# default: +# CONFIG_SLAVE_IDF_TARGET_ESP32C3 is not set +# default: +# CONFIG_SLAVE_IDF_TARGET_ESP32S3 is not set +# default: +# CONFIG_SLAVE_IDF_TARGET_ESP32C2 is not set +# default: +# CONFIG_SLAVE_IDF_TARGET_ESP32C6 is not set +# default: +# CONFIG_SLAVE_IDF_TARGET_ESP32C5 is not set +# default: +# CONFIG_SLAVE_IDF_TARGET_ESP32C61 is not set +# default: +# CONFIG_SLAVE_IDF_TARGET_ESP32S31 is not set +# default: +CONFIG_SLAVE_SOC_WIFI_SUPPORTED=y +# default: +CONFIG_SLAVE_SOC_WIFI_WAPI_SUPPORT=y +# default: +CONFIG_SLAVE_SOC_WIFI_CSI_SUPPORT=y +# default: +CONFIG_SLAVE_SOC_WIFI_MESH_SUPPORT=y +# default: +CONFIG_SLAVE_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +# default: +CONFIG_SLAVE_SOC_WIFI_NAN_SUPPORT=y +# default: +CONFIG_SLAVE_IDF_TARGET_ARCH_XTENSA=y + +# +# Wi-Fi configuration +# +# default: +CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=10 +# default: +CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=32 +# default: +# CONFIG_WIFI_RMT_STATIC_TX_BUFFER is not set +# default: +CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER=y +# default: +CONFIG_WIFI_RMT_TX_BUFFER_TYPE=1 +# default: +CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=32 +# default: +CONFIG_WIFI_RMT_STATIC_RX_MGMT_BUFFER=y +# default: +# CONFIG_WIFI_RMT_DYNAMIC_RX_MGMT_BUFFER is not set +# default: +CONFIG_WIFI_RMT_DYNAMIC_RX_MGMT_BUF=0 +# default: +CONFIG_WIFI_RMT_RX_MGMT_BUF_NUM_DEF=5 +# default: +# CONFIG_WIFI_RMT_CSI_ENABLED is not set +# default: +CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y +# default: +CONFIG_WIFI_RMT_TX_BA_WIN=6 +# default: +CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y +# default: +CONFIG_WIFI_RMT_RX_BA_WIN=6 +# default: +CONFIG_WIFI_RMT_NVS_ENABLED=y +# default: +CONFIG_WIFI_RMT_TASK_PINNED_TO_CORE_0=y +# default: +# CONFIG_WIFI_RMT_TASK_PINNED_TO_CORE_1 is not set +# default: +CONFIG_WIFI_RMT_SOFTAP_BEACON_MAX_LEN=752 +# default: +CONFIG_WIFI_RMT_MGMT_SBUF_NUM=32 +# default: +CONFIG_WIFI_RMT_IRAM_OPT=y +# default: +# CONFIG_WIFI_RMT_EXTRA_IRAM_OPT is not set +# default: +CONFIG_WIFI_RMT_RX_IRAM_OPT=y +# default: +CONFIG_WIFI_RMT_ENABLE_WPA3_SAE=y +# default: +CONFIG_WIFI_RMT_ENABLE_SAE_H2E=y +# default: +CONFIG_WIFI_RMT_ENABLE_SAE_PK=y +# default: +CONFIG_WIFI_RMT_SOFTAP_SAE_SUPPORT=y +# default: +CONFIG_WIFI_RMT_ENABLE_WPA3_OWE_STA=y +# default: +CONFIG_WIFI_RMT_WPA3_COMPATIBLE_SUPPORT=y +# default: +CONFIG_WIFI_RMT_ENABLE_WPA3_OWE_SOFTAP=y +# default: +# CONFIG_WIFI_RMT_PASN_SUPPORT is not set +# default: +# CONFIG_WIFI_RMT_SLP_IRAM_OPT is not set +# default: +CONFIG_WIFI_RMT_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +# default: +# CONFIG_WIFI_RMT_BSS_MAX_IDLE_SUPPORT is not set +# default: +CONFIG_WIFI_RMT_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +# default: +CONFIG_WIFI_RMT_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 +# default: +CONFIG_WIFI_RMT_STA_DISCONNECTED_PM_ENABLE=y +# default: +CONFIG_WIFI_RMT_GMAC_SUPPORT=y +# default: +CONFIG_WIFI_RMT_SOFTAP_SUPPORT=y +# default: +# CONFIG_WIFI_RMT_SLP_BEACON_LOST_OPT is not set +# default: +CONFIG_WIFI_RMT_ESPNOW_MAX_ENCRYPT_NUM=7 +# default: +# CONFIG_WIFI_RMT_NAN_SYNC_ENABLE is not set +# default: +CONFIG_WIFI_RMT_MBEDTLS_CRYPTO=y +# default: +CONFIG_WIFI_RMT_MBEDTLS_TLS_CLIENT=y +# default: +# CONFIG_WIFI_RMT_WAPI_PSK is not set +# default: +# CONFIG_WIFI_RMT_11KV_SUPPORT is not set +# default: +# CONFIG_WIFI_RMT_MBO_SUPPORT is not set +# default: +# CONFIG_WIFI_RMT_ENABLE_ROAMING_APP is not set +# default: +# CONFIG_WIFI_RMT_DPP_SUPPORT is not set +# default: +# CONFIG_WIFI_RMT_11R_SUPPORT is not set +# default: +# CONFIG_WIFI_RMT_WPS_SOFTAP_REGISTRAR is not set + +# +# WPS Configuration Options +# +# default: +# CONFIG_WIFI_RMT_WPS_STRICT is not set +# default: +# CONFIG_WIFI_RMT_WPS_PASSPHRASE is not set +# default: +# CONFIG_WIFI_RMT_WPS_RECONNECT_ON_FAIL is not set +# end of WPS Configuration Options + +# default: +# CONFIG_WIFI_RMT_DEBUG_PRINT is not set +# default: +CONFIG_WIFI_RMT_ENTERPRISE_SUPPORT=y +# default: +# CONFIG_WIFI_RMT_ENT_FREE_DYNAMIC_BUFFER is not set +# default: +# CONFIG_WIFI_RMT_PASSIVE_HIDDEN_AP_SUPPORT is not set +# default: +# CONFIG_WIFI_RMT_PRIVACY_ENHANCEMENTS_ENABLED is not set +# end of Wi-Fi configuration + +# default: +CONFIG_ESP_WIFI_REMOTE_LIBRARY_HOSTED=y +# default: +# CONFIG_ESP_WIFI_REMOTE_LIBRARY_EPPP is not set +# default: +# CONFIG_ESP_WIFI_REMOTE_LIBRARY_CUSTOM is not set +# default: +CONFIG_ESP_WIFI_REMOTE_EAP_ENABLED=y +# end of Wi-Fi Remote + +# +# Core dump +# +# default: +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# default: +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +# default: +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# default: +CONFIG_FATFS_VOLUME_COUNT=2 +# default: +# CONFIG_FATFS_LFN_NONE is not set +# default: +CONFIG_FATFS_LFN_HEAP=y +# default: +# CONFIG_FATFS_LFN_STACK is not set +# default: +# CONFIG_FATFS_SECTOR_512 is not set +# default: +CONFIG_FATFS_SECTOR_4096=y +# default: +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +# default: +CONFIG_FATFS_CODEPAGE_437=y +# default: +# CONFIG_FATFS_CODEPAGE_720 is not set +# default: +# CONFIG_FATFS_CODEPAGE_737 is not set +# default: +# CONFIG_FATFS_CODEPAGE_771 is not set +# default: +# CONFIG_FATFS_CODEPAGE_775 is not set +# default: +# CONFIG_FATFS_CODEPAGE_850 is not set +# default: +# CONFIG_FATFS_CODEPAGE_852 is not set +# default: +# CONFIG_FATFS_CODEPAGE_855 is not set +# default: +# CONFIG_FATFS_CODEPAGE_857 is not set +# default: +# CONFIG_FATFS_CODEPAGE_860 is not set +# default: +# CONFIG_FATFS_CODEPAGE_861 is not set +# default: +# CONFIG_FATFS_CODEPAGE_862 is not set +# default: +# CONFIG_FATFS_CODEPAGE_863 is not set +# default: +# CONFIG_FATFS_CODEPAGE_864 is not set +# default: +# CONFIG_FATFS_CODEPAGE_865 is not set +# default: +# CONFIG_FATFS_CODEPAGE_866 is not set +# default: +# CONFIG_FATFS_CODEPAGE_869 is not set +# default: +# CONFIG_FATFS_CODEPAGE_932 is not set +# default: +# CONFIG_FATFS_CODEPAGE_936 is not set +# default: +# CONFIG_FATFS_CODEPAGE_949 is not set +# default: +# CONFIG_FATFS_CODEPAGE_950 is not set +# default: +CONFIG_FATFS_CODEPAGE=437 +# default: +CONFIG_FATFS_MAX_LFN=255 +# default: +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +# default: +# CONFIG_FATFS_API_ENCODING_UTF_8 is not set +# default: +CONFIG_FATFS_FS_LOCK=0 +# default: +CONFIG_FATFS_TIMEOUT_MS=10000 +# default: +CONFIG_FATFS_PER_FILE_CACHE=y +# default: +CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS=y +# default: +# CONFIG_FATFS_USE_FASTSEEK is not set +# default: +CONFIG_FATFS_USE_STRFUNC_NONE=y +# default: +# CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV is not set +# default: +# CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV is not set +# default: +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# default: +# CONFIG_FATFS_IMMEDIATE_FSYNC is not set +# default: +# CONFIG_FATFS_USE_LABEL is not set +# default: +CONFIG_FATFS_LINK_LOCK=y +# default: +CONFIG_FATFS_USE_DYN_BUFFERS=y + +# +# File system free space calculation behavior +# +# default: +CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 +# default: +CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 +# end of File system free space calculation behavior +# end of FAT Filesystem support + +# +# FreeRTOS +# + +# +# Kernel +# +# default: +# CONFIG_FREERTOS_UNICORE is not set +# default: +CONFIG_FREERTOS_HZ=100 +# default: +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# default: +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +# default: +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# default: +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +# default: +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# default: +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# default: +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +# default: +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# default: +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +# default: +CONFIG_FREERTOS_USE_TIMERS=y +# default: +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# default: +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +# default: +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set +# default: +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +# default: +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF +# default: +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +# default: +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +# default: +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +# default: +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# default: +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +# default: +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# default: +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set +# default: +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# default: +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set +# end of Kernel + +# +# Port +# +# default: +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +# default: +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +# default: +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# default: +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set +# default: +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# default: +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# default: +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +# default: +# CONFIG_FREERTOS_FPU_IN_ISR is not set +# default: +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +# default: +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# default: +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +# default: +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +# default: +# CONFIG_FREERTOS_IN_IRAM is not set +# default: +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# end of Port + +# +# Extra +# +# end of Extra + +# default: +CONFIG_FREERTOS_PORT=y +# default: +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +# default: +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +# default: +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# default: +CONFIG_FREERTOS_NUMBER_OF_CORES=2 +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +# default: +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# default: +# CONFIG_HAL_ASSERTION_DISABLE is not set +# default: +# CONFIG_HAL_ASSERTION_SILENT is not set +# default: +# CONFIG_HAL_ASSERTION_ENABLE is not set +# default: +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +# default: +CONFIG_HAL_WDT_USE_ROM_IMPL=y +# default: +CONFIG_HAL_GPIO_USE_ROM_IMPL=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +# default: +CONFIG_HEAP_POISONING_DISABLED=y +# default: +# CONFIG_HEAP_POISONING_LIGHT is not set +# default: +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +# default: +CONFIG_HEAP_TRACING_OFF=y +# default: +# CONFIG_HEAP_TRACING_STANDALONE is not set +# default: +# CONFIG_HEAP_TRACING_TOHOST is not set +# default: +# CONFIG_HEAP_USE_HOOKS is not set +# default: +# CONFIG_HEAP_TASK_TRACKING is not set +# default: +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# default: +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging + +# +# Log +# +# default: +CONFIG_LOG_VERSION_1=y +# default: +# CONFIG_LOG_VERSION_2 is not set +# default: +CONFIG_LOG_VERSION=1 + +# +# Log Level +# +# default: +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# default: +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# default: +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +# default: +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# default: +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# default: +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +# default: +CONFIG_LOG_DEFAULT_LEVEL=3 +# default: +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# default: +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# default: +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +# default: +CONFIG_LOG_MAXIMUM_LEVEL=3 + +# +# Level Settings +# +# default: +# CONFIG_LOG_MASTER_LEVEL is not set +# default: +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# default: +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# default: +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +# default: +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# default: +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +# default: +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +# default: +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level + +# +# Format +# +# default: +# CONFIG_LOG_COLORS is not set +# default: +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# default: +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Format + +# +# Settings +# +# default: +CONFIG_LOG_MODE_TEXT_EN=y +# default: +CONFIG_LOG_MODE_TEXT=y +# end of Settings + +# default: +CONFIG_LOG_IN_IRAM=y +# end of Log + +# +# LWIP +# +# default: +CONFIG_LWIP_ENABLE=y +# default: +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# default: +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# default: +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# default: +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +# default: +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# default: +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# default: +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# default: +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set +# default: +CONFIG_LWIP_TIMERS_ONDEMAND=y +# default: +CONFIG_LWIP_ND6=y +# default: +# CONFIG_LWIP_ND6_SUPPORT_STATIC_ENTRIES is not set +# default: +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +# default: +CONFIG_LWIP_MAX_SOCKETS=10 +# default: +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# default: +# CONFIG_LWIP_SO_LINGER is not set +# default: +CONFIG_LWIP_SO_REUSE=y +# default: +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# default: +# CONFIG_LWIP_SO_RCVBUF is not set +# default: +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# default: +CONFIG_LWIP_IP_DEFAULT_TTL=64 +# default: +CONFIG_LWIP_IP4_FRAG=y +# default: +CONFIG_LWIP_IP6_FRAG=y +# default: +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# default: +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# default: +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 +# default: +CONFIG_LWIP_IPV6_DUP_DETECT_ATTEMPTS=1 +# default: +# CONFIG_LWIP_IP_FORWARD is not set +# default: +# CONFIG_LWIP_STATS is not set +# default: +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +# default: +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +# default: +CONFIG_LWIP_ESP_MLDV6_REPORT=y +# default: +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +# default: +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# default: +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# default: +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# default: +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set +# default: +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# default: +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# default: +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +# default: +CONFIG_LWIP_DHCP_OPTIONS_LEN=69 +# default: +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 +# default: +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 + +# +# DHCP server +# +# default: +CONFIG_LWIP_DHCPS=y +# default: +CONFIG_LWIP_DHCPS_REPORT_CLIENT_HOSTNAME=y +# default: +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +# default: +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# default: +CONFIG_LWIP_DHCPS_MAX_HOSTNAME_LEN=64 +# default: +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +# end of DHCP server + +# default: +# CONFIG_LWIP_AUTOIP is not set +# default: +CONFIG_LWIP_IPV4=y +# default: +CONFIG_LWIP_IPV6=y +# default: +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +# default: +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# default: +# CONFIG_LWIP_IPV6_FORWARD is not set +# default: +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# default: +# CONFIG_LWIP_NETIF_LINK_CALLBACK is not set +# default: +CONFIG_LWIP_NETIF_LOOPBACK=y +# default: +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +# default: +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +# default: +CONFIG_LWIP_MAX_LISTENING_TCP=16 +# default: +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +# default: +CONFIG_LWIP_TCP_MAXRTX=12 +# default: +CONFIG_LWIP_TCP_SYNMAXRTX=12 +# default: +CONFIG_LWIP_TCP_MSS=1440 +# default: +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +# default: +CONFIG_LWIP_TCP_MSL=60000 +# default: +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +# default: +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 +# default: +CONFIG_LWIP_TCP_WND_DEFAULT=5760 +# default: +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# default: +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 +# default: +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# default: +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +# default: +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 +# default: +# CONFIG_LWIP_TCP_SACK_OUT is not set +# default: +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# default: +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# default: +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# default: +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +# default: +CONFIG_LWIP_MAX_UDP_PCBS=16 +# default: +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# default: +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# default: +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +# default: +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# default: +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +# default: +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# default: +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# default: +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +# default: +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# default: +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +# default: +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# default: +CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 +# default: +CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 +# default: +CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# default: +# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set +# default: +# CONFIG_LWIP_PPP_SUPPORT is not set +# default: +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +# default: +CONFIG_LWIP_ICMP=y +# default: +# CONFIG_LWIP_MULTICAST_PING is not set +# default: +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +# default: +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +# default: +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# default: +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# default: +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# default: +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +# default: +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 +# end of SNTP + +# +# DNS +# +# default: +CONFIG_LWIP_DNS_MAX_HOST_IP=1 +# default: +CONFIG_LWIP_DNS_MAX_SERVERS=3 +# default: +# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# default: +# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set +# default: +# CONFIG_LWIP_USE_ESP_GETADDRINFO is not set +# end of DNS + +# default: +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 +# default: +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# default: +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +# default: +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# default: +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +# default: +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# default: +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# default: +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +# default: +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# default: +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# default: +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +# default: +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y +# default: +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set +# default: +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set +# default: +CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_NONE=y +# default: +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_DEFAULT is not set +# default: +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_CUSTOM is not set +# default: +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# default: +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# default: +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +# default: +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# default: +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +# default: +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +# default: +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y +# default: +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks + +# default: +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# + +# +# Core Configuration +# +# default: +CONFIG_MBEDTLS_VER_4_X_SUPPORT=y +# default: +# CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_NONE is not set +# default: +CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SIZE=y +# default: +# CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_PERF is not set +# default: +CONFIG_MBEDTLS_FS_IO=y +# default: +# CONFIG_MBEDTLS_PSA_ITS_CUSTOM_STORAGE_BACKEND is not set +# default: +CONFIG_MBEDTLS_THREADING_C=y +# default: +# CONFIG_MBEDTLS_THREADING_ALT is not set +# default: +CONFIG_MBEDTLS_THREADING_PTHREAD=y +# default: +CONFIG_MBEDTLS_ERROR_STRINGS=y +# default: +CONFIG_MBEDTLS_VERSION_C=y +# default: +CONFIG_MBEDTLS_HAVE_TIME=y +# default: +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# default: +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +# default: +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# default: +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# default: +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +# default: +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +# default: +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +# default: +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# default: +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# default: +# CONFIG_MBEDTLS_VERSION_FEATURES is not set +# default: +# CONFIG_MBEDTLS_DEBUG is not set +# default: +CONFIG_MBEDTLS_SELF_TEST=y +# end of Core Configuration + +# +# Certificates +# +# default: +CONFIG_MBEDTLS_X509_USE_C=y +# default: +CONFIG_MBEDTLS_PEM_PARSE_C=y +# default: +CONFIG_MBEDTLS_PEM_WRITE_C=y +# default: +CONFIG_MBEDTLS_PK_C=y +# default: +CONFIG_MBEDTLS_PK_PARSE_C=y +# default: +CONFIG_MBEDTLS_PK_WRITE_C=y +# default: +# CONFIG_MBEDTLS_X509_REMOVE_INFO is not set +# default: +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +# default: +CONFIG_MBEDTLS_X509_CRT_PARSE_C=y +# default: +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# default: +# CONFIG_MBEDTLS_X509_CREATE_C is not set +# default: +CONFIG_MBEDTLS_X509_RSASSA_PSS_SUPPORT=y +# default: +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# default: +CONFIG_MBEDTLS_ASN1_PARSE_C=y +# default: +CONFIG_MBEDTLS_ASN1_WRITE_C=y +# default: +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y + +# +# Certificate Bundle Configuration +# +# default: +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# default: +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# default: +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# default: +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# default: +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set +# default: +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle Configuration + +# default: +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set +# default: +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY is not set +# end of Certificates + +# default: +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Protocol Configuration +# +# default: +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# default: +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# default: +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# default: +CONFIG_MBEDTLS_TLS_SERVER=y +# default: +CONFIG_MBEDTLS_TLS_CLIENT=y +# default: +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# default: +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# default: +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# default: +# CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is not set +# default: +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +# default: +CONFIG_MBEDTLS_SSL_CACHE_C=y +# default: +CONFIG_MBEDTLS_SSL_ALL_ALERT_MESSAGES=y + +# +# TLS Key Exchange Configuration +# +# default: +# CONFIG_MBEDTLS_PSK_MODES is not set +# default: +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +# default: +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +# default: +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +# default: +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +# end of TLS Key Exchange Configuration + +# default: +CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION=y +# default: +CONFIG_MBEDTLS_SSL_ALPN=y +# default: +CONFIG_MBEDTLS_SSL_MAX_FRAGMENT_LENGTH=y +# default: +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# default: +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# default: +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +# default: +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y +# default: +# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set +# end of TLS Protocol Configuration + +# default: +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set + +# +# Symmetric Ciphers +# +# default: +CONFIG_MBEDTLS_AES_C=y +# default: +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# default: +# CONFIG_MBEDTLS_ARIA_C is not set +# default: +# CONFIG_MBEDTLS_DES_C is not set +# default: +CONFIG_MBEDTLS_CCM_C=y +# default: +CONFIG_MBEDTLS_CIPHER_MODE_CBC=y +# default: +CONFIG_MBEDTLS_CIPHER_MODE_CFB=y +# default: +CONFIG_MBEDTLS_CIPHER_MODE_CTR=y +# default: +CONFIG_MBEDTLS_CIPHER_MODE_OFB=y +# default: +CONFIG_MBEDTLS_CIPHER_MODE_XTS=y +# default: +CONFIG_MBEDTLS_GCM_C=y +# default: +# CONFIG_MBEDTLS_NIST_KW_C is not set +# default: +CONFIG_MBEDTLS_AES_ROM_TABLES=y +# default: +# CONFIG_MBEDTLS_AES_FEWER_TABLES is not set +# default: +# CONFIG_MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH is not set +# default: +CONFIG_MBEDTLS_CMAC_C=y +# end of Symmetric Ciphers + +# +# Asymmetric Ciphers +# +# default: +CONFIG_MBEDTLS_RSA_C=y +# default: +CONFIG_MBEDTLS_ECP_C=y + +# +# Supported Curves +# +# default: +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +# default: +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +# default: +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +# default: +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +# default: +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +# default: +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +# default: +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +# default: +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +# end of Supported Curves + +# +# Elliptic Curve Ciphers Configuration +# +# default: +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# default: +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set +# default: +# CONFIG_MBEDTLS_DHM_C is not set +# default: +CONFIG_MBEDTLS_ECDH_C=y +# default: +# CONFIG_MBEDTLS_ECJPAKE_C is not set +# default: +CONFIG_MBEDTLS_ECDSA_C=y +# default: +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +# default: +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y +# default: +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +# default: +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# end of Elliptic Curve Ciphers Configuration +# end of Asymmetric Ciphers + +# +# Hash functions +# +# default: +# CONFIG_MBEDTLS_RIPEMD160_C is not set +# default: +CONFIG_MBEDTLS_MD_C=y +# default: +CONFIG_MBEDTLS_MD5_C=y +# default: +CONFIG_MBEDTLS_SHA1_C=y +# default: +# CONFIG_MBEDTLS_SHA224_C is not set +# default: +CONFIG_MBEDTLS_SHA256_C=y +# default: +CONFIG_MBEDTLS_SHA384_C=y +# default: +CONFIG_MBEDTLS_SHA512_C=y +# default: +# CONFIG_MBEDTLS_SHA3_C is not set +# default: +CONFIG_MBEDTLS_ROM_MD5=y +# end of Hash functions + +# +# Hardware Acceleration +# +# default: +CONFIG_MBEDTLS_HARDWARE_SHA=y +# default: +CONFIG_MBEDTLS_HARDWARE_MPI=y +# default: +CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI=y +# default: +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +# default: +CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 +# default: +CONFIG_MBEDTLS_HARDWARE_AES=y +# default: +# CONFIG_MBEDTLS_AES_SOFT_FALLBACK is not set +# default: +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y +# default: +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +# default: +CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 +# default: +CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM=y +# default: +# CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED is not set +# default: +CONFIG_MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL=y +# end of Hardware Acceleration + +# +# Entropy and Random Number Generation +# +# default: +# CONFIG_MBEDTLS_ENTROPY_FORCE_SHA256 is not set +# default: +CONFIG_MBEDTLS_CTR_DRBG_C=y +# default: +CONFIG_MBEDTLS_HMAC_DRBG_C=y +# end of Entropy and Random Number Generation + +# +# Encoding/Decoding +# +# default: +CONFIG_MBEDTLS_BASE64_C=y +# default: +CONFIG_MBEDTLS_PKCS5_C=y +# default: +CONFIG_MBEDTLS_PKCS7_C=y +# default: +CONFIG_MBEDTLS_PKCS1_V15=y +# default: +CONFIG_MBEDTLS_PKCS1_V21=y +# end of Encoding/Decoding + +# +# Stream Cipher +# +# default: +# CONFIG_MBEDTLS_CHACHA20_C is not set +# end of Stream Cipher +# end of mbedTLS + +# +# NVS +# +# default: +# CONFIG_NVS_ENCRYPTION is not set +# default: +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# default: +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set +# default: +# CONFIG_NVS_BDL_STACK is not set +# default: +# CONFIG_NVS_FLASH_VERIFY_ERASE is not set +# end of NVS + +# +# OpenThread +# +# default: +# CONFIG_OPENTHREAD_ENABLED is not set + +# +# OpenThread Spinel +# +# default: +# CONFIG_OPENTHREAD_SPINEL_ONLY is not set +# end of OpenThread Spinel + +# default: +# CONFIG_OPENTHREAD_DEBUG is not set +# end of OpenThread + +# +# Protocomm +# +# default: +# CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0 is not set +# default: +# CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 is not set +# default: +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +# default: +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y +# end of Protocomm + +# +# PThreads +# +# default: +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +# default: +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +# default: +CONFIG_PTHREAD_STACK_MIN=768 +# default: +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# default: +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# default: +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +# default: +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +# default: +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SD Protocol Layer Configuration +# +# default: +CONFIG_SD_ENABLE_SDIO_SUPPORT=y +# end of SD Protocol Layer Configuration + +# +# MMU Config +# +# default: +CONFIG_MMU_PAGE_SIZE_64KB=y +# default: +CONFIG_MMU_PAGE_MODE="64KB" +# default: +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# Main Flash configuration +# + +# +# SPI Flash behavior when brownout +# +# default: +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +# default: +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Optional and Experimental Features (READ DOCS FIRST) +# + +# +# Features here require specific hardware (READ DOCS FIRST!) +# +# default: +# CONFIG_SPI_FLASH_HPM_ENA is not set +# default: +CONFIG_SPI_FLASH_HPM_AUTO=y +# default: +# CONFIG_SPI_FLASH_HPM_DIS is not set +# default: +CONFIG_SPI_FLASH_HPM_ON=y +# default: +CONFIG_SPI_FLASH_HPM_DC_AUTO=y +# default: +# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set +# default: +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +# default: +CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 +# default: +# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# default: +# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set +# default: +CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM=y +# end of Optional and Experimental Features (READ DOCS FIRST) +# end of Main Flash configuration + +# +# SPI Flash driver +# +# default: +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# default: +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +# default: +# CONFIG_SPI_FLASH_ROM_IMPL is not set +# default: +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# default: +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# default: +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# default: +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +# default: +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +# default: +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +# default: +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +# default: +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# default: +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# default: +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# default: +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +# default: +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORT_ENABLED=y +# default: +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORT_ENABLED=y +# default: +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORT_ENABLED=y +# default: +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORT_ENABLED=y +# default: +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORT_ENABLED=y +# default: +CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORT_ENABLED=y +# default: +CONFIG_SPI_FLASH_VENDOR_TH_SUPPORT_ENABLED=y +# default: +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +# default: +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +# default: +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +# default: +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +# default: +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +# default: +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +# default: +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +# default: +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +# default: +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +# default: +CONFIG_SPIFFS_CACHE=y +# default: +CONFIG_SPIFFS_CACHE_WR=y +# default: +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +# default: +CONFIG_SPIFFS_PAGE_CHECK=y +# default: +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# default: +# CONFIG_SPIFFS_GC_STATS is not set +# default: +CONFIG_SPIFFS_PAGE_SIZE=256 +# default: +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# default: +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +# default: +CONFIG_SPIFFS_USE_MAGIC=y +# default: +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +# default: +CONFIG_SPIFFS_META_LENGTH=4 +# default: +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# default: +# CONFIG_SPIFFS_DBG is not set +# default: +# CONFIG_SPIFFS_API_DBG is not set +# default: +# CONFIG_SPIFFS_GC_DBG is not set +# default: +# CONFIG_SPIFFS_CACHE_DBG is not set +# default: +# CONFIG_SPIFFS_CHECK_DBG is not set +# default: +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +# default: +CONFIG_WS_TRANSPORT=y +# default: +CONFIG_WS_BUFFER_SIZE=1024 +# default: +# CONFIG_WS_DYNAMIC_BUFFER is not set +# end of Websocket +# end of TCP Transport + +# +# Ultra Low Power (ULP) Co-processor +# +# default: +# CONFIG_ULP_COPROC_ENABLED is not set + +# +# ULP Debugging Options +# +# end of ULP Debugging Options +# end of Ultra Low Power (ULP) Co-processor + +# +# Unity unit testing library +# +# default: +CONFIG_UNITY_ENABLE_FLOAT=y +# default: +CONFIG_UNITY_ENABLE_DOUBLE=y +# default: +# CONFIG_UNITY_ENABLE_64BIT is not set +# default: +# CONFIG_UNITY_ENABLE_COLOR is not set +# default: +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# default: +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# default: +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# Virtual file system +# +# default: +CONFIG_VFS_SUPPORT_IO=y +# default: +CONFIG_VFS_SUPPORT_DIR=y +# default: +CONFIG_VFS_SUPPORT_SELECT=y +# default: +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# default: +# CONFIG_VFS_SELECT_IN_RAM is not set +# default: +# CONFIG_VFS_SUPPORT_TERMIOS is not set +# default: +CONFIG_VFS_MAX_COUNT=8 +# default: +# CONFIG_VFS_SUPPRESS_CTX_DEPRECATION is not set + +# +# Host File System I/O (Semihosting) +# +# default: +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) + +# default: +CONFIG_VFS_INITIALIZE_DEV_NULL=y +# end of Virtual file system + +# +# Wear Levelling +# +# default: +# CONFIG_WL_SECTOR_SIZE_512 is not set +# default: +CONFIG_WL_SECTOR_SIZE_4096=y +# default: +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling +# end of Component config + +# default: +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set + +# Deprecated options for backward compatibility +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_EXTERNAL_COEX_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_CAM_CTLR_DVP_CAM_ISR_IRAM_SAFE is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_GDBSTUB_SUPPORT_TASKS=y +CONFIG_GDBSTUB_MAX_TASKS=32 +# CONFIG_OTA_ALLOW_HTTP is not set +# CONFIG_ESP_SYSTEM_PD_FLASH is not set +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_7=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_REDUCE_PHY_TX_POWER is not set +# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +# CONFIG_ESP32S3_SPIRAM_SUPPORT is not set +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=160 +CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_VIA_TEE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_IPC_TASK_STACK_SIZE=1280 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +# CONFIG_ESP32_APPTRACE_ENABLE is not set +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +CONFIG_WPA_MBEDTLS_CRYPTO=y +CONFIG_WPA_MBEDTLS_TLS_CLIENT=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_DEBUG_PRINT is not set +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +CONFIG_WPA_MBEDTLS_CRYPTO=y +CONFIG_WPA_MBEDTLS_TLS_CLIENT=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5760 +CONFIG_TCP_WND_DEFAULT=5760 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_SUPPORT_TERMIOS is not set +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..8446cd2 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +set(EXTRA_COMPONENT_DIRS + "${CMAKE_CURRENT_LIST_DIR}/main" + "${CMAKE_CURRENT_LIST_DIR}/components/libsmb2_esp" +) + +project(esp-spi) + +set(app_elf "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf") +set(app_disasm "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.s") + +add_custom_command( + OUTPUT "${app_disasm}" + COMMAND "${CMAKE_OBJDUMP}" -S "${app_elf}" > "${app_disasm}" + DEPENDS "${app_elf}" + VERBATIM +) + +add_custom_target(disasm ALL DEPENDS "${app_disasm}") diff --git a/src/WEATHER_GET.md b/src/WEATHER_GET.md new file mode 100644 index 0000000..94456d9 --- /dev/null +++ b/src/WEATHER_GET.md @@ -0,0 +1,58 @@ +# WEATHER_GET по SPI + +Команда `ESP_CMD_WEATHER_GET = 0x2D`. Код `0x24` исходного ZiFi занят в этом +проекте командой HTTPS_STREAM_START; UART-кадр ответа `0xA4` здесь не используется. +Сервисы: api.zippopotam.us и api.open-meteo.com, прямое HTTP-соединение. + +1. Подключить Wi-Fi обычными командами проекта. +2. Создать объект DATA или DATAF через MAKE_OBJECT и записать через WRITE_OBJECT + две строки с завершающими нулями: код страны ISO из двух латинских букв и индекс. + Например, `IT\0` + `00144\0` — 9 байт. Индекс: от 1 до 31 байта. + Допускается нулевое дополнение объекта для выравнивания DMA. +3. Записать handle входного объекта в ESP_REG_OBJ_HANDLE и выполнить `0x2D`. + Дождаться завершения BUSY; тайм-аут на стороне хоста рекомендуется 90 секунд. +4. При READY: ESP_REG_OBJ_HANDLE содержит новый объект DATA, + ESP_REG_DATA_OFFSET=0, ESP_REG_DATA_SIZE=90. Прочитать через READ_OBJECT. +5. Удалить входной и выходной объекты через DELETE_OBJECT, когда они больше не нужны. + Входной объект команда не изменяет и не удаляет; его handle следует сохранить. + +При ошибке новый объект не создаётся, входной handle сохраняется, DATA_SIZE=0. +Статусы: INV_HANDLE, INV_PARAM, INV_STR_LEN, AP_NOT_CONNECTED, +OUT_OF_MEMORY/OUT_OF_HANDLES; `ESP_ERR_WEATHER=0xB5` означает ошибку HTTP или +разбора JSON (подробность в логе `weather`). Без Wi-Fi команда даёт INV_COMMAND. + +Координаты кешируются до изменения пары страна/индекс или перезагрузки. +Прогноз запрашивается при каждом вызове. Для обрывов, 429 и 5xx — максимум три +попытки, паузы 1 и 2 секунды; новые запросы начинаются только в первые 30 секунд. +Ответы ограничены 4095 байтами, усечённые ответы не принимаются. +Параметры из zifi.ini передаёт хост: прошивка сама этот файл не читает. +Прокси из оригинального ZiFi не перенесён: в данном SPI API нет его настройки. + +## Запись версии 1 (90 байт) + +Все 16-битные числа little-endian. Температуры — знаковые байты в °C. + +| Смещение | Размер | Поле | +|---|---|---| +| 0 | 1 | 1: данные получены | +| 1 | 1 | Версия: 1 | +| 2 | 24 | Название места, CP866, с нулём | +| 26 | 1 | Текущая температура | +| 27 | 1 | Код WMO | +| 28 | 1 | 1: день | +| 29 | 2 | Ветер, км/ч ×10 | +| 31 | 2 | Осадки за час, мм ×10 | +| 33 | 2 | Давление, мм рт. ст. | +| 35 | 2 | Восход: час, минута | +| 37 | 2 | Закат: час, минута | +| 39 | 2 | Местное время данных: час, минута | +| 41 | 1 | Число дневных записей, до 6 | +| 42 | 48 | До 6 записей по 8 байт | + +Дневная запись: число, месяц, день недели (0=понедельник), код WMO, +tmin, tmax, осадки мм ×10 (u16). Первый день — сегодня. + +Парсер `main/weather_parse.cpp` и `main/zifi/weather_parse.hpp` перенесён из +локального ZiFi-ESP32-S3-Zero; формат совместим с коммитом +[616bee6](https://github.com/andrewinsidelazarev/ZiFi-ESP32-S3-Zero/commit/616bee6333d34dfd4dfd83ffb4bb8a44c2c974f9). +Проверка парсера: `python tests/test_weather_parse.py` (нужен MSVC). diff --git a/src/bump_api.sh b/src/bump_api.sh new file mode 100644 index 0000000..a7c9920 --- /dev/null +++ b/src/bump_api.sh @@ -0,0 +1,28 @@ +#!/bin/sh +set -eu + +SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" +HDR="${1:-$SCRIPT_DIR/../src/esp_spi_defs.h}" + +if [ ! -f "$HDR" ]; then + echo "bump-api: file not found: $HDR" >&2 + exit 1 +fi + +old="$(sed -nE 's/^[[:space:]]*#define[[:space:]]+API_VER[[:space:]]+([0-9]+).*/\1/p' "$HDR" | head -n1)" + +if [ -z "$old" ]; then + echo "bump-api: API_VER not found in $HDR" >&2 + exit 1 +fi + +if [ "$old" -ge 255 ]; then + echo "bump-api: API_VER is 1 byte and already at maximum 255" >&2 + exit 1 +fi + +new=$((old + 1)) + +sed -i -E "s/^([[:space:]]*#define[[:space:]]+API_VER[[:space:]]+)[0-9]+/\1${new}/" "$HDR" + +echo "bump-api: API ${old} -> ${new}" diff --git a/src/bump_feat.sh b/src/bump_feat.sh new file mode 100644 index 0000000..d0cb773 --- /dev/null +++ b/src/bump_feat.sh @@ -0,0 +1,28 @@ +#!/bin/sh +set -eu + +SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" +HDR="${1:-$SCRIPT_DIR/../src/esp_spi_defs.h}" + +if [ ! -f "$HDR" ]; then + echo "bump-feat: file not found: $HDR" >&2 + exit 1 +fi + +old="$(sed -nE 's/^[[:space:]]*#define[[:space:]]+FEAT_VER[[:space:]]+([0-9]+).*/\1/p' "$HDR" | head -n1)" + +if [ -z "$old" ]; then + echo "bump-feat: FEAT_VER not found in $HDR" >&2 + exit 1 +fi + +if [ "$old" -ge 65535 ]; then + echo "bump-feat: FEAT_VER is 2 bytes and already at maximum 65535" >&2 + exit 1 +fi + +new=$((old + 1)) + +sed -i -E "s/^([[:space:]]*#define[[:space:]]+FEAT_VER[[:space:]]+)[0-9]+/\1${new}/" "$HDR" + +echo "bump-feat: FEAT ${old} -> ${new}" diff --git a/src/bump_ver.sh b/src/bump_ver.sh new file mode 100644 index 0000000..4f43bc0 --- /dev/null +++ b/src/bump_ver.sh @@ -0,0 +1,26 @@ +#!/bin/sh +set -eu + +SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" +HDR="${1:-$SCRIPT_DIR/../src/esp_spi_defs.h}" + +if [ ! -f "$HDR" ]; then + echo "bump: file not found: $HDR" >&2 + exit 1 +fi + +set -- $(sed -nE 's/^[[:space:]]*#define[[:space:]]+PROD_VER([0-2])[[:space:]]+([0-9]+).*/\1 \2/p' "$HDR" | sort | awk '{print $2}') + +if [ "$#" -ne 3 ]; then + echo "bump: PROD_VER0..2 not found in $HDR" >&2 + exit 1 +fi + +major="$1" +minor="$2" +old="$3" +new=$((old + 1)) + +sed -i -E "s/^([[:space:]]*#define[[:space:]]+PROD_VER2[[:space:]]+)[0-9]+/\1${new}/" "$HDR" + +echo "bump: ver.${major}.${minor}.${old} -> ver.${major}.${minor}.${new}" diff --git a/src/components/libsmb2_esp/CMakeLists.txt b/src/components/libsmb2_esp/CMakeLists.txt new file mode 100644 index 0000000..478b2e8 --- /dev/null +++ b/src/components/libsmb2_esp/CMakeLists.txt @@ -0,0 +1,103 @@ +# Modern ESP-IDF (idf_component_register) wrapper around the vendored +# libsmb2 checkout at E:\esp32\src\third_party\libsmb2 (upstream +# sahlberg/libsmb2, LGPL-2.1). Vendored outside components/ deliberately: +# ESP-IDF auto-scans every immediate subdirectory of components/ as a +# candidate component, and libsmb2's own CMakeLists.txt predates +# idf_component_register (calls add_definitions() at the top level, which +# ESP-IDF 6.1's two-pass component requirement scan rejects with +# "add_definitions command is not scriptable") — so it must never be +# auto-discovered directly. Source list and compile definitions below are +# copied from the upstream lib/CMakeLists.txt ESP_PLATFORM branch, minus +# aes_apple.c/krb5-wrapper.c (excluded there too for this platform). + +set(LIBSMB2_DIR "${CMAKE_CURRENT_LIST_DIR}/../../third_party/libsmb2") +set(LIBSMB2_LIB_DIR "${LIBSMB2_DIR}/lib") + +set(LIBSMB2_SOURCES + aes.c + aes_reference.c + aes128ccm.c + alloc.c + asn1-ber.c + compat.c + libsmb2-dcerpc.c + libsmb2-dcerpc-srvsvc.c + errors.c + hmac.c + hmac-md5.c + init.c + libsmb2.c + md4c.c + md5.c + ntlmssp.c + pdu.c + sha1.c + sha224-256.c + sha384-512.c + smb2-cmd-close.c + smb2-cmd-create.c + smb2-cmd-echo.c + smb2-cmd-error.c + smb2-cmd-flush.c + smb2-cmd-ioctl.c + smb2-cmd-lock.c + smb2-cmd-logoff.c + smb2-cmd-negotiate.c + smb2-cmd-notify-change.c + smb2-cmd-oplock-break.c + smb2-cmd-query-directory.c + smb2-cmd-query-info.c + smb2-cmd-read.c + smb2-cmd-session-setup.c + smb2-cmd-set-info.c + smb2-cmd-tree-connect.c + smb2-cmd-tree-disconnect.c + smb2-cmd-write.c + smb2-data-file-info.c + smb2-data-filesystem-info.c + smb2-data-security-descriptor.c + smb2-data-reparse-point.c + smb2-share-enum.c + smb3-seal.c + smb2-signing.c + socket.c + spnego-wrapper.c + sync.c + timestamps.c + unicode.c + usha.c +) + +list(TRANSFORM LIBSMB2_SOURCES PREPEND "${LIBSMB2_LIB_DIR}/") + +idf_component_register( + SRCS ${LIBSMB2_SOURCES} + INCLUDE_DIRS + "${LIBSMB2_DIR}/include" + "${LIBSMB2_DIR}/include/smb2" + "${LIBSMB2_DIR}/include/esp" + PRIV_INCLUDE_DIRS + "${LIBSMB2_LIB_DIR}" + REQUIRES + lwip + mbedtls + sock_utils +) + +target_compile_definitions(${COMPONENT_LIB} PRIVATE + HAVE_CONFIG_H + NEED_READV + NEED_WRITEV + NEED_GETLOGIN_R + NEED_RANDOM + NEED_SRANDOM + "_U_=__attribute__((unused))" +) + +# Vendored upstream code, built as-is: relax -Werror for warning classes that +# are harmless in practice (e.g. a tautological unsigned comparison in +# libsmb2.c) rather than patching third-party sources to satisfy this +# project's stricter default warning flags. +target_compile_options(${COMPONENT_LIB} PRIVATE + -Wno-error=type-limits +) diff --git a/src/components/libsmb2_esp/idf_component.yml b/src/components/libsmb2_esp/idf_component.yml new file mode 100644 index 0000000..043062a --- /dev/null +++ b/src/components/libsmb2_esp/idf_component.yml @@ -0,0 +1,8 @@ +## IDF Component Manager Manifest File +dependencies: + idf: + version: '>=4.1.0' + # gethostname() is not provided by ESP-IDF's libc; libsmb2's server accept + # path (smb2_serve_port) calls it directly. sock_utils supplies a minimal + # implementation. + espressif/sock_utils: "*" diff --git a/src/dependencies.lock b/src/dependencies.lock new file mode 100644 index 0000000..26d4164 --- /dev/null +++ b/src/dependencies.lock @@ -0,0 +1,83 @@ +dependencies: + espressif/esp_new_jpeg: + component_hash: e1e7e6991193c41ed6c9fc386702aa7821433319e7aa9c3147cd3236310cd69c + dependencies: [] + source: + registry_url: https://components.espressif.com/ + type: service + targets: + - esp32 + - esp32s2 + - esp32s3 + - esp32s31 + - esp32p4 + - esp32c2 + - esp32c3 + - esp32c5 + - esp32c6 + - esp32c61 + - esp32h4 + version: 1.0.2 + espressif/sock_utils: + component_hash: b2e5cafc60dfefd05720ababb9fca0dfe2830fb9d71f97e5336de36a84c591c9 + dependencies: + - name: idf + require: private + version: '>=5.0' + source: + registry_url: https://components.espressif.com/ + type: service + version: 0.2.2 + espressif/usb: + component_hash: 6c2cff118141dbbca181d0d27d71801fdddfc78f7ac03ae43f6e5a8cbd89cb99 + dependencies: + - name: idf + require: private + version: '>=5.5.3' + source: + registry_url: https://components.espressif.com + type: service + targets: + - esp32s2 + - esp32s3 + - esp32s31 + - esp32p4 + - esp32h4 + - linux + version: 1.5.0 + espressif/usb_host_hid: + component_hash: a6c5366f9b6d80b0d5f56d085d62941464512e0968b96c5877e76a80fcc23f13 + dependencies: + - name: idf + require: private + version: '>=5.0' + - name: espressif/usb + registry_url: https://components.espressif.com + require: public + rules: + - if: idf_version >=6.0 + - if: target not in ["linux"] + version: ^1.0.0 + source: + registry_url: https://components.espressif.com/ + type: service + targets: + - esp32s2 + - esp32s3 + - esp32p4 + - esp32h4 + - esp32s31 + - linux + version: 1.2.0 + idf: + source: + type: idf + version: 6.1.0 +direct_dependencies: +- espressif/esp_new_jpeg +- espressif/sock_utils +- espressif/usb_host_hid +- idf +manifest_hash: a4d460bb515c6dffc30079d44d3c29fccc46d49abbe9d3c15eabf6486c7456c0 +target: esp32s3 +version: 3.0.0 diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt new file mode 100644 index 0000000..d2f9b7b --- /dev/null +++ b/src/main/CMakeLists.txt @@ -0,0 +1,12 @@ +file(GLOB SOURCES "*.c" "*.cpp") + +idf_component_register(SRCS ${SOURCES} INCLUDE_DIRS ".") + +idf_build_set_property(COMPILE_OPTIONS "-ggdb;-g3" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-Wno-missing-field-initializers" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-Wno-implicit-fallthrough" APPEND) + +# target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format) +# target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error) +# target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-but-set-variable) +# target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-function) diff --git a/src/main/at_cip.cpp b/src/main/at_cip.cpp new file mode 100644 index 0000000..863db58 --- /dev/null +++ b/src/main/at_cip.cpp @@ -0,0 +1,314 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_tls.h" +#include "esp_crt_bundle.h" + +#include "main.h" +#include "at_uart.h" +#include "at_cip.h" +#include "wifi.h" + +static const char *TAG = "at_cip"; + +static int cip_sock = -1; +static int cip_type = CIP_TYPE_NONE; +static char cip_host[64]; +static int cip_port = 0; +static esp_tls_t *cip_tls = NULL; + +void at_cip_init() +{ + cip_sock = -1; + cip_type = CIP_TYPE_NONE; + cip_host[0] = 0; + cip_port = 0; + cip_tls = NULL; +} + +bool at_cip_is_connected() +{ + return cip_sock >= 0 || cip_tls != NULL; +} + +void at_cip_status_line(char *buf, size_t buflen) +{ + if (!at_cip_is_connected()) + { + snprintf(buf, buflen, "STATUS:0"); + return; + } + + const char *type_str = cip_type == CIP_TYPE_UDP ? "UDP" : cip_type == CIP_TYPE_SSL ? "SSL" : "TCP"; + snprintf(buf, buflen, "STATUS:3\r\n+CIPSTATUS:0,\"%s\",\"%s\",%d,0,0", type_str, cip_host, cip_port); +} + +// Resolves and connects a raw socket via the plain BSD gethostbyname()/connect() +// path. Shared by plain TCP and (as of the SSL support below) also by the TLS +// path: esp_tls's own built-in connect step goes through getaddrinfo() instead, +// which crashes (LoadProhibited, NULL FreeRTOS queue handle deep inside lwIP's +// tcpip_task message-passing - confirmed via backtrace against esp-spi.elf, +// root cause not fully understood) the first time it's exercised from this +// task. gethostbyname() uses a different, older lwIP DNS code path that has +// always worked fine here, so SSL connects through it too and only hands +// esp_tls an already-open socket, skipping esp_tls's DNS/connect step entirely. +static int at_cip_connect_raw_tcp(int sock_type, const char *host, int port, bool set_rcv_timeout) +{ + // gethostbyname() (and, for the SSL caller, esp_tls's own getaddrinfo() + // fallback below) both post through tcpip_task's mailbox - if this is the + // very first network command since boot (no AT+CWJAP/AT+CWLAP yet), that + // mailbox doesn't exist yet and the post crashes with a NULL-queue-handle + // LoadProhibited (EXCVADDR=0x54, confirmed via console backtrace: reproduced + // with a plain AT+CIPSTART="TCP" to a literal IP right after a fresh boot, + // fixed by ensuring the WiFi stack is up first, same lazy-init used by + // AT+CWLAP - safe to call again if already initialized). + if (!net_mtx) + initialize_wifi(); + + struct hostent *server = gethostbyname(host); + if (!server) + { + ESP_LOGW(TAG, "DNS lookup failed for '%s'", host); + return -1; + } + + int sock = socket(AF_INET, sock_type, 0); + if (sock < 0) + { + ESP_LOGW(TAG, "socket() failed"); + return -1; + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + memcpy(&addr.sin_addr.s_addr, server->h_addr, server->h_length); + + // A short receive timeout lets at_cip_rx_task poll periodically instead of + // blocking forever, so it notices at_cip_close() promptly. Skipped here for + // the SSL caller: applying it before the TLS handshake made mbedtls's own + // blocking reads see spurious timeouts mid-handshake (a partial/timed-out + // read on a socket mbedtls expects to block on desyncs its record parser - + // confirmed by this exact change turning consistent MBEDTLS_ERR_SSL_INVALID_RECORD + // handshake failures into a clean handshake). The SSL path sets this itself + // after the handshake completes, once the socket moves to steady-state reads. + if (set_rcv_timeout) + { + struct timeval tv = { 0, 200 * 1000 }; + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + } + + if (sock_type == SOCK_DGRAM) + return sock; // UDP: no connect() handshake to wait on + + // Bound the connect() itself with an explicit timeout via a non-blocking + // connect + select(): an unreachable-but-not-immediately-rejected address + // (e.g. a black-holed IP) can otherwise leave the OS/lwip TCP SYN retry + // logic blocking this call for a minute or more, freezing the whole AT + // command interface for that entire time. + int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + + int rc = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); + + if (rc < 0 && errno != EINPROGRESS) + { + ESP_LOGW(TAG, "connect() to %s:%d failed immediately", host, port); + close(sock); + return -1; + } + + if (rc < 0) // EINPROGRESS - wait for it to complete + { + fd_set wfds; + FD_ZERO(&wfds); + FD_SET(sock, &wfds); + struct timeval conn_tv = { 10, 0 }; // 10s connect timeout + + int sel = select(sock + 1, NULL, &wfds, NULL, &conn_tv); + + if (sel <= 0) + { + ESP_LOGW(TAG, "connect() to %s:%d timed out", host, port); + close(sock); + return -1; + } + + int so_err = 0; + socklen_t so_len = sizeof(so_err); + getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_err, &so_len); + + if (so_err != 0) + { + ESP_LOGW(TAG, "connect() to %s:%d failed: errno %d", host, port, so_err); + close(sock); + return -1; + } + } + + fcntl(sock, F_SETFL, flags); // back to blocking for the (rare) case send() would need it + return sock; +} + +static int at_cip_start_ssl(const char *host, int port) +{ + int sock = at_cip_connect_raw_tcp(SOCK_STREAM, host, port, false); + if (sock < 0) + return -1; + + // Kept local until the handshake fully succeeds below, deliberately not + // written to the global cip_tls yet: at_cip_is_connected() (checked by + // at_cip_rx_task's poll loop, running concurrently in its own task) goes by + // cip_tls != NULL, and that task calling esp_tls_conn_read() on a context + // that's mid-handshake raced with esp_tls_conn_new_sync() below over the + // same mbedtls ssl_context - confirmed via mbedtls debug log showing + // interleaved flush-output calls and a corrupted ssl->out_left, manifesting + // as MBEDTLS_ERR_SSL_INTERNAL_ERROR then MBEDTLS_ERR_SSL_INVALID_RECORD. + // The plain-TCP path never had this problem because it keeps its socket in + // a local variable the same way, only publishing to cip_sock at the very end. + esp_tls_t *tls = esp_tls_init(); + if (!tls) + { + ESP_LOGW(TAG, "esp_tls_init failed"); + close(sock); + return -1; + } + + esp_tls_set_conn_sockfd(tls, sock); + esp_tls_set_conn_state(tls, ESP_TLS_CONNECTING); // skip esp_tls's own DNS/connect step - see at_cip_connect_raw_tcp() + + esp_tls_cfg_t cfg = {}; + cfg.crt_bundle_attach = esp_crt_bundle_attach; + cfg.timeout_ms = 10000; // matches the connect timeout already spent above + + int rc = esp_tls_conn_new_sync(host, strlen(host), port, &cfg, tls); + if (rc != 1) + { + ESP_LOGW(TAG, "TLS handshake with %s:%d failed", host, port); + esp_tls_conn_destroy(tls); // also closes sock, it now owns the fd + return -1; + } + + // Now that the handshake is done, throttle reads the same way the plain-TCP + // path does, so at_cip_rx_task's poll loop notices at_cip_close() promptly. + struct timeval tv = { 0, 200 * 1000 }; + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + cip_tls = tls; // now safe to publish: handshake is done, at_cip_rx_task may use it + cip_type = CIP_TYPE_SSL; + strlcpy(cip_host, host, sizeof(cip_host)); + cip_port = port; + + ESP_LOGI(TAG, "connected SSL %s:%d", host, port); + return 0; +} + +int at_cip_start(const char *type, const char *host, int port) +{ + if (at_cip_is_connected()) + return -2; // already connected + + if (!strcasecmp(type, "SSL")) + return at_cip_start_ssl(host, port); + + int sock_type = 0; + + if (!strcasecmp(type, "TCP")) + sock_type = SOCK_STREAM; + else if (!strcasecmp(type, "UDP")) + sock_type = SOCK_DGRAM; + else + { + ESP_LOGW(TAG, "unknown type '%s'", type); + return -1; + } + + int sock = at_cip_connect_raw_tcp(sock_type, host, port, true); + if (sock < 0) + return -1; + + cip_sock = sock; + cip_type = (sock_type == SOCK_DGRAM) ? CIP_TYPE_UDP : CIP_TYPE_TCP; + strlcpy(cip_host, host, sizeof(cip_host)); + cip_port = port; + + ESP_LOGI(TAG, "connected %s %s:%d", cip_type == CIP_TYPE_UDP ? "UDP" : "TCP", host, port); + return 0; +} + +int at_cip_send(const uint8_t *data, size_t len) +{ + if (cip_tls) return (int)esp_tls_conn_write(cip_tls, data, len); + if (cip_sock < 0) return -1; + return send(cip_sock, data, len, 0); +} + +void at_cip_close() +{ + if (!at_cip_is_connected()) return; + + if (cip_tls) + { + esp_tls_conn_destroy(cip_tls); + cip_tls = NULL; + } + else + { + close(cip_sock); + cip_sock = -1; + } + + cip_type = CIP_TYPE_NONE; + cip_host[0] = 0; + cip_port = 0; +} + +void at_cip_rx_task(void *arg) +{ + uint8_t buf[1024]; + + while (1) + { + if (!at_cip_is_connected()) + { + vTaskDelay(pdMS_TO_TICKS(100)); + continue; + } + + esp_tls_t *tls = cip_tls; // snapshot; at_cip_close() may change these concurrently + int sock = cip_sock; + int n = tls ? (int)esp_tls_conn_read(tls, buf, sizeof(buf)) : recv(sock, buf, sizeof(buf), 0); + + if (n > 0) + { + char hdr[24]; + snprintf(hdr, sizeof(hdr), "\r\n+IPD,%d:", n); + at_send_str(hdr); + at_send_raw(buf, n); + } + else if (n == 0) + { + // Peer closed (TCP/SSL only - UDP recv() doesn't return 0 on a connected socket). + at_cip_close(); + at_send_str("\r\nCLOSED\r\n"); + } + // n < 0: either the SO_RCVTIMEO timeout expired (EAGAIN/EWOULDBLOCK, expected - + // esp_tls_conn_read() surfaces the same underlying-socket timeout as a generic + // negative return too, not distinguished from a real error here, matching how + // the plain-TCP path already treats every negative read as "retry") or the + // connection was closed out from under us by at_cip_close() (also fine, + // at_cip_is_connected() will be false at the top next time). + } +} diff --git a/src/main/at_cip.h b/src/main/at_cip.h new file mode 100644 index 0000000..9b1e6d0 --- /dev/null +++ b/src/main/at_cip.h @@ -0,0 +1,22 @@ + +#pragma once + +#include +#include + +enum +{ + CIP_TYPE_NONE = 0, + CIP_TYPE_TCP, + CIP_TYPE_UDP, + CIP_TYPE_SSL, +}; + +void at_cip_init(); +int at_cip_start(const char *type, const char *host, int port); // 0 ok, <0 on error, -2 if already connected +int at_cip_send(const uint8_t *data, size_t len); // returns bytes sent, or <0 +void at_cip_close(); +bool at_cip_is_connected(); +void at_cip_status_line(char *buf, size_t buflen); + +void at_cip_rx_task(void *arg); diff --git a/src/main/at_uart.cpp b/src/main/at_uart.cpp new file mode 100644 index 0000000..c3b100c --- /dev/null +++ b/src/main/at_uart.cpp @@ -0,0 +1,572 @@ +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/uart.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_wifi.h" + +#include "main.h" +#include "esp_spi_defs.h" +#include "wifi.h" +#include "at_cip.h" +#include "at_uart.h" + +#define AT_CIPSEND_MAX_LEN 1460 + +static const char *TAG = "at_uart"; + +static bool at_echo = true; + +enum +{ + AT_MODE_LINE, + AT_MODE_CIPSEND_DATA, +}; + +static int at_mode = AT_MODE_LINE; +static uint8_t at_cipsend_buf[AT_CIPSEND_MAX_LEN]; +static size_t at_cipsend_len = 0; +static size_t at_cipsend_have = 0; + +void at_uart_init() +{ + uart_config_t cfg = {}; + cfg.baud_rate = AT_UART_BAUD; + cfg.data_bits = UART_DATA_8_BITS; + cfg.parity = UART_PARITY_DISABLE; + cfg.stop_bits = UART_STOP_BITS_1; + cfg.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; + cfg.source_clk = UART_SCLK_DEFAULT; + + ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, AT_UART_RX_BUF_SIZE, AT_UART_TX_BUF_SIZE, 0, NULL, 0)); + ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &cfg)); + ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, AT_UART_TX_PIN, AT_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); + + ESP_LOGI(TAG, "AT UART ready: TX=%d RX=%d %d 8N1", AT_UART_TX_PIN, AT_UART_RX_PIN, AT_UART_BAUD); + + // Real ESP8266 AT firmware emits this on the AT UART itself after boot/AT+RST; + // AT client libraries commonly block waiting for it before sending further commands. + at_send_raw("\r\nready\r\n", 9); +} + +void at_send_raw(const void *data, size_t len) +{ + uart_write_bytes(UART_NUM_1, (const char*)data, len); +} + +void at_send_str(const char *s) +{ + at_send_raw(s, strlen(s)); +} + +static void at_reply_ok() +{ + at_send_str("\r\nOK\r\n"); +} + +static void at_reply_error() +{ + at_send_str("\r\nERROR\r\n"); +} + +static void at_cmd_gmr() +{ + // The ZX Evolution client's single-shot display capture after AT+GMR is + // timing-sensitive on real hardware (verified: even small changes in send + // timing shift what fraction of this reply the client's display happens to + // catch, sometimes none of it, without affecting correctness - GMR's actual + // reply content and the OK are always sent and processed correctly + // regardless). A short delay between the echoed command line and the reply + // gives the client's display time to get ready before the content arrives. + vTaskDelay(pdMS_TO_TICKS(500)); + + // No leading CRLF and no blank line before OK: verified byte-for-byte + // against a real ESP8266 AT module's actual AT+GMR reply on real hardware. + char buf[192]; + at_send_str(CP_STRING); + at_send_str("\r\n"); + + at_send_str(API_STRING); + at_send_str("\r\n"); + + snprintf(buf, sizeof(buf), "SDK version:%s", IDF_VER); + at_send_str(buf); + at_send_str("\r\n"); + + at_send_str("OK"); + at_send_str("\r\n"); +} + +// Splits comma-separated args in place, honoring double-quoted tokens +// (e.g. `"ssid","pass"` or `"TCP",host,port`). Returns the number of tokens +// found (up to max_args); each out[i] points into 'args' (NUL-terminated). +static int at_parse_args(char *args, char *out[], int max_args) +{ + int count = 0; + char *p = args; + + while (*p && count < max_args) + { + while (*p == ' ') p++; + if (!*p) break; + + if (*p == '"') + { + p++; + out[count++] = p; + while (*p && *p != '"') p++; + if (*p == '"') *p++ = 0; + } + else + { + out[count++] = p; + while (*p && *p != ',') p++; + } + + while (*p == ' ') p++; + if (*p == ',') { *p = 0; p++; } + else if (*p) *p = 0; + } + + return count; +} + +static void at_cmd_cwmode(char *args, bool is_query) +{ + if (is_query) + { + char buf[24]; + snprintf(buf, sizeof(buf), "\r\n+CWMODE:1\r\n"); + at_send_str(buf); + at_reply_ok(); + return; + } + + if (!args || strcmp(args, "1")) + { + at_reply_error(); // only STA mode (1) is supported - AP/APSTA out of scope + return; + } + + at_reply_ok(); +} + +static void at_cmd_cwjap(char *args) +{ + char *tok[2]; + + if (!args || at_parse_args(args, tok, 2) != 2) + { + at_reply_error(); + return; + } + + bool connected = wifi_connect_locked(tok[0], tok[1], CONNECT_TIMEOUT_MS); + + if (!connected) + { + at_reply_error(); + return; + } + + // The ZX Evolution client (zifi_orig.asm) sends every AT command via zifi_send, + // which does a throwaway read (zifi_check_receive_command) right after writing + // the command - it patiently polls (screen-frame-gated, ~5s worst case) until + // ANY byte shows up, then slurps and discards it. For AT+CWJAP specifically, + // a SEPARATE loop right after re-polls for "OK\r" with no timeout at all. Real + // ESP8266 hardware takes several seconds to actually join, so that throwaway + // read naturally times out empty before the real reply lands, leaving it for + // the real wait loop to catch. Our join is near-instant (verified: the discard + // read grabs our whole reply within milliseconds, then the real wait loop hangs + // forever with nothing left to find) - so replying quickly here deterministically + // breaks this client. Deliberately hold the reply past that ~5s throwaway window. + vTaskDelay(pdMS_TO_TICKS(6500)); + at_reply_ok(); +} + +static void at_cmd_cwqap() +{ + wifi_disconnect_now_locked(); + at_reply_ok(); +} + +static void at_cmd_cwlap() +{ + if (!net_mtx) + initialize_wifi(); // lazily creates net_mtx as its first action + + if (xSemaphoreTake(net_mtx, portMAX_DELAY) != pdTRUE) + { + at_reply_error(); + return; + } + + esp_err_t err = (esp_err_t)wf_scan(300); + + if (err != ESP_OK) + { + xSemaphoreGive(net_mtx); + at_reply_error(); + return; + } + + uint16_t num = wf_get_ap_num(); + char line[160]; + + for (uint16_t i = 0; i < num; i++) + { + uint8_t auth, chan; + int8_t rssi; + uint8_t *ssid; + wf_get_ap(i, auth, rssi, chan, ssid); + snprintf(line, sizeof(line), "\r\n+CWLAP:(%u,\"%s\",%d,%u)", auth, ssid, rssi, chan); + at_send_str(line); + } + + xSemaphoreGive(net_mtx); + at_reply_ok(); +} + +static void at_cmd_cipsntpcfg(char *args, bool is_query) +{ + bool enable; + int timezone; + char s1[64], s2[64], s3[64]; + + if (is_query) + { + sntp_get_config(enable, timezone, s1, s2, s3, sizeof(s1)); + + char buf[220]; + if (s3[0]) + snprintf(buf, sizeof(buf), "\r\n+CIPSNTPCFG:%d,%d,\"%s\",\"%s\",\"%s\"\r\n", enable ? 1 : 0, timezone, s1, s2, s3); + else if (s2[0]) + snprintf(buf, sizeof(buf), "\r\n+CIPSNTPCFG:%d,%d,\"%s\",\"%s\"\r\n", enable ? 1 : 0, timezone, s1, s2); + else + snprintf(buf, sizeof(buf), "\r\n+CIPSNTPCFG:%d,%d,\"%s\"\r\n", enable ? 1 : 0, timezone, s1); + at_send_str(buf); + at_reply_ok(); + return; + } + + char *tok[5]; + int n = args ? at_parse_args(args, tok, 5) : 0; + + if (n < 2) + { + at_reply_error(); + return; + } + + char *endp = NULL; + long en = strtol(tok[0], &endp, 10); + if (!endp || *endp || (en != 0 && en != 1)) + { + at_reply_error(); + return; + } + + endp = NULL; + long tz = strtol(tok[1], &endp, 10); + if (!endp || *endp || tz < -12 || tz > 14) + { + at_reply_error(); + return; + } + + sntp_apply_config(en != 0, (int)tz, n >= 3 ? tok[2] : NULL, n >= 4 ? tok[3] : NULL, n >= 5 ? tok[4] : NULL); + at_reply_ok(); +} + +static void at_cmd_cipsntptime() +{ + char timestr[40]; + sntp_format_time(timestr, sizeof(timestr)); + + char buf[64]; + snprintf(buf, sizeof(buf), "\r\n+CIPSNTPTIME:%s\r\n", timestr); + at_send_str(buf); + at_reply_ok(); +} + +static void at_cmd_cifsr() +{ + uint8_t ip[4], mask[4], gate[4], mac[6] = {0}; + get_ip(ip, mask, gate); + esp_wifi_get_mac(WIFI_IF_STA, mac); + + char buf[96]; + snprintf(buf, sizeof(buf), "\r\n+CIFSR:STAIP,\"%u.%u.%u.%u\"\r\n+CIFSR:STAMAC,\"%02x:%02x:%02x:%02x:%02x:%02x\"\r\n", + ip[0], ip[1], ip[2], ip[3], mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + at_send_str(buf); + at_reply_ok(); +} + +static void at_cmd_cipstatus() +{ + char buf[128]; + at_cip_status_line(buf, sizeof(buf)); + at_send_str("\r\n"); + at_send_str(buf); + at_send_str("\r\n"); + at_reply_ok(); +} + +static void at_cmd_cipstart(char *args) +{ + char *tok[3]; + + if (!args || at_parse_args(args, tok, 3) != 3) + { + at_reply_error(); + return; + } + + int port = atoi(tok[2]); + int rc = at_cip_start(tok[0], tok[1], port); + + if (rc == -2) + { + at_send_str("\r\nALREADY CONNECTED\r\n"); + at_reply_error(); + return; + } + + if (rc != 0) + { + at_reply_error(); + return; + } + + at_send_str("\r\nCONNECT\r\n"); + at_reply_ok(); +} + +static void at_cmd_cipsend(char *args) +{ + if (!args) + { + at_reply_error(); + return; + } + + int len = atoi(args); + + if (len <= 0 || len > AT_CIPSEND_MAX_LEN) + { + at_reply_error(); + return; + } + + if (!at_cip_is_connected()) + { + at_reply_error(); + return; + } + + at_cipsend_len = (size_t)len; + at_cipsend_have = 0; + at_mode = AT_MODE_CIPSEND_DATA; + + at_send_str("\r\nOK\r\n>"); +} + +static void at_cmd_cipclose() +{ + at_cip_close(); + at_send_str("\r\nCLOSED\r\n"); + at_reply_ok(); +} + +// Dispatches one complete, NUL-terminated line (trailing \r/\n already stripped by caller). +static void at_dispatch_line(char *line, size_t len) +{ + if (at_echo) + { + at_send_str(line); + at_send_str("\r\n"); + } + + if (len == 0) return; // silently ignore stray blank lines, matches real AT modules + + if (!strcasecmp(line, "AT")) + { + at_reply_ok(); + return; + } + + if (!strncasecmp(line, "ATE", 3) && len == 4 && (line[3] == '0' || line[3] == '1')) + { + at_echo = (line[3] == '1'); + at_reply_ok(); + return; + } + + if (strncasecmp(line, "AT+", 3) != 0) + { + at_reply_error(); + return; + } + + char *cmd = line + 3; + char *eq = strchr(cmd, '='); + char *args = NULL; + bool is_query = false; + + if (eq) + { + *eq = 0; + args = eq + 1; + } + else + { + size_t clen = strlen(cmd); + if (clen && cmd[clen - 1] == '?') + { + cmd[clen - 1] = 0; + is_query = true; + } + } + + if (!strcasecmp(cmd, "RST")) + { + at_reply_ok(); + ESP_LOGE(TAG, "software restart requested by AT+RST on UART1"); + vTaskDelay(pdMS_TO_TICKS(50)); + esp_restart(); + } + else if (!strcasecmp(cmd, "GMR")) + at_cmd_gmr(); + else if (!strcasecmp(cmd, "CWMODE") || !strcasecmp(cmd, "CWMODE_CUR") || !strcasecmp(cmd, "CWMODE_DEF")) + at_cmd_cwmode(args, is_query); + else if (!strcasecmp(cmd, "CWJAP") || !strcasecmp(cmd, "CWJAP_CUR") || !strcasecmp(cmd, "CWJAP_DEF")) + at_cmd_cwjap(args); + else if (!strcasecmp(cmd, "CWQAP")) + at_cmd_cwqap(); + else if (!strcasecmp(cmd, "CWLAP")) + at_cmd_cwlap(); + else if (!strcasecmp(cmd, "CWAUTOCONN")) + at_reply_ok(); // autoconnect-on-boot persistence is out of scope by design; accept and no-op + else if (!strcasecmp(cmd, "CIPMUX")) + { + // Only single-connection mode (0) is supported - CIPMUX multi-connection is out of scope. + if (args && !strcmp(args, "0")) + at_reply_ok(); + else + at_reply_error(); + } + else if (!strcasecmp(cmd, "CIFSR")) + at_cmd_cifsr(); + else if (!strcasecmp(cmd, "CIPSNTPCFG")) + at_cmd_cipsntpcfg(args, is_query); + else if (!strcasecmp(cmd, "CIPSNTPTIME")) + at_cmd_cipsntptime(); + else if (!strcasecmp(cmd, "CIPSTATUS")) + at_cmd_cipstatus(); + else if (!strcasecmp(cmd, "CIPSTART")) + at_cmd_cipstart(args); + else if (!strcasecmp(cmd, "CIPSEND")) + at_cmd_cipsend(args); + else if (!strcasecmp(cmd, "CIPCLOSE")) + at_cmd_cipclose(); + else + { + ESP_LOGW(TAG, "unknown command '%s'", cmd); + at_reply_error(); + } +} + +static void at_process_cipsend_byte(uint8_t b) +{ + at_cipsend_buf[at_cipsend_have++] = b; + + if (at_cipsend_have < at_cipsend_len) + return; + + int sent = at_cip_send(at_cipsend_buf, at_cipsend_have); + at_mode = AT_MODE_LINE; + + if (sent < 0 || (size_t)sent != at_cipsend_have) + at_send_str("\r\nSEND FAIL\r\n"); + else + at_send_str("\r\nSEND OK\r\n"); +} + +void at_task(void *arg) +{ + char linebuf[AT_LINE_MAX_LEN]; + size_t linelen = 0; + bool just_saw_cr = false; + uint8_t rxbuf[64]; + + while (1) + { + int n = uart_read_bytes(UART_NUM_1, rxbuf, sizeof(rxbuf), pdMS_TO_TICKS(20)); + + for (int i = 0; i < n; i++) + { + uint8_t b = rxbuf[i]; + + // Swallow the LF half of a CRLF pair unconditionally, *before* looking at + // at_mode - a command dispatched on '\r' (e.g. AT+CIPSEND=) can switch + // straight into AT_MODE_CIPSEND_DATA, and the following '\n' must not be + // mistaken for the first byte of that payload. + if (just_saw_cr) + { + just_saw_cr = false; + if (b == '\n') continue; + } + + if (at_mode == AT_MODE_CIPSEND_DATA) + { + at_process_cipsend_byte(b); + continue; + } + + char c = (char)b; + + if (c == '\r') + { + linebuf[linelen] = 0; + at_dispatch_line(linebuf, linelen); + linelen = 0; + just_saw_cr = true; + } + else if (c == '\n') + { + linebuf[linelen] = 0; + at_dispatch_line(linebuf, linelen); + linelen = 0; + } + else if (linelen < AT_LINE_MAX_LEN - 1) + { + linebuf[linelen++] = c; + } + else + { + linelen = 0; + at_reply_error(); + } + } + } +} + +TaskHandle_t g_at_task_handle = NULL; +TaskHandle_t g_at_cip_rx_task_handle = NULL; + +void at_uart_suspend() +{ + if (g_at_task_handle) vTaskSuspend(g_at_task_handle); + if (g_at_cip_rx_task_handle) vTaskSuspend(g_at_cip_rx_task_handle); +} + +void at_uart_resume() +{ + if (g_at_task_handle) vTaskResume(g_at_task_handle); + if (g_at_cip_rx_task_handle) vTaskResume(g_at_cip_rx_task_handle); +} diff --git a/src/main/at_uart.h b/src/main/at_uart.h new file mode 100644 index 0000000..fd830c6 --- /dev/null +++ b/src/main/at_uart.h @@ -0,0 +1,30 @@ + +#pragma once + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define AT_UART_TX_PIN 18 +#define AT_UART_RX_PIN 8 +#define AT_UART_BAUD 115200 +#define AT_UART_RX_BUF_SIZE 2048 +#define AT_UART_TX_BUF_SIZE 2048 +#define AT_LINE_MAX_LEN 512 + +void at_uart_init(); +void at_task(void *arg); +void at_send_raw(const void *data, size_t len); +void at_send_str(const char *s); + +// Populated by main.cpp's xTaskCreatePinnedToCoreWithCaps() calls for +// at_task/at_cip_rx_task - used by at_uart_suspend()/at_uart_resume() below. +extern TaskHandle_t g_at_task_handle; +extern TaskHandle_t g_at_cip_rx_task_handle; + +// Pause/resume the whole AT-command modem interface (both the UART command +// parser and the CIP data-mode RX relay) - used while the SMB2/3 server is +// active, since the Z80 side is single-tasking and can't be driving both +// the classic ZiFi AT interface and the smbvfs.wmf plugin at once anyway. +void at_uart_suspend(); +void at_uart_resume(); diff --git a/src/main/cmd.cpp b/src/main/cmd.cpp new file mode 100644 index 0000000..78f9e19 --- /dev/null +++ b/src/main/cmd.cpp @@ -0,0 +1,10835 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/uart.h" + +#include "esp_console.h" +#include "esp_err.h" +#include "esp_heap_caps.h" +#include "esp_attr.h" +#include "esp_private/esp_clk.h" +#include "esp_vfs_fat.h" +#include "sdkconfig.h" + +#include "cmd.h" +#include "ft8xx.h" +#include "tracker.h" +#include "sfx.h" +#include "mem_obj.h" +#include "esp_spi_defs.h" +#include "sdmmc.h" +#include "fatfs.h" +#include "stats.h" +#include "tsf.h" + + +#define CMD_LAYOUT_TOP_Y 0 +#define CMD_LAYOUT_PANEL_Y 0 + +#define CMD_PANEL_LEFT 0 +#define CMD_PANEL_RIGHT 1 + +#define CMD_APP_STATUS_MAX 80 +#define CMD_APP_DEVICE_ITEM_MAX 40 +#define CMD_APP_DEVICE_DIALOG_W 44 +#define CMD_APP_DEVICE_DIALOG_H 9 +#define CMD_APP_HELP_DIALOG_W 70 +#define CMD_APP_HELP_DIALOG_H 25 +#define CMD_APP_HELP_DIALOG_REFRESH_MS 100 +#define CMD_APP_FILEOP_DIALOG_W 58 +#define CMD_APP_FILEOP_DIALOG_H 8 +#define CMD_APP_ERROR_DIALOG_W 60 +#define CMD_APP_ERROR_DIALOG_H 8 +#define CMD_APP_MKDIR_DIALOG_W 54 +#define CMD_APP_MKDIR_DIALOG_H 7 +#define CMD_APP_ERROR_TITLE_MAX 40 +#define CMD_APP_VIEWER_READ_BUFFER_SIZE 512 +#define CMD_APP_VIEWER_MAX_ROWS (CMD_DISPLAY_ROWS - 2) +#define CMD_APP_VIEWER_LINE_SIZE (CMD_DISPLAY_COLS + 1) +#define CMD_APP_HEX_VIEWER_BYTES_PER_ROW 16 +#define CMD_APP_BAUD_SWITCH_DELAY_MS 100 +#define CMD_APP_BAUD_SEQ_MAX 96 +#define CMD_APP_BAUD_DEFAULT 115200 +#define CMD_APP_SFX_PREVIEW_GROUP 255 +#define CMD_APP_MODULE_INFO_INITIAL_CAP 4096 +#define CMD_APP_MODULE_INFO_MAX_TEXT_SIZE (512 * 1024) +#define CMD_APP_MODULE_INFO_READ_BUFFER_SIZE MOD_HEADER_SIZE +#define CMD_APP_XM_MAX_ROWS 256 +#define CMD_APP_S3M_FILE_TYPE_OFFSET 29 +#define CMD_APP_S3M_ORDERS_OFFSET 32 +#define CMD_APP_S3M_SAMPLES_OFFSET 34 +#define CMD_APP_S3M_PATTERNS_OFFSET 36 +#define CMD_APP_S3M_FLAGS_OFFSET 38 +#define CMD_APP_S3M_CWTV_OFFSET 40 +#define CMD_APP_S3M_FORMAT_VERSION_OFFSET 42 +#define CMD_APP_S3M_GLOBAL_VOLUME_OFFSET 48 +#define CMD_APP_S3M_SPEED_OFFSET 49 +#define CMD_APP_S3M_TEMPO_OFFSET 50 +#define CMD_APP_S3M_MASTER_VOLUME_OFFSET 51 +#define CMD_APP_S3M_PANNING_TABLE_FLAG_OFFSET 53 +#define CMD_APP_S3M_CHANNEL_SETTINGS_OFFSET 64 +#define CMD_APP_S3M_FILE_TYPE_MODULE 0x10 +#define CMD_APP_S3M_PANNING_TABLE_PRESENT 0xFC +#define CMD_APP_S3M_SAMPLE_TYPE_NONE 0 +#define CMD_APP_S3M_SAMPLE_TYPE_PCM 1 +#define CMD_APP_S3M_SAMPLE_FLAG_LOOP 0x01 +#define CMD_APP_S3M_SAMPLE_FLAG_STEREO 0x02 +#define CMD_APP_S3M_SAMPLE_FLAG_16BIT 0x04 +#define CMD_APP_S3M_SAMPLE_PACK_NONE 0 + +#ifndef CONFIG_ESP_CONSOLE_UART_NUM +#define CONFIG_ESP_CONSOLE_UART_NUM UART_NUM_0 +#endif + +typedef enum +{ + CMD_APP_FILEOP_NONE = 0, + CMD_APP_FILEOP_COPY, + CMD_APP_FILEOP_MOVE, + CMD_APP_FILEOP_DELETE +} cmd_app_fileop_t; + +typedef enum +{ + CMD_APP_NAME_DIALOG_MKDIR = 0, + CMD_APP_NAME_DIALOG_RENAME +} cmd_app_name_dialog_op_t; + +typedef struct CmdApp +{ + CmdFsManager fs; + CmdPanel left_panel; + CmdPanel right_panel; + CmdDisplayBuffer buffer; + CmdDisplayMux mux; + CmdInputBackend *input; + int active_panel; + bool device_dialog_open; + int device_dialog_panel; + int device_dialog_selected; + bool device_dialog_available[CMD_DEVICE_MAX]; + char device_dialog_items[CMD_DEVICE_MAX][CMD_APP_DEVICE_ITEM_MAX + 1]; + bool help_dialog_open; + bool mkdir_dialog_open; + cmd_app_name_dialog_op_t mkdir_dialog_op; + char mkdir_name[CMD_FILE_NAME_MAX]; + char rename_src_path[CMD_PATH_MAX]; + char rename_dst_path[CMD_PATH_MAX]; + char rename_remap_path[CMD_PATH_MAX]; + bool fileop_confirm_open; + cmd_app_fileop_t fileop_confirm_op; + char fileop_name[CMD_FILE_NAME_MAX]; + char fileop_dst_path[CMD_PATH_MAX]; + bool fileop_progress_open; + cmd_app_fileop_t fileop_progress_op; + char fileop_progress_name[CMD_FILE_NAME_MAX]; + uint64_t fileop_bytes_done; + uint64_t fileop_bytes_total; + size_t fileop_files_done; + size_t fileop_files_total; + bool fileop_progress_can_cancel; + bool fileop_group; + size_t fileop_item_count; + uint64_t fileop_item_size; + bool fileop_cancel_requested; + bool error_dialog_open; + esp_err_t error_dialog_err; + char error_dialog_title[CMD_APP_ERROR_TITLE_MAX + 1]; + char error_dialog_message[CMD_APP_STATUS_MAX + 1]; + bool viewer_open; + cmd_device_id_t viewer_device; + char viewer_path[CMD_PATH_MAX]; + char viewer_title[CMD_FILE_NAME_MAX]; + CmdFsFile viewer_file; + bool viewer_file_open; + uint8_t viewer_read_buffer[CMD_APP_VIEWER_READ_BUFFER_SIZE]; + uint8_t viewer_seek_buffer[CMD_APP_VIEWER_READ_BUFFER_SIZE]; + uint64_t viewer_prev_offsets[CMD_APP_VIEWER_MAX_ROWS + 1]; + char viewer_draw_line[CMD_DISPLAY_COLS + 1]; + char viewer_num[24]; + size_t viewer_read_pos; + size_t viewer_read_len; + uint64_t viewer_read_base; + uint64_t viewer_top_offset; + uint64_t viewer_next_offset; + uint64_t viewer_line_offsets[CMD_APP_VIEWER_MAX_ROWS + 1]; + size_t viewer_top_line; + size_t viewer_next_line; + size_t viewer_page_lines; + bool viewer_eof; + char viewer_lines[CMD_APP_VIEWER_MAX_ROWS][CMD_APP_VIEWER_LINE_SIZE]; + bool hex_viewer_open; + cmd_device_id_t hex_viewer_device; + char hex_viewer_path[CMD_PATH_MAX]; + char hex_viewer_title[CMD_FILE_NAME_MAX]; + CmdFsFile hex_viewer_file; + bool hex_viewer_file_open; + uint8_t hex_viewer_read_buffer[CMD_APP_VIEWER_READ_BUFFER_SIZE]; + uint8_t hex_viewer_row[CMD_APP_HEX_VIEWER_BYTES_PER_ROW]; + char hex_viewer_tmp[8]; + uint64_t hex_viewer_offset; + uint64_t hex_viewer_size; + bool hex_viewer_size_known; + size_t hex_viewer_page_rows; + bool hex_viewer_eof; + char hex_viewer_lines[CMD_APP_VIEWER_MAX_ROWS][CMD_APP_VIEWER_LINE_SIZE]; + bool module_info_open; + cmd_device_id_t module_info_device; + char module_info_path[CMD_PATH_MAX]; + char module_info_title[CMD_FILE_NAME_MAX]; + char *module_info_text; + size_t module_info_text_len; + size_t module_info_text_cap; + size_t module_info_top_line; + size_t module_info_line_count; + uint8_t module_info_read_buffer[CMD_APP_MODULE_INFO_READ_BUFFER_SIZE]; + char module_info_tmp[CMD_DISPLAY_COLS + 1]; + char module_info_name[64]; + char module_info_sample_name[64]; + bool jpg_viewer_open; + bool jpg_viewer_added_ft812_backend; + int jpg_viewer_panel; + size_t jpg_viewer_index; + bool jpg_viewer_stretch; + char jpg_viewer_path[CMD_PATH_MAX]; + char jpg_viewer_status[96 + 1]; + int sfx_preview_handle; + int sfx_preview_channel; + void *sfx_preview_addr; + char status[CMD_APP_STATUS_MAX + 1]; +} CmdApp; + +CmdApp *g_cmd_app; + +esp_err_t cmd_app_render(CmdApp *app); +esp_err_t cmd_app_render_console(CmdApp *app); +esp_err_t cmd_app_reload_panel(CmdApp *app, CmdPanel *panel, const char *name); + +int cmd_app_screen_w(const CmdApp *app) +{ + if (!app || app->buffer.size.w <= 0) return CMD_DISPLAY_DEFAULT_COLS; + return app->buffer.size.w; +} + +int cmd_app_screen_h(const CmdApp *app) +{ + if (!app || app->buffer.size.h <= 0) return CMD_DISPLAY_DEFAULT_ROWS; + return app->buffer.size.h; +} + +int cmd_app_bottom_y(const CmdApp *app) +{ + return cmd_app_screen_h(app) - 1; +} + +int cmd_app_panel_info_y(const CmdApp *app) +{ + int y = cmd_app_bottom_y(app) - 2 + 1; + if (y < CMD_LAYOUT_PANEL_Y + 1) y = CMD_LAYOUT_PANEL_Y + 1; + return y; +} + +void cmd_app_make_panel_rects(const CmdApp *app, cmd_rect_t *left, cmd_rect_t *right) +{ + int cols = cmd_app_screen_w(app); + int left_w = cols / 2; + int right_w = cols - left_w; + int panel_h = cmd_app_panel_info_y(app) - CMD_LAYOUT_PANEL_Y; + + if (panel_h < 3) panel_h = 3; + + if (left) + { + left->x = 0; + left->y = CMD_LAYOUT_PANEL_Y; + left->w = left_w; + left->h = panel_h; + } + + if (right) + { + right->x = left_w; + right->y = CMD_LAYOUT_PANEL_Y; + right->w = right_w; + right->h = panel_h; + } +} + +int cmd_app_center_x(const CmdApp *app, int w) +{ + int cols = cmd_app_screen_w(app); + if (w >= cols) return 0; + return (cols - w) / 2; +} + +int cmd_app_center_y(const CmdApp *app, int h) +{ + int rows = cmd_app_screen_h(app); + if (h >= rows) return 0; + return (rows - h) / 2; +} + +CmdApp *cmd_app_alloc() +{ + return (CmdApp *)heap_caps_calloc( + 1, + sizeof(CmdApp), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +} + +void cmd_app_free(CmdApp *app) +{ + if (!app) return; + + heap_caps_free(app); +} + +cmd_display_attr_t cmd_app_normal_attr() +{ + return cmd_display_make_attr(CMD_DISPLAY_COLOR_WHITE, CMD_DISPLAY_COLOR_BLACK, CMD_DISPLAY_ATTR_FLAG_NONE); +} + +cmd_display_attr_t cmd_app_bar_attr() +{ + return cmd_display_make_attr(CMD_DISPLAY_COLOR_BLACK, CMD_DISPLAY_COLOR_CYAN, CMD_DISPLAY_ATTR_FLAG_BOLD); +} + +size_t cmd_app_text_len(const char *s) +{ + size_t len = 0; + + if (!s) return 0; + + while (s[len]) + len++; + + return len; +} + +void cmd_app_text_clear(char *out, size_t out_size) +{ + if (!out || out_size == 0) return; + out[0] = 0; +} + +void cmd_app_append_limited(char *out, size_t out_size, const char *text, size_t max_chars) +{ + size_t len; + size_t pos = 0; + + if (!out || out_size == 0 || !text) return; + + len = cmd_app_text_len(out); + + while (text[pos] && pos < max_chars && len + 1 < out_size) + { + out[len] = text[pos]; + len++; + pos++; + } + + out[len] = 0; +} + +void cmd_app_append_text(char *out, size_t out_size, const char *text) +{ + if (!text) return; + cmd_app_append_limited(out, out_size, text, cmd_app_text_len(text)); +} + +void cmd_app_format_baud(char *out, size_t out_size, uint32_t baud) +{ + unsigned long whole; + unsigned long frac; + + if (!out || out_size == 0) return; + + if (baud >= 1000000) + { + whole = (unsigned long)(baud / 1000000); + frac = (unsigned long)(((baud % 1000000) + 50000) / 100000); + if (frac >= 10) + { + whole++; + frac = 0; + } + if (frac == 0) + snprintf(out, out_size, "%luM", whole); + else + snprintf(out, out_size, "%lu.%luM", whole, frac); + return; + } + + if (baud >= 1000) + { + whole = (unsigned long)(baud / 1000); + frac = (unsigned long)(((baud % 1000) + 50) / 100); + if (frac >= 10) + { + whole++; + frac = 0; + } + if (frac == 0) + snprintf(out, out_size, "%luk", whole); + else + snprintf(out, out_size, "%lu.%luk", whole, frac); + return; + } + + snprintf(out, out_size, "%lu", (unsigned long)baud); +} + +bool cmd_app_get_uart_baud_text(char *out, size_t out_size) +{ + uint32_t baud = 0; + esp_err_t err; + + if (!out || out_size == 0) return false; + + err = uart_get_baudrate((uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, &baud); + if (err != ESP_OK || baud == 0) + { + out[0] = 0; + return false; + } + + cmd_app_format_baud(out, out_size, baud); + return true; +} + +void cmd_app_format_bytes(char *out, size_t out_size, uint64_t value) +{ + unsigned long long whole; + unsigned long long frac; + + if (!out || out_size == 0) return; + + if (value >= (1ULL << 30)) + { + whole = (unsigned long long)(value >> 30); + frac = (unsigned long long)(((value & ((1ULL << 30) - 1)) * 100ULL) >> 30); + snprintf(out, out_size, "%llu.%02llu GiB", whole, frac); + return; + } + + if (value >= (1ULL << 20)) + { + whole = (unsigned long long)(value >> 20); + frac = (unsigned long long)(((value & ((1ULL << 20) - 1)) * 100ULL) >> 20); + snprintf(out, out_size, "%llu.%02llu MiB", whole, frac); + return; + } + + if (value >= (1ULL << 10)) + { + whole = (unsigned long long)(value >> 10); + frac = (unsigned long long)(((value & ((1ULL << 10) - 1)) * 100ULL) >> 10); + snprintf(out, out_size, "%llu.%02llu KiB", whole, frac); + return; + } + + snprintf(out, out_size, "%llu bytes", (unsigned long long)value); +} + +const char *cmd_err_name(esp_err_t err) +{ + switch (err) + { + case CMD_ERR_INVALID_DEVICE: return "CMD_ERR_INVALID_DEVICE"; + case CMD_ERR_NOT_MOUNTED: return "CMD_ERR_NOT_MOUNTED"; + case CMD_ERR_PATH_TOO_LONG: return "CMD_ERR_PATH_TOO_LONG"; + case CMD_ERR_ENTRY_TOO_LONG: return "CMD_ERR_ENTRY_TOO_LONG"; + case CMD_ERR_DIR_FULL: return "CMD_ERR_DIR_FULL"; + case CMD_ERR_INPUT_UNAVAILABLE: return "CMD_ERR_INPUT_UNAVAILABLE"; + case CMD_ERR_CANCELLED: return "CMD_ERR_CANCELLED"; + default: return esp_err_to_name(err); + } +} + +void cmd_set_status(CmdApp *app, const char *fmt, ...) +{ + va_list args; + int written; + + if (!app) return; + + app->status[0] = 0; + if (!fmt) return; + + va_start(args, fmt); + written = vsnprintf(app->status, sizeof(app->status), fmt, args); + va_end(args); + + if (written < 0) + app->status[0] = 0; + else + app->status[sizeof(app->status) - 1] = 0; +} + +void cmd_show_error(CmdApp *app, const char *title, esp_err_t err) +{ + if (!app) return; + + app->error_dialog_open = true; + app->error_dialog_err = err; + cmd_app_text_clear(app->error_dialog_title, sizeof(app->error_dialog_title)); + cmd_app_append_text(app->error_dialog_title, sizeof(app->error_dialog_title), title ? title : "Error"); + cmd_app_text_clear(app->error_dialog_message, sizeof(app->error_dialog_message)); + cmd_app_append_text(app->error_dialog_message, sizeof(app->error_dialog_message), title ? title : "Error"); + cmd_app_append_text(app->error_dialog_message, sizeof(app->error_dialog_message), ": "); + cmd_app_append_text(app->error_dialog_message, sizeof(app->error_dialog_message), cmd_err_name(err)); + cmd_set_status(app, "%s", app->error_dialog_message); +} + +void cmd_app_make_top_bar_line(char *out, size_t out_size, CmdPanel *panel, const char *status) +{ + cmd_app_text_clear(out, out_size); + cmd_app_append_text(out, out_size, "Active: "); + + if (panel) + { + cmd_app_append_text(out, out_size, cmd_device_name(panel->device_id)); + cmd_app_append_text(out, out_size, " Path: "); + cmd_app_append_text(out, out_size, panel->current_path); + if (panel->selected_count > 0) + { + char sel[48]; + snprintf(sel, sizeof(sel), " Sel: %u/%llu", + (unsigned)panel->selected_count, + (unsigned long long)panel->selected_size); + cmd_app_append_text(out, out_size, sel); + } + } + else + { + cmd_app_append_text(out, out_size, "? Path: /"); + } + + cmd_app_append_text(out, out_size, " Free/Used: n/a "); + cmd_app_append_text(out, out_size, status ? status : "ready"); +} + +void cmd_app_set_status(CmdApp *app, const char *text) +{ + cmd_set_status(app, "%s", text ? text : ""); +} + +void cmd_app_set_status_err(CmdApp *app, const char *op, esp_err_t err) +{ + cmd_set_status(app, "%s failed: %s", op ? op : "operation", cmd_err_name(err)); +} + +CmdPanel *cmd_app_panel_by_index(CmdApp *app, int index) +{ + if (!app) return NULL; + if (index == CMD_PANEL_LEFT) return &app->left_panel; + if (index == CMD_PANEL_RIGHT) return &app->right_panel; + return NULL; +} + +CmdPanel *cmd_app_active_panel(CmdApp *app) +{ + if (!app) return NULL; + return cmd_app_panel_by_index(app, app->active_panel); +} + +CmdPanel *cmd_app_passive_panel(CmdApp *app) +{ + if (!app) return NULL; + if (app->active_panel == CMD_PANEL_LEFT) return &app->right_panel; + return &app->left_panel; +} + +void cmd_app_set_active_panel(CmdApp *app, int index) +{ + if (!app) return; + if (index != CMD_PANEL_LEFT && index != CMD_PANEL_RIGHT) return; + + app->active_panel = index; + cmd_panel_set_active(&app->left_panel, index == CMD_PANEL_LEFT); + cmd_panel_set_active(&app->right_panel, index == CMD_PANEL_RIGHT); +} + +void cmd_app_switch_panel(CmdApp *app) +{ + if (!app) return; + + if (app->active_panel == CMD_PANEL_LEFT) + cmd_app_set_active_panel(app, CMD_PANEL_RIGHT); + else + cmd_app_set_active_panel(app, CMD_PANEL_LEFT); +} + +const char *cmd_app_panel_name(int index) +{ + if (index == CMD_PANEL_LEFT) return "left panel"; + if (index == CMD_PANEL_RIGHT) return "right panel"; + return "panel"; +} + +cmd_display_attr_t cmd_app_dialog_attr() +{ + return cmd_display_make_attr(CMD_DISPLAY_COLOR_WHITE, CMD_DISPLAY_COLOR_BLACK, CMD_DISPLAY_ATTR_FLAG_NONE); +} + +cmd_display_attr_t cmd_app_dialog_frame_attr() +{ + return cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_WHITE, CMD_DISPLAY_COLOR_BLACK, CMD_DISPLAY_ATTR_FLAG_BOLD); +} + +cmd_display_attr_t cmd_app_dialog_selected_attr() +{ + return cmd_display_make_attr(CMD_DISPLAY_COLOR_BLACK, CMD_DISPLAY_COLOR_BRIGHT_YELLOW, CMD_DISPLAY_ATTR_FLAG_BOLD | CMD_DISPLAY_ATTR_FLAG_SELECTED); +} + +cmd_display_attr_t cmd_app_dialog_unavailable_attr() +{ + return cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_BLACK, CMD_DISPLAY_COLOR_BLACK, CMD_DISPLAY_ATTR_FLAG_NONE); +} + +void cmd_app_open_device_dialog(CmdApp *app, int panel_index) +{ + CmdPanel *panel; + + if (!app) return; + if (panel_index != CMD_PANEL_LEFT && panel_index != CMD_PANEL_RIGHT) return; + + panel = cmd_app_panel_by_index(app, panel_index); + if (!panel) return; + + app->device_dialog_open = true; + app->device_dialog_panel = panel_index; + app->device_dialog_selected = cmd_fs_is_valid_device_id(panel->device_id) ? (int)panel->device_id : 0; + + for (int i = 0; i < CMD_DEVICE_MAX; i++) + { + cmd_device_id_t device_id = (cmd_device_id_t)i; + bool available = cmd_fs_manager_mount(&app->fs, device_id) == ESP_OK; + + app->device_dialog_available[device_id] = available; + snprintf(app->device_dialog_items[device_id], + sizeof(app->device_dialog_items[device_id]), + "%d %-6s %s", + i + 1, + cmd_device_name(device_id), + available ? "" : "(unavailable)"); + } + + cmd_app_set_status(app, "select device: Enter/1..3, Esc cancel"); +} + +void cmd_app_close_device_dialog(CmdApp *app) +{ + if (!app) return; + + app->device_dialog_open = false; + app->device_dialog_panel = CMD_PANEL_LEFT; + app->device_dialog_selected = 0; +} + +esp_err_t cmd_app_select_device(CmdApp *app, int panel_index, cmd_device_id_t device_id) +{ + CmdPanel *panel; + esp_err_t err; + char line[CMD_APP_STATUS_MAX + 1]; + + if (!app) return ESP_ERR_INVALID_ARG; + if (!cmd_fs_is_valid_device_id(device_id)) return CMD_ERR_INVALID_DEVICE; + + panel = cmd_app_panel_by_index(app, panel_index); + if (!panel) return ESP_ERR_INVALID_ARG; + + err = cmd_panel_change_device(panel, device_id); + if (err != ESP_OK) + { + snprintf(line, sizeof(line), "%s %s unavailable: %s", + cmd_app_panel_name(panel_index), + cmd_device_name(device_id), + cmd_err_name(err)); + cmd_app_set_status(app, line); + return ESP_OK; + } + + snprintf(line, sizeof(line), "%s device: %s", + cmd_app_panel_name(panel_index), + cmd_device_name(device_id)); + cmd_app_set_status(app, line); + return ESP_OK; +} + +esp_err_t cmd_app_select_dialog_device(CmdApp *app, cmd_device_id_t device_id) +{ + int panel_index; + + if (!app) return ESP_ERR_INVALID_ARG; + panel_index = app->device_dialog_panel; + cmd_app_close_device_dialog(app); + return cmd_app_select_device(app, panel_index, device_id); +} + +void cmd_app_draw_device_dialog(CmdApp *app) +{ + cmd_rect_t rect; + cmd_rect_t row_rect; + cmd_display_attr_t attr; + cmd_display_attr_t frame_attr; + cmd_display_attr_t selected_attr; + cmd_display_attr_t unavailable_attr; + char title[CMD_APP_DEVICE_ITEM_MAX + 1]; + + if (!app) return; + if (!app->device_dialog_open) return; + + rect.x = cmd_app_center_x(app, CMD_APP_DEVICE_DIALOG_W); + rect.y = cmd_app_center_y(app, CMD_APP_DEVICE_DIALOG_H); + rect.w = CMD_APP_DEVICE_DIALOG_W; + rect.h = CMD_APP_DEVICE_DIALOG_H; + + attr = cmd_app_dialog_attr(); + frame_attr = cmd_app_dialog_frame_attr(); + selected_attr = cmd_app_dialog_selected_attr(); + unavailable_attr = cmd_app_dialog_unavailable_attr(); + + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_draw_box(&app->buffer, &rect, frame_attr); + + snprintf(title, sizeof(title), " Select device: %s ", cmd_app_panel_name(app->device_dialog_panel)); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y, title, frame_attr); + + for (int i = 0; i < CMD_DEVICE_MAX; i++) + { + cmd_display_attr_t row_attr = attr; + + row_rect.x = rect.x + 2; + row_rect.y = rect.y + 2 + i; + row_rect.w = rect.w - 4; + row_rect.h = 1; + + if (i == app->device_dialog_selected) + row_attr = selected_attr; + else if (!app->device_dialog_available[i]) + row_attr = unavailable_attr; + + cmd_display_buffer_fill_rect(&app->buffer, &row_rect, ' ', row_attr); + cmd_display_buffer_write_text(&app->buffer, row_rect.x + 1, row_rect.y, app->device_dialog_items[i], row_attr); + } + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + rect.h - 2, + "Enter select 1..3 quick Esc cancel", attr); +} + +esp_err_t cmd_app_handle_device_dialog_key(CmdApp *app, const cmd_event_t *event) +{ + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->device_dialog_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY) return ESP_OK; + + if (event->key == CMD_KEY_ESC || event->key == CMD_KEY_F10 || + (event->key == CMD_KEY_CHAR && (event->ch == 'q' || event->ch == 'Q'))) + { + cmd_app_close_device_dialog(app); + cmd_app_set_status(app, "device selection cancelled"); + return ESP_OK; + } + + if (event->key == CMD_KEY_UP) + { + if (app->device_dialog_selected > 0) + app->device_dialog_selected--; + return ESP_OK; + } + + if (event->key == CMD_KEY_DOWN) + { + if (app->device_dialog_selected + 1 < CMD_DEVICE_MAX) + app->device_dialog_selected++; + return ESP_OK; + } + + if (event->key == CMD_KEY_HOME) + { + app->device_dialog_selected = 0; + return ESP_OK; + } + + if (event->key == CMD_KEY_END) + { + app->device_dialog_selected = CMD_DEVICE_MAX - 1; + return ESP_OK; + } + + if (event->key == CMD_KEY_ENTER) + return cmd_app_select_dialog_device(app, (cmd_device_id_t)app->device_dialog_selected); + + if (event->key == CMD_KEY_CHAR && event->ch >= '1' && event->ch <= '0' + CMD_DEVICE_MAX) + return cmd_app_select_dialog_device(app, (cmd_device_id_t)(event->ch - '1')); + + return ESP_OK; +} + +void cmd_app_open_help_dialog(CmdApp *app) +{ + if (!app) return; + + app->help_dialog_open = true; + cmd_app_set_status(app, "help: Enter/Esc close"); +} + +void cmd_app_close_help_dialog(CmdApp *app) +{ + if (!app) return; + + app->help_dialog_open = false; + cmd_app_set_status(app, "ready"); +} + +void cmd_app_draw_help_dialog(CmdApp *app) +{ + cmd_rect_t rect; + cmd_display_attr_t attr; + cmd_display_attr_t frame_attr; + char backend_line[64]; + char baud_text[16]; + char info_line[96]; + char sram_text[32]; + char spiram_text[32]; + size_t sram_free; + size_t spiram_free; + + if (!app) return; + if (!app->help_dialog_open) return; + + rect.x = cmd_app_center_x(app, CMD_APP_HELP_DIALOG_W); + rect.y = cmd_app_center_y(app, CMD_APP_HELP_DIALOG_H); + rect.w = CMD_APP_HELP_DIALOG_W; + rect.h = CMD_APP_HELP_DIALOG_H; + + attr = cmd_app_dialog_attr(); + frame_attr = cmd_app_dialog_frame_attr(); + + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_draw_box(&app->buffer, &rect, frame_attr); + + cmd_app_text_clear(backend_line, sizeof(backend_line)); + for (size_t i = 0; i < app->mux.count; i++) + { + CmdDisplayBackend *backend = app->mux.backends[i]; + const char *backend_name = "?"; + + if (backend == &cmd_display_console_backend) + backend_name = "uart"; + else if (backend == &cmd_display_ft812_backend) + backend_name = "ft"; + else if (backend && backend->name) + backend_name = backend->name; + + if (i > 0) cmd_app_append_text(backend_line, sizeof(backend_line), "+"); + cmd_app_append_text(backend_line, sizeof(backend_line), backend_name); + if (backend == &cmd_display_console_backend && + cmd_app_get_uart_baud_text(baud_text, sizeof(baud_text))) + { + cmd_app_append_text(backend_line, sizeof(backend_line), " ("); + cmd_app_append_text(backend_line, sizeof(backend_line), baud_text); + cmd_app_append_text(backend_line, sizeof(backend_line), ")"); + } + } + + snprintf(info_line, sizeof(info_line), "Window: %dx%d Display: %s", + cmd_app_screen_w(app), + cmd_app_screen_h(app), + backend_line[0] ? backend_line : "?"); + + sram_free = heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + spiram_free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + cmd_app_format_bytes(sram_text, sizeof(sram_text), (uint64_t)sram_free); + cmd_app_format_bytes(spiram_text, sizeof(spiram_text), (uint64_t)spiram_free); + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y, " Commander help ", frame_attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 2, "Tab switch active panel", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 3, "Alt+F1 / Alt+F2 select left/right device", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 4, "F9 or 1 select active panel device", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 5, "Enter open directory or file", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 6, "Backspace go to parent directory", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 7, "Ins / * select item / invert selection", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 8, "F2 rename selected entry", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 9, "F3 / Alt+F3 text/module info / hex viewer", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 10, "F5 / F6 copy / move to opposite panel", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 11, "F7 / F8 / Del mkdir / delete", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 12, "Left / Right page up / page down", attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 13, "Alt+F9 stop XM playback", attr); + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 15, info_line, attr); + snprintf(info_line, sizeof(info_line), "Memory: SRAM free %s SPIRAM free %s", sram_text, spiram_text); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 16, info_line, attr); + + snprintf(info_line, sizeof(info_line), "Firmware: %s API %u Feature %u", + PROD_VER_STRING, + API_VER, + FEAT_VER); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 18, info_line, attr); + snprintf(info_line, sizeof(info_line), "Chip: %s CPU: %d MHz", + CONFIG_IDF_TARGET, + esp_clk_cpu_freq() / 1000000); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 19, info_line, attr); + snprintf(info_line, sizeof(info_line), "Audio CPU: %d.%d/%d.%d%% (last/max)", + stats::_st.audio_total_last_cpu_x10 / 10, + stats::_st.audio_total_last_cpu_x10 % 10, + stats::_st.audio_total_max_cpu_x10 / 10, + stats::_st.audio_total_max_cpu_x10 % 10); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 20, info_line, attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + rect.h - 2, "Enter/Esc/F1/F10 close", attr); +} + +esp_err_t cmd_app_handle_help_dialog_key(CmdApp *app, const cmd_event_t *event) +{ + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->help_dialog_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY && event->type != CMD_EVENT_QUIT) return ESP_OK; + + if (event->type == CMD_EVENT_QUIT || event->key == CMD_KEY_ESC || event->key == CMD_KEY_ENTER || + event->key == CMD_KEY_F1 || event->key == CMD_KEY_F10) + { + cmd_app_close_help_dialog(app); + return ESP_OK; + } + + return ESP_OK; +} + +const char *cmd_app_fileop_verb(cmd_app_fileop_t op) +{ + switch (op) + { + case CMD_APP_FILEOP_COPY: return "Copy"; + case CMD_APP_FILEOP_MOVE: return "Move"; + case CMD_APP_FILEOP_DELETE: return "Delete"; + default: return "Operation"; + } +} + +const char *cmd_app_fileop_past(cmd_app_fileop_t op) +{ + switch (op) + { + case CMD_APP_FILEOP_COPY: return "copied"; + case CMD_APP_FILEOP_MOVE: return "moved"; + case CMD_APP_FILEOP_DELETE: return "deleted"; + default: return "done"; + } +} + +const char *cmd_app_fileop_status_name(cmd_app_fileop_t op) +{ + switch (op) + { + case CMD_APP_FILEOP_COPY: return "copy"; + case CMD_APP_FILEOP_MOVE: return "move"; + case CMD_APP_FILEOP_DELETE: return "delete"; + default: return "operation"; + } +} + +bool cmd_app_has_modal(CmdApp *app) +{ + if (!app) return false; + if (app->device_dialog_open) return true; + if (app->help_dialog_open) return true; + if (app->mkdir_dialog_open) return true; + if (app->fileop_confirm_open) return true; + if (app->fileop_progress_open) return true; + if (app->viewer_open) return true; + if (app->hex_viewer_open) return true; + if (app->module_info_open) return true; + if (app->jpg_viewer_open) return true; + if (app->error_dialog_open) return true; + return false; +} + +void cmd_app_copy_string(char *out, size_t out_size, const char *text) +{ + if (!out || out_size == 0) return; + out[0] = 0; + cmd_app_append_text(out, out_size, text ? text : ""); +} + +esp_err_t cmd_app_join_selected_path(CmdPanel *panel, const cmd_file_entry_t *entry, char *out, size_t out_size) +{ + if (!panel || !entry || !out || out_size == 0) return ESP_ERR_INVALID_ARG; + if (entry->type == CMD_ENTRY_PARENT) return ESP_ERR_INVALID_ARG; + return cmd_fs_join_path(panel->current_path, entry->name, out, out_size); +} + +bool cmd_app_extension_is(const char *name, const char *ext) +{ + const char *dot; + size_t ext_len; + + if (!name || !ext) return false; + + dot = strrchr(name, '.'); + if (!dot) return false; + + ext_len = strlen(ext); + if (strlen(dot) != ext_len) return false; + + for (size_t i = 0; i < ext_len; i++) + { + char a = dot[i]; + char b = ext[i]; + + if (a >= 'A' && a <= 'Z') a = (char)(a - 'A' + 'a'); + if (b >= 'A' && b <= 'Z') b = (char)(b - 'A' + 'a'); + if (a != b) return false; + } + + return true; +} + +bool cmd_app_entry_is_xm(const cmd_file_entry_t *entry) +{ + if (!entry || entry->type != CMD_ENTRY_FILE) return false; + if (cmd_app_extension_is(entry->name, ".xm")) return true; + if (cmd_app_extension_is(entry->name, ".xmz")) return true; + if (cmd_app_extension_is(entry->name, ".mod")) return true; + if (cmd_app_extension_is(entry->name, ".s3m")) return true; + return false; +} + +bool cmd_app_entry_is_module_info(const cmd_file_entry_t *entry) +{ + if (!entry || entry->type != CMD_ENTRY_FILE) return false; + if (cmd_app_extension_is(entry->name, ".xm")) return true; + if (cmd_app_extension_is(entry->name, ".mod")) return true; + if (cmd_app_extension_is(entry->name, ".s3m")) return true; + return false; +} + +bool cmd_app_entry_is_jpg(const cmd_file_entry_t *entry) +{ + if (!entry || entry->type != CMD_ENTRY_FILE) return false; + return ft_jpg_ext_match(entry->name) != 0; +} + +bool cmd_app_entry_is_dxp(const cmd_file_entry_t *entry) +{ + if (!entry || entry->type != CMD_ENTRY_FILE) return false; + return ft_dxp_ext_match(entry->name) != 0; +} + +bool cmd_app_entry_is_ft_image(const cmd_file_entry_t *entry) +{ + return cmd_app_entry_is_jpg(entry) || cmd_app_entry_is_dxp(entry); +} + +bool cmd_app_entry_is_wav(const cmd_file_entry_t *entry) +{ + if (!entry || entry->type != CMD_ENTRY_FILE) return false; + return cmd_app_extension_is(entry->name, ".wav"); +} + +bool cmd_app_has_ft812_backend(CmdApp *app) +{ + if (!app) return false; + + for (size_t i = 0; i < app->mux.count; i++) + if (app->mux.backends[i] == &cmd_display_ft812_backend) + return true; + + return false; +} + +bool cmd_app_has_console_backend(CmdApp *app) +{ + if (!app) return false; + + for (size_t i = 0; i < app->mux.count; i++) + if (app->mux.backends[i] == &cmd_display_console_backend) + return true; + + return false; +} + +esp_err_t cmd_app_build_entry_abs_path(CmdApp *app, CmdPanel *panel, const cmd_file_entry_t *entry, char *out, size_t out_size) +{ + esp_err_t err; + + if (!app || !panel || !entry || !out || out_size == 0) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_manager_mount(&app->fs, panel->device_id); + if (err != ESP_OK) return err; + + return cmd_fs_manager_build_abs_path(&app->fs, panel->device_id, + panel->current_path, entry->name, out, out_size); +} + +esp_err_t cmd_app_play_xm_file(CmdApp *app, CmdPanel *panel, const cmd_file_entry_t *entry) +{ + char path[CMD_PATH_MAX]; + esp_err_t err; + + if (!app || !panel || !entry) return ESP_ERR_INVALID_ARG; + if (!cmd_app_entry_is_xm(entry)) return ESP_ERR_INVALID_ARG; + + err = cmd_app_build_entry_abs_path(app, panel, entry, path, sizeof(path)); + if (err != ESP_OK) + { + cmd_show_error(app, "Module path", err); + return ESP_OK; + } + + if (xm_load_play_file(path, true)) + { + cmd_show_error(app, "Module play", ESP_FAIL); + return ESP_OK; + } + + cmd_set_status(app, "Module playing: %s", entry->name); + return ESP_OK; +} + +esp_err_t cmd_app_stop_xm_playback(CmdApp *app) +{ + if (!app) return ESP_ERR_INVALID_ARG; + + if (xm_stop_cmd(true)) + { + cmd_show_error(app, "Module stop", ESP_FAIL); + return ESP_OK; + } + + cmd_set_status(app, "Module stopped"); + return ESP_OK; +} + +void cmd_app_delete_sfx_preview(CmdApp *app) +{ + if (!app) return; + + int handle = app->sfx_preview_handle; + void *addr = app->sfx_preview_addr; + + app->sfx_preview_handle = -1; + app->sfx_preview_channel = -1; + app->sfx_preview_addr = NULL; + + if (handle < 0 || handle >= OBJ_HANDLES_MAX) return; + if (!check_handle(handle)) return; + if (mem_obj[handle].type != OBJ_TYPE_WAV) return; + if (addr && mem_obj[handle].addr != addr) return; + + delete_obj(handle); +} + +esp_err_t cmd_app_play_wav_file(CmdApp *app, CmdPanel *panel, const cmd_file_entry_t *entry) +{ + char path[CMD_PATH_MAX]; + SFX_WAV_INFO info = {}; + int handle = -1; + int channel = -1; + esp_err_t err; + + if (!app || !panel || !entry) return ESP_ERR_INVALID_ARG; + if (!cmd_app_entry_is_wav(entry)) return ESP_ERR_INVALID_ARG; + + err = cmd_app_build_entry_abs_path(app, panel, entry, path, sizeof(path)); + if (err != ESP_OK) + { + cmd_show_error(app, "WAV path", err); + return ESP_OK; + } + + cmd_app_delete_sfx_preview(app); + + err = sfx_load_file(path, &handle, &info); + if (err != ESP_OK) + { + cmd_show_error(app, "WAV load", err); + return ESP_OK; + } + + app->sfx_preview_handle = handle; + app->sfx_preview_channel = -1; + app->sfx_preview_addr = mem_obj[handle].addr; + + err = sfx_play_sync(handle, CMD_APP_SFX_PREVIEW_GROUP, SFX_VOLUME_MAX, SFX_PAN_CENTER, SFX_PITCH_ONE, &channel); + if (err != ESP_OK) + { + cmd_app_delete_sfx_preview(app); + cmd_show_error(app, "WAV play", err); + return ESP_OK; + } + + app->sfx_preview_channel = channel; + cmd_set_status(app, "WAV playing: %s handle=%02X ch=%u %uHz %u-bit %s", + entry->name, + (unsigned)handle, + (unsigned)channel, + (unsigned)info.sample_rate, + (unsigned)info.bits_per_sample, + info.channels == 1 ? "mono" : "stereo"); + return ESP_OK; +} + +void cmd_app_close_jpg_viewer(CmdApp *app) +{ + bool remove_ft812_backend; + + if (!app) return; + + remove_ft812_backend = app->jpg_viewer_added_ft812_backend; + + app->jpg_viewer_open = false; + app->jpg_viewer_added_ft812_backend = false; + app->jpg_viewer_panel = CMD_PANEL_LEFT; + app->jpg_viewer_index = 0; + app->jpg_viewer_stretch = false; + app->jpg_viewer_path[0] = 0; + app->jpg_viewer_status[0] = 0; + + if (remove_ft812_backend) + { + cmd_display_backend_deinit(&cmd_display_ft812_backend); + cmd_display_mux_remove_backend(&app->mux, &cmd_display_ft812_backend); + return; + } + + if (cmd_app_has_ft812_backend(app)) + { + esp_err_t err = ft_text_attr_mode_show(); + if (err == ESP_OK) err = ft_wait_swap(1000); + if (err != ESP_OK) cmd_show_error(app, "FT restore", err); + } +} + +esp_err_t cmd_app_show_jpg_current(CmdApp *app) +{ + CmdPanel *panel; + const cmd_file_entry_t *entry; + esp_err_t err; + int status_len; + size_t used; + size_t name_len; + size_t dst_len; + + if (!app || !app->jpg_viewer_open) return ESP_ERR_INVALID_ARG; + + panel = cmd_app_panel_by_index(app, app->jpg_viewer_panel); + if (!panel) return ESP_ERR_INVALID_STATE; + if (app->jpg_viewer_index >= panel->count) return ESP_ERR_INVALID_STATE; + + entry = &panel->entries[app->jpg_viewer_index]; + if (!cmd_app_entry_is_ft_image(entry)) return ESP_ERR_INVALID_STATE; + + err = cmd_app_build_entry_abs_path(app, panel, entry, app->jpg_viewer_path, sizeof(app->jpg_viewer_path)); + if (err != ESP_OK) return err; + + status_len = snprintf(app->jpg_viewer_status, sizeof(app->jpg_viewer_status), + "%s %u/%u %s ", + cmd_app_entry_is_dxp(entry) ? "DXP" : "JPEG", + (unsigned)(app->jpg_viewer_index + 1), + (unsigned)panel->count, + cmd_app_entry_is_dxp(entry) ? "center" : (app->jpg_viewer_stretch ? "stretch" : "center")); + if (status_len < 0) return ESP_FAIL; + + if ((size_t)status_len >= sizeof(app->jpg_viewer_status)) + { + app->jpg_viewer_status[sizeof(app->jpg_viewer_status) - 1] = 0; + } + else + { + used = (size_t)status_len; + name_len = strlen(entry->name); + dst_len = sizeof(app->jpg_viewer_status) - used - 1; + if (name_len > dst_len) name_len = dst_len; + memcpy(&app->jpg_viewer_status[used], entry->name, name_len); + app->jpg_viewer_status[used + name_len] = 0; + } + + cmd_set_status(app, "%s", app->jpg_viewer_status); + + if (cmd_app_entry_is_dxp(entry)) + return ft_dxp_show_file_mode(app->jpg_viewer_path, true); + + return ft_jpg_show_file_mode(app->jpg_viewer_path, app->jpg_viewer_stretch, true); +} + +esp_err_t cmd_app_open_jpg_viewer(CmdApp *app, CmdPanel *panel, const cmd_file_entry_t *entry) +{ + esp_err_t err; + bool added_ft812_backend = false; + + if (!app || !panel || !entry) return ESP_ERR_INVALID_ARG; + if (!cmd_app_entry_is_ft_image(entry)) return ESP_ERR_INVALID_ARG; + + if (!cmd_app_has_ft812_backend(app)) + { + err = cmd_display_mux_add_backend(&app->mux, &cmd_display_ft812_backend); + if (err != ESP_OK) + { + cmd_show_error(app, "image viewer", err); + return ESP_OK; + } + + err = cmd_display_backend_init(&cmd_display_ft812_backend); + if (err != ESP_OK) + { + cmd_display_mux_remove_backend(&app->mux, &cmd_display_ft812_backend); + cmd_show_error(app, "image viewer", err); + return ESP_OK; + } + + added_ft812_backend = true; + } + + app->jpg_viewer_open = true; + app->jpg_viewer_added_ft812_backend = added_ft812_backend; + app->jpg_viewer_panel = app->active_panel; + app->jpg_viewer_index = panel->cursor; + app->jpg_viewer_stretch = true; + + err = cmd_app_show_jpg_current(app); + if (err != ESP_OK) + { + cmd_app_close_jpg_viewer(app); + cmd_show_error(app, "image viewer", err); + } + + return ESP_OK; +} + +bool cmd_app_find_next_jpg(CmdApp *app, int dir, size_t *out_index) +{ + CmdPanel *panel; + size_t count; + + if (!app || !out_index) return false; + + panel = cmd_app_panel_by_index(app, app->jpg_viewer_panel); + if (!panel || panel->count == 0) return false; + + count = panel->count; + for (size_t step = 1; step <= count; step++) + { + size_t index; + + if (dir > 0) + index = (app->jpg_viewer_index + step) % count; + else + index = (app->jpg_viewer_index + count - (step % count)) % count; + + if (cmd_app_entry_is_ft_image(&panel->entries[index])) + { + *out_index = index; + return true; + } + } + + return false; +} + +esp_err_t cmd_app_jpg_viewer_step(CmdApp *app, int dir) +{ + CmdPanel *panel; + size_t index; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + if (!cmd_app_find_next_jpg(app, dir, &index)) + { + cmd_set_status(app, "no other image file"); + return ESP_OK; + } + + panel = cmd_app_panel_by_index(app, app->jpg_viewer_panel); + if (!panel) return ESP_ERR_INVALID_STATE; + + app->jpg_viewer_index = index; + panel->cursor = index; + cmd_panel_ensure_cursor_visible(panel); + + err = cmd_app_show_jpg_current(app); + if (err != ESP_OK) + { + cmd_show_error(app, "image viewer", err); + cmd_app_close_jpg_viewer(app); + return ESP_OK; + } + + err = cmd_app_render_console(app); + if (err != ESP_OK) + { + cmd_show_error(app, "console render", err); + cmd_app_close_jpg_viewer(app); + } + + return ESP_OK; +} + +esp_err_t cmd_app_jpg_viewer_set_stretch(CmdApp *app, bool stretch) +{ + esp_err_t err; + + if (!app || !app->jpg_viewer_open) return ESP_ERR_INVALID_ARG; + + CmdPanel *panel = cmd_app_panel_by_index(app, app->jpg_viewer_panel); + if (!panel) return ESP_ERR_INVALID_STATE; + if (app->jpg_viewer_index >= panel->count) return ESP_ERR_INVALID_STATE; + + const cmd_file_entry_t *entry = &panel->entries[app->jpg_viewer_index]; + if (cmd_app_entry_is_dxp(entry)) + { + cmd_set_status(app, "DXP viewer: stretch is not supported"); + return ESP_OK; + } + + app->jpg_viewer_stretch = stretch; + err = ft_rgb888_640x480_show_current(stretch); + if (err != ESP_OK) + { + cmd_show_error(app, "JPEG display", err); + cmd_app_close_jpg_viewer(app); + return ESP_OK; + } + + cmd_set_status(app, "JPEG %s", stretch ? "stretch" : "center"); + return ESP_OK; +} + +esp_err_t cmd_app_handle_jpg_viewer_key(CmdApp *app, const cmd_event_t *event) +{ + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->jpg_viewer_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY && event->type != CMD_EVENT_QUIT) return ESP_OK; + + if (event->type == CMD_EVENT_QUIT || event->key == CMD_KEY_ESC || event->key == CMD_KEY_F10) + { + cmd_app_close_jpg_viewer(app); + cmd_set_status(app, "image viewer closed"); + return ESP_OK; + } + + if (event->key == CMD_KEY_PAGE_UP || event->key == CMD_KEY_LEFT) + return cmd_app_jpg_viewer_step(app, -1); + + if (event->key == CMD_KEY_PAGE_DOWN || event->key == CMD_KEY_RIGHT) + return cmd_app_jpg_viewer_step(app, 1); + + if (event->key == CMD_KEY_CHAR && event->ch == '*') + return cmd_app_jpg_viewer_set_stretch(app, true); + + if (event->key == CMD_KEY_CHAR && event->ch == '/') + return cmd_app_jpg_viewer_set_stretch(app, false); + + return ESP_OK; +} + +int cmd_app_viewer_visible_rows(CmdApp *app) +{ + int rows; + + rows = cmd_app_screen_h(app) - 2; + if (rows < 1) rows = 1; + if (rows > CMD_APP_VIEWER_MAX_ROWS) rows = CMD_APP_VIEWER_MAX_ROWS; + return rows; +} + +int cmd_app_viewer_visible_cols(CmdApp *app) +{ + int cols; + + cols = cmd_app_screen_w(app); + if (cols < 1) cols = 1; + if (cols > CMD_DISPLAY_COLS) cols = CMD_DISPLAY_COLS; + return cols; +} + +void cmd_app_viewer_clear_page(CmdApp *app) +{ + if (!app) return; + + app->viewer_page_lines = 0; + app->viewer_eof = true; + + for (int i = 0; i < CMD_APP_VIEWER_MAX_ROWS; i++) + app->viewer_lines[i][0] = 0; +} + +char cmd_app_viewer_char(uint8_t ch) +{ + if (ch == '\t') return ' '; + if (ch < 32) return '.'; + return (char)ch; +} + +void cmd_app_viewer_reset_stream(CmdApp *app) +{ + if (!app) return; + + app->viewer_read_pos = 0; + app->viewer_read_len = 0; + app->viewer_read_base = 0; +} + +uint64_t cmd_app_viewer_stream_offset(CmdApp *app) +{ + if (!app) return 0; + return app->viewer_read_base + app->viewer_read_pos; +} + +esp_err_t cmd_app_viewer_close_file(CmdApp *app) +{ + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + if (!app->viewer_file_open) return ESP_OK; + + err = cmd_fs_manager_close(&app->fs, &app->viewer_file); + app->viewer_file_open = false; + memset(&app->viewer_file, 0, sizeof(app->viewer_file)); + cmd_app_viewer_reset_stream(app); + return err; +} + +esp_err_t cmd_app_viewer_open_file(CmdApp *app) +{ + CmdFsDriver *driver; + esp_err_t err; + + if (!app || !app->viewer_open) return ESP_ERR_INVALID_ARG; + + err = cmd_app_viewer_close_file(app); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_mount(&app->fs, app->viewer_device); + if (err != ESP_OK) return err; + + driver = cmd_fs_manager_get_driver(&app->fs, app->viewer_device); + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->open_read || !driver->read || !driver->seek || !driver->tell || !driver->close) + return ESP_ERR_NOT_SUPPORTED; + + memset(&app->viewer_file, 0, sizeof(app->viewer_file)); + err = cmd_fs_manager_open_read(&app->fs, app->viewer_device, app->viewer_path, &app->viewer_file); + if (err != ESP_OK) return err; + + app->viewer_file_open = true; + cmd_app_viewer_reset_stream(app); + return ESP_OK; +} + +esp_err_t cmd_app_viewer_seek_stream(CmdApp *app, uint64_t offset) +{ + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + if (!app->viewer_file_open) return ESP_ERR_INVALID_STATE; + if (offset > (uint64_t)INT64_MAX) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_manager_seek(&app->fs, &app->viewer_file, (int64_t)offset, SEEK_SET); + if (err != ESP_OK) return err; + + app->viewer_read_pos = 0; + app->viewer_read_len = 0; + app->viewer_read_base = offset; + return ESP_OK; +} + +esp_err_t cmd_app_viewer_read_line(CmdApp *app, char *out, size_t out_size, bool *out_have_line) +{ + size_t got = 0; + size_t pos = 0; + size_t cols; + uint64_t file_pos = 0; + bool have_line = false; + esp_err_t err; + + if (!app || !out || out_size == 0 || !out_have_line) return ESP_ERR_INVALID_ARG; + + out[0] = 0; + *out_have_line = false; + + if (!app->viewer_file_open) return ESP_ERR_INVALID_STATE; + + cols = (size_t)cmd_app_viewer_visible_cols(app); + if (cols >= out_size) cols = out_size - 1; + + while (true) + { + if (app->viewer_read_pos >= app->viewer_read_len) + { + err = cmd_fs_manager_tell(&app->fs, &app->viewer_file, &file_pos); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_read(&app->fs, &app->viewer_file, app->viewer_read_buffer, + sizeof(app->viewer_read_buffer), &got); + if (err != ESP_OK) return err; + + app->viewer_read_base = file_pos; + app->viewer_read_pos = 0; + app->viewer_read_len = got; + + if (got == 0) + { + if (!have_line) return ESP_OK; + out[pos] = 0; + *out_have_line = true; + return ESP_OK; + } + } + + uint8_t ch = app->viewer_read_buffer[app->viewer_read_pos++]; + if (ch == '\r') continue; + + if (ch == '\n') + { + out[pos] = 0; + *out_have_line = true; + return ESP_OK; + } + + have_line = true; + if (pos < cols) + { + out[pos] = cmd_app_viewer_char(ch); + pos++; + } + } +} + +esp_err_t cmd_app_viewer_read_page_from_offset(CmdApp *app, uint64_t offset) +{ + size_t rows; + bool have_line; + esp_err_t err; + + if (!app || !app->viewer_open) return ESP_ERR_INVALID_ARG; + + err = cmd_app_viewer_seek_stream(app, offset); + if (err != ESP_OK) return err; + + cmd_app_viewer_clear_page(app); + + rows = (size_t)cmd_app_viewer_visible_rows(app); + app->viewer_top_offset = offset; + app->viewer_next_offset = offset; + app->viewer_next_line = app->viewer_top_line; + app->viewer_eof = false; + + while (app->viewer_page_lines < rows) + { + app->viewer_line_offsets[app->viewer_page_lines] = cmd_app_viewer_stream_offset(app); + + err = cmd_app_viewer_read_line(app, + app->viewer_lines[app->viewer_page_lines], + sizeof(app->viewer_lines[app->viewer_page_lines]), + &have_line); + if (err != ESP_OK) return err; + + if (!have_line) + { + app->viewer_eof = true; + app->viewer_next_offset = cmd_app_viewer_stream_offset(app); + app->viewer_line_offsets[app->viewer_page_lines] = app->viewer_next_offset; + return ESP_OK; + } + + app->viewer_page_lines++; + app->viewer_next_line++; + } + + app->viewer_next_offset = cmd_app_viewer_stream_offset(app); + app->viewer_line_offsets[app->viewer_page_lines] = app->viewer_next_offset; + return ESP_OK; +} + +void cmd_app_viewer_set_status(CmdApp *app) +{ + if (!app) return; + + cmd_set_status(app, "view: %s line %llu", + app->viewer_title[0] ? app->viewer_title : cmd_fs_filename_ptr(app->viewer_path), + (unsigned long long)(app->viewer_top_line + 1)); +} + +esp_err_t cmd_app_viewer_find_prev_offset(CmdApp *app, uint64_t before_offset, size_t lines_back, + uint64_t *out_offset, size_t *out_lines) +{ + uint64_t *candidates; + uint8_t *read_buffer; + size_t candidate_count; + size_t total_count; + size_t capacity = CMD_APP_VIEWER_MAX_ROWS + 1; + size_t got = 0; + uint64_t window; + uint64_t start; + uint64_t pos; + uint64_t left; + esp_err_t err; + + if (!app || !out_offset || !out_lines) return ESP_ERR_INVALID_ARG; + if (!app->viewer_file_open) return ESP_ERR_INVALID_STATE; + + candidates = app->viewer_prev_offsets; + read_buffer = app->viewer_seek_buffer; + + *out_offset = 0; + *out_lines = 0; + if (before_offset == 0 || lines_back == 0) return ESP_OK; + + if (lines_back > CMD_APP_VIEWER_MAX_ROWS) lines_back = CMD_APP_VIEWER_MAX_ROWS; + window = (uint64_t)CMD_APP_VIEWER_READ_BUFFER_SIZE * (lines_back + 2); + + while (true) + { + start = before_offset > window ? before_offset - window : 0; + candidate_count = 0; + total_count = 0; + pos = start; + + if (start == 0) + { + candidates[candidate_count++] = 0; + total_count++; + } + + err = cmd_fs_manager_seek(&app->fs, &app->viewer_file, (int64_t)start, SEEK_SET); + if (err != ESP_OK) return err; + + while (pos < before_offset) + { + left = before_offset - pos; + size_t want = CMD_APP_VIEWER_READ_BUFFER_SIZE; + if (left < want) want = (size_t)left; + + err = cmd_fs_manager_read(&app->fs, &app->viewer_file, read_buffer, want, &got); + if (err != ESP_OK) return err; + if (got == 0) break; + + for (size_t i = 0; i < got && pos < before_offset; i++) + { + uint8_t ch = read_buffer[i]; + pos++; + if (ch != '\n' || pos >= before_offset) continue; + + if (candidate_count < capacity) + { + candidates[candidate_count++] = pos; + } + else + { + memmove(candidates, candidates + 1, (capacity - 1) * sizeof(candidates[0])); + candidates[capacity - 1] = pos; + } + total_count++; + } + } + + if (candidate_count >= lines_back) + { + *out_offset = candidates[candidate_count - lines_back]; + *out_lines = lines_back; + return ESP_OK; + } + + if (start == 0) + { + if (candidate_count > 0) + { + *out_offset = candidates[0]; + *out_lines = total_count; + } + return ESP_OK; + } + + if (window >= before_offset) window = before_offset; + else window *= 2; + } +} + +esp_err_t cmd_app_viewer_scroll_down(CmdApp *app) +{ + bool have_line; + esp_err_t err; + + if (!app || !app->viewer_open) return ESP_ERR_INVALID_ARG; + if (app->viewer_page_lines == 0) return ESP_OK; + if (app->viewer_eof && app->viewer_page_lines <= 1) return ESP_OK; + + uint64_t new_top_offset = app->viewer_page_lines > 1 ? + app->viewer_line_offsets[1] : app->viewer_next_offset; + + for (size_t i = 1; i < app->viewer_page_lines; i++) + { + memcpy(app->viewer_lines[i - 1], app->viewer_lines[i], sizeof(app->viewer_lines[i - 1])); + app->viewer_line_offsets[i - 1] = app->viewer_line_offsets[i]; + } + + app->viewer_page_lines--; + app->viewer_top_line++; + app->viewer_top_offset = new_top_offset; + app->viewer_line_offsets[0] = new_top_offset; + + if (!app->viewer_eof) + { + app->viewer_line_offsets[app->viewer_page_lines] = app->viewer_next_offset; + + err = cmd_app_viewer_read_line(app, + app->viewer_lines[app->viewer_page_lines], + sizeof(app->viewer_lines[app->viewer_page_lines]), + &have_line); + if (err != ESP_OK) return err; + + if (have_line) + { + app->viewer_page_lines++; + app->viewer_next_line++; + app->viewer_next_offset = cmd_app_viewer_stream_offset(app); + app->viewer_line_offsets[app->viewer_page_lines] = app->viewer_next_offset; + } + else + { + app->viewer_eof = true; + app->viewer_next_offset = cmd_app_viewer_stream_offset(app); + app->viewer_line_offsets[app->viewer_page_lines] = app->viewer_next_offset; + } + } + + cmd_app_viewer_set_status(app); + return ESP_OK; +} + +esp_err_t cmd_app_viewer_page_down(CmdApp *app) +{ + size_t rows; + uint64_t old_offset; + size_t old_top_line; + esp_err_t err; + + if (!app || !app->viewer_open) return ESP_ERR_INVALID_ARG; + if (app->viewer_page_lines == 0) return ESP_OK; + + rows = (size_t)cmd_app_viewer_visible_rows(app); + + if (app->viewer_eof) + { + size_t step = app->viewer_page_lines > 1 ? app->viewer_page_lines - 1 : 0; + while (step > 0) + { + err = cmd_app_viewer_scroll_down(app); + if (err != ESP_OK) return err; + step--; + } + return ESP_OK; + } + + old_offset = app->viewer_top_offset; + old_top_line = app->viewer_top_line; + app->viewer_top_line += rows; + + err = cmd_app_viewer_read_page_from_offset(app, app->viewer_next_offset); + if (err != ESP_OK) return err; + + if (app->viewer_page_lines == 0) + { + app->viewer_top_line = old_top_line; + err = cmd_app_viewer_read_page_from_offset(app, old_offset); + if (err != ESP_OK) return err; + } + + cmd_app_viewer_set_status(app); + return ESP_OK; +} + +esp_err_t cmd_app_viewer_move_up(CmdApp *app, size_t lines) +{ + uint64_t old_offset; + uint64_t new_offset = 0; + size_t old_top_line; + size_t moved = 0; + esp_err_t err; + + if (!app || !app->viewer_open) return ESP_ERR_INVALID_ARG; + if (lines == 0 || app->viewer_top_offset == 0 || app->viewer_top_line == 0) return ESP_OK; + + old_offset = app->viewer_top_offset; + old_top_line = app->viewer_top_line; + + err = cmd_app_viewer_find_prev_offset(app, app->viewer_top_offset, lines, &new_offset, &moved); + if (err != ESP_OK) return err; + + if (moved == 0 && new_offset == old_offset) return ESP_OK; + + if (old_top_line > moved) app->viewer_top_line = old_top_line - moved; + else app->viewer_top_line = 0; + + err = cmd_app_viewer_read_page_from_offset(app, new_offset); + if (err != ESP_OK) + { + app->viewer_top_line = old_top_line; + cmd_app_viewer_read_page_from_offset(app, old_offset); + return err; + } + + cmd_app_viewer_set_status(app); + return ESP_OK; +} + +esp_err_t cmd_app_viewer_home(CmdApp *app) +{ + esp_err_t err; + + if (!app || !app->viewer_open) return ESP_ERR_INVALID_ARG; + + app->viewer_top_line = 0; + err = cmd_app_viewer_read_page_from_offset(app, 0); + if (err != ESP_OK) return err; + + cmd_app_viewer_set_status(app); + return ESP_OK; +} + +void cmd_app_close_text_viewer(CmdApp *app) +{ + if (!app) return; + + cmd_app_viewer_close_file(app); + app->viewer_open = false; + app->viewer_device = CMD_DEVICE_INVALID; + app->viewer_path[0] = 0; + app->viewer_title[0] = 0; + app->viewer_top_offset = 0; + app->viewer_next_offset = 0; + app->viewer_top_line = 0; + app->viewer_next_line = 0; + cmd_app_viewer_reset_stream(app); + cmd_app_viewer_clear_page(app); + cmd_app_set_status(app, "ready"); +} + +esp_err_t cmd_app_open_text_viewer(CmdApp *app, CmdPanel *panel, const cmd_file_entry_t *entry) +{ + esp_err_t err; + + if (!app || !panel || !entry) return ESP_ERR_INVALID_ARG; + + if (entry->type != CMD_ENTRY_FILE) + { + cmd_app_set_status(app, "view supports files only"); + return ESP_OK; + } + + err = cmd_app_join_selected_path(panel, entry, app->viewer_path, sizeof(app->viewer_path)); + if (err != ESP_OK) + { + cmd_show_error(app, "view", err); + return ESP_OK; + } + + app->viewer_open = true; + app->viewer_device = panel->device_id; + app->viewer_top_offset = 0; + app->viewer_next_offset = 0; + app->viewer_top_line = 0; + app->viewer_next_line = 0; + app->viewer_eof = false; + cmd_app_viewer_reset_stream(app); + cmd_app_copy_string(app->viewer_title, sizeof(app->viewer_title), entry->name); + + err = cmd_app_viewer_open_file(app); + if (err == ESP_OK) err = cmd_app_viewer_read_page_from_offset(app, 0); + if (err != ESP_OK) + { + cmd_app_close_text_viewer(app); + cmd_show_error(app, "view", err); + return ESP_OK; + } + + cmd_app_viewer_set_status(app); + return ESP_OK; +} + +esp_err_t cmd_app_handle_text_viewer_key(CmdApp *app, const cmd_event_t *event) +{ + size_t rows; + esp_err_t err; + + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->viewer_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY && event->type != CMD_EVENT_QUIT) return ESP_OK; + + if (event->type == CMD_EVENT_QUIT || event->key == CMD_KEY_ESC) + { + cmd_app_close_text_viewer(app); + return ESP_OK; + } + + rows = (size_t)cmd_app_viewer_visible_rows(app); + + switch (event->key) + { + case CMD_KEY_UP: + if (app->viewer_top_line > 0) + { + err = cmd_app_viewer_move_up(app, 1); + if (err != ESP_OK) + { + cmd_show_error(app, "view", err); + return ESP_OK; + } + } + return ESP_OK; + + case CMD_KEY_DOWN: + err = cmd_app_viewer_scroll_down(app); + if (err != ESP_OK) + { + cmd_show_error(app, "view", err); + return ESP_OK; + } + return ESP_OK; + + case CMD_KEY_PAGE_UP: + case CMD_KEY_LEFT: + if (app->viewer_top_line > 0) + { + err = cmd_app_viewer_move_up(app, rows); + if (err != ESP_OK) + { + cmd_show_error(app, "view", err); + return ESP_OK; + } + } + return ESP_OK; + + case CMD_KEY_PAGE_DOWN: + case CMD_KEY_RIGHT: + err = cmd_app_viewer_page_down(app); + if (err != ESP_OK) + { + cmd_show_error(app, "view", err); + return ESP_OK; + } + return ESP_OK; + + case CMD_KEY_HOME: + err = cmd_app_viewer_home(app); + if (err != ESP_OK) + { + cmd_show_error(app, "view", err); + return ESP_OK; + } + return ESP_OK; + + default: + return ESP_OK; + } +} + +void cmd_app_make_viewer_title(char *out, size_t out_size, CmdApp *app) +{ + if (!out || out_size == 0) return; + + cmd_app_text_clear(out, out_size); + if (!app) return; + + cmd_app_append_text(out, out_size, "View: "); + cmd_app_append_text(out, out_size, cmd_device_name(app->viewer_device)); + cmd_app_append_text(out, out_size, ":"); + cmd_app_append_text(out, out_size, app->viewer_path); + cmd_app_append_text(out, out_size, " line "); + snprintf(app->viewer_num, sizeof(app->viewer_num), "%llu", (unsigned long long)(app->viewer_top_line + 1)); + cmd_app_append_text(out, out_size, app->viewer_num); +} + +void cmd_app_draw_text_viewer(CmdApp *app) +{ + cmd_rect_t rect; + cmd_rect_t line_rect; + cmd_display_attr_t attr; + cmd_display_attr_t bar_attr; + int rows; + int cols; + int bottom_y; + + if (!app || !app->viewer_open) return; + + rows = cmd_app_viewer_visible_rows(app); + cols = cmd_app_viewer_visible_cols(app); + bottom_y = cmd_app_bottom_y(app); + attr = cmd_app_normal_attr(); + bar_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_YELLOW, CMD_DISPLAY_COLOR_CYAN, + CMD_DISPLAY_ATTR_FLAG_BOLD); + + rect.x = 0; + rect.y = 0; + rect.w = cmd_app_screen_w(app); + rect.h = cmd_app_screen_h(app); + + line_rect.x = 0; + line_rect.y = 0; + line_rect.w = rect.w; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', bar_attr); + cmd_app_make_viewer_title(app->viewer_draw_line, sizeof(app->viewer_draw_line), app); + cmd_display_buffer_write_text(&app->buffer, 0, 0, app->viewer_draw_line, bar_attr); + + for (int row = 0; row < rows; row++) + { + line_rect.x = 0; + line_rect.y = 1 + row; + line_rect.w = cols; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', attr); + + if ((size_t)row < app->viewer_page_lines) + cmd_display_buffer_write_text(&app->buffer, 0, line_rect.y, app->viewer_lines[row], attr); + } + + line_rect.x = 0; + line_rect.y = bottom_y; + line_rect.w = rect.w; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', bar_attr); + cmd_display_buffer_write_text(&app->buffer, 0, bottom_y, + "Viewer Up/Down PgUp/PgDn Left/Right Home Esc Close", bar_attr); +} + + +uint16_t cmd_app_info_rd_le16(const uint8_t *p) +{ + return (uint16_t)p[0] | ((uint16_t)p[1] << 8); +} + +uint32_t cmd_app_info_rd_le24(const uint8_t *p) +{ + return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16); +} + +uint32_t cmd_app_info_rd_le32(const uint8_t *p) +{ + return (uint32_t)cmd_app_info_rd_le16(p) | ((uint32_t)cmd_app_info_rd_le16(p + 2) << 16); +} + +bool cmd_app_module_info_u64_add(uint64_t *value, uint64_t add) +{ + if (!value) return false; + if (UINT64_MAX - *value < add) return false; + *value += add; + return true; +} + +void cmd_app_module_info_copy_text(char *dst, size_t dst_size, const uint8_t *src, size_t src_size) +{ + size_t n; + + if (!dst || dst_size == 0) return; + + dst[0] = 0; + if (!src) return; + + n = src_size; + while (n > 0 && (src[n - 1] == 0 || src[n - 1] == ' ')) n--; + if (n >= dst_size) n = dst_size - 1; + + for (size_t i = 0; i < n; i++) + { + uint8_t ch = src[i]; + dst[i] = (ch >= 32 && ch <= 126) ? (char)ch : '.'; + } + dst[n] = 0; +} + +void cmd_app_module_info_free_text(CmdApp *app) +{ + if (!app) return; + + if (app->module_info_text) + heap_caps_free(app->module_info_text); + + app->module_info_text = NULL; + app->module_info_text_len = 0; + app->module_info_text_cap = 0; + app->module_info_top_line = 0; + app->module_info_line_count = 0; +} + +esp_err_t cmd_app_module_info_reserve(CmdApp *app, size_t needed) +{ + char *new_text; + size_t new_cap; + + if (!app) return ESP_ERR_INVALID_ARG; + if (needed > CMD_APP_MODULE_INFO_MAX_TEXT_SIZE) return ESP_ERR_NO_MEM; + if (needed <= app->module_info_text_cap) return ESP_OK; + + new_cap = app->module_info_text_cap ? app->module_info_text_cap : CMD_APP_MODULE_INFO_INITIAL_CAP; + while (new_cap < needed) + { + if (new_cap > CMD_APP_MODULE_INFO_MAX_TEXT_SIZE / 2) + { + new_cap = CMD_APP_MODULE_INFO_MAX_TEXT_SIZE; + break; + } + new_cap *= 2; + } + + if (new_cap < needed) return ESP_ERR_NO_MEM; + + new_text = (char*)heap_caps_realloc(app->module_info_text, new_cap, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!new_text) return ESP_ERR_NO_MEM; + + app->module_info_text = new_text; + app->module_info_text_cap = new_cap; + return ESP_OK; +} + +esp_err_t cmd_app_module_info_append_line(CmdApp *app, const char *fmt, ...) +{ + va_list ap; + int written; + size_t line_len; + size_t needed; + esp_err_t err; + + if (!app || !fmt) return ESP_ERR_INVALID_ARG; + + va_start(ap, fmt); + written = vsnprintf(app->module_info_tmp, sizeof(app->module_info_tmp), fmt, ap); + va_end(ap); + + if (written < 0) return ESP_FAIL; + + app->module_info_tmp[sizeof(app->module_info_tmp) - 1] = 0; + line_len = strlen(app->module_info_tmp); + needed = app->module_info_text_len + line_len + 2; + + err = cmd_app_module_info_reserve(app, needed); + if (err != ESP_OK) return err; + + memcpy(app->module_info_text + app->module_info_text_len, app->module_info_tmp, line_len); + app->module_info_text_len += line_len; + app->module_info_text[app->module_info_text_len++] = '\n'; + app->module_info_text[app->module_info_text_len] = 0; + app->module_info_line_count++; + return ESP_OK; +} + +esp_err_t cmd_app_module_info_read_at(CmdApp *app, CmdFsFile *file, uint64_t offset, void *dst, size_t size, size_t *out_got) +{ + size_t got = 0; + esp_err_t err; + + if (!app || !file || !dst) return ESP_ERR_INVALID_ARG; + if (offset > (uint64_t)INT64_MAX) return ESP_ERR_INVALID_ARG; + + memset(dst, 0, size); + + err = cmd_fs_manager_seek(&app->fs, file, (int64_t)offset, SEEK_SET); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_read(&app->fs, file, dst, size, &got); + if (err != ESP_OK) return err; + + if (out_got) *out_got = got; + return ESP_OK; +} + +const char *cmd_app_module_info_mod_magic_text(CmdApp *app, const uint8_t *header, const mod_layout_t *layout) +{ + if (!app || !header || !layout) return "?"; + + if (layout->sample_count != MOD_SAMPLE_COUNT) return "15-sample"; + + cmd_app_module_info_copy_text(app->module_info_name, sizeof(app->module_info_name), header + MOD_MAGIC_OFFSET, 4); + return app->module_info_name[0] ? app->module_info_name : "?"; +} + +const char *cmd_app_module_info_mod_loop_text(const mod_layout_t *layout, uint16_t index) +{ + if (!layout || index >= layout->sample_count) return "no"; + if (layout->sample_length[index] == 0) return "no"; + if (layout->sample_loop_start[index] >= layout->sample_length[index]) return "no"; + if (layout->sample_loop_length[index] <= 2) return "no"; + return "yes"; +} + +esp_err_t cmd_app_module_info_build_mod(CmdApp *app, CmdFsFile *file, const cmd_file_entry_t *entry) +{ + mod_layout_t layout; + uint8_t *header; + size_t want; + size_t got = 0; + esp_err_t err; + + if (!app || !file || !entry) return ESP_ERR_INVALID_ARG; + + header = app->module_info_read_buffer; + want = entry->size < CMD_APP_MODULE_INFO_READ_BUFFER_SIZE ? (size_t)entry->size : CMD_APP_MODULE_INFO_READ_BUFFER_SIZE; + err = cmd_app_module_info_read_at(app, file, 0, header, want, &got); + if (err != ESP_OK) return err; + if (got < MOD_15_HEADER_SIZE) return ESP_FAIL; + if (!mod_read_layout_from_header(header, got, (size_t)entry->size, &layout)) return ESP_FAIL; + + cmd_app_module_info_copy_text(app->module_info_name, sizeof(app->module_info_name), header, MOD_TITLE_SIZE); + + err = cmd_app_module_info_append_line(app, "MOD module: %s", app->module_info_name[0] ? app->module_info_name : ""); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "File: %s", entry->name); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Format: %s channels=%u orders=%u patterns=%u restart=%u", + cmd_app_module_info_mod_magic_text(app, header, &layout), + (unsigned)layout.channels, + (unsigned)layout.song_length, + (unsigned)layout.patterns, + (unsigned)layout.restart_position); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Expected size=%u file size=%llu sample bytes=%u", + (unsigned)layout.expected_size, + (unsigned long long)entry->size, + (unsigned)layout.sample_bytes); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, ""); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Samples / instruments:"); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, " # Name LenB LoopSt LoopLen Loop Vol Fine"); + if (err != ESP_OK) return err; + + for (uint16_t i = 0; i < layout.sample_count; i++) + { + size_t off = MOD_TITLE_SIZE + (size_t)i * MOD_SAMPLE_HEADER_SIZE; + uint8_t volume = header[off + 25]; + int finetune = header[off + 24] & 0x0f; + + if (finetune >= 8) finetune -= 16; + if (volume > 64) volume = 64; + + cmd_app_module_info_copy_text(app->module_info_name, sizeof(app->module_info_name), header + off, 22); + err = cmd_app_module_info_append_line(app, "%02u %-22s %6u %6u %7u %-4s %3u %4d", + (unsigned)i + 1, + app->module_info_name, + (unsigned)layout.sample_length[i], + (unsigned)layout.sample_loop_start[i], + (unsigned)layout.sample_loop_length[i], + cmd_app_module_info_mod_loop_text(&layout, i), + (unsigned)volume, + finetune); + if (err != ESP_OK) return err; + } + + return ESP_OK; +} + +const char *cmd_app_module_info_xm_loop_text(uint8_t flags) +{ + switch (flags & 0x03) + { + case 1: return "fwd"; + case 2: return "ping"; + default: return "no"; + } +} + +esp_err_t cmd_app_module_info_skip_xm_patterns(CmdApp *app, CmdFsFile *file, uint64_t *offset, uint16_t num_patterns, uint64_t file_size) +{ + uint8_t *buf; + + if (!app || !file || !offset) return ESP_ERR_INVALID_ARG; + + buf = app->module_info_read_buffer; + + for (uint16_t i = 0; i < num_patterns; i++) + { + size_t got = 0; + uint32_t header_size; + uint16_t rows; + uint16_t packed_size; + uint64_t next; + esp_err_t err; + + err = cmd_app_module_info_read_at(app, file, *offset, buf, 9, &got); + if (err != ESP_OK) return err; + if (got < 9) return ESP_FAIL; + + header_size = cmd_app_info_rd_le32(buf); + rows = cmd_app_info_rd_le16(buf + 5); + packed_size = cmd_app_info_rd_le16(buf + 7); + if (header_size < 9 || rows == 0 || rows > CMD_APP_XM_MAX_ROWS) return ESP_FAIL; + + next = *offset; + if (!cmd_app_module_info_u64_add(&next, header_size)) return ESP_ERR_INVALID_SIZE; + if (!cmd_app_module_info_u64_add(&next, packed_size)) return ESP_ERR_INVALID_SIZE; + if (next > file_size) return ESP_FAIL; + *offset = next; + } + + return ESP_OK; +} + +esp_err_t cmd_app_module_info_build_xm(CmdApp *app, CmdFsFile *file, const cmd_file_entry_t *entry) +{ + uint8_t *buf; + uint32_t header_size; + uint16_t version; + uint16_t length; + uint16_t restart; + uint16_t channels; + uint16_t patterns; + uint16_t instruments; + uint16_t flags; + uint16_t tempo; + uint16_t bpm; + uint64_t offset; + uint64_t instruments_offset; + size_t got = 0; + esp_err_t err; + + if (!app || !file || !entry) return ESP_ERR_INVALID_ARG; + + buf = app->module_info_read_buffer; + err = cmd_app_module_info_read_at(app, file, 0, buf, 336, &got); + if (err != ESP_OK) return err; + if (got < 80) return ESP_FAIL; + if (memcmp(buf, "Extended Module: ", 17) != 0) return ESP_FAIL; + if (buf[37] != 0x1a) return ESP_FAIL; + + header_size = cmd_app_info_rd_le32(buf + 60); + if (header_size < 20) return ESP_FAIL; + if ((uint64_t)60 + header_size > entry->size) return ESP_FAIL; + + version = cmd_app_info_rd_le16(buf + 58); + length = cmd_app_info_rd_le16(buf + 64); + restart = cmd_app_info_rd_le16(buf + 66); + channels = cmd_app_info_rd_le16(buf + 68); + patterns = cmd_app_info_rd_le16(buf + 70); + instruments = cmd_app_info_rd_le16(buf + 72); + flags = cmd_app_info_rd_le16(buf + 74); + tempo = cmd_app_info_rd_le16(buf + 76); + bpm = cmd_app_info_rd_le16(buf + 78); + + cmd_app_module_info_copy_text(app->module_info_name, sizeof(app->module_info_name), buf + 17, 20); + cmd_app_module_info_copy_text(app->module_info_sample_name, sizeof(app->module_info_sample_name), buf + 38, 20); + + err = cmd_app_module_info_append_line(app, "XM module: %s", app->module_info_name[0] ? app->module_info_name : ""); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "File: %s", entry->name); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Tracker: %s version=%u.%02u", + app->module_info_sample_name[0] ? app->module_info_sample_name : "?", + (unsigned)(version >> 8), + (unsigned)(version & 0xff)); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Orders=%u restart=%u channels=%u patterns=%u instruments=%u", + (unsigned)length, + (unsigned)restart, + (unsigned)channels, + (unsigned)patterns, + (unsigned)instruments); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Tempo=%u BPM=%u frequency=%s file size=%llu", + (unsigned)tempo, + (unsigned)bpm, + (flags & 1) ? "linear" : "amiga", + (unsigned long long)entry->size); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, ""); + if (err != ESP_OK) return err; + + offset = (uint64_t)60 + header_size; + err = cmd_app_module_info_skip_xm_patterns(app, file, &offset, patterns, entry->size); + if (err != ESP_OK) return err; + + instruments_offset = offset; + + err = cmd_app_module_info_append_line(app, "Instruments:"); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Idx Samples Name"); + if (err != ESP_OK) return err; + + for (uint8_t pass = 0; pass < 2; pass++) + { + offset = instruments_offset; + + if (pass == 1) + { + err = cmd_app_module_info_append_line(app, ""); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Samples:"); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Ins Smp Name LenB LoopSt LoopLen Loop Bit Vol Pan Rel Fine"); + if (err != ESP_OK) return err; + } + + for (uint16_t i = 0; i < instruments; i++) + { + uint32_t instr_header_size; + uint16_t sample_count; + uint32_t sample_header_size = 0; + uint64_t sample_data_bytes = 0; + + err = cmd_app_module_info_read_at(app, file, offset, buf, 263, &got); + if (err != ESP_OK) return err; + if (got < 29) return ESP_FAIL; + + instr_header_size = cmd_app_info_rd_le32(buf); + if (instr_header_size < 29) return ESP_FAIL; + + sample_count = cmd_app_info_rd_le16(buf + 27); + if (sample_count > 0) + { + if (got < 33) return ESP_FAIL; + sample_header_size = cmd_app_info_rd_le32(buf + 29); + if (sample_header_size < 18) return ESP_FAIL; + } + + if (pass == 0) + { + cmd_app_module_info_copy_text(app->module_info_name, sizeof(app->module_info_name), buf + 4, 22); + err = cmd_app_module_info_append_line(app, "%03u %7u %s", + (unsigned)i + 1, + (unsigned)sample_count, + app->module_info_name); + if (err != ESP_OK) return err; + } + + if (!cmd_app_module_info_u64_add(&offset, instr_header_size)) return ESP_ERR_INVALID_SIZE; + if (offset > entry->size) return ESP_FAIL; + + for (uint16_t j = 0; j < sample_count; j++) + { + uint32_t sample_len; + uint32_t loop_start; + uint32_t loop_len; + uint8_t volume; + uint8_t sample_flags; + uint8_t panning; + int rel_note; + int finetune; + + err = cmd_app_module_info_read_at(app, file, offset, buf, sample_header_size < 40 ? sample_header_size : 40, &got); + if (err != ESP_OK) return err; + if (got < sample_header_size && got < 18) return ESP_FAIL; + + sample_len = cmd_app_info_rd_le32(buf); + + if (pass == 1) + { + loop_start = cmd_app_info_rd_le32(buf + 4); + loop_len = cmd_app_info_rd_le32(buf + 8); + volume = buf[12]; + finetune = (int8_t)buf[13]; + sample_flags = buf[14]; + panning = buf[15]; + rel_note = (int8_t)buf[16]; + cmd_app_module_info_copy_text(app->module_info_sample_name, sizeof(app->module_info_sample_name), buf + 18, got >= 40 ? 22 : 0); + + err = cmd_app_module_info_append_line(app, "%03u %03u %-22s %6u %6u %7u %-4s %3u %3u %3u %3d %4d", + (unsigned)i + 1, + (unsigned)j + 1, + app->module_info_sample_name, + (unsigned)sample_len, + (unsigned)loop_start, + (unsigned)loop_len, + cmd_app_module_info_xm_loop_text(sample_flags), + (sample_flags & 0x10) ? 16u : 8u, + (unsigned)volume, + (unsigned)panning, + rel_note, + finetune); + if (err != ESP_OK) return err; + } + + sample_data_bytes += sample_len; + if (!cmd_app_module_info_u64_add(&offset, sample_header_size)) return ESP_ERR_INVALID_SIZE; + if (offset > entry->size) return ESP_FAIL; + } + + if (!cmd_app_module_info_u64_add(&offset, sample_data_bytes)) return ESP_ERR_INVALID_SIZE; + if (offset > entry->size) return ESP_FAIL; + } + } + + return ESP_OK; +} + + +esp_err_t cmd_app_module_info_build_s3m(CmdApp *app, CmdFsFile *file, const cmd_file_entry_t *entry) +{ + uint8_t *buf; + uint16_t order_count; + uint16_t sample_count; + uint16_t pattern_count; + uint16_t flags; + uint16_t cwtv; + uint16_t format_version; + uint16_t playable_orders = 0; + uint16_t max_order_pattern = 0; + uint16_t channels = 0; + uint64_t tables_size; + uint64_t sample_ptr_offset; + size_t got = 0; + esp_err_t err; + + if (!app || !file || !entry) return ESP_ERR_INVALID_ARG; + + buf = app->module_info_read_buffer; + err = cmd_app_module_info_read_at(app, file, 0, buf, S3M_HEADER_SIZE, &got); + if (err != ESP_OK) return err; + if (got < S3M_HEADER_SIZE) return ESP_FAIL; + if (memcmp(buf + S3M_MAGIC_OFFSET, "SCRM", 4) != 0) return ESP_FAIL; + if (buf[CMD_APP_S3M_FILE_TYPE_OFFSET] != CMD_APP_S3M_FILE_TYPE_MODULE) return ESP_FAIL; + + order_count = cmd_app_info_rd_le16(buf + CMD_APP_S3M_ORDERS_OFFSET); + sample_count = cmd_app_info_rd_le16(buf + CMD_APP_S3M_SAMPLES_OFFSET); + pattern_count = cmd_app_info_rd_le16(buf + CMD_APP_S3M_PATTERNS_OFFSET); + flags = cmd_app_info_rd_le16(buf + CMD_APP_S3M_FLAGS_OFFSET); + cwtv = cmd_app_info_rd_le16(buf + CMD_APP_S3M_CWTV_OFFSET); + format_version = cmd_app_info_rd_le16(buf + CMD_APP_S3M_FORMAT_VERSION_OFFSET); + + if (!order_count || order_count > S3M_MAX_ORDERS) return ESP_FAIL; + if (sample_count > S3M_MAX_SAMPLES) return ESP_FAIL; + if (!pattern_count || pattern_count > S3M_MAX_PATTERNS) return ESP_FAIL; + + tables_size = (uint64_t)order_count + (uint64_t)sample_count * 2 + (uint64_t)pattern_count * 2; + if ((uint64_t)S3M_HEADER_SIZE + tables_size > entry->size) return ESP_FAIL; + if (buf[CMD_APP_S3M_PANNING_TABLE_FLAG_OFFSET] == CMD_APP_S3M_PANNING_TABLE_PRESENT && + (uint64_t)S3M_HEADER_SIZE + tables_size + S3M_MAX_CHANNELS > entry->size) return ESP_FAIL; + + for (uint16_t i = 0; i < S3M_MAX_CHANNELS; i++) + if (buf[CMD_APP_S3M_CHANNEL_SETTINGS_OFFSET + i] != 0xFF) + channels++; + + if (channels < S3M_MIN_CHANNELS || channels > S3M_MAX_CHANNELS) return ESP_FAIL; + + err = cmd_app_module_info_read_at(app, file, S3M_HEADER_SIZE, buf, order_count, &got); + if (err != ESP_OK) return err; + if (got < order_count) return ESP_FAIL; + + for (uint16_t i = 0; i < order_count; i++) + { + uint8_t order = buf[i]; + + if (order == 0xFF) break; + if (order == 0xFE) continue; + if (order >= pattern_count) return ESP_FAIL; + playable_orders++; + if (order > max_order_pattern) max_order_pattern = order; + } + + if (!playable_orders) return ESP_FAIL; + + err = cmd_app_module_info_read_at(app, file, 0, buf, S3M_HEADER_SIZE, &got); + if (err != ESP_OK) return err; + if (got < S3M_HEADER_SIZE) return ESP_FAIL; + cmd_app_module_info_copy_text(app->module_info_name, sizeof(app->module_info_name), buf, 28); + + err = cmd_app_module_info_append_line(app, "S3M module: %s", app->module_info_name[0] ? app->module_info_name : ""); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "File: %s", entry->name); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Orders=%u playable=%u channels=%u patterns=%u samples=%u", + (unsigned)order_count, + (unsigned)playable_orders, + (unsigned)channels, + (unsigned)pattern_count, + (unsigned)sample_count); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Speed=%u Tempo=%u GlobalVol=%u MasterVol=%u %s panning=%s", + (unsigned)buf[CMD_APP_S3M_SPEED_OFFSET], + (unsigned)buf[CMD_APP_S3M_TEMPO_OFFSET], + (unsigned)buf[CMD_APP_S3M_GLOBAL_VOLUME_OFFSET], + (unsigned)(buf[CMD_APP_S3M_MASTER_VOLUME_OFFSET] & 0x7F), + (buf[CMD_APP_S3M_MASTER_VOLUME_OFFSET] & 0x80) ? "stereo" : "mono", + buf[CMD_APP_S3M_PANNING_TABLE_FLAG_OFFSET] == CMD_APP_S3M_PANNING_TABLE_PRESENT ? "table" : "default"); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Flags=0x%04X CWT/V=0x%04X sample format=%s max order pattern=%u file size=%llu", + (unsigned)flags, + (unsigned)cwtv, + format_version == 1 ? "signed" : (format_version == 2 ? "unsigned" : "unknown"), + (unsigned)max_order_pattern, + (unsigned long long)entry->size); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, ""); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, "Samples / instruments:"); + if (err != ESP_OK) return err; + err = cmd_app_module_info_append_line(app, " # Name LenB DataOfs LoopSt LoopEnd Loop Bit Vol C4Spd Flags"); + if (err != ESP_OK) return err; + + sample_ptr_offset = (uint64_t)S3M_HEADER_SIZE + order_count; + for (uint16_t i = 0; i < sample_count; i++) + { + uint16_t para; + uint64_t header_offset; + uint64_t data_offset = 0; + uint64_t length_bytes = 0; + uint32_t length = 0; + uint32_t loop_start = 0; + uint32_t loop_end = 0; + uint32_t c4speed = S3M_DEFAULT_C4SPEED; + uint8_t type = CMD_APP_S3M_SAMPLE_TYPE_NONE; + uint8_t volume = 0; + uint8_t pack = CMD_APP_S3M_SAMPLE_PACK_NONE; + uint8_t sample_flags = 0; + unsigned bits = 8; + const char *loop_text = "no"; + + err = cmd_app_module_info_read_at(app, file, sample_ptr_offset + (uint64_t)i * 2, buf, 2, &got); + if (err != ESP_OK) return err; + if (got < 2) return ESP_FAIL; + + para = cmd_app_info_rd_le16(buf); + if (!para) + { + err = cmd_app_module_info_append_line(app, "%02u %-28s %8u %10u %6u %7u %-4s %3u %3u %5u 0x%02X", + (unsigned)i + 1, + "", + 0u, + 0u, + 0u, + 0u, + "no", + 8u, + 0u, + S3M_DEFAULT_C4SPEED, + 0u); + if (err != ESP_OK) return err; + continue; + } + + header_offset = (uint64_t)para << 4; + if (header_offset > entry->size || entry->size - header_offset < S3M_SAMPLE_HEADER_SIZE) return ESP_FAIL; + + err = cmd_app_module_info_read_at(app, file, header_offset, buf, S3M_SAMPLE_HEADER_SIZE, &got); + if (err != ESP_OK) return err; + if (got < S3M_SAMPLE_HEADER_SIZE) return ESP_FAIL; + + type = buf[0]; + data_offset = (((uint64_t)buf[13] << 16) | cmd_app_info_rd_le16(buf + 14)) << 4; + length = cmd_app_info_rd_le32(buf + 16); + loop_start = cmd_app_info_rd_le32(buf + 20); + loop_end = cmd_app_info_rd_le32(buf + 24); + volume = buf[28]; + pack = buf[30]; + sample_flags = buf[31]; + c4speed = cmd_app_info_rd_le32(buf + 32); + if (!c4speed) c4speed = S3M_DEFAULT_C4SPEED; + bits = (sample_flags & CMD_APP_S3M_SAMPLE_FLAG_16BIT) ? 16u : 8u; + length_bytes = (uint64_t)length * (bits == 16 ? 2u : 1u); + if ((sample_flags & CMD_APP_S3M_SAMPLE_FLAG_LOOP) && loop_end > loop_start) + { + loop_text = "yes"; + } + + cmd_app_module_info_copy_text(app->module_info_sample_name, sizeof(app->module_info_sample_name), buf + 48, 28); + if (!app->module_info_sample_name[0] && type == CMD_APP_S3M_SAMPLE_TYPE_NONE) + cmd_app_copy_string(app->module_info_sample_name, sizeof(app->module_info_sample_name), ""); + + err = cmd_app_module_info_append_line(app, "%02u %-28s %8llu %10llu %6u %7u %-4s %3u %3u %5u 0x%02X%s%s%s", + (unsigned)i + 1, + app->module_info_sample_name, + (unsigned long long)length_bytes, + (unsigned long long)data_offset, + (unsigned)loop_start, + (unsigned)loop_end, + loop_text, + bits, + (unsigned)volume, + (unsigned)c4speed, + (unsigned)sample_flags, + (type == CMD_APP_S3M_SAMPLE_TYPE_NONE || type == CMD_APP_S3M_SAMPLE_TYPE_PCM) ? "" : " type!", + pack == CMD_APP_S3M_SAMPLE_PACK_NONE ? "" : " packed!", + (sample_flags & CMD_APP_S3M_SAMPLE_FLAG_STEREO) ? " stereo!" : ""); + if (err != ESP_OK) return err; + + } + + return ESP_OK; +} + +void cmd_app_close_module_info_viewer(CmdApp *app) +{ + if (!app) return; + + cmd_app_module_info_free_text(app); + app->module_info_open = false; + app->module_info_device = CMD_DEVICE_INVALID; + app->module_info_path[0] = 0; + app->module_info_title[0] = 0; + cmd_app_set_status(app, "ready"); +} + +esp_err_t cmd_app_open_module_info_viewer(CmdApp *app, CmdPanel *panel, const cmd_file_entry_t *entry) +{ + CmdFsFile file; + CmdFsDriver *driver; + bool file_open = false; + esp_err_t err; + + if (!app || !panel || !entry) return ESP_ERR_INVALID_ARG; + + if (!cmd_app_entry_is_module_info(entry)) + { + cmd_app_set_status(app, "module info supports MOD/XM/S3M files only"); + return ESP_OK; + } + + err = cmd_app_join_selected_path(panel, entry, app->module_info_path, sizeof(app->module_info_path)); + if (err != ESP_OK) + { + cmd_show_error(app, "module info", err); + return ESP_OK; + } + + err = cmd_fs_manager_mount(&app->fs, panel->device_id); + if (err != ESP_OK) + { + cmd_show_error(app, "module info", err); + return ESP_OK; + } + + driver = cmd_fs_manager_get_driver(&app->fs, panel->device_id); + if (!driver || !driver->open_read || !driver->read || !driver->seek || !driver->close) + { + cmd_show_error(app, "module info", ESP_ERR_NOT_SUPPORTED); + return ESP_OK; + } + + memset(&file, 0, sizeof(file)); + err = cmd_fs_manager_open_read(&app->fs, panel->device_id, app->module_info_path, &file); + if (err != ESP_OK) + { + cmd_show_error(app, "module info", err); + return ESP_OK; + } + file_open = true; + + cmd_app_module_info_free_text(app); + cmd_app_copy_string(app->module_info_title, sizeof(app->module_info_title), entry->name); + + if (cmd_app_extension_is(entry->name, ".mod")) + err = cmd_app_module_info_build_mod(app, &file, entry); + else if (cmd_app_extension_is(entry->name, ".s3m")) + err = cmd_app_module_info_build_s3m(app, &file, entry); + else + err = cmd_app_module_info_build_xm(app, &file, entry); + + if (file_open) + { + esp_err_t close_err = cmd_fs_manager_close(&app->fs, &file); + file_open = false; + if (err == ESP_OK && close_err != ESP_OK) err = close_err; + } + + if (err != ESP_OK) + { + cmd_app_module_info_free_text(app); + cmd_show_error(app, "module info", err); + return ESP_OK; + } + + app->module_info_open = true; + app->module_info_device = panel->device_id; + app->module_info_top_line = 0; + cmd_set_status(app, "module info: %s lines=%u", entry->name, (unsigned)app->module_info_line_count); + return ESP_OK; +} + +size_t cmd_app_module_info_max_top_line(CmdApp *app) +{ + size_t rows; + + if (!app) return 0; + + rows = (size_t)cmd_app_viewer_visible_rows(app); + if (app->module_info_line_count <= rows) return 0; + return app->module_info_line_count - rows; +} + +void cmd_app_module_info_set_status(CmdApp *app) +{ + if (!app) return; + + cmd_set_status(app, "module info: %s line %u/%u", + app->module_info_title[0] ? app->module_info_title : cmd_fs_filename_ptr(app->module_info_path), + (unsigned)(app->module_info_top_line + 1), + (unsigned)app->module_info_line_count); +} + +void cmd_app_module_info_move_to(CmdApp *app, size_t top_line) +{ + size_t max_top; + + if (!app) return; + + max_top = cmd_app_module_info_max_top_line(app); + if (top_line > max_top) top_line = max_top; + app->module_info_top_line = top_line; + cmd_app_module_info_set_status(app); +} + +esp_err_t cmd_app_handle_module_info_viewer_key(CmdApp *app, const cmd_event_t *event) +{ + size_t rows; + + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->module_info_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY && event->type != CMD_EVENT_QUIT) return ESP_OK; + + if (event->type == CMD_EVENT_QUIT || event->key == CMD_KEY_ESC) + { + cmd_app_close_module_info_viewer(app); + return ESP_OK; + } + + rows = (size_t)cmd_app_viewer_visible_rows(app); + + switch (event->key) + { + case CMD_KEY_UP: + if (app->module_info_top_line > 0) + cmd_app_module_info_move_to(app, app->module_info_top_line - 1); + return ESP_OK; + + case CMD_KEY_DOWN: + cmd_app_module_info_move_to(app, app->module_info_top_line + 1); + return ESP_OK; + + case CMD_KEY_PAGE_UP: + case CMD_KEY_LEFT: + if (app->module_info_top_line > rows) + cmd_app_module_info_move_to(app, app->module_info_top_line - rows); + else + cmd_app_module_info_move_to(app, 0); + return ESP_OK; + + case CMD_KEY_PAGE_DOWN: + case CMD_KEY_RIGHT: + cmd_app_module_info_move_to(app, app->module_info_top_line + rows); + return ESP_OK; + + case CMD_KEY_HOME: + cmd_app_module_info_move_to(app, 0); + return ESP_OK; + + case CMD_KEY_END: + cmd_app_module_info_move_to(app, cmd_app_module_info_max_top_line(app)); + return ESP_OK; + + default: + return ESP_OK; + } +} + +void cmd_app_module_info_copy_line(CmdApp *app, size_t line_index, char *out, size_t out_size) +{ + const char *p; + size_t current = 0; + size_t len = 0; + + if (!out || out_size == 0) return; + out[0] = 0; + if (!app || !app->module_info_text) return; + + p = app->module_info_text; + while (current < line_index && *p) + { + if (*p == '\n') current++; + p++; + } + + if (current != line_index) return; + + while (p[len] && p[len] != '\n') len++; + if (len >= out_size) len = out_size - 1; + memcpy(out, p, len); + out[len] = 0; +} + +void cmd_app_make_module_info_title(char *out, size_t out_size, CmdApp *app) +{ + if (!out || out_size == 0) return; + + cmd_app_text_clear(out, out_size); + if (!app) return; + + cmd_app_append_text(out, out_size, "Module: "); + cmd_app_append_text(out, out_size, cmd_device_name(app->module_info_device)); + cmd_app_append_text(out, out_size, ":"); + cmd_app_append_text(out, out_size, app->module_info_path); + cmd_app_append_text(out, out_size, " line "); + snprintf(app->viewer_num, sizeof(app->viewer_num), "%u", (unsigned)(app->module_info_top_line + 1)); + cmd_app_append_text(out, out_size, app->viewer_num); +} + +void cmd_app_draw_module_info_viewer(CmdApp *app) +{ + cmd_rect_t rect; + cmd_rect_t line_rect; + cmd_display_attr_t attr; + cmd_display_attr_t bar_attr; + int rows; + int cols; + int bottom_y; + + if (!app || !app->module_info_open) return; + + rows = cmd_app_viewer_visible_rows(app); + cols = cmd_app_viewer_visible_cols(app); + bottom_y = cmd_app_bottom_y(app); + attr = cmd_app_normal_attr(); + bar_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_YELLOW, CMD_DISPLAY_COLOR_CYAN, + CMD_DISPLAY_ATTR_FLAG_BOLD); + + rect.x = 0; + rect.y = 0; + rect.w = cmd_app_screen_w(app); + rect.h = cmd_app_screen_h(app); + + line_rect.x = 0; + line_rect.y = 0; + line_rect.w = rect.w; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', bar_attr); + cmd_app_make_module_info_title(app->viewer_draw_line, sizeof(app->viewer_draw_line), app); + cmd_display_buffer_write_text(&app->buffer, 0, 0, app->viewer_draw_line, bar_attr); + + for (int row = 0; row < rows; row++) + { + line_rect.x = 0; + line_rect.y = 1 + row; + line_rect.w = cols; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', attr); + + cmd_app_module_info_copy_line(app, + app->module_info_top_line + (size_t)row, + app->viewer_draw_line, + sizeof(app->viewer_draw_line)); + cmd_display_buffer_write_text(&app->buffer, 0, line_rect.y, app->viewer_draw_line, attr); + } + + line_rect.x = 0; + line_rect.y = bottom_y; + line_rect.w = rect.w; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', bar_attr); + cmd_display_buffer_write_text(&app->buffer, 0, bottom_y, + "Module info Up/Down PgUp/PgDn Left/Right Home/End Esc Close", bar_attr); +} + +char cmd_app_hex_viewer_ascii(uint8_t ch) +{ + if (ch >= 32 && ch <= 126) return (char)ch; + return '.'; +} + +void cmd_app_hex_viewer_clear_page(CmdApp *app) +{ + if (!app) return; + + app->hex_viewer_page_rows = 0; + app->hex_viewer_eof = true; + + for (int i = 0; i < CMD_APP_VIEWER_MAX_ROWS; i++) + app->hex_viewer_lines[i][0] = 0; +} + +void cmd_app_hex_viewer_make_line(CmdApp *app, char *out, size_t out_size, uint64_t offset, const uint8_t *data, size_t size) +{ + char *tmp; + + if (!app || !out || out_size == 0) return; + + tmp = app->hex_viewer_tmp; + + cmd_app_text_clear(out, out_size); + snprintf(out, out_size, "%08llX ", (unsigned long long)offset); + + for (size_t i = 0; i < CMD_APP_HEX_VIEWER_BYTES_PER_ROW; i++) + { + if (i == 8) cmd_app_append_text(out, out_size, " "); + + if (i < size) + snprintf(tmp, sizeof(app->hex_viewer_tmp), "%02X ", data[i]); + else + snprintf(tmp, sizeof(app->hex_viewer_tmp), " "); + + cmd_app_append_text(out, out_size, tmp); + } + + cmd_app_append_text(out, out_size, " |"); + + for (size_t i = 0; i < CMD_APP_HEX_VIEWER_BYTES_PER_ROW; i++) + { + tmp[0] = i < size ? cmd_app_hex_viewer_ascii(data[i]) : ' '; + tmp[1] = 0; + cmd_app_append_text(out, out_size, tmp); + } + + cmd_app_append_text(out, out_size, "|"); +} + +uint64_t cmd_app_hex_viewer_page_bytes(CmdApp *app) +{ + return (uint64_t)cmd_app_viewer_visible_rows(app) * CMD_APP_HEX_VIEWER_BYTES_PER_ROW; +} + +uint64_t cmd_app_hex_viewer_align_offset(uint64_t offset) +{ + return (offset / CMD_APP_HEX_VIEWER_BYTES_PER_ROW) * CMD_APP_HEX_VIEWER_BYTES_PER_ROW; +} + +esp_err_t cmd_app_hex_viewer_close_file(CmdApp *app) +{ + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + if (!app->hex_viewer_file_open) return ESP_OK; + + err = cmd_fs_manager_close(&app->fs, &app->hex_viewer_file); + app->hex_viewer_file_open = false; + memset(&app->hex_viewer_file, 0, sizeof(app->hex_viewer_file)); + return err; +} + +esp_err_t cmd_app_hex_viewer_open_file(CmdApp *app) +{ + CmdFsDriver *driver; + esp_err_t err; + + if (!app || !app->hex_viewer_open) return ESP_ERR_INVALID_ARG; + + err = cmd_app_hex_viewer_close_file(app); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_mount(&app->fs, app->hex_viewer_device); + if (err != ESP_OK) return err; + + driver = cmd_fs_manager_get_driver(&app->fs, app->hex_viewer_device); + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->open_read || !driver->read || !driver->seek || !driver->tell || !driver->close) + return ESP_ERR_NOT_SUPPORTED; + + memset(&app->hex_viewer_file, 0, sizeof(app->hex_viewer_file)); + err = cmd_fs_manager_open_read(&app->fs, app->hex_viewer_device, + app->hex_viewer_path, &app->hex_viewer_file); + if (err != ESP_OK) return err; + + app->hex_viewer_file_open = true; + return ESP_OK; +} + +esp_err_t cmd_app_hex_viewer_update_size(CmdApp *app) +{ + uint64_t size = 0; + esp_err_t err; + + if (!app || !app->hex_viewer_file_open) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_manager_seek(&app->fs, &app->hex_viewer_file, 0, SEEK_END); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_tell(&app->fs, &app->hex_viewer_file, &size); + if (err != ESP_OK) return err; + + app->hex_viewer_size = size; + app->hex_viewer_size_known = true; + return cmd_fs_manager_seek(&app->fs, &app->hex_viewer_file, 0, SEEK_SET); +} + +esp_err_t cmd_app_hex_viewer_read_page(CmdApp *app) +{ + uint8_t *row; + size_t got = 0; + size_t data_pos = 0; + size_t data_len = 0; + size_t row_len; + size_t rows; + uint64_t offset; + bool hit_eof = false; + esp_err_t err; + + if (!app || !app->hex_viewer_open) return ESP_ERR_INVALID_ARG; + if (!app->hex_viewer_file_open) return ESP_ERR_INVALID_STATE; + + row = app->hex_viewer_row; + + cmd_app_hex_viewer_clear_page(app); + + rows = (size_t)cmd_app_viewer_visible_rows(app); + offset = cmd_app_hex_viewer_align_offset(app->hex_viewer_offset); + app->hex_viewer_offset = offset; + + if (offset > (uint64_t)INT64_MAX) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_manager_seek(&app->fs, &app->hex_viewer_file, (int64_t)offset, SEEK_SET); + if (err != ESP_OK) return err; + + while (app->hex_viewer_page_rows < rows) + { + row_len = 0; + + while (row_len < CMD_APP_HEX_VIEWER_BYTES_PER_ROW) + { + if (data_pos >= data_len) + { + err = cmd_fs_manager_read(&app->fs, &app->hex_viewer_file, + app->hex_viewer_read_buffer, sizeof(app->hex_viewer_read_buffer), &got); + if (err != ESP_OK) return err; + if (got == 0) + { + hit_eof = true; + break; + } + + data_pos = 0; + data_len = got; + } + + row[row_len++] = app->hex_viewer_read_buffer[data_pos++]; + offset++; + } + + if (row_len == 0) break; + + cmd_app_hex_viewer_make_line( + app, + app->hex_viewer_lines[app->hex_viewer_page_rows], + sizeof(app->hex_viewer_lines[app->hex_viewer_page_rows]), + offset - row_len, + row, + row_len); + app->hex_viewer_page_rows++; + + if (row_len < CMD_APP_HEX_VIEWER_BYTES_PER_ROW) break; + } + + if (app->hex_viewer_size_known && offset >= app->hex_viewer_size) + hit_eof = true; + + app->hex_viewer_eof = hit_eof; + return ESP_OK; +} + +void cmd_app_hex_viewer_set_status(CmdApp *app) +{ + if (!app) return; + + cmd_set_status(app, "hex: %s offset 0x%08llX", + app->hex_viewer_title[0] ? app->hex_viewer_title : cmd_fs_filename_ptr(app->hex_viewer_path), + (unsigned long long)app->hex_viewer_offset); +} + +esp_err_t cmd_app_hex_viewer_move_to(CmdApp *app, uint64_t offset) +{ + uint64_t old_offset; + esp_err_t err; + + if (!app || !app->hex_viewer_open) return ESP_ERR_INVALID_ARG; + + old_offset = app->hex_viewer_offset; + app->hex_viewer_offset = cmd_app_hex_viewer_align_offset(offset); + + err = cmd_app_hex_viewer_read_page(app); + if (err != ESP_OK) + { + app->hex_viewer_offset = old_offset; + cmd_app_hex_viewer_read_page(app); + cmd_show_error(app, "hex view", err); + return ESP_OK; + } + + if (app->hex_viewer_offset > 0 && app->hex_viewer_page_rows == 0) + { + app->hex_viewer_offset = old_offset; + cmd_app_hex_viewer_read_page(app); + return ESP_OK; + } + + cmd_app_hex_viewer_set_status(app); + return ESP_OK; +} + +void cmd_app_close_hex_viewer(CmdApp *app) +{ + if (!app) return; + + cmd_app_hex_viewer_close_file(app); + app->hex_viewer_open = false; + app->hex_viewer_device = CMD_DEVICE_INVALID; + app->hex_viewer_path[0] = 0; + app->hex_viewer_title[0] = 0; + app->hex_viewer_offset = 0; + app->hex_viewer_size = 0; + app->hex_viewer_size_known = false; + cmd_app_hex_viewer_clear_page(app); + cmd_app_set_status(app, "ready"); +} + +esp_err_t cmd_app_open_hex_viewer(CmdApp *app, CmdPanel *panel, const cmd_file_entry_t *entry) +{ + esp_err_t err; + + if (!app || !panel || !entry) return ESP_ERR_INVALID_ARG; + + if (entry->type != CMD_ENTRY_FILE) + { + cmd_app_set_status(app, "hex view supports files only"); + return ESP_OK; + } + + err = cmd_app_join_selected_path(panel, entry, app->hex_viewer_path, sizeof(app->hex_viewer_path)); + if (err != ESP_OK) + { + cmd_show_error(app, "hex view", err); + return ESP_OK; + } + + app->hex_viewer_open = true; + app->hex_viewer_device = panel->device_id; + app->hex_viewer_offset = 0; + app->hex_viewer_size = entry->size; + app->hex_viewer_size_known = true; + cmd_app_copy_string(app->hex_viewer_title, sizeof(app->hex_viewer_title), entry->name); + + err = cmd_app_hex_viewer_open_file(app); + if (err == ESP_OK) + { + esp_err_t size_err = cmd_app_hex_viewer_update_size(app); + if (size_err != ESP_OK) + { + app->hex_viewer_size = entry->size; + app->hex_viewer_size_known = true; + } + } + if (err == ESP_OK) err = cmd_app_hex_viewer_read_page(app); + if (err != ESP_OK) + { + cmd_app_close_hex_viewer(app); + cmd_show_error(app, "hex view", err); + return ESP_OK; + } + + cmd_app_hex_viewer_set_status(app); + return ESP_OK; +} + +esp_err_t cmd_app_handle_hex_viewer_key(CmdApp *app, const cmd_event_t *event) +{ + uint64_t page_bytes; + uint64_t offset; + + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->hex_viewer_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY && event->type != CMD_EVENT_QUIT) return ESP_OK; + + if (event->type == CMD_EVENT_QUIT || event->key == CMD_KEY_ESC) + { + cmd_app_close_hex_viewer(app); + return ESP_OK; + } + + page_bytes = cmd_app_hex_viewer_page_bytes(app); + + switch (event->key) + { + case CMD_KEY_UP: + if (app->hex_viewer_offset >= CMD_APP_HEX_VIEWER_BYTES_PER_ROW) + return cmd_app_hex_viewer_move_to(app, app->hex_viewer_offset - CMD_APP_HEX_VIEWER_BYTES_PER_ROW); + return cmd_app_hex_viewer_move_to(app, 0); + + case CMD_KEY_DOWN: + if (!app->hex_viewer_eof || app->hex_viewer_page_rows > 1) + return cmd_app_hex_viewer_move_to(app, app->hex_viewer_offset + CMD_APP_HEX_VIEWER_BYTES_PER_ROW); + return ESP_OK; + + case CMD_KEY_PAGE_UP: + case CMD_KEY_LEFT: + if (app->hex_viewer_offset > page_bytes) + return cmd_app_hex_viewer_move_to(app, app->hex_viewer_offset - page_bytes); + return cmd_app_hex_viewer_move_to(app, 0); + + case CMD_KEY_PAGE_DOWN: + case CMD_KEY_RIGHT: + if (app->hex_viewer_eof) + { + if (app->hex_viewer_page_rows > 1) + return cmd_app_hex_viewer_move_to( + app, + app->hex_viewer_offset + (app->hex_viewer_page_rows - 1) * CMD_APP_HEX_VIEWER_BYTES_PER_ROW); + return ESP_OK; + } + return cmd_app_hex_viewer_move_to(app, app->hex_viewer_offset + page_bytes); + + case CMD_KEY_HOME: + return cmd_app_hex_viewer_move_to(app, 0); + + case CMD_KEY_END: + if (!app->hex_viewer_size_known) + { + cmd_app_set_status(app, "hex view: file size unknown"); + return ESP_OK; + } + + if (app->hex_viewer_size <= page_bytes) + return cmd_app_hex_viewer_move_to(app, 0); + + offset = app->hex_viewer_size - page_bytes; + offset = cmd_app_hex_viewer_align_offset(offset); + return cmd_app_hex_viewer_move_to(app, offset); + + default: + return ESP_OK; + } +} + +void cmd_app_make_hex_viewer_title(char *out, size_t out_size, CmdApp *app) +{ + if (!out || out_size == 0) return; + + cmd_app_text_clear(out, out_size); + if (!app) return; + + cmd_app_append_text(out, out_size, "Hex: "); + cmd_app_append_text(out, out_size, cmd_device_name(app->hex_viewer_device)); + cmd_app_append_text(out, out_size, ":"); + cmd_app_append_text(out, out_size, app->hex_viewer_path); + cmd_app_append_text(out, out_size, " offset 0x"); + snprintf(app->viewer_num, sizeof(app->viewer_num), "%08llX", (unsigned long long)app->hex_viewer_offset); + cmd_app_append_text(out, out_size, app->viewer_num); +} + +void cmd_app_draw_hex_viewer(CmdApp *app) +{ + cmd_rect_t rect; + cmd_rect_t line_rect; + cmd_display_attr_t attr; + cmd_display_attr_t bar_attr; + int rows; + int cols; + int bottom_y; + + if (!app || !app->hex_viewer_open) return; + + rows = cmd_app_viewer_visible_rows(app); + cols = cmd_app_viewer_visible_cols(app); + bottom_y = cmd_app_bottom_y(app); + attr = cmd_app_normal_attr(); + bar_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_YELLOW, CMD_DISPLAY_COLOR_CYAN, + CMD_DISPLAY_ATTR_FLAG_BOLD); + + rect.x = 0; + rect.y = 0; + rect.w = cmd_app_screen_w(app); + rect.h = cmd_app_screen_h(app); + + line_rect.x = 0; + line_rect.y = 0; + line_rect.w = rect.w; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', bar_attr); + cmd_app_make_hex_viewer_title(app->viewer_draw_line, sizeof(app->viewer_draw_line), app); + cmd_display_buffer_write_text(&app->buffer, 0, 0, app->viewer_draw_line, bar_attr); + + for (int row_index = 0; row_index < rows; row_index++) + { + line_rect.x = 0; + line_rect.y = 1 + row_index; + line_rect.w = cols; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', attr); + + if ((size_t)row_index < app->hex_viewer_page_rows) + cmd_display_buffer_write_text(&app->buffer, 0, line_rect.y, app->hex_viewer_lines[row_index], attr); + } + + line_rect.x = 0; + line_rect.y = bottom_y; + line_rect.w = rect.w; + line_rect.h = 1; + cmd_display_buffer_fill_rect(&app->buffer, &line_rect, ' ', bar_attr); + cmd_display_buffer_write_text(&app->buffer, 0, bottom_y, + "Hex viewer Up/Down PgUp/PgDn Left/Right Home End Esc Close", bar_attr); +} + +esp_err_t cmd_app_reload_both_panels(CmdApp *app) +{ + esp_err_t left_err; + esp_err_t right_err; + + if (!app) return ESP_ERR_INVALID_ARG; + + left_err = cmd_panel_reload(&app->left_panel); + right_err = cmd_panel_reload(&app->right_panel); + + if (left_err != ESP_OK) return left_err; + return right_err; +} + +void cmd_app_set_fileop_result_status(CmdApp *app, cmd_app_fileop_t op, const char *name, esp_err_t err) +{ + if (!app) return; + + if (err == ESP_OK) + { + cmd_set_status(app, "%s: %s", cmd_app_fileop_past(op), name ? name : ""); + return; + } + + if (err == CMD_ERR_CANCELLED) + { + cmd_set_status(app, "%s cancelled", cmd_app_fileop_status_name(op)); + return; + } + + cmd_show_error(app, cmd_app_fileop_status_name(op), err); +} + +esp_err_t cmd_app_open_fileop_confirm(CmdApp *app, cmd_app_fileop_t op) +{ + CmdPanel *active; + CmdPanel *passive; + const cmd_file_entry_t *entry; + bool group; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + active = cmd_app_active_panel(app); + passive = cmd_app_passive_panel(app); + if (!active || !passive) return ESP_ERR_INVALID_STATE; + + cmd_panel_update_selection_stats(active); + group = cmd_panel_has_selection(active); + + app->fileop_group = group; + app->fileop_item_count = group ? active->selected_count : 1; + app->fileop_item_size = group ? active->selected_size : 0; + app->fileop_dst_path[0] = 0; + + if (group) + { + snprintf(app->fileop_name, sizeof(app->fileop_name), "%u selected items", (unsigned)active->selected_count); + + if (op == CMD_APP_FILEOP_COPY || op == CMD_APP_FILEOP_MOVE) + cmd_app_copy_string(app->fileop_dst_path, sizeof(app->fileop_dst_path), passive->current_path); + + app->fileop_confirm_open = true; + app->fileop_confirm_op = op; + cmd_app_set_status(app, "Enter OK Esc cancel"); + return ESP_OK; + } + + entry = cmd_panel_get_selected_entry(active); + if (!entry) + { + cmd_app_set_status(app, "no selected entry"); + return ESP_OK; + } + + if (entry->type == CMD_ENTRY_PARENT) + { + cmd_app_set_status(app, "cannot operate on .."); + return ESP_OK; + } + + cmd_app_copy_string(app->fileop_name, sizeof(app->fileop_name), entry->name); + app->fileop_item_size = (entry->type == CMD_ENTRY_FILE) ? entry->size : 0; + + if (op == CMD_APP_FILEOP_COPY || op == CMD_APP_FILEOP_MOVE) + { + err = cmd_fs_join_path(passive->current_path, entry->name, app->fileop_dst_path, sizeof(app->fileop_dst_path)); + if (err != ESP_OK) + { + cmd_app_set_status_err(app, cmd_app_fileop_status_name(op), err); + return ESP_OK; + } + } + else + { + err = cmd_app_join_selected_path(active, entry, app->fileop_dst_path, sizeof(app->fileop_dst_path)); + if (err != ESP_OK) + { + cmd_app_set_status_err(app, cmd_app_fileop_status_name(op), err); + return ESP_OK; + } + } + + app->fileop_confirm_open = true; + app->fileop_confirm_op = op; + cmd_app_set_status(app, "Enter OK Esc cancel"); + return ESP_OK; +} + +void cmd_app_close_fileop_confirm(CmdApp *app) +{ + if (!app) return; + + app->fileop_confirm_open = false; + app->fileop_confirm_op = CMD_APP_FILEOP_NONE; + app->fileop_name[0] = 0; + app->fileop_dst_path[0] = 0; + app->fileop_group = false; + app->fileop_item_count = 0; + app->fileop_item_size = 0; +} + +void cmd_app_draw_confirm_dialog(CmdApp *app) +{ + cmd_rect_t rect; + cmd_display_attr_t attr; + cmd_display_attr_t frame_attr; + char title[CMD_DISPLAY_COLS + 1]; + char line[CMD_DISPLAY_COLS + 1]; + + if (!app || !app->fileop_confirm_open) return; + + rect.x = cmd_app_center_x(app, CMD_APP_FILEOP_DIALOG_W); + rect.y = cmd_app_center_y(app, CMD_APP_FILEOP_DIALOG_H); + rect.w = CMD_APP_FILEOP_DIALOG_W; + rect.h = CMD_APP_FILEOP_DIALOG_H; + + attr = cmd_app_dialog_attr(); + frame_attr = cmd_app_dialog_frame_attr(); + + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_draw_box(&app->buffer, &rect, frame_attr); + + snprintf(title, sizeof(title), " %s ", cmd_app_fileop_verb(app->fileop_confirm_op)); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y, title, frame_attr); + + cmd_app_text_clear(line, sizeof(line)); + if (app->fileop_group) + { + cmd_app_append_text(line, sizeof(line), cmd_app_fileop_verb(app->fileop_confirm_op)); + cmd_app_append_text(line, sizeof(line), " "); + snprintf(line + cmd_app_text_len(line), sizeof(line) - cmd_app_text_len(line), + "%u selected items", (unsigned)app->fileop_item_count); + if (app->fileop_confirm_op == CMD_APP_FILEOP_DELETE) + cmd_app_append_text(line, sizeof(line), "?"); + } + else if (app->fileop_confirm_op == CMD_APP_FILEOP_DELETE) + { + cmd_app_append_text(line, sizeof(line), "Delete "); + cmd_app_append_text(line, sizeof(line), app->fileop_name); + cmd_app_append_text(line, sizeof(line), "?"); + } + else + { + cmd_app_append_text(line, sizeof(line), cmd_app_fileop_verb(app->fileop_confirm_op)); + cmd_app_append_text(line, sizeof(line), " "); + cmd_app_append_text(line, sizeof(line), app->fileop_name); + } + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 2, line, attr); + + if (app->fileop_confirm_op == CMD_APP_FILEOP_COPY || app->fileop_confirm_op == CMD_APP_FILEOP_MOVE) + { + cmd_app_text_clear(line, sizeof(line)); + cmd_app_append_text(line, sizeof(line), "to "); + cmd_app_append_text(line, sizeof(line), app->fileop_dst_path); + cmd_app_append_text(line, sizeof(line), "?"); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 3, line, attr); + } + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + rect.h - 2, + "Enter/OK start Esc/Cancel", attr); +} + +void cmd_app_draw_progress_bar(CmdApp *app, int x, int y, int w) +{ + uint64_t percent = 0; + int fill; + + if (!app || w <= 2) return; + + if (app->fileop_bytes_total > 0) + percent = (app->fileop_bytes_done * 100ull) / app->fileop_bytes_total; + else if (app->fileop_files_total > 0) + percent = ((uint64_t)app->fileop_files_done * 100ull) / (uint64_t)app->fileop_files_total; + else + percent = 100; + + if (percent > 100) percent = 100; + + cmd_display_buffer_put_char(&app->buffer, x, y, '[', cmd_app_dialog_frame_attr()); + cmd_display_buffer_put_char(&app->buffer, x + w - 1, y, ']', cmd_app_dialog_frame_attr()); + + fill = (int)((percent * (uint64_t)(w - 2)) / 100ull); + for (int i = 0; i < w - 2; i++) + { + char ch = i < fill ? '#' : ' '; + cmd_display_buffer_put_char(&app->buffer, x + 1 + i, y, ch, cmd_app_dialog_selected_attr()); + } +} + +void cmd_app_draw_progress_dialog(CmdApp *app) +{ + cmd_rect_t rect; + cmd_display_attr_t attr; + cmd_display_attr_t frame_attr; + char title[CMD_DISPLAY_COLS + 1]; + char line[CMD_DISPLAY_COLS + 1]; + uint64_t percent = 0; + + if (!app || !app->fileop_progress_open) return; + + rect.x = cmd_app_center_x(app, CMD_APP_FILEOP_DIALOG_W); + rect.y = cmd_app_center_y(app, CMD_APP_FILEOP_DIALOG_H); + rect.w = CMD_APP_FILEOP_DIALOG_W; + rect.h = CMD_APP_FILEOP_DIALOG_H; + + attr = cmd_app_dialog_attr(); + frame_attr = cmd_app_dialog_frame_attr(); + + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_draw_box(&app->buffer, &rect, frame_attr); + + snprintf(title, sizeof(title), " %s progress ", cmd_app_fileop_verb(app->fileop_progress_op)); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y, title, frame_attr); + + cmd_app_text_clear(line, sizeof(line)); + cmd_app_append_text(line, sizeof(line), cmd_app_fileop_verb(app->fileop_progress_op)); + cmd_app_append_text(line, sizeof(line), ": "); + cmd_app_append_text(line, sizeof(line), app->fileop_progress_name); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 2, line, attr); + + cmd_app_draw_progress_bar(app, rect.x + 2, rect.y + 4, rect.w - 4); + + if (app->fileop_bytes_total > 0) + percent = (app->fileop_bytes_done * 100ull) / app->fileop_bytes_total; + else if (app->fileop_files_total > 0) + percent = ((uint64_t)app->fileop_files_done * 100ull) / (uint64_t)app->fileop_files_total; + else + percent = 100; + + if (percent > 100) percent = 100; + + if (app->fileop_files_total > 0) + { + snprintf(line, sizeof(line), "%u / %u items %llu / %llu bytes %llu%%", + (unsigned)app->fileop_files_done, + (unsigned)app->fileop_files_total, + (unsigned long long)app->fileop_bytes_done, + (unsigned long long)app->fileop_bytes_total, + (unsigned long long)percent); + } + else + { + snprintf(line, sizeof(line), "%llu / %llu bytes %llu%%", + (unsigned long long)app->fileop_bytes_done, + (unsigned long long)app->fileop_bytes_total, + (unsigned long long)percent); + } + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 5, line, attr); + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + rect.h - 2, + app->fileop_progress_can_cancel ? "Esc cancel" : "Finishing...", attr); +} + +void cmd_app_close_error_dialog(CmdApp *app) +{ + if (!app) return; + + app->error_dialog_open = false; + app->error_dialog_err = ESP_OK; + app->error_dialog_title[0] = 0; + app->error_dialog_message[0] = 0; +} + +void cmd_app_draw_error_dialog(CmdApp *app) +{ + cmd_rect_t rect; + cmd_display_attr_t attr; + cmd_display_attr_t frame_attr; + char title[CMD_APP_ERROR_TITLE_MAX + 4]; + char line[CMD_DISPLAY_COLS + 1]; + + if (!app || !app->error_dialog_open) return; + + rect.x = cmd_app_center_x(app, CMD_APP_ERROR_DIALOG_W); + rect.y = cmd_app_center_y(app, CMD_APP_ERROR_DIALOG_H); + rect.w = CMD_APP_ERROR_DIALOG_W; + rect.h = CMD_APP_ERROR_DIALOG_H; + + attr = cmd_app_dialog_attr(); + frame_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_RED, CMD_DISPLAY_COLOR_BLACK, CMD_DISPLAY_ATTR_FLAG_BOLD); + + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_draw_box(&app->buffer, &rect, frame_attr); + + cmd_app_text_clear(title, sizeof(title)); + cmd_app_append_text(title, sizeof(title), " "); + cmd_app_append_text(title, sizeof(title), app->error_dialog_title[0] ? app->error_dialog_title : "Error"); + cmd_app_append_text(title, sizeof(title), " "); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y, title, frame_attr); + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 2, app->error_dialog_message, attr); + + cmd_app_text_clear(line, sizeof(line)); + cmd_app_append_text(line, sizeof(line), "Code: 0x"); + snprintf(line + cmd_app_text_len(line), sizeof(line) - cmd_app_text_len(line), "%x", (unsigned)app->error_dialog_err); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 3, line, attr); + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + rect.h - 2, + "Enter/Esc close", attr); +} + +esp_err_t cmd_app_handle_error_dialog_key(CmdApp *app, const cmd_event_t *event) +{ + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->error_dialog_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY && event->type != CMD_EVENT_QUIT) return ESP_OK; + + if (event->type == CMD_EVENT_QUIT || event->key == CMD_KEY_ESC || event->key == CMD_KEY_ENTER || event->key == CMD_KEY_F10) + { + cmd_app_close_error_dialog(app); + return ESP_OK; + } + + return ESP_OK; +} + + +bool cmd_app_mkdir_name_is_valid(const char *name) +{ + if (!name || !name[0]) return false; + + for (size_t i = 0; name[i]; i++) + { + if (name[i] == '/' || name[i] == '\\') return false; + } + + return true; +} + +bool cmd_app_panel_is_at_path(const CmdPanel *panel, cmd_device_id_t device_id, const char *path) +{ + if (!panel || !path) return false; + if (panel->device_id != device_id) return false; + return strcmp(panel->current_path, path) == 0; +} + +esp_err_t cmd_app_reload_matching_panel(CmdApp *app, CmdPanel *panel, cmd_device_id_t device_id, const char *path, const char *name) +{ + if (!cmd_app_panel_is_at_path(panel, device_id, path)) return ESP_OK; + return cmd_app_reload_panel(app, panel, name); +} + +bool cmd_app_focus_panel_entry(CmdPanel *panel, const char *name) +{ + if (!panel || !panel->entries || !name) return false; + + for (size_t i = 0; i < panel->count; i++) + { + if (strcmp(panel->entries[i].name, name) != 0) continue; + + panel->cursor = i; + cmd_panel_ensure_cursor_visible(panel); + return true; + } + + return false; +} + +bool cmd_app_path_is_same_or_child(const char *parent, const char *path) +{ + const char *base = parent; + const char *child = path; + size_t base_len; + + if (!base || !base[0]) base = "/"; + if (!child || !child[0]) child = "/"; + + if (strcmp(base, child) == 0) return true; + if (cmd_fs_path_is_root(base)) return true; + + base_len = strlen(base); + while (base_len > 1 && base[base_len - 1] == '/') + base_len--; + + if (strncmp(base, child, base_len) != 0) return false; + return child[base_len] == '/'; +} + +esp_err_t cmd_app_recover_panel_from_removed_path(CmdPanel *panel, cmd_device_id_t device_id, const char *removed_path) +{ + char parent[CMD_PATH_MAX]; + esp_err_t err; + + if (!panel || !removed_path) return ESP_ERR_INVALID_ARG; + if (panel->device_id != device_id) return ESP_OK; + if (!cmd_app_path_is_same_or_child(removed_path, panel->current_path)) return ESP_OK; + + err = cmd_fs_parent_path(removed_path, parent, sizeof(parent)); + if (err != ESP_OK) return err; + + return cmd_panel_set_path(panel, parent); +} + +esp_err_t cmd_app_recover_panels_from_removed_path(CmdApp *app, cmd_device_id_t device_id, const char *removed_path) +{ + esp_err_t err; + + if (!app || !removed_path) return ESP_ERR_INVALID_ARG; + + err = cmd_app_recover_panel_from_removed_path(&app->left_panel, device_id, removed_path); + if (err != ESP_OK) return err; + + return cmd_app_recover_panel_from_removed_path(&app->right_panel, device_id, removed_path); +} + +esp_err_t cmd_app_recover_panels_after_source_removal(CmdApp *app, CmdPanel *active) +{ + const cmd_file_entry_t *entry; + char path[CMD_PATH_MAX]; + esp_err_t err; + + if (!app || !active) return ESP_ERR_INVALID_ARG; + + if (app->fileop_group) + { + for (size_t i = 0; i < active->count; i++) + { + entry = &active->entries[i]; + if (!(entry->flags & CMD_ENTRY_FLAG_SELECTED)) continue; + if (entry->type != CMD_ENTRY_FILE && entry->type != CMD_ENTRY_DIR) continue; + + err = cmd_fs_join_path(active->current_path, entry->name, path, sizeof(path)); + if (err != ESP_OK) return err; + + err = cmd_app_recover_panels_from_removed_path(app, active->device_id, path); + if (err != ESP_OK) return err; + } + + return ESP_OK; + } + + entry = cmd_panel_get_selected_entry(active); + if (!entry) return ESP_OK; + if (entry->type != CMD_ENTRY_FILE && entry->type != CMD_ENTRY_DIR) return ESP_OK; + + err = cmd_fs_join_path(active->current_path, entry->name, path, sizeof(path)); + if (err != ESP_OK) return err; + + return cmd_app_recover_panels_from_removed_path(app, active->device_id, path); +} + +esp_err_t cmd_app_open_mkdir_dialog(CmdApp *app) +{ + if (!app) return ESP_ERR_INVALID_ARG; + + app->mkdir_dialog_open = true; + app->mkdir_dialog_op = CMD_APP_NAME_DIALOG_MKDIR; + app->mkdir_name[0] = 0; + app->rename_src_path[0] = 0; + app->rename_dst_path[0] = 0; + app->rename_remap_path[0] = 0; + cmd_app_set_status(app, "mkdir: type name, Enter OK, Esc cancel"); + return ESP_OK; +} + +esp_err_t cmd_app_open_rename_dialog(CmdApp *app) +{ + CmdPanel *panel; + const cmd_file_entry_t *entry; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + panel = cmd_app_active_panel(app); + if (!panel) return ESP_ERR_INVALID_STATE; + + entry = cmd_panel_get_selected_entry(panel); + if (!entry) + { + cmd_app_set_status(app, "no selected entry"); + return ESP_OK; + } + + if (entry->type == CMD_ENTRY_PARENT) + { + cmd_app_set_status(app, "cannot rename .."); + return ESP_OK; + } + + if (entry->type != CMD_ENTRY_FILE && entry->type != CMD_ENTRY_DIR) + { + cmd_app_set_status(app, "cannot rename entry"); + return ESP_OK; + } + + err = cmd_fs_join_path(panel->current_path, entry->name, app->rename_src_path, sizeof(app->rename_src_path)); + if (err != ESP_OK) + { + cmd_show_error(app, "rename", err); + return ESP_OK; + } + + cmd_app_copy_string(app->mkdir_name, sizeof(app->mkdir_name), entry->name); + app->mkdir_dialog_open = true; + app->mkdir_dialog_op = CMD_APP_NAME_DIALOG_RENAME; + cmd_app_set_status(app, "rename: edit name, Enter OK, Esc cancel"); + return ESP_OK; +} + +void cmd_app_close_mkdir_dialog(CmdApp *app) +{ + if (!app) return; + + app->mkdir_dialog_open = false; + app->mkdir_dialog_op = CMD_APP_NAME_DIALOG_MKDIR; + app->mkdir_name[0] = 0; + app->rename_src_path[0] = 0; + app->rename_dst_path[0] = 0; + app->rename_remap_path[0] = 0; +} + +esp_err_t cmd_app_create_directory(CmdApp *app) +{ + CmdPanel *panel; + char path[CMD_PATH_MAX]; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + panel = cmd_app_active_panel(app); + if (!panel) return ESP_ERR_INVALID_STATE; + + if (!cmd_app_mkdir_name_is_valid(app->mkdir_name)) + { + cmd_app_set_status(app, "invalid folder name"); + return ESP_OK; + } + + err = cmd_fs_join_path(panel->current_path, app->mkdir_name, path, sizeof(path)); + if (err != ESP_OK) + { + cmd_show_error(app, "mkdir", err); + return ESP_OK; + } + + err = cmd_fs_manager_mount(panel->fs, panel->device_id); + if (err == ESP_OK) + err = cmd_fs_manager_mkdir(panel->fs, panel->device_id, path); + + if (err != ESP_OK) + { + cmd_show_error(app, "mkdir", err); + return ESP_OK; + } + + cmd_app_close_mkdir_dialog(app); + + err = cmd_app_reload_panel(app, panel, "mkdir reload"); + if (err == ESP_OK) + { + cmd_app_focus_panel_entry(panel, cmd_fs_filename_ptr(path)); + err = cmd_app_reload_matching_panel(app, cmd_app_passive_panel(app), panel->device_id, panel->current_path, "mkdir reload"); + } + + if (err != ESP_OK) + { + cmd_show_error(app, "mkdir", err); + return ESP_OK; + } + + cmd_set_status(app, "folder created: %s", cmd_fs_filename_ptr(path)); + return ESP_OK; +} + +esp_err_t cmd_app_remap_panel_after_rename(CmdPanel *panel, + cmd_device_id_t device_id, + const char *old_path, + const char *new_path, + char *work_path, + size_t work_path_size) +{ + size_t old_len; + int len; + + if (!panel || !old_path || !new_path || !work_path || work_path_size == 0) return ESP_ERR_INVALID_ARG; + if (panel->device_id != device_id) return ESP_OK; + if (!cmd_app_path_is_same_or_child(old_path, panel->current_path)) return ESP_OK; + + if (strcmp(old_path, panel->current_path) == 0) + return cmd_panel_set_path(panel, new_path); + + old_len = strlen(old_path); + len = snprintf(work_path, work_path_size, "%s%s", new_path, panel->current_path + old_len); + if (len < 0 || (size_t)len >= work_path_size) return CMD_ERR_PATH_TOO_LONG; + + return cmd_panel_set_path(panel, work_path); +} + +esp_err_t cmd_app_rename_entry(CmdApp *app) +{ + CmdPanel *panel; + cmd_file_entry_t entry; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + panel = cmd_app_active_panel(app); + if (!panel) return ESP_ERR_INVALID_STATE; + + if (!cmd_app_mkdir_name_is_valid(app->mkdir_name)) + { + cmd_app_set_status(app, "invalid file name"); + return ESP_OK; + } + + err = cmd_fs_join_path(panel->current_path, app->mkdir_name, app->rename_dst_path, sizeof(app->rename_dst_path)); + if (err != ESP_OK) + { + cmd_show_error(app, "rename", err); + return ESP_OK; + } + + if (strcmp(app->rename_src_path, app->rename_dst_path) == 0) + { + cmd_app_close_mkdir_dialog(app); + cmd_app_set_status(app, "rename unchanged"); + return ESP_OK; + } + + err = cmd_fs_manager_mount(panel->fs, panel->device_id); + if (err == ESP_OK) + { + err = cmd_fs_manager_stat(panel->fs, panel->device_id, app->rename_dst_path, &entry); + if (err == ESP_OK) + err = ESP_ERR_INVALID_STATE; + else if (err == ESP_ERR_NOT_FOUND) + err = cmd_fs_manager_rename(panel->fs, panel->device_id, app->rename_src_path, app->rename_dst_path); + } + + if (err != ESP_OK) + { + cmd_show_error(app, "rename", err); + return ESP_OK; + } + + err = cmd_app_remap_panel_after_rename(&app->left_panel, + panel->device_id, + app->rename_src_path, + app->rename_dst_path, + app->rename_remap_path, + sizeof(app->rename_remap_path)); + if (err == ESP_OK) + err = cmd_app_remap_panel_after_rename(&app->right_panel, + panel->device_id, + app->rename_src_path, + app->rename_dst_path, + app->rename_remap_path, + sizeof(app->rename_remap_path)); + + if (err == ESP_OK) + err = cmd_app_reload_both_panels(app); + if (err == ESP_OK) + cmd_app_focus_panel_entry(panel, cmd_fs_filename_ptr(app->rename_dst_path)); + + if (err != ESP_OK) + { + cmd_app_close_mkdir_dialog(app); + cmd_show_error(app, "rename", err); + return ESP_OK; + } + + cmd_set_status(app, "renamed to: %s", cmd_fs_filename_ptr(app->rename_dst_path)); + cmd_app_close_mkdir_dialog(app); + return ESP_OK; +} + +void cmd_app_draw_mkdir_dialog(CmdApp *app) +{ + cmd_rect_t rect; + cmd_display_attr_t attr; + cmd_display_attr_t frame_attr; + char line[CMD_DISPLAY_COLS + 1]; + const char *title; + const char *label; + const char *footer; + + if (!app || !app->mkdir_dialog_open) return; + + if (app->mkdir_dialog_op == CMD_APP_NAME_DIALOG_RENAME) + { + title = " Rename "; + label = "New name:"; + footer = "Enter/OK rename Esc/Cancel"; + } + else + { + title = " MkDir "; + label = "Folder name:"; + footer = "Enter/OK create Esc/Cancel"; + } + + rect.x = cmd_app_center_x(app, CMD_APP_MKDIR_DIALOG_W); + rect.y = cmd_app_center_y(app, CMD_APP_MKDIR_DIALOG_H); + rect.w = CMD_APP_MKDIR_DIALOG_W; + rect.h = CMD_APP_MKDIR_DIALOG_H; + + attr = cmd_app_dialog_attr(); + frame_attr = cmd_app_dialog_frame_attr(); + + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_draw_box(&app->buffer, &rect, frame_attr); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y, title, frame_attr); + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 2, label, attr); + + cmd_app_text_clear(line, sizeof(line)); + cmd_app_append_text(line, sizeof(line), app->mkdir_name); + cmd_app_append_text(line, sizeof(line), "_"); + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + 3, line, attr); + + cmd_display_buffer_write_text(&app->buffer, rect.x + 2, rect.y + rect.h - 2, footer, attr); +} + +esp_err_t cmd_app_submit_mkdir_dialog(CmdApp *app) +{ + if (!app) return ESP_ERR_INVALID_ARG; + + if (app->mkdir_dialog_op == CMD_APP_NAME_DIALOG_RENAME) + return cmd_app_rename_entry(app); + + return cmd_app_create_directory(app); +} + +esp_err_t cmd_app_handle_mkdir_dialog_key(CmdApp *app, const cmd_event_t *event) +{ + size_t len; + + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->mkdir_dialog_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY && event->type != CMD_EVENT_QUIT) return ESP_OK; + + if (event->type == CMD_EVENT_QUIT || event->key == CMD_KEY_ESC || event->key == CMD_KEY_F10) + { + if (app->mkdir_dialog_op == CMD_APP_NAME_DIALOG_RENAME) + cmd_app_set_status(app, "rename cancelled"); + else + cmd_app_set_status(app, "mkdir cancelled"); + cmd_app_close_mkdir_dialog(app); + return ESP_OK; + } + + if (event->key == CMD_KEY_ENTER) + return cmd_app_submit_mkdir_dialog(app); + + if (event->key == CMD_KEY_BACKSPACE) + { + len = cmd_app_text_len(app->mkdir_name); + if (len > 0) app->mkdir_name[len - 1] = 0; + return ESP_OK; + } + + if (event->key == CMD_KEY_CHAR && event->ch >= 32 && event->ch < 127) + { + len = cmd_app_text_len(app->mkdir_name); + if (len + 1 >= sizeof(app->mkdir_name)) return ESP_OK; + app->mkdir_name[len] = (char)event->ch; + app->mkdir_name[len + 1] = 0; + return ESP_OK; + } + + return ESP_OK; +} + +bool cmd_app_progress_poll_cancel(CmdApp *app, bool can_cancel) +{ + cmd_event_t event; + esp_err_t err; + + if (!app || !can_cancel) return false; + + err = cmd_input_poll_event(app->input, &event, 0); + if (err != ESP_OK) return false; + if (event.type != CMD_EVENT_KEY && event.type != CMD_EVENT_QUIT) return false; + + if (event.type == CMD_EVENT_QUIT || event.key == CMD_KEY_ESC) + { + app->fileop_cancel_requested = true; + cmd_app_set_status(app, "cancel requested"); + return true; + } + + return false; +} + +bool cmd_app_fileops_progress_cb(const CmdFileopsProgress *progress, void *ctx) +{ + CmdApp *app = (CmdApp *)ctx; + + if (!app || !progress) return true; + + app->fileop_bytes_done = progress->bytes_done; + app->fileop_bytes_total = progress->bytes_total; + app->fileop_files_done = progress->files_done; + app->fileop_files_total = progress->files_total; + app->fileop_progress_can_cancel = progress->can_cancel; + cmd_app_copy_string(app->fileop_progress_name, sizeof(app->fileop_progress_name), progress->filename); + + cmd_app_render(app); + + if (cmd_app_progress_poll_cancel(app, progress->can_cancel)) return false; + if (app->fileop_cancel_requested && progress->can_cancel) return false; + return true; +} + +esp_err_t cmd_app_run_fileop(CmdApp *app, cmd_app_fileop_t op) +{ + CmdFileopsOptions options = {}; + CmdPanel *active; + CmdPanel *passive; + esp_err_t op_err; + esp_err_t reload_err; + + if (!app) return ESP_ERR_INVALID_ARG; + + active = cmd_app_active_panel(app); + passive = cmd_app_passive_panel(app); + if (!active || !passive) return ESP_ERR_INVALID_STATE; + + app->fileop_progress_open = true; + app->fileop_progress_op = op; + app->fileop_bytes_done = 0; + app->fileop_bytes_total = app->fileop_group ? app->fileop_item_size : 0; + app->fileop_files_done = 0; + app->fileop_files_total = app->fileop_group ? app->fileop_item_count : 0; + app->fileop_progress_can_cancel = true; + app->fileop_cancel_requested = false; + cmd_app_copy_string(app->fileop_progress_name, sizeof(app->fileop_progress_name), app->fileop_name); + + options.flags = CMD_FILEOPS_FLAG_RECURSIVE; + options.progress = cmd_app_fileops_progress_cb; + options.progress_ctx = app; + + cmd_app_set_status(app, "operation started"); + cmd_app_render(app); + + if (op == CMD_APP_FILEOP_DELETE) + op_err = cmd_app_recover_panels_after_source_removal(app, active); + else + op_err = ESP_OK; + + if (op_err == ESP_OK && op == CMD_APP_FILEOP_COPY) + op_err = cmd_fileops_copy_selected(active, passive, &options); + else if (op_err == ESP_OK && op == CMD_APP_FILEOP_MOVE) + op_err = cmd_fileops_move_selected(active, passive, &options); + else if (op_err == ESP_OK && op == CMD_APP_FILEOP_DELETE) + op_err = cmd_fileops_delete_selected(active, &options); + else if (op_err == ESP_OK) + op_err = ESP_ERR_INVALID_ARG; + + app->fileop_progress_open = false; + + if (op_err == ESP_OK) + cmd_panel_clear_selection(active); + + reload_err = cmd_app_reload_both_panels(app); + + if (op_err == ESP_OK && reload_err != ESP_OK) + op_err = reload_err; + + cmd_app_set_fileop_result_status(app, op, app->fileop_name, op_err); + return ESP_OK; +} + +esp_err_t cmd_app_handle_fileop_confirm_key(CmdApp *app, const cmd_event_t *event) +{ + cmd_app_fileop_t op; + + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (!app->fileop_confirm_open) return ESP_ERR_INVALID_STATE; + if (event->type != CMD_EVENT_KEY) return ESP_OK; + + if (event->key == CMD_KEY_ESC || event->key == CMD_KEY_F10 || + (event->key == CMD_KEY_CHAR && (event->ch == 'q' || event->ch == 'Q'))) + { + cmd_app_close_fileop_confirm(app); + cmd_app_set_status(app, "operation cancelled"); + return ESP_OK; + } + + if (event->key == CMD_KEY_ENTER) + { + op = app->fileop_confirm_op; + app->fileop_confirm_open = false; + app->fileop_confirm_op = CMD_APP_FILEOP_NONE; + return cmd_app_run_fileop(app, op); + } + + return ESP_OK; +} + +esp_err_t cmd_app_reload_panel(CmdApp *app, CmdPanel *panel, const char *name) +{ + esp_err_t err; + + if (!app || !panel) return ESP_ERR_INVALID_ARG; + + err = cmd_panel_reload(panel); + if (err != ESP_OK) + { + cmd_app_set_status_err(app, name, err); + return err; + } + + return ESP_OK; +} + +esp_err_t cmd_app_init_panels(CmdApp *app) +{ + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + cmd_panel_init(&app->left_panel, &app->fs, CMD_DEVICE_SD); + cmd_panel_init(&app->right_panel, &app->fs, CMD_DEVICE_SD); + + err = cmd_panel_alloc_entries(&app->left_panel, CMD_PANEL_MAX_ENTRIES); + if (err != ESP_OK) return err; + + err = cmd_panel_alloc_entries(&app->right_panel, CMD_PANEL_MAX_ENTRIES); + if (err != ESP_OK) return err; + + cmd_app_set_active_panel(app, CMD_PANEL_LEFT); + + cmd_app_reload_panel(app, &app->left_panel, "left panel reload"); + cmd_app_reload_panel(app, &app->right_panel, "right panel reload"); + + return ESP_OK; +} + +void cmd_app_draw_top_bar(CmdApp *app) +{ + char line[CMD_DISPLAY_COLS + 1]; + cmd_rect_t rect; + cmd_display_attr_t attr; + CmdPanel *panel; + const char *status; + + if (!app) return; + + rect.x = 0; + rect.y = CMD_LAYOUT_TOP_Y; + rect.w = cmd_app_screen_w(app); + rect.h = 1; + attr = cmd_app_bar_attr(); + panel = cmd_app_active_panel(app); + status = app->status[0] ? app->status : "ready"; + + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + + cmd_app_make_top_bar_line(line, sizeof(line), panel, status); + cmd_display_buffer_write_text(&app->buffer, 0, CMD_LAYOUT_TOP_Y, line, attr); +} + +void cmd_app_draw_bottom_bar(CmdApp *app) +{ + cmd_rect_t rect; + cmd_display_attr_t attr; + int y; + + if (!app) return; + + y = cmd_app_bottom_y(app); + rect.x = 0; + rect.y = y; + rect.w = cmd_app_screen_w(app); + rect.h = 1; + attr = cmd_app_bar_attr(); + + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_write_text(&app->buffer, 0, y, + "F1 Help F2 Rename F3 View A+F3 Hex F5 Copy F6 Move F7 MkDir F8 Del", attr); +} + +void cmd_app_make_panel_info_line(char *out, size_t out_size, const CmdPanel *panel, int width) +{ + const cmd_file_entry_t *entry; + char size_text[32]; + size_t size_len; + size_t name_len; + size_t line_w; + size_t size_pos; + size_t name_max; + + if (!out || out_size == 0) return; + + cmd_app_text_clear(out, out_size); + + if (!panel || width <= 0) return; + + if (panel->selected_count > 0) + { + line_w = (size_t)width; + if (line_w >= out_size) line_w = out_size - 1; + if (line_w == 0) return; + + memset(out, ' ', line_w); + out[line_w] = 0; + + snprintf(size_text, sizeof(size_text), "%u selected", (unsigned)panel->selected_count); + name_len = strlen(size_text); + if (name_len > line_w) name_len = line_w; + if (name_len > 0) memcpy(out, size_text, name_len); + + snprintf(size_text, sizeof(size_text), "%llu bytes", (unsigned long long)panel->selected_size); + size_len = strlen(size_text); + if (size_len < line_w) + { + size_pos = line_w - size_len; + if (size_pos > 0) size_pos--; + memcpy(&out[size_pos], size_text, size_len); + } + return; + } + + entry = cmd_panel_get_selected_entry(panel); + if (!entry || entry->type != CMD_ENTRY_FILE) return; + + line_w = (size_t)width; + if (line_w >= out_size) line_w = out_size - 1; + if (line_w == 0) return; + + memset(out, ' ', line_w); + out[line_w] = 0; + + snprintf(size_text, sizeof(size_text), "%llu bytes", (unsigned long long)entry->size); + size_len = strlen(size_text); + + if (size_len >= line_w) + { + memcpy(out, size_text, line_w); + return; + } + + size_pos = line_w - size_len; + if (size_pos > 0) size_pos--; + memcpy(&out[size_pos], size_text, size_len); + + name_max = size_pos > 1 ? size_pos - 1 : 0; + name_len = strlen(entry->name); + if (name_len > name_max) name_len = name_max; + if (name_len > 0) memcpy(out, entry->name, name_len); +} + +void cmd_app_draw_panel_info_at(CmdApp *app, const CmdPanel *panel, int x, int y, int w) +{ + char line[CMD_DISPLAY_COLS + 1]; + cmd_rect_t rect; + cmd_display_attr_t attr; + int text_w; + + if (!app || !panel) return; + + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = 1; + attr = cmd_app_normal_attr(); + text_w = w; + if (text_w < 0) text_w = 0; + + cmd_app_make_panel_info_line(line, sizeof(line), panel, text_w); + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_write_text(&app->buffer, x, y, line, attr); +} + +void cmd_app_make_panel_free_line(char *out, size_t out_size, CmdApp *app, const CmdPanel *panel, int width) +{ + char size_text[32]; + size_t line_w; + esp_err_t err; + + if (!out || out_size == 0) return; + + cmd_app_text_clear(out, out_size); + if (!app || !panel || width <= 0) return; + + line_w = (size_t)width; + if (line_w >= out_size) line_w = out_size - 1; + if (line_w == 0) return; + + memset(out, ' ', line_w); + out[line_w] = 0; + + err = panel->space_info_valid ? panel->space_info_error : ESP_ERR_INVALID_STATE; + if (err == ESP_OK) + { + cmd_app_format_bytes(size_text, sizeof(size_text), panel->space_info.free_bytes); + snprintf(out, line_w + 1, "Free: %s", size_text); + return; + } + + snprintf(out, line_w + 1, "Free: n/a (%s)", cmd_err_name(err)); +} + +void cmd_app_draw_panel_free_at(CmdApp *app, const CmdPanel *panel, int x, int y, int w) +{ + char line[CMD_DISPLAY_COLS + 1]; + cmd_rect_t rect; + cmd_display_attr_t attr; + int text_w; + + if (!app || !panel) return; + + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = 1; + attr = cmd_app_normal_attr(); + text_w = w; + if (text_w < 0) text_w = 0; + + cmd_app_make_panel_free_line(line, sizeof(line), app, panel, text_w); + cmd_display_buffer_fill_rect(&app->buffer, &rect, ' ', attr); + cmd_display_buffer_write_text(&app->buffer, x, y, line, attr); +} + +void cmd_app_draw_panel_info(CmdApp *app) +{ + cmd_rect_t left_rect; + cmd_rect_t right_rect; + int info_y; + int free_y; + int bottom_y; + + if (!app) return; + + cmd_app_make_panel_rects(app, &left_rect, &right_rect); + info_y = cmd_app_panel_info_y(app); + free_y = info_y + 1; + bottom_y = cmd_app_bottom_y(app); + if (free_y > bottom_y) free_y = bottom_y; + + cmd_app_draw_panel_free_at(app, &app->left_panel, left_rect.x, info_y, left_rect.w); + cmd_app_draw_panel_free_at(app, &app->right_panel, right_rect.x, info_y, right_rect.w); + cmd_app_draw_panel_info_at(app, &app->left_panel, left_rect.x, free_y, left_rect.w); + cmd_app_draw_panel_info_at(app, &app->right_panel, right_rect.x, free_y, right_rect.w); +} + +esp_err_t cmd_app_render(CmdApp *app) +{ + cmd_rect_t left_rect; + cmd_rect_t right_rect; + uint32_t console_flags; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + cmd_app_make_panel_rects(app, &left_rect, &right_rect); + + cmd_display_buffer_clear(&app->buffer, ' ', cmd_app_normal_attr()); + + err = cmd_panel_draw(&app->left_panel, &app->buffer, &left_rect); + if (err != ESP_OK) return err; + + err = cmd_panel_draw(&app->right_panel, &app->buffer, &right_rect); + if (err != ESP_OK) return err; + + cmd_app_draw_panel_info(app); + cmd_app_draw_device_dialog(app); + cmd_app_draw_help_dialog(app); + cmd_app_draw_mkdir_dialog(app); + cmd_app_draw_confirm_dialog(app); + cmd_app_draw_progress_dialog(app); + cmd_app_draw_text_viewer(app); + cmd_app_draw_hex_viewer(app); + cmd_app_draw_module_info_viewer(app); + cmd_app_draw_error_dialog(app); + + console_flags = cmd_display_console_backend.flags; + if (app->viewer_open || app->hex_viewer_open || app->module_info_open) + cmd_display_console_backend.flags = console_flags | CMD_DISPLAY_BACKEND_FLAG_FORCE_PARTIAL; + + err = cmd_display_mux_present(&app->mux, &app->buffer); + cmd_display_console_backend.flags = console_flags; + return err; +} + +esp_err_t cmd_app_render_console(CmdApp *app) +{ + cmd_rect_t left_rect; + cmd_rect_t right_rect; + uint32_t console_flags; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + if (!cmd_app_has_console_backend(app)) return ESP_OK; + + cmd_app_make_panel_rects(app, &left_rect, &right_rect); + + cmd_display_buffer_clear(&app->buffer, ' ', cmd_app_normal_attr()); + + err = cmd_panel_draw(&app->left_panel, &app->buffer, &left_rect); + if (err != ESP_OK) return err; + + err = cmd_panel_draw(&app->right_panel, &app->buffer, &right_rect); + if (err != ESP_OK) return err; + + cmd_app_draw_panel_info(app); + cmd_app_draw_device_dialog(app); + cmd_app_draw_help_dialog(app); + cmd_app_draw_mkdir_dialog(app); + cmd_app_draw_confirm_dialog(app); + cmd_app_draw_progress_dialog(app); + cmd_app_draw_text_viewer(app); + cmd_app_draw_hex_viewer(app); + cmd_app_draw_module_info_viewer(app); + cmd_app_draw_error_dialog(app); + + console_flags = cmd_display_console_backend.flags; + if (app->viewer_open || app->hex_viewer_open || app->module_info_open) + cmd_display_console_backend.flags = console_flags | CMD_DISPLAY_BACKEND_FLAG_FORCE_PARTIAL; + + err = cmd_display_backend_present(&cmd_display_console_backend, &app->buffer); + cmd_display_console_backend.flags = console_flags; + return err; +} + +esp_err_t cmd_app_enter_selected(CmdApp *app) +{ + CmdPanel *panel; + const cmd_file_entry_t *entry; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + panel = cmd_app_active_panel(app); + if (!panel) return ESP_ERR_INVALID_STATE; + + entry = cmd_panel_get_selected_entry(panel); + if (!entry) + { + cmd_app_set_status(app, "no selected entry"); + return ESP_OK; + } + + if (entry->type == CMD_ENTRY_DIR || entry->type == CMD_ENTRY_PARENT) + { + err = cmd_panel_enter_selected_dir(panel); + if (err != ESP_OK) cmd_app_set_status_err(app, "enter", err); + else cmd_app_set_status(app, "ready"); + return ESP_OK; + } + + if (entry->type == CMD_ENTRY_FILE) + { + if (cmd_app_entry_is_xm(entry)) return cmd_app_play_xm_file(app, panel, entry); + if (cmd_app_entry_is_wav(entry)) return cmd_app_play_wav_file(app, panel, entry); + if (cmd_app_entry_is_ft_image(entry)) return cmd_app_open_jpg_viewer(app, panel, entry); + cmd_app_set_status(app, "open: unsupported file type"); + return ESP_OK; + } + + cmd_app_set_status(app, "unknown entry type"); + return ESP_OK; +} + +esp_err_t cmd_app_go_parent(CmdApp *app) +{ + CmdPanel *panel; + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + panel = cmd_app_active_panel(app); + if (!panel) return ESP_ERR_INVALID_STATE; + + err = cmd_panel_go_parent(panel); + if (err != ESP_OK) cmd_app_set_status_err(app, "parent", err); + else cmd_app_set_status(app, "ready"); + + return ESP_OK; +} + +bool cmd_app_event_is_exit(const cmd_event_t *event) +{ + if (!event) return false; + if (event->type == CMD_EVENT_QUIT) return true; + if (event->type != CMD_EVENT_KEY) return false; + if (event->key == CMD_KEY_F10) return true; + return false; +} + +esp_err_t cmd_app_handle_key(CmdApp *app, const cmd_event_t *event) +{ + CmdPanel *panel; + + if (!app || !event) return ESP_ERR_INVALID_ARG; + + if (app->error_dialog_open) + return cmd_app_handle_error_dialog_key(app, event); + + if (app->help_dialog_open) + return cmd_app_handle_help_dialog_key(app, event); + + if (app->mkdir_dialog_open) + return cmd_app_handle_mkdir_dialog_key(app, event); + + if (app->jpg_viewer_open) + return cmd_app_handle_jpg_viewer_key(app, event); + + if (app->hex_viewer_open) + return cmd_app_handle_hex_viewer_key(app, event); + + if (app->module_info_open) + return cmd_app_handle_module_info_viewer_key(app, event); + + if (app->viewer_open) + return cmd_app_handle_text_viewer_key(app, event); + + if (app->fileop_confirm_open) + return cmd_app_handle_fileop_confirm_key(app, event); + + if (app->device_dialog_open) + return cmd_app_handle_device_dialog_key(app, event); + + if ((event->mods & CMD_KEY_MOD_ALT) && event->key == CMD_KEY_F1) + { + cmd_app_open_device_dialog(app, CMD_PANEL_LEFT); + return ESP_OK; + } + + if (event->key == CMD_KEY_F1) + { + cmd_app_open_help_dialog(app); + return ESP_OK; + } + + if ((event->mods & CMD_KEY_MOD_ALT) && event->key == CMD_KEY_F2) + { + cmd_app_open_device_dialog(app, CMD_PANEL_RIGHT); + return ESP_OK; + } + + if ((event->mods & CMD_KEY_MOD_ALT) && event->key == CMD_KEY_F9) + return cmd_app_stop_xm_playback(app); + + if (event->key == CMD_KEY_F9) + { + cmd_app_open_device_dialog(app, app->active_panel); + return ESP_OK; + } + + if (event->key == CMD_KEY_CHAR && event->ch == '1') + { + cmd_app_open_device_dialog(app, app->active_panel); + return ESP_OK; + } + + panel = cmd_app_active_panel(app); + if (!panel) return ESP_ERR_INVALID_STATE; + + switch (event->key) + { + case CMD_KEY_INSERT: + cmd_panel_toggle_selection(panel); + if (cmd_panel_has_selection(panel)) + cmd_set_status(app, "%u selected, %llu bytes", + (unsigned)panel->selected_count, + (unsigned long long)panel->selected_size); + else + cmd_app_set_status(app, "selection cleared"); + return ESP_OK; + + case CMD_KEY_CHAR: + if (event->ch != '*') return ESP_OK; + cmd_panel_invert_selection(panel); + if (cmd_panel_has_selection(panel)) + cmd_set_status(app, "%u selected, %llu bytes", + (unsigned)panel->selected_count, + (unsigned long long)panel->selected_size); + else + cmd_app_set_status(app, "selection cleared"); + return ESP_OK; + + case CMD_KEY_F2: + return cmd_app_open_rename_dialog(app); + + case CMD_KEY_F3: + { + const cmd_file_entry_t *entry = cmd_panel_get_selected_entry(panel); + + if (event->mods & CMD_KEY_MOD_ALT) + return cmd_app_open_hex_viewer(app, panel, entry); + if (cmd_app_entry_is_module_info(entry)) + return cmd_app_open_module_info_viewer(app, panel, entry); + return cmd_app_open_text_viewer(app, panel, entry); + } + + case CMD_KEY_F5: + return cmd_app_open_fileop_confirm(app, CMD_APP_FILEOP_COPY); + + case CMD_KEY_F6: + return cmd_app_open_fileop_confirm(app, CMD_APP_FILEOP_MOVE); + + case CMD_KEY_F7: + return cmd_app_open_mkdir_dialog(app); + + case CMD_KEY_F8: + case CMD_KEY_DELETE: + return cmd_app_open_fileop_confirm(app, CMD_APP_FILEOP_DELETE); + + case CMD_KEY_TAB: + cmd_app_switch_panel(app); + return ESP_OK; + + case CMD_KEY_UP: + cmd_panel_cursor_up(panel); + return ESP_OK; + + case CMD_KEY_DOWN: + cmd_panel_cursor_down(panel); + return ESP_OK; + + case CMD_KEY_PAGE_UP: + case CMD_KEY_LEFT: + cmd_panel_cursor_page_up(panel); + return ESP_OK; + + case CMD_KEY_PAGE_DOWN: + case CMD_KEY_RIGHT: + cmd_panel_cursor_page_down(panel); + return ESP_OK; + + case CMD_KEY_HOME: + cmd_panel_cursor_home(panel); + return ESP_OK; + + case CMD_KEY_END: + cmd_panel_cursor_end(panel); + return ESP_OK; + + case CMD_KEY_ENTER: + return cmd_app_enter_selected(app); + + case CMD_KEY_BACKSPACE: + return cmd_app_go_parent(app); + + default: + return ESP_OK; + } +} + +esp_err_t cmd_app_handle_event(CmdApp *app, const cmd_event_t *event) +{ + if (!app || !event) return ESP_ERR_INVALID_ARG; + if (event->type != CMD_EVENT_KEY) return ESP_OK; + + return cmd_app_handle_key(app, event); +} + + +bool cmd_app_parse_baud_arg(const char *text, uint32_t *baud) +{ + char *end = NULL; + unsigned long value; + + if (!text || !text[0] || !baud) return false; + + errno = 0; + value = strtoul(text, &end, 10); + if (errno != 0 || !end || *end || value == 0 || value > 0xffffffffUL) return false; + + *baud = (uint32_t)value; + return true; +} + +bool cmd_app_parse_launch_args(int argc, char **argv, CmdDisplayMode *display_mode, uint32_t *baud) +{ + int arg = 1; + + if (!display_mode || !baud) return false; + + *display_mode = CMD_DISPLAY_MODE_CONSOLE; + *baud = 0; + + if (argc < 0 || !argv) return false; + + if (arg < argc && cmd_display_mode_parse(argv[arg], display_mode)) + arg++; + + if (arg < argc && cmd_app_parse_baud_arg(argv[arg], baud)) + arg++; + + return arg == argc; +} + +void cmd_app_print_usage() +{ + printf("usage: cmd [console|ft|ft812|mirror] [baud]\r\n"); + printf(" cmd [baud]\r\n"); +} + +esp_err_t cmd_app_uart_wait_tx_done() +{ + return uart_wait_tx_done( + (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, + pdMS_TO_TICKS(1000)); +} + +void cmd_app_uart_send_baud_msg(const char *name, uint32_t baud, uint32_t nonce) +{ + printf("\x1b]777;ZIFI32;%s;%lu;%08lX\x1b\\", + name, + (unsigned long)baud, + (unsigned long)nonce); + fflush(stdout); +} + +size_t cmd_app_match_seq(size_t pos, const char *seq, size_t seq_len, uint8_t c) +{ + if (!seq || seq_len == 0) return 0; + + if (c == (uint8_t)seq[pos]) + { + pos++; + if (pos >= seq_len) return seq_len; + return pos; + } + + if (c == (uint8_t)seq[0]) return 1; + return 0; +} + +bool cmd_app_uart_wait_baud_msg(const char *name, uint32_t baud, uint32_t nonce, uint32_t timeout_ms) +{ + char expected_st[CMD_APP_BAUD_SEQ_MAX]; + char expected_bel[CMD_APP_BAUD_SEQ_MAX]; + size_t expected_st_len; + size_t expected_bel_len; + size_t match_st = 0; + size_t match_bel = 0; + TickType_t deadline; + + if (!name) return false; + + snprintf(expected_st, sizeof(expected_st), "\x1b]777;ZIFI32;%s;%lu;%08lX\x1b\\", + name, + (unsigned long)baud, + (unsigned long)nonce); + snprintf(expected_bel, sizeof(expected_bel), "\x1b]777;ZIFI32;%s;%lu;%08lX\a", + name, + (unsigned long)baud, + (unsigned long)nonce); + + expected_st_len = strlen(expected_st); + expected_bel_len = strlen(expected_bel); + deadline = xTaskGetTickCount() + pdMS_TO_TICKS(timeout_ms); + + while ((int32_t)(deadline - xTaskGetTickCount()) > 0) + { + uint8_t c = 0; + int got = uart_read_bytes( + (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, + &c, + 1, + pdMS_TO_TICKS(10)); + + if (got <= 0) continue; + + match_st = cmd_app_match_seq(match_st, expected_st, expected_st_len, c); + match_bel = cmd_app_match_seq(match_bel, expected_bel, expected_bel_len, c); + + if (match_st == expected_st_len || match_bel == expected_bel_len) return true; + } + + return false; +} + +uint32_t cmd_app_uart_canonical_baud(uint32_t baud) +{ + const uint32_t known[] = + { + 115200, + 230400, + 460800, + 921600, + 1000000, + 1500000, + 2000000 + }; + + for (size_t i = 0; i < sizeof(known) / sizeof(known[0]); i++) + { + uint32_t ref = known[i]; + uint32_t diff = baud > ref ? baud - ref : ref - baud; + uint32_t limit = ref / 1000; + + if (limit < 16) limit = 16; + if (diff <= limit) return ref; + } + + return baud; +} + +bool cmd_app_uart_restore_needed(uint32_t requested_baud, esp_err_t baud_err) +{ + if (requested_baud == 0) return false; + if (baud_err != ESP_OK) return false; + return cmd_app_uart_canonical_baud(requested_baud) != CMD_APP_BAUD_DEFAULT; +} + +esp_err_t cmd_app_uart_switch_baud(uint32_t baud, uint32_t *old_baud, bool *switched) +{ + uart_port_t uart_num = (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM; + uint32_t current_baud = 0; + uint32_t nonce; + esp_err_t err; + + if (old_baud) *old_baud = 0; + if (switched) *switched = false; + if (baud == 0) return ESP_ERR_INVALID_ARG; + + err = uart_get_baudrate(uart_num, ¤t_baud); + if (err != ESP_OK) return err; + + current_baud = cmd_app_uart_canonical_baud(current_baud); + baud = cmd_app_uart_canonical_baud(baud); + + if (old_baud) *old_baud = current_baud; + if (current_baud == baud) return ESP_OK; + + uart_flush_input(uart_num); + + nonce = ((uint32_t)xTaskGetTickCount() << 16) ^ baud ^ current_baud; + cmd_app_uart_send_baud_msg("BAUD-REQ", baud, nonce); + err = cmd_app_uart_wait_tx_done(); + if (err != ESP_OK) return err; + + if (!cmd_app_uart_wait_baud_msg("BAUD-ACK", baud, nonce, 300)) + return ESP_ERR_TIMEOUT; + + cmd_app_uart_send_baud_msg("BAUD-GO", baud, nonce); + err = cmd_app_uart_wait_tx_done(); + if (err != ESP_OK) return err; + + vTaskDelay(pdMS_TO_TICKS(CMD_APP_BAUD_SWITCH_DELAY_MS)); + + err = uart_set_baudrate(uart_num, baud); + if (err != ESP_OK) return err; + + vTaskDelay(pdMS_TO_TICKS(CMD_APP_BAUD_SWITCH_DELAY_MS)); + + if (!cmd_app_uart_wait_baud_msg("BAUD-RDY", baud, nonce, 1000)) + { + uart_set_baudrate(uart_num, current_baud); + vTaskDelay(pdMS_TO_TICKS(CMD_APP_BAUD_SWITCH_DELAY_MS)); + return ESP_ERR_TIMEOUT; + } + + cmd_app_uart_send_baud_msg("BAUD-OK", baud, nonce); + err = cmd_app_uart_wait_tx_done(); + if (err != ESP_OK) return err; + + if (!cmd_app_uart_wait_baud_msg("BAUD-DONE", baud, nonce, 500)) + { + uart_set_baudrate(uart_num, current_baud); + vTaskDelay(pdMS_TO_TICKS(CMD_APP_BAUD_SWITCH_DELAY_MS)); + return ESP_ERR_TIMEOUT; + } + + if (switched) *switched = true; + return ESP_OK; +} + +void cmd_app_mount_internal_fs_early(CmdApp *app) +{ + if (!app) return; + + cmd_fs_manager_mount(&app->fs, CMD_DEVICE_FAT); + cmd_fs_manager_mount(&app->fs, CMD_DEVICE_TSF); +} + +esp_err_t cmd_app_init_runtime(CmdApp *app, CmdDisplayMode display_mode) +{ + esp_err_t err; + + if (!app) return ESP_ERR_INVALID_ARG; + + memset(app, 0, sizeof(*app)); + app->sfx_preview_handle = -1; + app->sfx_preview_channel = -1; + + cmd_display_buffer_init(&app->buffer); + cmd_display_mux_init(&app->mux); + cmd_fs_manager_init(&app->fs); + + err = cmd_fs_manager_register_default_drivers(&app->fs); + if (err != ESP_OK) return err; + + cmd_app_mount_internal_fs_early(app); + + err = cmd_panel_alloc_global_buffers(); + if (err != ESP_OK) return err; + + err = cmd_fileops_alloc_global_buffers(); + if (err != ESP_OK) return err; + + err = cmd_display_mux_add_mode(&app->mux, display_mode); + if (err != ESP_OK) return err; + + err = cmd_display_mux_init_backends(&app->mux); + if (err != ESP_OK) return err; + + cmd_size_t display_size; + err = cmd_display_mux_get_size(&app->mux, &display_size); + if (err != ESP_OK) return err; + + err = cmd_display_buffer_set_size(&app->buffer, display_size.w, display_size.h); + if (err != ESP_OK) return err; + + app->input = cmd_input_default_backend(); + err = cmd_input_begin(app->input); + if (err != ESP_OK) return err; + + cmd_set_status(app, "ready display=%s %dx%d", cmd_display_mode_name(display_mode), app->buffer.size.w, app->buffer.size.h); + return cmd_app_init_panels(app); +} + +void cmd_app_shutdown_runtime(CmdApp *app) +{ + if (!app) return; + + cmd_app_delete_sfx_preview(app); + cmd_app_close_module_info_viewer(app); + cmd_input_end(app->input); + cmd_display_mux_deinit_backends(&app->mux); + cmd_fs_manager_unmount_all(&app->fs); + cmd_panel_free_entries(&app->left_panel); + cmd_panel_free_entries(&app->right_panel); + cmd_fileops_free_global_buffers(); + cmd_panel_free_global_buffers(); + printf("\x1b[0m\x1b[?25h\x1b[2J\x1b[H"); + fflush(stdout); +} + +int cmd_cmd(int argc, char **argv) +{ + CmdApp *app; + CmdDisplayMode display_mode; + uint32_t requested_baud = 0; + uint32_t old_baud = 0; + bool baud_switched = false; + bool baud_restore_needed = false; + esp_err_t baud_err = ESP_OK; + esp_err_t err; + + if (argc < 0 || !argv) return 1; + if (g_cmd_app) return 1; + + if (!cmd_app_parse_launch_args(argc, argv, &display_mode, &requested_baud)) + { + cmd_app_print_usage(); + return 1; + } + + if (requested_baud > 0) + { + baud_err = cmd_app_uart_switch_baud(requested_baud, &old_baud, &baud_switched); + baud_restore_needed = cmd_app_uart_restore_needed(requested_baud, baud_err); + if (baud_err != ESP_OK && baud_err != ESP_ERR_TIMEOUT) + printf("W: cmd baud switch failed: %s\r\n", cmd_err_name(baud_err)); + } + + app = cmd_app_alloc(); + if (!app) + { + if (baud_restore_needed) cmd_app_uart_switch_baud(CMD_APP_BAUD_DEFAULT, NULL, NULL); + printf("E: cmd alloc failed: ESP_ERR_NO_MEM\r\n"); + return 1; + } + + g_cmd_app = app; + + err = cmd_app_init_runtime(app, display_mode); + if (err != ESP_OK) + { + if (baud_restore_needed) cmd_app_uart_switch_baud(CMD_APP_BAUD_DEFAULT, NULL, NULL); + printf("E: cmd init failed: %s\r\n", cmd_err_name(err)); + cmd_app_shutdown_runtime(app); + cmd_app_free(app); + g_cmd_app = NULL; + return 1; + } + + printf("\x1b[?25l"); + cmd_app_render(app); + + while (true) + { + cmd_event_t event; + uint32_t input_timeout_ms = app->help_dialog_open ? CMD_APP_HELP_DIALOG_REFRESH_MS : CMD_INPUT_WAIT_FOREVER; + + err = cmd_input_poll_event(app->input, &event, input_timeout_ms); + if (err == ESP_ERR_TIMEOUT) + { + if (app->help_dialog_open) + cmd_app_render(app); + continue; + } + if (err != ESP_OK) continue; + + if (!cmd_app_has_modal(app) && cmd_app_event_is_exit(&event)) break; + + err = cmd_app_handle_event(app, &event); + if (err != ESP_OK) cmd_show_error(app, "event", err); + + if (!app->jpg_viewer_open) + cmd_app_render(app); + } + + if (baud_restore_needed) cmd_app_uart_switch_baud(CMD_APP_BAUD_DEFAULT, NULL, NULL); + + cmd_app_shutdown_runtime(app); + cmd_app_free(app); + g_cmd_app = NULL; + return 0; +} + +void cmd_console_register_system_commands() +{ + const esp_console_cmd_t cmd = + { + .command = "cmd", + .help = "Two-panel file commander", + .hint = NULL, + .func = &cmd_cmd, + .argtable = NULL + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} + +// --------------- cmd_display.cpp --------------- + +#ifndef CONFIG_ESP_CONSOLE_UART_NUM +#define CONFIG_ESP_CONSOLE_UART_NUM UART_NUM_0 +#endif + +#define CMD_DISPLAY_TERMINAL_QUERY_TIMEOUT_MS 250 + +CmdDisplayBackend cmd_display_console_backend = +{ + .name = "console", + .ctx = NULL, + .flags = 0, + .init = cmd_display_console_init, + .deinit = cmd_display_console_deinit, + .clear = cmd_display_console_clear, + .present = cmd_display_console_present, + .put_char = cmd_display_console_put_char, + .write_text = cmd_display_console_write_text, + .get_size = cmd_display_console_get_size +}; + +CmdDisplayBackend cmd_display_ft812_backend = +{ + .name = "ft812", + .ctx = NULL, + .flags = 0, + .init = cmd_display_ft812_begin, + .deinit = cmd_display_ft812_end, + .clear = cmd_display_ft812_clear, + .present = cmd_display_ft812_present, + .put_char = cmd_display_ft812_put_char, + .write_text = cmd_display_ft812_write_text, + .get_size = cmd_display_ft812_get_size +}; + +typedef struct +{ + CmdDisplayBuffer prev; + bool prev_valid; +} CmdDisplayConsoleContext; + +typedef struct +{ + cmd_display_attr_t attr; + int x; + int y; + int width; + bool attr_valid; + bool pos_valid; +} CmdDisplayConsoleEmitState; + +typedef struct +{ + uint8_t chars[CMD_DISPLAY_CELL_COUNT]; + uint8_t attrs[CMD_DISPLAY_CELL_COUNT]; + bool active; +} CmdDisplayFt812Context; + +EXT_RAM_BSS_ATTR CmdDisplayConsoleContext cmd_display_console_ctx; +EXT_RAM_BSS_ATTR CmdDisplayFt812Context cmd_display_ft812_ctx; + +cmd_display_attr_t cmd_display_make_attr(cmd_display_color_t fg, cmd_display_color_t bg, uint8_t flags) +{ + return (cmd_display_attr_t)(((uint16_t)fg & 0x0f) | + (((uint16_t)bg & 0x0f) << CMD_DISPLAY_ATTR_BG_SHIFT) | + ((uint16_t)flags << CMD_DISPLAY_ATTR_FLAGS_SHIFT)); +} + +cmd_display_color_t cmd_display_attr_fg(cmd_display_attr_t attr) +{ + return (cmd_display_color_t)(attr & CMD_DISPLAY_ATTR_FG_MASK); +} + +cmd_display_color_t cmd_display_attr_bg(cmd_display_attr_t attr) +{ + return (cmd_display_color_t)((attr & CMD_DISPLAY_ATTR_BG_MASK) >> CMD_DISPLAY_ATTR_BG_SHIFT); +} + +uint8_t cmd_display_attr_flags(cmd_display_attr_t attr) +{ + return (uint8_t)((attr & CMD_DISPLAY_ATTR_FLAGS_MASK) >> CMD_DISPLAY_ATTR_FLAGS_SHIFT); +} + +const char *cmd_display_mode_name(CmdDisplayMode mode) +{ + switch (mode) + { + case CMD_DISPLAY_MODE_CONSOLE: return "console"; + case CMD_DISPLAY_MODE_FT812: return "ft812"; + case CMD_DISPLAY_MODE_MIRROR: return "mirror"; + default: return "?"; + } +} + +bool cmd_display_mode_parse(const char *text, CmdDisplayMode *mode) +{ + if (!mode) return false; + + if (!text || !text[0] || !strcmp(text, "console")) + { + *mode = CMD_DISPLAY_MODE_CONSOLE; + return true; + } + + if (!strcmp(text, "ft") || !strcmp(text, "ft812")) + { + *mode = CMD_DISPLAY_MODE_FT812; + return true; + } + + if (!strcmp(text, "mirror") || !strcmp(text, "both")) + { + *mode = CMD_DISPLAY_MODE_MIRROR; + return true; + } + + return false; +} + +bool cmd_display_mode_has_console(CmdDisplayMode mode) +{ + return mode == CMD_DISPLAY_MODE_CONSOLE || mode == CMD_DISPLAY_MODE_MIRROR; +} + +bool cmd_display_mode_has_ft812(CmdDisplayMode mode) +{ + return mode == CMD_DISPLAY_MODE_FT812 || mode == CMD_DISPLAY_MODE_MIRROR; +} + +bool cmd_display_point_inside(int x, int y) +{ + if (x < 0 || y < 0) return false; + if (x >= CMD_DISPLAY_COLS || y >= CMD_DISPLAY_ROWS) return false; + return true; +} + +bool cmd_display_buffer_point_inside(const CmdDisplayBuffer *buffer, int x, int y) +{ + if (!buffer) return false; + if (x < 0 || y < 0) return false; + if (x >= buffer->size.w || y >= buffer->size.h) return false; + return true; +} + +esp_err_t cmd_display_buffer_set_size(CmdDisplayBuffer *buffer, int w, int h) +{ + if (!buffer) return ESP_ERR_INVALID_ARG; + + if (w <= 0) w = CMD_DISPLAY_DEFAULT_COLS; + if (h <= 0) h = CMD_DISPLAY_DEFAULT_ROWS; + if (w > CMD_DISPLAY_COLS) w = CMD_DISPLAY_COLS; + if (h > CMD_DISPLAY_ROWS) h = CMD_DISPLAY_ROWS; + + buffer->size.w = w; + buffer->size.h = h; + return ESP_OK; +} + +void cmd_display_buffer_init(CmdDisplayBuffer *buffer) +{ + if (!buffer) return; + + memset(buffer, 0, sizeof(*buffer)); + cmd_display_buffer_set_size(buffer, CMD_DISPLAY_DEFAULT_COLS, CMD_DISPLAY_DEFAULT_ROWS); + cmd_display_buffer_clear(buffer, ' ', CMD_DISPLAY_ATTR_DEFAULT); +} + +void cmd_display_buffer_clear(CmdDisplayBuffer *buffer, char ch, cmd_display_attr_t attr) +{ + if (!buffer) return; + + if (ch == 0) + ch = ' '; + + for (int y = 0; y < buffer->size.h; y++) + { + for (int x = 0; x < buffer->size.w; x++) + { + buffer->cells[y][x].ch = ch; + buffer->cells[y][x].attr = attr; + } + } +} + +CmdDisplayCell *cmd_display_buffer_cell(CmdDisplayBuffer *buffer, int x, int y) +{ + if (!cmd_display_buffer_point_inside(buffer, x, y)) return NULL; + return &buffer->cells[y][x]; +} + +const CmdDisplayCell *cmd_display_buffer_cell_const(const CmdDisplayBuffer *buffer, int x, int y) +{ + if (!cmd_display_buffer_point_inside(buffer, x, y)) return NULL; + return &buffer->cells[y][x]; +} + +esp_err_t cmd_display_buffer_put_char(CmdDisplayBuffer *buffer, int x, int y, char ch, cmd_display_attr_t attr) +{ + CmdDisplayCell *cell; + + if (!buffer) return ESP_ERR_INVALID_ARG; + if (!cmd_display_buffer_point_inside(buffer, x, y)) return ESP_ERR_INVALID_ARG; + + if (ch == 0) + ch = ' '; + + cell = &buffer->cells[y][x]; + cell->ch = ch; + cell->attr = attr; + return ESP_OK; +} + +esp_err_t cmd_display_buffer_write_text(CmdDisplayBuffer *buffer, int x, int y, const char *text, cmd_display_attr_t attr) +{ + int pos = x; + + if (!buffer || !text) return ESP_ERR_INVALID_ARG; + if (y < 0 || y >= buffer->size.h) return ESP_ERR_INVALID_ARG; + if (x >= buffer->size.w) return ESP_OK; + if (pos < 0) pos = 0; + + while (*text && pos < buffer->size.w) + { + esp_err_t err = cmd_display_buffer_put_char(buffer, pos, y, *text, attr); + if (err != ESP_OK) return err; + text++; + pos++; + } + + return ESP_OK; +} + +esp_err_t cmd_display_buffer_fill_rect(CmdDisplayBuffer *buffer, const cmd_rect_t *rect, char ch, cmd_display_attr_t attr) +{ + int x0; + int y0; + int x1; + int y1; + + if (!buffer || !rect) return ESP_ERR_INVALID_ARG; + if (rect->w <= 0 || rect->h <= 0) return ESP_OK; + + x0 = rect->x; + y0 = rect->y; + x1 = rect->x + rect->w; + y1 = rect->y + rect->h; + + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > buffer->size.w) x1 = buffer->size.w; + if (y1 > buffer->size.h) y1 = buffer->size.h; + if (x0 >= x1 || y0 >= y1) return ESP_OK; + + for (int y = y0; y < y1; y++) + { + for (int x = x0; x < x1; x++) + { + esp_err_t err = cmd_display_buffer_put_char(buffer, x, y, ch, attr); + if (err != ESP_OK) return err; + } + } + + return ESP_OK; +} + +esp_err_t cmd_display_buffer_draw_hline(CmdDisplayBuffer *buffer, int x, int y, int w, char ch, cmd_display_attr_t attr) +{ + if (!buffer) return ESP_ERR_INVALID_ARG; + if (y < 0 || y >= buffer->size.h) return ESP_ERR_INVALID_ARG; + if (w <= 0) return ESP_OK; + + for (int i = 0; i < w; i++) + { + int px = x + i; + if (px < 0) continue; + if (px >= buffer->size.w) break; + + esp_err_t err = cmd_display_buffer_put_char(buffer, px, y, ch, attr); + if (err != ESP_OK) return err; + } + + return ESP_OK; +} + +esp_err_t cmd_display_buffer_draw_vline(CmdDisplayBuffer *buffer, int x, int y, int h, char ch, cmd_display_attr_t attr) +{ + if (!buffer) return ESP_ERR_INVALID_ARG; + if (x < 0 || x >= buffer->size.w) return ESP_ERR_INVALID_ARG; + if (h <= 0) return ESP_OK; + + for (int i = 0; i < h; i++) + { + int py = y + i; + if (py < 0) continue; + if (py >= buffer->size.h) break; + + esp_err_t err = cmd_display_buffer_put_char(buffer, x, py, ch, attr); + if (err != ESP_OK) return err; + } + + return ESP_OK; +} + +esp_err_t cmd_display_buffer_draw_box(CmdDisplayBuffer *buffer, const cmd_rect_t *rect, cmd_display_attr_t attr) +{ + esp_err_t err; + + if (!buffer || !rect) return ESP_ERR_INVALID_ARG; + if (rect->w <= 0 || rect->h <= 0) return ESP_OK; + + if (rect->w == 1 && rect->h == 1) + return cmd_display_buffer_put_char(buffer, rect->x, rect->y, CMD_DISPLAY_BOX_TL, attr); + + err = cmd_display_buffer_draw_hline(buffer, rect->x, rect->y, rect->w, CMD_DISPLAY_BOX_H, attr); + if (err != ESP_OK) return err; + + err = cmd_display_buffer_draw_hline(buffer, rect->x, rect->y + rect->h - 1, rect->w, CMD_DISPLAY_BOX_H, attr); + if (err != ESP_OK) return err; + + err = cmd_display_buffer_draw_vline(buffer, rect->x, rect->y, rect->h, CMD_DISPLAY_BOX_V, attr); + if (err != ESP_OK) return err; + + err = cmd_display_buffer_draw_vline(buffer, rect->x + rect->w - 1, rect->y, rect->h, CMD_DISPLAY_BOX_V, attr); + if (err != ESP_OK) return err; + + cmd_display_buffer_put_char(buffer, rect->x, rect->y, CMD_DISPLAY_BOX_TL, attr); + cmd_display_buffer_put_char(buffer, rect->x + rect->w - 1, rect->y, CMD_DISPLAY_BOX_TR, attr); + cmd_display_buffer_put_char(buffer, rect->x, rect->y + rect->h - 1, CMD_DISPLAY_BOX_BL, attr); + cmd_display_buffer_put_char(buffer, rect->x + rect->w - 1, rect->y + rect->h - 1, CMD_DISPLAY_BOX_BR, attr); + + return ESP_OK; +} + +esp_err_t cmd_display_backend_init(CmdDisplayBackend *backend) +{ + if (!backend) return ESP_ERR_INVALID_ARG; + if (!backend->init) return ESP_OK; + return backend->init(backend); +} + +void cmd_display_backend_deinit(CmdDisplayBackend *backend) +{ + if (!backend || !backend->deinit) return; + backend->deinit(backend); +} + +esp_err_t cmd_display_backend_clear(CmdDisplayBackend *backend) +{ + if (!backend) return ESP_ERR_INVALID_ARG; + if (!backend->clear) return ESP_ERR_NOT_SUPPORTED; + return backend->clear(backend); +} + +esp_err_t cmd_display_backend_present(CmdDisplayBackend *backend, const CmdDisplayBuffer *buffer) +{ + if (!backend || !buffer) return ESP_ERR_INVALID_ARG; + if (!backend->present) return ESP_ERR_NOT_SUPPORTED; + return backend->present(backend, buffer); +} + +esp_err_t cmd_display_backend_put_char(CmdDisplayBackend *backend, int x, int y, char ch, cmd_display_attr_t attr) +{ + if (!backend) return ESP_ERR_INVALID_ARG; + if (!backend->put_char) return ESP_ERR_NOT_SUPPORTED; + return backend->put_char(backend, x, y, ch, attr); +} + +esp_err_t cmd_display_backend_write_text(CmdDisplayBackend *backend, int x, int y, const char *text, cmd_display_attr_t attr) +{ + if (!backend || !text) return ESP_ERR_INVALID_ARG; + if (!backend->write_text) return ESP_ERR_NOT_SUPPORTED; + return backend->write_text(backend, x, y, text, attr); +} + +esp_err_t cmd_display_backend_get_size(CmdDisplayBackend *backend, cmd_size_t *size) +{ + if (!backend || !size) return ESP_ERR_INVALID_ARG; + + size->w = CMD_DISPLAY_DEFAULT_COLS; + size->h = CMD_DISPLAY_DEFAULT_ROWS; + + if (!backend->get_size) return ESP_OK; + return backend->get_size(backend, size); +} + +void cmd_display_mux_init(CmdDisplayMux *mux) +{ + if (!mux) return; + memset(mux, 0, sizeof(*mux)); +} + +esp_err_t cmd_display_mux_add_backend(CmdDisplayMux *mux, CmdDisplayBackend *backend) +{ + if (!mux || !backend) return ESP_ERR_INVALID_ARG; + if (mux->count >= CMD_DISPLAY_MUX_MAX_BACKENDS) return ESP_ERR_INVALID_SIZE; + + for (size_t i = 0; i < mux->count; i++) + { + if (mux->backends[i] == backend) return ESP_OK; + } + + mux->backends[mux->count] = backend; + mux->count++; + return ESP_OK; +} + +esp_err_t cmd_display_mux_add_mode(CmdDisplayMux *mux, CmdDisplayMode mode) +{ + esp_err_t err; + + if (!mux) return ESP_ERR_INVALID_ARG; + + if (mode == CMD_DISPLAY_MODE_FT812 || mode == CMD_DISPLAY_MODE_MIRROR) + { + err = cmd_display_mux_add_backend(mux, &cmd_display_ft812_backend); + if (err != ESP_OK) return err; + } + + if (mode == CMD_DISPLAY_MODE_CONSOLE || mode == CMD_DISPLAY_MODE_MIRROR) + { + err = cmd_display_mux_add_backend(mux, &cmd_display_console_backend); + if (err != ESP_OK) return err; + } + + if (mux->count == 0) return ESP_ERR_INVALID_ARG; + return ESP_OK; +} + +esp_err_t cmd_display_mux_remove_backend(CmdDisplayMux *mux, CmdDisplayBackend *backend) +{ + if (!mux || !backend) return ESP_ERR_INVALID_ARG; + + for (size_t i = 0; i < mux->count; i++) + { + if (mux->backends[i] != backend) + continue; + + for (size_t j = i; j + 1 < mux->count; j++) + mux->backends[j] = mux->backends[j + 1]; + + mux->count--; + mux->backends[mux->count] = NULL; + return ESP_OK; + } + + return ESP_ERR_NOT_FOUND; +} + +esp_err_t cmd_display_mux_init_backends(CmdDisplayMux *mux) +{ + if (!mux) return ESP_ERR_INVALID_ARG; + + for (size_t i = 0; i < mux->count; i++) + { + esp_err_t err = cmd_display_backend_init(mux->backends[i]); + if (err != ESP_OK) return err; + } + + return ESP_OK; +} + +esp_err_t cmd_display_mux_get_size(CmdDisplayMux *mux, cmd_size_t *size) +{ + bool have = false; + + if (!mux || !size) return ESP_ERR_INVALID_ARG; + + size->w = CMD_DISPLAY_DEFAULT_COLS; + size->h = CMD_DISPLAY_DEFAULT_ROWS; + + for (size_t i = 0; i < mux->count; i++) + { + cmd_size_t backend_size; + esp_err_t err = cmd_display_backend_get_size(mux->backends[i], &backend_size); + + if (err != ESP_OK) continue; + if (backend_size.w <= 0 || backend_size.h <= 0) continue; + + if (backend_size.w > CMD_DISPLAY_COLS) backend_size.w = CMD_DISPLAY_COLS; + if (backend_size.h > CMD_DISPLAY_ROWS) backend_size.h = CMD_DISPLAY_ROWS; + + if (!have) + { + *size = backend_size; + have = true; + } + else + { + if (backend_size.w < size->w) size->w = backend_size.w; + if (backend_size.h < size->h) size->h = backend_size.h; + } + } + + return ESP_OK; +} + +void cmd_display_mux_deinit_backends(CmdDisplayMux *mux) +{ + if (!mux) return; + + for (size_t i = 0; i < mux->count; i++) + cmd_display_backend_deinit(mux->backends[i]); +} + +esp_err_t cmd_display_mux_clear(CmdDisplayMux *mux) +{ + esp_err_t first_err = ESP_OK; + + if (!mux) return ESP_ERR_INVALID_ARG; + + for (size_t i = 0; i < mux->count; i++) + { + esp_err_t err = cmd_display_backend_clear(mux->backends[i]); + if (first_err == ESP_OK && err != ESP_OK) first_err = err; + } + + return first_err; +} + +esp_err_t cmd_display_mux_present(CmdDisplayMux *mux, const CmdDisplayBuffer *buffer) +{ + esp_err_t first_err = ESP_OK; + + if (!mux || !buffer) return ESP_ERR_INVALID_ARG; + + for (size_t i = 0; i < mux->count; i++) + { + esp_err_t err = cmd_display_backend_present(mux->backends[i], buffer); + if (first_err == ESP_OK && err != ESP_OK) first_err = err; + } + + return first_err; +} + +esp_err_t cmd_display_mux_put_char(CmdDisplayMux *mux, int x, int y, char ch, cmd_display_attr_t attr) +{ + esp_err_t first_err = ESP_OK; + + if (!mux) return ESP_ERR_INVALID_ARG; + + for (size_t i = 0; i < mux->count; i++) + { + esp_err_t err = cmd_display_backend_put_char(mux->backends[i], x, y, ch, attr); + if (first_err == ESP_OK && err != ESP_OK) first_err = err; + } + + return first_err; +} + +esp_err_t cmd_display_mux_write_text(CmdDisplayMux *mux, int x, int y, const char *text, cmd_display_attr_t attr) +{ + esp_err_t first_err = ESP_OK; + + if (!mux || !text) return ESP_ERR_INVALID_ARG; + + for (size_t i = 0; i < mux->count; i++) + { + esp_err_t err = cmd_display_backend_write_text(mux->backends[i], x, y, text, attr); + if (first_err == ESP_OK && err != ESP_OK) first_err = err; + } + + return first_err; +} + +int cmd_display_console_fg_code(cmd_display_color_t color) +{ + switch (color) + { + case CMD_DISPLAY_COLOR_BLACK: return 30; + case CMD_DISPLAY_COLOR_BLUE: return 34; + case CMD_DISPLAY_COLOR_GREEN: return 32; + case CMD_DISPLAY_COLOR_CYAN: return 36; + case CMD_DISPLAY_COLOR_RED: return 31; + case CMD_DISPLAY_COLOR_MAGENTA: return 35; + case CMD_DISPLAY_COLOR_YELLOW: return 33; + case CMD_DISPLAY_COLOR_WHITE: return 37; + case CMD_DISPLAY_COLOR_BRIGHT_BLACK: return 90; + case CMD_DISPLAY_COLOR_BRIGHT_BLUE: return 94; + case CMD_DISPLAY_COLOR_BRIGHT_GREEN: return 92; + case CMD_DISPLAY_COLOR_BRIGHT_CYAN: return 96; + case CMD_DISPLAY_COLOR_BRIGHT_RED: return 91; + case CMD_DISPLAY_COLOR_BRIGHT_MAGENTA: return 95; + case CMD_DISPLAY_COLOR_BRIGHT_YELLOW: return 93; + case CMD_DISPLAY_COLOR_BRIGHT_WHITE: return 97; + default: return 37; + } +} + +int cmd_display_console_bg_code(cmd_display_color_t color) +{ + switch (color) + { + case CMD_DISPLAY_COLOR_BLACK: return 40; + case CMD_DISPLAY_COLOR_BLUE: return 44; + case CMD_DISPLAY_COLOR_GREEN: return 42; + case CMD_DISPLAY_COLOR_CYAN: return 46; + case CMD_DISPLAY_COLOR_RED: return 41; + case CMD_DISPLAY_COLOR_MAGENTA: return 45; + case CMD_DISPLAY_COLOR_YELLOW: return 43; + case CMD_DISPLAY_COLOR_WHITE: return 47; + case CMD_DISPLAY_COLOR_BRIGHT_BLACK: return 100; + case CMD_DISPLAY_COLOR_BRIGHT_BLUE: return 104; + case CMD_DISPLAY_COLOR_BRIGHT_GREEN: return 102; + case CMD_DISPLAY_COLOR_BRIGHT_CYAN: return 106; + case CMD_DISPLAY_COLOR_BRIGHT_RED: return 101; + case CMD_DISPLAY_COLOR_BRIGHT_MAGENTA: return 105; + case CMD_DISPLAY_COLOR_BRIGHT_YELLOW: return 103; + case CMD_DISPLAY_COLOR_BRIGHT_WHITE: return 107; + default: return 40; + } +} + +const char *cmd_display_console_utf8_char(char ch) +{ + switch ((uint8_t)ch) + { + case 0xC9: return "╔"; + case 0xBB: return "╗"; + case 0xC8: return "╚"; + case 0xBC: return "╝"; + case 0xCD: return "═"; + case 0xBA: return "║"; + default: return NULL; + } +} + +void cmd_display_console_emit_char(char ch) +{ + const char *utf8 = cmd_display_console_utf8_char(ch); + + if (utf8) + { + fputs(utf8, stdout); + return; + } + + fputc((unsigned char)(ch ? ch : ' '), stdout); +} + +void cmd_display_console_emit_attr(cmd_display_attr_t attr) +{ + int fg = cmd_display_console_fg_code(cmd_display_attr_fg(attr)); + int bg = cmd_display_console_bg_code(cmd_display_attr_bg(attr)); + uint8_t flags = cmd_display_attr_flags(attr); + + printf("\x1b[0"); + + if (flags & CMD_DISPLAY_ATTR_FLAG_BOLD) + printf(";1"); + + if (flags & CMD_DISPLAY_ATTR_FLAG_UNDERLINE) + printf(";4"); + + if (flags & CMD_DISPLAY_ATTR_FLAG_INVERSE) + printf(";7"); + + printf(";%d;%dm", fg, bg); +} + +bool cmd_display_cell_equal(const CmdDisplayCell *a, const CmdDisplayCell *b) +{ + if (!a || !b) return false; + return a->ch == b->ch && a->attr == b->attr; +} + +size_t cmd_display_console_decimal_len(int value) +{ + size_t len = 1; + + while (value >= 10) + { + value /= 10; + len++; + } + + return len; +} + +size_t cmd_display_console_attr_bytes(cmd_display_attr_t attr) +{ + uint8_t flags = cmd_display_attr_flags(attr); + size_t len = 6; + + len += cmd_display_console_decimal_len(cmd_display_console_fg_code(cmd_display_attr_fg(attr))); + len += cmd_display_console_decimal_len(cmd_display_console_bg_code(cmd_display_attr_bg(attr))); + + if (flags & CMD_DISPLAY_ATTR_FLAG_BOLD) len += 2; + if (flags & CMD_DISPLAY_ATTR_FLAG_UNDERLINE) len += 2; + if (flags & CMD_DISPLAY_ATTR_FLAG_INVERSE) len += 2; + + return len; +} + +void cmd_display_console_count_range(const CmdDisplayBuffer *buffer, int y, int x0, int x1, CmdDisplayConsoleEmitState *state, size_t *bytes) +{ + if (!buffer || !state || !bytes) return; + + if (!state->pos_valid || state->x != x0 || state->y != y) + { + *bytes += 4 + cmd_display_console_decimal_len(y + 1) + cmd_display_console_decimal_len(x0 + 1); + state->x = x0; + state->y = y; + state->pos_valid = true; + } + + for (int x = x0; x < x1; x++) + { + const CmdDisplayCell *cell = &buffer->cells[y][x]; + + if (!state->attr_valid || cell->attr != state->attr) + { + *bytes += cmd_display_console_attr_bytes(cell->attr); + state->attr = cell->attr; + state->attr_valid = true; + } + + *bytes += (cmd_display_console_utf8_char(cell->ch) ? 3 : 1); + state->x++; + if (state->width > 0 && state->x >= state->width) + state->pos_valid = false; + } +} + +size_t cmd_display_console_count_full_present(const CmdDisplayBuffer *buffer) +{ + CmdDisplayConsoleEmitState state; + size_t bytes = 11; + + if (!buffer) return 0; + + state.attr = 0; + state.x = 0; + state.y = 0; + state.width = buffer->size.w; + state.attr_valid = false; + state.pos_valid = true; + + for (int y = 0; y < buffer->size.h; y++) + { + cmd_display_console_count_range(buffer, y, 0, buffer->size.w, &state, &bytes); + + if (y + 1 < buffer->size.h) + { + bytes += 2; + state.x = 0; + state.y = y + 1; + state.pos_valid = true; + } + } + + bytes += 4; + return bytes; +} + +size_t cmd_display_console_count_partial_present(const CmdDisplayBuffer *buffer, const CmdDisplayBuffer *prev, bool *any_dirty) +{ + CmdDisplayConsoleEmitState state; + size_t bytes = 0; + + if (any_dirty) *any_dirty = false; + if (!buffer || !prev) return 0; + + state.attr = 0; + state.x = -1; + state.y = -1; + state.width = buffer->size.w; + state.attr_valid = false; + state.pos_valid = false; + + for (int y = 0; y < buffer->size.h; y++) + { + int x = 0; + + while (x < buffer->size.w) + { + while (x < buffer->size.w && cmd_display_cell_equal(&buffer->cells[y][x], &prev->cells[y][x])) + x++; + + if (x >= buffer->size.w) + break; + + int x0 = x; + + while (x < buffer->size.w && !cmd_display_cell_equal(&buffer->cells[y][x], &prev->cells[y][x])) + x++; + + cmd_display_console_count_range(buffer, y, x0, x, &state, &bytes); + if (any_dirty) *any_dirty = true; + } + } + + if (any_dirty && *any_dirty) + bytes += 4; + + return bytes; +} + +void cmd_display_console_store_prev(CmdDisplayConsoleContext *ctx, const CmdDisplayBuffer *buffer) +{ + if (!ctx || !buffer) return; + ctx->prev = *buffer; + ctx->prev_valid = true; +} + +void cmd_display_console_emit_range(const CmdDisplayBuffer *buffer, int y, int x0, int x1, CmdDisplayConsoleEmitState *state) +{ + if (!state || !state->pos_valid || state->x != x0 || state->y != y) + { + printf("\x1b[%d;%dH", y + 1, x0 + 1); + + if (state) + { + state->x = x0; + state->y = y; + state->pos_valid = true; + } + } + + for (int x = x0; x < x1; x++) + { + const CmdDisplayCell *cell = &buffer->cells[y][x]; + + if (!state || !state->attr_valid || cell->attr != state->attr) + { + cmd_display_console_emit_attr(cell->attr); + + if (state) + { + state->attr = cell->attr; + state->attr_valid = true; + } + } + + cmd_display_console_emit_char(cell->ch); + + if (state && state->pos_valid) + { + state->x++; + if (state->width > 0 && state->x >= state->width) + state->pos_valid = false; + } + } +} + +esp_err_t cmd_display_console_full_present(CmdDisplayConsoleContext *ctx, const CmdDisplayBuffer *buffer) +{ + CmdDisplayConsoleEmitState state = + { + .attr = 0, + .x = 0, + .y = 0, + .width = buffer->size.w, + .attr_valid = false, + .pos_valid = true + }; + + printf("\x1b[0m\x1b[2J\x1b[H"); + + for (int y = 0; y < buffer->size.h; y++) + { + cmd_display_console_emit_range(buffer, y, 0, buffer->size.w, &state); + + if (y + 1 < buffer->size.h) + { + printf("\r\n"); + state.x = 0; + state.y = y + 1; + state.pos_valid = true; + } + } + + printf("\x1b[0m"); + fflush(stdout); + cmd_display_console_store_prev(ctx, buffer); + return ESP_OK; +} + +bool cmd_display_console_parse_size_response(const char *seq, int *rows, int *cols) +{ + int first = 0; + int second = 0; + int third = 0; + size_t i = 0; + + if (!seq || !rows || !cols) return false; + + while (seq[i] && seq[i] != '[') + i++; + + if (seq[i] != '[') return false; + i++; + + while (seq[i] >= '0' && seq[i] <= '9') + { + first = first * 10 + (seq[i] - '0'); + i++; + } + + if (seq[i] != ';') return false; + i++; + + while (seq[i] >= '0' && seq[i] <= '9') + { + second = second * 10 + (seq[i] - '0'); + i++; + } + + if (seq[i] == 'R') + { + if (first <= 0 || second <= 0) return false; + *rows = first; + *cols = second; + return true; + } + + if (seq[i] != ';') return false; + i++; + + while (seq[i] >= '0' && seq[i] <= '9') + { + third = third * 10 + (seq[i] - '0'); + i++; + } + + if (seq[i] != 't') return false; + if (first != 8 || second <= 0 || third <= 0) return false; + + *rows = second; + *cols = third; + return true; +} + +bool cmd_display_console_read_ansi_response(char *out, size_t out_size, uint32_t timeout_ms) +{ + size_t len = 0; + uint8_t c; + TickType_t ticks; + + if (!out || out_size == 0) return false; + + out[0] = 0; + ticks = pdMS_TO_TICKS(timeout_ms); + + while (len + 1 < out_size) + { + int n = uart_read_bytes((uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, &c, 1, ticks); + if (n <= 0) break; + + out[len++] = (char)c; + out[len] = 0; + + if (c == 'R' || c == 't') + return true; + } + + return false; +} + +bool cmd_display_console_query_size(cmd_size_t *size) +{ + char seq[48]; + int rows; + int cols; + + if (!size) return false; + + printf("\x1b[18t"); + fflush(stdout); + if (cmd_display_console_read_ansi_response(seq, sizeof(seq), CMD_DISPLAY_TERMINAL_QUERY_TIMEOUT_MS) && + cmd_display_console_parse_size_response(seq, &rows, &cols)) + { + size->w = cols; + size->h = rows; + return true; + } + + printf("\x1b[s\x1b[999;999H\x1b[6n"); + fflush(stdout); + if (cmd_display_console_read_ansi_response(seq, sizeof(seq), CMD_DISPLAY_TERMINAL_QUERY_TIMEOUT_MS) && + cmd_display_console_parse_size_response(seq, &rows, &cols)) + { + printf("\x1b[u"); + fflush(stdout); + size->w = cols; + size->h = rows; + return true; + } + + printf("\x1b[u"); + fflush(stdout); + return false; +} + +esp_err_t cmd_display_console_get_size(CmdDisplayBackend *backend, cmd_size_t *size) +{ + if (!backend || !size) return ESP_ERR_INVALID_ARG; + + size->w = CMD_DISPLAY_DEFAULT_COLS; + size->h = CMD_DISPLAY_DEFAULT_ROWS; + + if (!cmd_display_console_query_size(size)) + return ESP_OK; + + if (size->w > CMD_DISPLAY_COLS) size->w = CMD_DISPLAY_COLS; + if (size->h > CMD_DISPLAY_ROWS) size->h = CMD_DISPLAY_ROWS; + if (size->w <= 0) size->w = CMD_DISPLAY_DEFAULT_COLS; + if (size->h <= 0) size->h = CMD_DISPLAY_DEFAULT_ROWS; + return ESP_OK; +} + +esp_err_t cmd_display_console_init(CmdDisplayBackend *backend) +{ + if (!backend) return ESP_ERR_INVALID_ARG; + + memset(&cmd_display_console_ctx, 0, sizeof(cmd_display_console_ctx)); + backend->ctx = &cmd_display_console_ctx; + + printf("\x1b[0m\x1b[2J\x1b[H"); + fflush(stdout); + return ESP_OK; +} + +void cmd_display_console_deinit(CmdDisplayBackend *backend) +{ + if (!backend) return; + backend->ctx = NULL; + memset(&cmd_display_console_ctx, 0, sizeof(cmd_display_console_ctx)); +} + +esp_err_t cmd_display_console_clear(CmdDisplayBackend *backend) +{ + CmdDisplayConsoleContext *ctx; + + if (!backend) return ESP_ERR_INVALID_ARG; + + ctx = (CmdDisplayConsoleContext *)backend->ctx; + if (ctx) + ctx->prev_valid = false; + + printf("\x1b[0m\x1b[2J\x1b[H"); + fflush(stdout); + return ESP_OK; +} + +esp_err_t cmd_display_console_present(CmdDisplayBackend *backend, const CmdDisplayBuffer *buffer) +{ + CmdDisplayConsoleContext *ctx; + CmdDisplayConsoleEmitState state = + { + .attr = 0, + .x = -1, + .y = -1, + .width = buffer ? buffer->size.w : 0, + .attr_valid = false, + .pos_valid = false + }; + size_t full_bytes; + size_t partial_bytes; + bool any_dirty = false; + + if (!backend || !buffer) return ESP_ERR_INVALID_ARG; + + ctx = (CmdDisplayConsoleContext *)backend->ctx; + if (!ctx) return ESP_ERR_INVALID_STATE; + + if (!ctx->prev_valid || ctx->prev.size.w != buffer->size.w || ctx->prev.size.h != buffer->size.h) + return cmd_display_console_full_present(ctx, buffer); + + partial_bytes = cmd_display_console_count_partial_present(buffer, &ctx->prev, &any_dirty); + + if (!any_dirty) + { + cmd_display_console_store_prev(ctx, buffer); + return ESP_OK; + } + + if (!(backend->flags & CMD_DISPLAY_BACKEND_FLAG_FORCE_PARTIAL)) + { + full_bytes = cmd_display_console_count_full_present(buffer); + if (full_bytes <= partial_bytes) + return cmd_display_console_full_present(ctx, buffer); + } + + for (int y = 0; y < buffer->size.h; y++) + { + int x = 0; + + while (x < buffer->size.w) + { + while (x < buffer->size.w && cmd_display_cell_equal(&buffer->cells[y][x], &ctx->prev.cells[y][x])) + x++; + + if (x >= buffer->size.w) + break; + + int x0 = x; + + while (x < buffer->size.w && !cmd_display_cell_equal(&buffer->cells[y][x], &ctx->prev.cells[y][x])) + x++; + + cmd_display_console_emit_range(buffer, y, x0, x, &state); + } + } + + printf("\x1b[0m"); + fflush(stdout); + + cmd_display_console_store_prev(ctx, buffer); + return ESP_OK; +} + +esp_err_t cmd_display_console_put_char(CmdDisplayBackend *backend, int x, int y, char ch, cmd_display_attr_t attr) +{ + CmdDisplayConsoleContext *ctx; + + if (!backend) return ESP_ERR_INVALID_ARG; + if (!cmd_display_point_inside(x, y)) return ESP_ERR_INVALID_ARG; + + if (ch == 0) + ch = ' '; + + printf("\x1b[%d;%dH", y + 1, x + 1); + cmd_display_console_emit_attr(attr); + cmd_display_console_emit_char(ch); + printf("\x1b[0m"); + fflush(stdout); + + ctx = (CmdDisplayConsoleContext *)backend->ctx; + if (ctx && ctx->prev_valid) + { + ctx->prev.cells[y][x].ch = ch; + ctx->prev.cells[y][x].attr = attr; + } + + return ESP_OK; +} + +esp_err_t cmd_display_console_write_text(CmdDisplayBackend *backend, int x, int y, const char *text, cmd_display_attr_t attr) +{ + CmdDisplayConsoleContext *ctx; + int pos = x; + + if (!backend || !text) return ESP_ERR_INVALID_ARG; + if (y < 0 || y >= CMD_DISPLAY_ROWS) return ESP_ERR_INVALID_ARG; + if (pos >= CMD_DISPLAY_COLS) return ESP_OK; + if (pos < 0) pos = 0; + + printf("\x1b[%d;%dH", y + 1, pos + 1); + cmd_display_console_emit_attr(attr); + + ctx = (CmdDisplayConsoleContext *)backend->ctx; + + while (*text && pos < CMD_DISPLAY_COLS) + { + cmd_display_console_emit_char(*text); + + if (ctx && ctx->prev_valid) + { + ctx->prev.cells[y][pos].ch = *text; + ctx->prev.cells[y][pos].attr = attr; + } + + text++; + pos++; + } + + printf("\x1b[0m"); + fflush(stdout); + return ESP_OK; +} + +uint8_t cmd_display_ft812_color(cmd_display_color_t color) +{ + uint8_t c = (uint8_t)color & 0x0f; + uint8_t out = 0; + + if (c & 0x01) out |= 0x01; + if (c & 0x02) out |= 0x04; + if (c & 0x04) out |= 0x02; + if (c & 0x08) out |= 0x08; + + return out; +} + +uint8_t cmd_display_ft812_attr(cmd_display_attr_t attr) +{ + uint8_t fg = cmd_display_ft812_color(cmd_display_attr_fg(attr)); + uint8_t bg = cmd_display_ft812_color(cmd_display_attr_bg(attr)); + uint8_t flags = cmd_display_attr_flags(attr); + + if (flags & CMD_DISPLAY_ATTR_FLAG_BOLD) + fg |= 0x08; + + if (flags & CMD_DISPLAY_ATTR_FLAG_INVERSE) + { + uint8_t tmp = fg; + fg = bg; + bg = tmp; + } + + return (uint8_t)((bg << 4) | fg); +} + +CmdDisplayFt812Context *cmd_display_ft812_context(CmdDisplayBackend *backend) +{ + if (!backend) return NULL; + return (CmdDisplayFt812Context *)backend->ctx; +} + +void cmd_display_ft812_fill_local(CmdDisplayFt812Context *ctx, char ch, cmd_display_attr_t attr) +{ + uint8_t glyph = ch ? (uint8_t)ch : (uint8_t)' '; + uint8_t ft_attr = cmd_display_ft812_attr(attr); + + if (!ctx) return; + + memset(ctx->chars, glyph, sizeof(ctx->chars)); + memset(ctx->attrs, ft_attr, sizeof(ctx->attrs)); +} + +void cmd_display_ft812_pack(CmdDisplayFt812Context *ctx, const CmdDisplayBuffer *buffer) +{ + uint16_t cols; + uint16_t rows; + + if (!ctx || !buffer) return; + + ft_text_attr_mode_get_size(&cols, &rows); + cmd_display_ft812_fill_local(ctx, ' ', CMD_DISPLAY_ATTR_DEFAULT); + + for (int y = 0; y < buffer->size.h && y < (int)rows; y++) + { + for (int x = 0; x < buffer->size.w && x < (int)cols; x++) + { + const CmdDisplayCell *cell = &buffer->cells[y][x]; + size_t off = (size_t)y * (size_t)cols + (size_t)x; + + ctx->chars[off] = cell->ch ? (uint8_t)cell->ch : (uint8_t)' '; + ctx->attrs[off] = cmd_display_ft812_attr(cell->attr); + } + } +} + +esp_err_t cmd_display_ft812_get_size(CmdDisplayBackend *backend, cmd_size_t *size) +{ + uint16_t cols; + uint16_t rows; + + if (!backend || !size) return ESP_ERR_INVALID_ARG; + + ft_text_attr_mode_get_size(&cols, &rows); + size->w = (int)cols; + size->h = (int)rows; + + if (size->w <= 0) size->w = CMD_DISPLAY_DEFAULT_COLS; + if (size->h <= 0) size->h = CMD_DISPLAY_DEFAULT_ROWS; + if (size->w > CMD_DISPLAY_COLS) size->w = CMD_DISPLAY_COLS; + if (size->h > CMD_DISPLAY_ROWS) size->h = CMD_DISPLAY_ROWS; + return ESP_OK; +} + +esp_err_t cmd_display_ft812_begin(CmdDisplayBackend *backend) +{ + esp_err_t err; + + if (!backend) return ESP_ERR_INVALID_ARG; + + memset(&cmd_display_ft812_ctx, 0, sizeof(cmd_display_ft812_ctx)); + cmd_display_ft812_fill_local(&cmd_display_ft812_ctx, ' ', CMD_DISPLAY_ATTR_DEFAULT); + + err = ft_text_attr_mode_begin(); + if (err != ESP_OK) return err; + + backend->ctx = &cmd_display_ft812_ctx; + cmd_display_ft812_ctx.active = true; + return ESP_OK; +} + +void cmd_display_ft812_end(CmdDisplayBackend *backend) +{ + if (!backend) return; + + ft_text_attr_mode_end(); + backend->ctx = NULL; + memset(&cmd_display_ft812_ctx, 0, sizeof(cmd_display_ft812_ctx)); +} + +esp_err_t cmd_display_ft812_clear(CmdDisplayBackend *backend) +{ + CmdDisplayFt812Context *ctx = cmd_display_ft812_context(backend); + + if (!ctx || !ctx->active) return ESP_ERR_INVALID_STATE; + + cmd_display_ft812_fill_local(ctx, ' ', CMD_DISPLAY_ATTR_DEFAULT); + return ft_text_attr_mode_clear(' ', cmd_display_ft812_attr(CMD_DISPLAY_ATTR_DEFAULT)); +} + +esp_err_t cmd_display_ft812_present(CmdDisplayBackend *backend, const CmdDisplayBuffer *buffer) +{ + CmdDisplayFt812Context *ctx = cmd_display_ft812_context(backend); + + if (!ctx || !ctx->active) return ESP_ERR_INVALID_STATE; + if (!buffer) return ESP_ERR_INVALID_ARG; + + cmd_display_ft812_pack(ctx, buffer); + return ft_text_attr_mode_present(ctx->chars, ctx->attrs); +} + +esp_err_t cmd_display_ft812_put_char(CmdDisplayBackend *backend, int x, int y, char ch, cmd_display_attr_t attr) +{ + CmdDisplayFt812Context *ctx = cmd_display_ft812_context(backend); + uint16_t cols; + uint16_t rows; + size_t off; + + if (!ctx || !ctx->active) return ESP_ERR_INVALID_STATE; + + ft_text_attr_mode_get_size(&cols, &rows); + if (x < 0 || y < 0 || x >= (int)cols || y >= (int)rows) return ESP_ERR_INVALID_ARG; + + off = (size_t)y * (size_t)cols + (size_t)x; + ctx->chars[off] = ch ? (uint8_t)ch : (uint8_t)' '; + ctx->attrs[off] = cmd_display_ft812_attr(attr); + + return ft_text_attr_mode_present(ctx->chars, ctx->attrs); +} + +esp_err_t cmd_display_ft812_write_text(CmdDisplayBackend *backend, int x, int y, const char *text, cmd_display_attr_t attr) +{ + CmdDisplayFt812Context *ctx = cmd_display_ft812_context(backend); + uint16_t cols; + uint16_t rows; + uint8_t ft_attr = cmd_display_ft812_attr(attr); + int pos = x; + + if (!ctx || !ctx->active) return ESP_ERR_INVALID_STATE; + if (!text) return ESP_ERR_INVALID_ARG; + + ft_text_attr_mode_get_size(&cols, &rows); + if (y < 0 || y >= (int)rows) return ESP_ERR_INVALID_ARG; + if (pos >= (int)cols) return ESP_OK; + if (pos < 0) pos = 0; + + while (*text && pos < (int)cols) + { + size_t off = (size_t)y * (size_t)cols + (size_t)pos; + ctx->chars[off] = (uint8_t)*text; + ctx->attrs[off] = ft_attr; + text++; + pos++; + } + + return ft_text_attr_mode_present(ctx->chars, ctx->attrs); +} + +// --------------- cmd_fileops.cpp --------------- + +typedef struct +{ + CmdFsList lists[CMD_FILEOPS_MAX_DEPTH]; + cmd_file_entry_t entries[CMD_FILEOPS_MAX_DEPTH]; + char src_paths[CMD_FILEOPS_MAX_DEPTH + 1][CMD_PATH_MAX]; + char dst_paths[CMD_FILEOPS_MAX_DEPTH + 1][CMD_PATH_MAX]; + char scratch_path[CMD_PATH_MAX]; + char scratch_src_path[CMD_PATH_MAX]; + char scratch_dst_path[CMD_PATH_MAX]; + uint8_t copy_buffer[CMD_FILEOPS_BUFFER_SIZE]; +} CmdFileopsWorkspace; + +CmdFileopsWorkspace *g_cmd_fileops_workspace; + +esp_err_t cmd_fileops_alloc_global_buffers() +{ + if (g_cmd_fileops_workspace) return ESP_OK; + + g_cmd_fileops_workspace = (CmdFileopsWorkspace *)heap_caps_calloc( + 1, + sizeof(CmdFileopsWorkspace), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + + if (!g_cmd_fileops_workspace) return ESP_ERR_NO_MEM; + return ESP_OK; +} + +void cmd_fileops_free_global_buffers() +{ + if (!g_cmd_fileops_workspace) return; + + heap_caps_free(g_cmd_fileops_workspace); + g_cmd_fileops_workspace = NULL; +} + +CmdFileopsWorkspace *cmd_fileops_workspace() +{ + return g_cmd_fileops_workspace; +} + +esp_err_t cmd_fileops_copy_path_to_slot(char *dst, size_t dst_size, const char *src) +{ + size_t len; + + if (!dst || dst_size == 0 || !src) return ESP_ERR_INVALID_ARG; + if (dst == src) return ESP_OK; + + len = strlen(src); + if (len >= dst_size) return CMD_ERR_PATH_TOO_LONG; + + memmove(dst, src, len + 1); + return ESP_OK; +} + +esp_err_t cmd_fileops_ensure_device(CmdFsManager *fs, cmd_device_id_t device_id) +{ + if (!fs) return ESP_ERR_INVALID_ARG; + if (!cmd_fs_is_valid_device_id(device_id)) return CMD_ERR_INVALID_DEVICE; + return cmd_fs_manager_mount(fs, device_id); +} + +bool cmd_fileops_should_overwrite(const CmdFileopsOptions *options) +{ + if (!options) return false; + return (options->flags & CMD_FILEOPS_FLAG_OVERWRITE) != 0; +} + +bool cmd_fileops_should_recurse(const CmdFileopsOptions *options) +{ + if (!options) return false; + return (options->flags & CMD_FILEOPS_FLAG_RECURSIVE) != 0; +} + +bool cmd_fileops_same_location(cmd_device_id_t a_device, + const char *a_path, + cmd_device_id_t b_device, + const char *b_path) +{ + if (a_device != b_device) return false; + if (!a_path || !b_path) return false; + return strcmp(a_path, b_path) == 0; +} + +size_t cmd_fileops_trim_path_len(const char *path) +{ + size_t len; + + if (!path || !path[0]) return 1; + + len = strlen(path); + while (len > 1 && path[len - 1] == '/') + len--; + + return len; +} + +bool cmd_fileops_path_contains(const char *parent, const char *child) +{ + size_t parent_len; + size_t child_len; + + if (!parent || !child) return false; + + parent_len = cmd_fileops_trim_path_len(parent); + child_len = cmd_fileops_trim_path_len(child); + + if (parent_len == 1 && parent[0] == '/') return child_len >= 1 && child[0] == '/'; + if (child_len < parent_len) return false; + if (strncmp(parent, child, parent_len) != 0) return false; + if (child_len == parent_len) return true; + return child[parent_len] == '/'; +} + +esp_err_t cmd_fileops_check_dst_available(CmdFsManager *fs, + cmd_device_id_t device_id, + const char *path, + const CmdFileopsOptions *options, + bool *out_existed) +{ + cmd_file_entry_t entry; + esp_err_t err; + + if (out_existed) *out_existed = false; + if (!fs || !path) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_manager_stat(fs, device_id, path, &entry); + if (err == ESP_ERR_NOT_FOUND) return ESP_OK; + if (err != ESP_OK) return err; + + if (out_existed) *out_existed = true; + if (cmd_fileops_should_overwrite(options)) return ESP_OK; + return ESP_ERR_INVALID_STATE; +} + +esp_err_t cmd_fileops_prepare_dst_dir(CmdFsManager *fs, + cmd_device_id_t device_id, + const char *path, + const CmdFileopsOptions *options) +{ + cmd_file_entry_t entry; + esp_err_t err; + + if (!fs || !path) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_manager_stat(fs, device_id, path, &entry); + if (err == ESP_ERR_NOT_FOUND) return cmd_fs_manager_mkdir(fs, device_id, path); + if (err != ESP_OK) return err; + if (entry.type != CMD_ENTRY_DIR) return ESP_ERR_INVALID_STATE; + if (!cmd_fileops_should_overwrite(options)) return ESP_ERR_INVALID_STATE; + return ESP_OK; +} + +bool cmd_fileops_progress_call_ex(const CmdFileopsOptions *options, + cmd_fileops_op_t op, + const char *filename, + uint64_t bytes_done, + uint64_t bytes_total, + size_t files_done, + size_t files_total, + bool can_cancel) +{ + CmdFileopsProgress progress; + + if (!options || !options->progress) return true; + + progress.op = op; + progress.filename = filename; + progress.bytes_done = bytes_done; + progress.bytes_total = bytes_total; + progress.files_done = files_done; + progress.files_total = files_total; + progress.can_cancel = can_cancel; + + if (options->progress(&progress, options->progress_ctx)) return true; + return !can_cancel; +} + +typedef struct +{ + const CmdFileopsOptions *options; + cmd_fileops_op_t op; + uint64_t bytes_done; + uint64_t bytes_total; + size_t files_done; + size_t files_total; +} CmdFileopsTreeCtx; + +esp_err_t cmd_fileops_prepare_tree_context(CmdFileopsTreeCtx *ctx, + const CmdFileopsOptions *options, + cmd_fileops_op_t op, + uint64_t bytes_total, + size_t files_total) +{ + if (!ctx) return ESP_ERR_INVALID_ARG; + + memset(ctx, 0, sizeof(*ctx)); + ctx->options = options; + ctx->op = op; + ctx->bytes_total = bytes_total; + ctx->files_total = files_total; + return ESP_OK; +} + +bool cmd_fileops_tree_progress(CmdFileopsTreeCtx *ctx, const char *filename, bool can_cancel) +{ + if (!ctx) return true; + + return cmd_fileops_progress_call_ex(ctx->options, + ctx->op, + filename, + ctx->bytes_done, + ctx->bytes_total, + ctx->files_done, + ctx->files_total, + can_cancel); +} + +esp_err_t cmd_fileops_close_keep_first(CmdFsManager *fs, CmdFsFile *file, bool *opened, esp_err_t first_err) +{ + esp_err_t close_err; + + if (!opened || !*opened) return first_err; + + close_err = cmd_fs_manager_close(fs, file); + *opened = false; + if (first_err != ESP_OK) return first_err; + return close_err; +} + +esp_err_t cmd_fileops_join_selected_path(const CmdPanel *panel, + const cmd_file_entry_t *entry, + char *out, + size_t out_size) +{ + if (!panel || !entry || !out || out_size == 0) return ESP_ERR_INVALID_ARG; + if (entry->type == CMD_ENTRY_PARENT) return ESP_ERR_INVALID_ARG; + return cmd_fs_join_path(panel->current_path, entry->name, out, out_size); +} + +bool cmd_fileops_entry_is_marked(const cmd_file_entry_t *entry); + +esp_err_t cmd_fileops_scan_tree(CmdFsManager *fs, + cmd_device_id_t device_id, + const char *path, + size_t depth, + uint64_t *bytes_total, + size_t *files_total) +{ + CmdFileopsWorkspace *workspace; + CmdFsList *list; + cmd_file_entry_t *entry; + char *child_path; + bool list_open = false; + esp_err_t err; + + if (!fs || !path || !bytes_total || !files_total) return ESP_ERR_INVALID_ARG; + if (depth >= CMD_FILEOPS_MAX_DEPTH) return ESP_ERR_INVALID_SIZE; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + + list = &workspace->lists[depth]; + entry = &workspace->entries[depth]; + child_path = workspace->src_paths[depth + 1]; + memset(list, 0, sizeof(*list)); + + err = cmd_fs_manager_list_begin(fs, device_id, path, list); + if (err != ESP_OK) return err; + list_open = true; + + for (;;) + { + err = cmd_fs_manager_list_next(fs, list, entry); + if (err == ESP_ERR_NOT_FOUND) + { + err = ESP_OK; + break; + } + if (err != ESP_OK) break; + if (entry->type == CMD_ENTRY_PARENT) continue; + + err = cmd_fs_join_path(path, entry->name, child_path, CMD_PATH_MAX); + if (err != ESP_OK) break; + + if (entry->type == CMD_ENTRY_FILE) + { + *bytes_total += entry->size; + (*files_total)++; + } + else if (entry->type == CMD_ENTRY_DIR) + { + err = cmd_fileops_scan_tree(fs, device_id, child_path, depth + 1, bytes_total, files_total); + if (err != ESP_OK) break; + } + else + { + err = ESP_ERR_NOT_SUPPORTED; + break; + } + } + + if (list_open) + cmd_fs_manager_list_close(fs, list); + + return err; +} + +esp_err_t cmd_fileops_delete_file_with_progress(CmdFsManager *fs, + cmd_device_id_t device_id, + const char *path, + const cmd_file_entry_t *entry, + const CmdFileopsOptions *options, + uint64_t *bytes_done, + uint64_t bytes_total, + size_t *files_done, + size_t files_total, + bool can_cancel) +{ + uint64_t size = entry ? entry->size : 0; + const char *filename; + esp_err_t err; + + if (!fs || !path || !bytes_done || !files_done) return ESP_ERR_INVALID_ARG; + + filename = cmd_fs_filename_ptr(path); + if (!cmd_fileops_progress_call_ex(options, + CMD_FILEOPS_OP_DELETE, + filename, + *bytes_done, + bytes_total, + *files_done, + files_total, + can_cancel)) return CMD_ERR_CANCELLED; + + err = cmd_fs_manager_remove(fs, device_id, path); + if (err != ESP_OK) return err; + + *bytes_done += size; + (*files_done)++; + + if (!cmd_fileops_progress_call_ex(options, + CMD_FILEOPS_OP_DELETE, + filename, + *bytes_done, + bytes_total, + *files_done, + files_total, + can_cancel)) return CMD_ERR_CANCELLED; + + return ESP_OK; +} + +esp_err_t cmd_fileops_delete_dir_recursive(CmdFsManager *fs, + cmd_device_id_t device_id, + const char *path, + const CmdFileopsOptions *options, + uint64_t *bytes_done, + uint64_t bytes_total, + size_t *files_done, + size_t files_total, + size_t depth, + bool can_cancel) +{ + CmdFileopsWorkspace *workspace; + CmdFsList *list; + cmd_file_entry_t *entry; + char *child_path; + bool list_open = false; + const char *filename; + esp_err_t err; + + if (!fs || !path || !bytes_done || !files_done) return ESP_ERR_INVALID_ARG; + if (depth >= CMD_FILEOPS_MAX_DEPTH) return ESP_ERR_INVALID_SIZE; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + + list = &workspace->lists[depth]; + entry = &workspace->entries[depth]; + child_path = workspace->src_paths[depth + 1]; + memset(list, 0, sizeof(*list)); + + filename = cmd_fs_filename_ptr(path); + if (!cmd_fileops_progress_call_ex(options, + CMD_FILEOPS_OP_DELETE, + filename, + *bytes_done, + bytes_total, + *files_done, + files_total, + can_cancel)) return CMD_ERR_CANCELLED; + + err = cmd_fs_manager_list_begin(fs, device_id, path, list); + if (err != ESP_OK) return err; + list_open = true; + + for (;;) + { + err = cmd_fs_manager_list_next(fs, list, entry); + if (err == ESP_ERR_NOT_FOUND) + { + err = ESP_OK; + break; + } + if (err != ESP_OK) break; + if (entry->type == CMD_ENTRY_PARENT) continue; + + err = cmd_fs_join_path(path, entry->name, child_path, CMD_PATH_MAX); + if (err != ESP_OK) break; + + if (entry->type == CMD_ENTRY_FILE) + { + err = cmd_fileops_delete_file_with_progress(fs, + device_id, + child_path, + entry, + options, + bytes_done, + bytes_total, + files_done, + files_total, + can_cancel); + if (err != ESP_OK) break; + } + else if (entry->type == CMD_ENTRY_DIR) + { + err = cmd_fileops_delete_dir_recursive(fs, + device_id, + child_path, + options, + bytes_done, + bytes_total, + files_done, + files_total, + depth + 1, + can_cancel); + if (err != ESP_OK) break; + } + else + { + err = ESP_ERR_NOT_SUPPORTED; + break; + } + } + + if (list_open) + cmd_fs_manager_list_close(fs, list); + + if (err != ESP_OK) return err; + + err = cmd_fs_manager_remove(fs, device_id, path); + if (err != ESP_OK) return err; + + if (!cmd_fileops_progress_call_ex(options, + CMD_FILEOPS_OP_DELETE, + filename, + *bytes_done, + bytes_total, + *files_done, + files_total, + can_cancel)) return CMD_ERR_CANCELLED; + + return ESP_OK; +} + +esp_err_t cmd_fileops_count_selected_tree_bytes(CmdPanel *panel, uint64_t *out_bytes_total) +{ + CmdFileopsWorkspace *workspace; + uint64_t bytes_total = 0; + size_t files_total = 0; + char *path; + esp_err_t err; + + if (!panel || !out_bytes_total) return ESP_ERR_INVALID_ARG; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + path = workspace->scratch_path; + + err = cmd_fileops_ensure_device(panel->fs, panel->device_id); + if (err != ESP_OK) return err; + + for (size_t i = 0; i < panel->count; i++) + { + const cmd_file_entry_t *entry = &panel->entries[i]; + + if (!cmd_fileops_entry_is_marked(entry)) continue; + + if (entry->type == CMD_ENTRY_FILE) + { + bytes_total += entry->size; + continue; + } + + if (entry->type != CMD_ENTRY_DIR) return ESP_ERR_NOT_SUPPORTED; + + err = cmd_fileops_join_selected_path(panel, entry, path, CMD_PATH_MAX); + if (err != ESP_OK) return err; + + err = cmd_fileops_scan_tree(panel->fs, + panel->device_id, + path, + 0, + &bytes_total, + &files_total); + if (err != ESP_OK) return err; + } + + *out_bytes_total = bytes_total; + return ESP_OK; +} + +esp_err_t cmd_fileops_copy_file_with_context(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + const cmd_file_entry_t *src_entry, + cmd_device_id_t dst_device, + const char *dst_path, + CmdFileopsTreeCtx *ctx) +{ + CmdFileopsWorkspace *workspace; + CmdFsFile src_file = {}; + CmdFsFile dst_file = {}; + cmd_file_entry_t entry; + const CmdFileopsOptions *options; + const char *filename; + bool src_open = false; + bool dst_open = false; + bool dst_existed = false; + bool dst_created = false; + uint64_t file_done = 0; + uint64_t file_total; + esp_err_t err; + + if (!fs || !src_path || !dst_path || !ctx) return ESP_ERR_INVALID_ARG; + if (cmd_fileops_same_location(src_device, src_path, dst_device, dst_path)) return ESP_ERR_INVALID_STATE; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + + options = ctx->options; + + if (!src_entry) + { + err = cmd_fs_manager_stat(fs, src_device, src_path, &entry); + if (err != ESP_OK) return err; + src_entry = &entry; + } + + if (src_entry->type != CMD_ENTRY_FILE) return ESP_ERR_NOT_SUPPORTED; + + err = cmd_fileops_check_dst_available(fs, dst_device, dst_path, options, &dst_existed); + if (err != ESP_OK) return err; + + file_total = src_entry->size; + filename = cmd_fs_filename_ptr(src_path); + + if (!cmd_fileops_tree_progress(ctx, filename, true)) return CMD_ERR_CANCELLED; + + err = cmd_fs_manager_open_read(fs, src_device, src_path, &src_file); + if (err != ESP_OK) goto done; + src_open = true; + + err = cmd_fs_manager_open_write(fs, dst_device, dst_path, &dst_file); + if (err != ESP_OK) goto done; + dst_open = true; + dst_created = !dst_existed; + + while (file_done < file_total) + { + uint64_t left = file_total - file_done; + size_t todo = left > CMD_FILEOPS_BUFFER_SIZE ? CMD_FILEOPS_BUFFER_SIZE : (size_t)left; + size_t got = 0; + size_t wrote = 0; + + err = cmd_fs_manager_read(fs, &src_file, workspace->copy_buffer, todo, &got); + if (err != ESP_OK) goto done; + if (got == 0) + { + err = ESP_FAIL; + goto done; + } + + err = cmd_fs_manager_write(fs, &dst_file, workspace->copy_buffer, got, &wrote); + if (err != ESP_OK) goto done; + if (wrote != got) + { + err = ESP_FAIL; + goto done; + } + + file_done += got; + ctx->bytes_done += got; + if (!cmd_fileops_tree_progress(ctx, filename, file_done < file_total)) + { + err = CMD_ERR_CANCELLED; + goto done; + } + } + + ctx->files_done++; + if (!cmd_fileops_tree_progress(ctx, filename, false)) + { + err = CMD_ERR_CANCELLED; + goto done; + } + + err = ESP_OK; + +done: + err = cmd_fileops_close_keep_first(fs, &dst_file, &dst_open, err); + err = cmd_fileops_close_keep_first(fs, &src_file, &src_open, err); + + if (err != ESP_OK && dst_created) + cmd_fs_manager_remove(fs, dst_device, dst_path); + + return err; +} + +esp_err_t cmd_fileops_copy_dir_with_context(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + cmd_device_id_t dst_device, + const char *dst_path, + CmdFileopsTreeCtx *ctx, + size_t depth) +{ + CmdFileopsWorkspace *workspace; + CmdFsList *list; + cmd_file_entry_t *entry; + char *src_child; + char *dst_child; + bool list_open = false; + esp_err_t err; + + if (!fs || !src_path || !dst_path || !ctx) return ESP_ERR_INVALID_ARG; + if (depth >= CMD_FILEOPS_MAX_DEPTH) return ESP_ERR_INVALID_SIZE; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + + list = &workspace->lists[depth]; + entry = &workspace->entries[depth]; + src_child = workspace->src_paths[depth + 1]; + dst_child = workspace->dst_paths[depth + 1]; + memset(list, 0, sizeof(*list)); + + err = cmd_fileops_prepare_dst_dir(fs, dst_device, dst_path, ctx->options); + if (err != ESP_OK) return err; + + if (!cmd_fileops_tree_progress(ctx, cmd_fs_filename_ptr(src_path), true)) return CMD_ERR_CANCELLED; + + err = cmd_fs_manager_list_begin(fs, src_device, src_path, list); + if (err != ESP_OK) return err; + list_open = true; + + for (;;) + { + err = cmd_fs_manager_list_next(fs, list, entry); + if (err == ESP_ERR_NOT_FOUND) + { + err = ESP_OK; + break; + } + if (err != ESP_OK) break; + if (entry->type == CMD_ENTRY_PARENT) continue; + + err = cmd_fs_join_path(src_path, entry->name, src_child, CMD_PATH_MAX); + if (err != ESP_OK) break; + + err = cmd_fs_join_path(dst_path, entry->name, dst_child, CMD_PATH_MAX); + if (err != ESP_OK) break; + + if (entry->type == CMD_ENTRY_FILE) + { + err = cmd_fileops_copy_file_with_context(fs, + src_device, + src_child, + entry, + dst_device, + dst_child, + ctx); + if (err != ESP_OK) break; + } + else if (entry->type == CMD_ENTRY_DIR) + { + err = cmd_fileops_copy_dir_with_context(fs, + src_device, + src_child, + dst_device, + dst_child, + ctx, + depth + 1); + if (err != ESP_OK) break; + } + else + { + err = ESP_ERR_NOT_SUPPORTED; + break; + } + } + + if (list_open) + cmd_fs_manager_list_close(fs, list); + + return err; +} + +esp_err_t cmd_fileops_copy_path_as_op(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + cmd_device_id_t dst_device, + const char *dst_path, + const CmdFileopsOptions *options, + cmd_fileops_op_t op) +{ + CmdFileopsWorkspace *workspace; + CmdFileopsTreeCtx ctx; + cmd_file_entry_t src_entry; + const char *src_root; + const char *dst_root; + uint64_t bytes_total = 0; + size_t files_total = 0; + esp_err_t err; + + if (!fs || !src_path || !dst_path) return ESP_ERR_INVALID_ARG; + if (cmd_fileops_same_location(src_device, src_path, dst_device, dst_path)) return ESP_ERR_INVALID_STATE; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + + err = cmd_fileops_copy_path_to_slot(workspace->src_paths[0], CMD_PATH_MAX, src_path); + if (err != ESP_OK) return err; + + err = cmd_fileops_copy_path_to_slot(workspace->dst_paths[0], CMD_PATH_MAX, dst_path); + if (err != ESP_OK) return err; + + src_root = workspace->src_paths[0]; + dst_root = workspace->dst_paths[0]; + + err = cmd_fileops_ensure_device(fs, src_device); + if (err != ESP_OK) return err; + + err = cmd_fileops_ensure_device(fs, dst_device); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_stat(fs, src_device, src_root, &src_entry); + if (err != ESP_OK) return err; + + if (src_entry.type == CMD_ENTRY_FILE) + { + err = cmd_fileops_prepare_tree_context(&ctx, options, op, src_entry.size, 1); + if (err != ESP_OK) return err; + + return cmd_fileops_copy_file_with_context(fs, + src_device, + src_root, + &src_entry, + dst_device, + dst_root, + &ctx); + } + + if (src_entry.type != CMD_ENTRY_DIR) return ESP_ERR_NOT_SUPPORTED; + if (!cmd_fileops_should_recurse(options)) return ESP_ERR_NOT_SUPPORTED; + if (src_device == dst_device && cmd_fileops_path_contains(src_root, dst_root)) + return ESP_ERR_INVALID_STATE; + + err = cmd_fileops_scan_tree(fs, src_device, src_root, 0, &bytes_total, &files_total); + if (err != ESP_OK) return err; + + err = cmd_fileops_prepare_tree_context(&ctx, options, op, bytes_total, files_total); + if (err != ESP_OK) return err; + + err = cmd_fileops_copy_dir_with_context(fs, src_device, src_root, dst_device, dst_root, &ctx, 0); + if (err != ESP_OK) return err; + + if (!cmd_fileops_tree_progress(&ctx, cmd_fs_filename_ptr(src_root), false)) return CMD_ERR_CANCELLED; + return ESP_OK; +} + +esp_err_t cmd_fileops_copy_path(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + cmd_device_id_t dst_device, + const char *dst_path, + const CmdFileopsOptions *options) +{ + return cmd_fileops_copy_path_as_op(fs, src_device, src_path, dst_device, dst_path, options, CMD_FILEOPS_OP_COPY); +} + +esp_err_t cmd_fileops_copy_file(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + cmd_device_id_t dst_device, + const char *dst_path, + const CmdFileopsOptions *options) +{ + CmdFileopsTreeCtx ctx; + cmd_file_entry_t src_entry; + esp_err_t err; + + if (!fs || !src_path || !dst_path) return ESP_ERR_INVALID_ARG; + if (cmd_fileops_same_location(src_device, src_path, dst_device, dst_path)) return ESP_ERR_INVALID_STATE; + + err = cmd_fileops_ensure_device(fs, src_device); + if (err != ESP_OK) return err; + + err = cmd_fileops_ensure_device(fs, dst_device); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_stat(fs, src_device, src_path, &src_entry); + if (err != ESP_OK) return err; + if (src_entry.type != CMD_ENTRY_FILE) return ESP_ERR_NOT_SUPPORTED; + + err = cmd_fileops_prepare_tree_context(&ctx, options, CMD_FILEOPS_OP_COPY, src_entry.size, 1); + if (err != ESP_OK) return err; + + return cmd_fileops_copy_file_with_context(fs, + src_device, + src_path, + &src_entry, + dst_device, + dst_path, + &ctx); +} + +esp_err_t cmd_fileops_move_path(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + cmd_device_id_t dst_device, + const char *dst_path, + const CmdFileopsOptions *options) +{ + CmdFileopsWorkspace *workspace; + CmdFileopsTreeCtx ctx; + CmdFileopsOptions delete_options = {}; + CmdFsDriver *driver; + cmd_file_entry_t src_entry; + const char *src_root; + const char *dst_root; + const char *filename; + uint64_t bytes_total = 0; + size_t files_total = 0; + esp_err_t err; + + if (!fs || !src_path || !dst_path) return ESP_ERR_INVALID_ARG; + if (cmd_fs_path_is_root(src_path)) return ESP_ERR_INVALID_ARG; + if (cmd_fileops_same_location(src_device, src_path, dst_device, dst_path)) return ESP_ERR_INVALID_STATE; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + + err = cmd_fileops_copy_path_to_slot(workspace->src_paths[0], CMD_PATH_MAX, src_path); + if (err != ESP_OK) return err; + + err = cmd_fileops_copy_path_to_slot(workspace->dst_paths[0], CMD_PATH_MAX, dst_path); + if (err != ESP_OK) return err; + + src_root = workspace->src_paths[0]; + dst_root = workspace->dst_paths[0]; + + err = cmd_fileops_ensure_device(fs, src_device); + if (err != ESP_OK) return err; + + err = cmd_fileops_ensure_device(fs, dst_device); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_stat(fs, src_device, src_root, &src_entry); + if (err != ESP_OK) return err; + + if (src_entry.type == CMD_ENTRY_DIR && src_device == dst_device && + cmd_fileops_path_contains(src_root, dst_root)) return ESP_ERR_INVALID_STATE; + + err = cmd_fileops_check_dst_available(fs, dst_device, dst_root, options, NULL); + if (err != ESP_OK) return err; + + if (src_entry.type == CMD_ENTRY_FILE) + { + bytes_total = src_entry.size; + files_total = 1; + } + else if (src_entry.type == CMD_ENTRY_DIR) + { + if (!cmd_fileops_should_recurse(options)) return ESP_ERR_NOT_SUPPORTED; + err = cmd_fileops_scan_tree(fs, src_device, src_root, 0, &bytes_total, &files_total); + if (err != ESP_OK) return err; + } + else + { + return ESP_ERR_NOT_SUPPORTED; + } + + filename = cmd_fs_filename_ptr(src_root); + err = cmd_fileops_prepare_tree_context(&ctx, options, CMD_FILEOPS_OP_MOVE, bytes_total, files_total); + if (err != ESP_OK) return err; + + driver = cmd_fs_manager_get_driver(fs, src_device); + if (src_device == dst_device && driver && driver->rename) + { + if (!cmd_fileops_tree_progress(&ctx, filename, true)) return CMD_ERR_CANCELLED; + + err = cmd_fs_manager_rename(fs, src_device, src_root, dst_root); + if (err == ESP_OK) + { + ctx.bytes_done = ctx.bytes_total; + ctx.files_done = ctx.files_total; + if (!cmd_fileops_tree_progress(&ctx, filename, false)) return CMD_ERR_CANCELLED; + return ESP_OK; + } + + if (src_entry.type != CMD_ENTRY_DIR) return err; + } + + err = cmd_fileops_copy_path_as_op(fs, + src_device, + src_root, + dst_device, + dst_root, + options, + CMD_FILEOPS_OP_MOVE); + if (err != ESP_OK) return err; + + if (options) + delete_options = *options; + delete_options.flags |= CMD_FILEOPS_FLAG_RECURSIVE; + delete_options.progress = NULL; + delete_options.progress_ctx = NULL; + + return cmd_fileops_delete_path(fs, src_device, src_root, &delete_options); +} + +esp_err_t cmd_fileops_delete_path(CmdFsManager *fs, + cmd_device_id_t device_id, + const char *path, + const CmdFileopsOptions *options) +{ + CmdFileopsWorkspace *workspace; + cmd_file_entry_t entry; + const char *path_root; + const char *filename; + uint64_t bytes_done = 0; + uint64_t bytes_total = 0; + size_t files_done = 0; + size_t files_total = 0; + esp_err_t err; + + if (!fs || !path) return ESP_ERR_INVALID_ARG; + if (cmd_fs_path_is_root(path)) return ESP_ERR_INVALID_ARG; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + + err = cmd_fileops_copy_path_to_slot(workspace->src_paths[0], CMD_PATH_MAX, path); + if (err != ESP_OK) return err; + + path_root = workspace->src_paths[0]; + + err = cmd_fileops_ensure_device(fs, device_id); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_stat(fs, device_id, path_root, &entry); + if (err != ESP_OK) return err; + + if (entry.type == CMD_ENTRY_PARENT) return ESP_ERR_INVALID_ARG; + if (entry.type == CMD_ENTRY_UNKNOWN) return ESP_ERR_NOT_SUPPORTED; + + filename = cmd_fs_filename_ptr(path_root); + + if (entry.type == CMD_ENTRY_FILE) + { + bytes_total = entry.size; + files_total = 1; + return cmd_fileops_delete_file_with_progress(fs, + device_id, + path_root, + &entry, + options, + &bytes_done, + bytes_total, + &files_done, + files_total, + true); + } + + if (entry.type != CMD_ENTRY_DIR) return ESP_ERR_NOT_SUPPORTED; + + if (!cmd_fileops_should_recurse(options)) + { + if (!cmd_fileops_progress_call_ex(options, + CMD_FILEOPS_OP_DELETE, + filename, + 0, + 0, + 0, + 0, + true)) return CMD_ERR_CANCELLED; + + err = cmd_fs_manager_remove(fs, device_id, path_root); + if (err != ESP_OK) return err; + + if (!cmd_fileops_progress_call_ex(options, + CMD_FILEOPS_OP_DELETE, + filename, + 0, + 0, + 0, + 0, + false)) return CMD_ERR_CANCELLED; + + return ESP_OK; + } + + err = cmd_fileops_scan_tree(fs, device_id, path_root, 0, &bytes_total, &files_total); + if (err != ESP_OK) return err; + + err = cmd_fileops_delete_dir_recursive(fs, + device_id, + path_root, + options, + &bytes_done, + bytes_total, + &files_done, + files_total, + 0, + true); + if (err != ESP_OK) return err; + + if (!cmd_fileops_progress_call_ex(options, + CMD_FILEOPS_OP_DELETE, + filename, + bytes_done, + bytes_total, + files_done, + files_total, + false)) return CMD_ERR_CANCELLED; + + return ESP_OK; +} + +typedef struct +{ + const CmdFileopsOptions *options; + cmd_fileops_op_t op; + uint64_t bytes_done_base; + uint64_t item_bytes_done_max; + uint64_t bytes_total; + size_t files_done_base; + size_t files_total; +} CmdFileopsBatchCtx; + +bool cmd_fileops_batch_progress_cb(const CmdFileopsProgress *progress, void *ctx) +{ + CmdFileopsBatchCtx *batch = (CmdFileopsBatchCtx *)ctx; + uint64_t bytes_done; + size_t files_done; + + if (!batch || !progress) return true; + + if (progress->bytes_done > batch->item_bytes_done_max) + batch->item_bytes_done_max = progress->bytes_done; + + bytes_done = batch->bytes_done_base + batch->item_bytes_done_max; + if (bytes_done > batch->bytes_total) bytes_done = batch->bytes_total; + + files_done = batch->files_done_base; + if (!progress->can_cancel && progress->bytes_done >= progress->bytes_total) + files_done++; + + if (files_done > batch->files_total) files_done = batch->files_total; + + return cmd_fileops_progress_call_ex(batch->options, + batch->op, + progress->filename, + bytes_done, + batch->bytes_total, + files_done, + batch->files_total, + progress->can_cancel); +} + +bool cmd_fileops_entry_is_marked(const cmd_file_entry_t *entry) +{ + if (!entry) return false; + if (!(entry->flags & CMD_ENTRY_FLAG_SELECTED)) return false; + if (entry->type == CMD_ENTRY_PARENT) return false; + return true; +} + +esp_err_t cmd_fileops_validate_selected_group(const CmdPanel *active, + const CmdPanel *passive, + cmd_fileops_op_t op) +{ + if (!active) return ESP_ERR_INVALID_ARG; + if ((op == CMD_FILEOPS_OP_COPY || op == CMD_FILEOPS_OP_MOVE) && !passive) return ESP_ERR_INVALID_ARG; + + for (size_t i = 0; i < active->count; i++) + { + const cmd_file_entry_t *entry = &active->entries[i]; + + if (!cmd_fileops_entry_is_marked(entry)) continue; + if (entry->type == CMD_ENTRY_FILE || entry->type == CMD_ENTRY_DIR) continue; + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +void cmd_fileops_batch_options(CmdFileopsBatchCtx *batch, + const CmdFileopsOptions *options, + CmdFileopsOptions *out_options) +{ + if (!out_options) return; + + if (options) + *out_options = *options; + else + memset(out_options, 0, sizeof(*out_options)); + + out_options->progress = cmd_fileops_batch_progress_cb; + out_options->progress_ctx = batch; +} + +esp_err_t cmd_fileops_make_selected_paths(const CmdPanel *active, + const CmdPanel *passive, + const cmd_file_entry_t *entry, + char *src_path, + size_t src_path_size, + char *dst_path, + size_t dst_path_size) +{ + esp_err_t err; + + if (!active || !passive || !entry || !src_path || !dst_path) return ESP_ERR_INVALID_ARG; + + err = cmd_fileops_join_selected_path(active, entry, src_path, src_path_size); + if (err != ESP_OK) return err; + + return cmd_fs_join_path(passive->current_path, entry->name, dst_path, dst_path_size); +} + +esp_err_t cmd_fileops_copy_selected_group(CmdPanel *active, + CmdPanel *passive, + const CmdFileopsOptions *options) +{ + CmdFileopsWorkspace *workspace; + CmdFileopsBatchCtx batch = {}; + CmdFileopsOptions item_options = {}; + char *src_path; + char *dst_path; + esp_err_t err; + + if (!active || !passive) return ESP_ERR_INVALID_ARG; + if (active->fs != passive->fs) return ESP_ERR_INVALID_ARG; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + src_path = workspace->scratch_src_path; + dst_path = workspace->scratch_dst_path; + + cmd_panel_update_selection_stats(active); + if (!cmd_panel_has_selection(active)) return ESP_ERR_NOT_FOUND; + + err = cmd_fileops_validate_selected_group(active, passive, CMD_FILEOPS_OP_COPY); + if (err != ESP_OK) return err; + + batch.options = options; + batch.op = CMD_FILEOPS_OP_COPY; + err = cmd_fileops_count_selected_tree_bytes(active, &batch.bytes_total); + if (err != ESP_OK) return err; + batch.files_total = active->selected_count; + cmd_fileops_batch_options(&batch, options, &item_options); + + for (size_t i = 0; i < active->count; i++) + { + const cmd_file_entry_t *entry = &active->entries[i]; + + if (!cmd_fileops_entry_is_marked(entry)) continue; + + err = cmd_fileops_make_selected_paths(active, + passive, + entry, + src_path, + CMD_PATH_MAX, + dst_path, + CMD_PATH_MAX); + if (err != ESP_OK) return err; + + batch.item_bytes_done_max = 0; + err = cmd_fileops_copy_path(active->fs, + active->device_id, + src_path, + passive->device_id, + dst_path, + &item_options); + if (err != ESP_OK) return err; + + batch.files_done_base++; + batch.bytes_done_base += batch.item_bytes_done_max; + } + + return cmd_panel_reload(passive); +} + +esp_err_t cmd_fileops_move_selected_group(CmdPanel *active, + CmdPanel *passive, + const CmdFileopsOptions *options) +{ + CmdFileopsWorkspace *workspace; + CmdFileopsBatchCtx batch = {}; + CmdFileopsOptions item_options = {}; + char *src_path; + char *dst_path; + esp_err_t err; + + if (!active || !passive) return ESP_ERR_INVALID_ARG; + if (active->fs != passive->fs) return ESP_ERR_INVALID_ARG; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + src_path = workspace->scratch_src_path; + dst_path = workspace->scratch_dst_path; + + cmd_panel_update_selection_stats(active); + if (!cmd_panel_has_selection(active)) return ESP_ERR_NOT_FOUND; + + err = cmd_fileops_validate_selected_group(active, passive, CMD_FILEOPS_OP_MOVE); + if (err != ESP_OK) return err; + + batch.options = options; + batch.op = CMD_FILEOPS_OP_MOVE; + err = cmd_fileops_count_selected_tree_bytes(active, &batch.bytes_total); + if (err != ESP_OK) return err; + batch.files_total = active->selected_count; + cmd_fileops_batch_options(&batch, options, &item_options); + + for (size_t i = 0; i < active->count; i++) + { + const cmd_file_entry_t *entry = &active->entries[i]; + + if (!cmd_fileops_entry_is_marked(entry)) continue; + + err = cmd_fileops_make_selected_paths(active, + passive, + entry, + src_path, + CMD_PATH_MAX, + dst_path, + CMD_PATH_MAX); + if (err != ESP_OK) return err; + + batch.item_bytes_done_max = 0; + err = cmd_fileops_move_path(active->fs, + active->device_id, + src_path, + passive->device_id, + dst_path, + &item_options); + if (err != ESP_OK) return err; + + batch.files_done_base++; + batch.bytes_done_base += batch.item_bytes_done_max; + } + + err = cmd_panel_reload(active); + if (err != ESP_OK) return err; + + if (passive != active) + err = cmd_panel_reload(passive); + + return err; +} + +esp_err_t cmd_fileops_delete_selected_group(CmdPanel *panel, + const CmdFileopsOptions *options) +{ + CmdFileopsWorkspace *workspace; + CmdFileopsBatchCtx batch = {}; + CmdFileopsOptions item_options = {}; + char *path; + esp_err_t err; + + if (!panel) return ESP_ERR_INVALID_ARG; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + path = workspace->scratch_path; + + cmd_panel_update_selection_stats(panel); + if (!cmd_panel_has_selection(panel)) return ESP_ERR_NOT_FOUND; + + err = cmd_fileops_validate_selected_group(panel, NULL, CMD_FILEOPS_OP_DELETE); + if (err != ESP_OK) return err; + + batch.options = options; + batch.op = CMD_FILEOPS_OP_DELETE; + err = cmd_fileops_count_selected_tree_bytes(panel, &batch.bytes_total); + if (err != ESP_OK) return err; + batch.files_total = panel->selected_count; + cmd_fileops_batch_options(&batch, options, &item_options); + + for (size_t i = 0; i < panel->count; i++) + { + const cmd_file_entry_t *entry = &panel->entries[i]; + + if (!cmd_fileops_entry_is_marked(entry)) continue; + + err = cmd_fileops_join_selected_path(panel, entry, path, CMD_PATH_MAX); + if (err != ESP_OK) return err; + + batch.item_bytes_done_max = 0; + err = cmd_fileops_delete_path(panel->fs, panel->device_id, path, &item_options); + if (err != ESP_OK) return err; + + batch.files_done_base++; + batch.bytes_done_base += batch.item_bytes_done_max; + } + + return cmd_panel_reload(panel); +} + +esp_err_t cmd_fileops_copy_selected(CmdPanel *active, + CmdPanel *passive, + const CmdFileopsOptions *options) +{ + CmdFileopsWorkspace *workspace; + const cmd_file_entry_t *entry; + char *src_path; + char *dst_path; + esp_err_t err; + + if (!active || !passive) return ESP_ERR_INVALID_ARG; + if (active->fs != passive->fs) return ESP_ERR_INVALID_ARG; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + src_path = workspace->scratch_src_path; + dst_path = workspace->scratch_dst_path; + + cmd_panel_update_selection_stats(active); + if (cmd_panel_has_selection(active)) + return cmd_fileops_copy_selected_group(active, passive, options); + + entry = cmd_panel_get_selected_entry(active); + if (!entry) return ESP_ERR_NOT_FOUND; + if (entry->type == CMD_ENTRY_PARENT) return ESP_ERR_INVALID_ARG; + if (entry->type != CMD_ENTRY_FILE && entry->type != CMD_ENTRY_DIR) return ESP_ERR_NOT_SUPPORTED; + + err = cmd_fileops_join_selected_path(active, entry, src_path, CMD_PATH_MAX); + if (err != ESP_OK) return err; + + err = cmd_fs_join_path(passive->current_path, entry->name, dst_path, CMD_PATH_MAX); + if (err != ESP_OK) return err; + + err = cmd_fileops_copy_path(active->fs, + active->device_id, + src_path, + passive->device_id, + dst_path, + options); + if (err != ESP_OK) return err; + + return cmd_panel_reload(passive); +} + +esp_err_t cmd_fileops_move_selected(CmdPanel *active, + CmdPanel *passive, + const CmdFileopsOptions *options) +{ + CmdFileopsWorkspace *workspace; + const cmd_file_entry_t *entry; + char *src_path; + char *dst_path; + esp_err_t err; + + if (!active || !passive) return ESP_ERR_INVALID_ARG; + if (active->fs != passive->fs) return ESP_ERR_INVALID_ARG; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + src_path = workspace->scratch_src_path; + dst_path = workspace->scratch_dst_path; + + cmd_panel_update_selection_stats(active); + if (cmd_panel_has_selection(active)) + return cmd_fileops_move_selected_group(active, passive, options); + + entry = cmd_panel_get_selected_entry(active); + if (!entry) return ESP_ERR_NOT_FOUND; + if (entry->type == CMD_ENTRY_PARENT) return ESP_ERR_INVALID_ARG; + + err = cmd_fileops_join_selected_path(active, entry, src_path, CMD_PATH_MAX); + if (err != ESP_OK) return err; + + err = cmd_fs_join_path(passive->current_path, entry->name, dst_path, CMD_PATH_MAX); + if (err != ESP_OK) return err; + + err = cmd_fileops_move_path(active->fs, + active->device_id, + src_path, + passive->device_id, + dst_path, + options); + if (err != ESP_OK) return err; + + err = cmd_panel_reload(active); + if (err != ESP_OK) return err; + + if (passive != active) + err = cmd_panel_reload(passive); + + return err; +} + +esp_err_t cmd_fileops_delete_selected(CmdPanel *panel, + const CmdFileopsOptions *options) +{ + CmdFileopsWorkspace *workspace; + const cmd_file_entry_t *entry; + char *path; + esp_err_t err; + + if (!panel) return ESP_ERR_INVALID_ARG; + + workspace = cmd_fileops_workspace(); + if (!workspace) return ESP_ERR_NO_MEM; + path = workspace->scratch_path; + + cmd_panel_update_selection_stats(panel); + if (cmd_panel_has_selection(panel)) + return cmd_fileops_delete_selected_group(panel, options); + + entry = cmd_panel_get_selected_entry(panel); + if (!entry) return ESP_ERR_NOT_FOUND; + if (entry->type == CMD_ENTRY_PARENT) return ESP_ERR_INVALID_ARG; + + err = cmd_fileops_join_selected_path(panel, entry, path, CMD_PATH_MAX); + if (err != ESP_OK) return err; + + err = cmd_fileops_delete_path(panel->fs, panel->device_id, path, options); + if (err != ESP_OK) return err; + + return cmd_panel_reload(panel); +} + +// --------------- cmd_fs.cpp --------------- + +esp_err_t cmd_fs_errno_to_err(int err) +{ + if (err == 0) return ESP_OK; + if (err == ENOENT) return ESP_ERR_NOT_FOUND; + if (err == ENOMEM) return ESP_ERR_NO_MEM; + if (err == EINVAL) return ESP_ERR_INVALID_ARG; + if (err == ENAMETOOLONG) return CMD_ERR_PATH_TOO_LONG; + if (err == ENOTDIR) return ESP_ERR_NOT_FOUND; + if (err == EEXIST) return ESP_ERR_INVALID_STATE; + if (err == ENOSPC) return ESP_ERR_NO_MEM; + return ESP_FAIL; +} + + +const char *cmd_device_name(cmd_device_id_t id) +{ + switch (id) + { + case CMD_DEVICE_SD: return "SD"; + case CMD_DEVICE_FAT: return "FAT"; + case CMD_DEVICE_TSF: return "TSF"; + default: return "?"; + } +} + +const char *cmd_entry_type_name(cmd_entry_type_t type) +{ + switch (type) + { + case CMD_ENTRY_FILE: return "file"; + case CMD_ENTRY_DIR: return "dir"; + case CMD_ENTRY_PARENT: return "parent"; + case CMD_ENTRY_UNKNOWN: return "unknown"; + default: return "unknown"; + } +} + +bool cmd_fs_is_valid_device_id(cmd_device_id_t device_id) +{ + if (device_id < 0) return false; + if (device_id >= CMD_DEVICE_MAX) return false; + return true; +} + +esp_err_t cmd_fs_copy_path(const char *src, char *out, size_t out_size) +{ + const char *s = src; + size_t len; + + if (!out || out_size == 0) return ESP_ERR_INVALID_ARG; + if (!s || !s[0]) s = "/"; + + len = strlen(s); + if (len >= out_size) return CMD_ERR_PATH_TOO_LONG; + + memcpy(out, s, len); + out[len] = 0; + return ESP_OK; +} + +bool cmd_fs_path_is_root(const char *path) +{ + if (!path || !path[0]) return true; + if (strcmp(path, "/") == 0) return true; + return false; +} + +esp_err_t cmd_fs_join_path(const char *left, const char *right, char *out, size_t out_size) +{ + const char *a = left; + const char *b = right; + size_t a_len; + size_t b_len; + size_t pos = 0; + bool need_slash; + + if (!out || out_size == 0) return ESP_ERR_INVALID_ARG; + if (!a || !a[0]) a = "/"; + if (!b) b = ""; + + a_len = strlen(a); + while (a_len > 1 && a[a_len - 1] == '/') + a_len--; + + while (*b == '/') + b++; + + b_len = strlen(b); + + if (b_len == 0) + { + if (a_len >= out_size) return CMD_ERR_PATH_TOO_LONG; + memcpy(out, a, a_len); + out[a_len] = 0; + return ESP_OK; + } + + need_slash = !(a_len == 1 && a[0] == '/'); + + if (a_len + (need_slash ? 1 : 0) + b_len >= out_size) + return CMD_ERR_PATH_TOO_LONG; + + if (a_len == 1 && a[0] == '/') + { + out[pos++] = '/'; + } + else + { + memcpy(out + pos, a, a_len); + pos += a_len; + out[pos++] = '/'; + } + + memcpy(out + pos, b, b_len); + pos += b_len; + out[pos] = 0; + return ESP_OK; +} + +esp_err_t cmd_fs_join3_path(const char *left, const char *middle, const char *right, char *out, size_t out_size) +{ + char tmp[CMD_PATH_MAX]; + esp_err_t err; + + err = cmd_fs_join_path(left, middle, tmp, sizeof(tmp)); + if (err != ESP_OK) return err; + + return cmd_fs_join_path(tmp, right, out, out_size); +} + +esp_err_t cmd_fs_parent_path(const char *path, char *out, size_t out_size) +{ + const char *src = path; + size_t len; + size_t i; + size_t parent_len; + + if (!out || out_size == 0) return ESP_ERR_INVALID_ARG; + if (!src || !src[0]) src = "/"; + + len = strlen(src); + while (len > 1 && src[len - 1] == '/') + len--; + + if (len == 1 && src[0] == '/') + return cmd_fs_copy_path("/", out, out_size); + + i = len; + while (i > 0 && src[i - 1] != '/') + i--; + + if (i == 0 || i == 1) + return cmd_fs_copy_path("/", out, out_size); + + parent_len = i - 1; + if (parent_len >= out_size) return CMD_ERR_PATH_TOO_LONG; + + memcpy(out, src, parent_len); + out[parent_len] = 0; + return ESP_OK; +} + +const char *cmd_fs_filename_ptr(const char *path) +{ + const char *p = path; + const char *name = path; + + if (!path) return ""; + if (!path[0]) return ""; + + while (*p) + { + if (*p == '/' && p[1]) + name = p + 1; + p++; + } + + return name; +} + +esp_err_t cmd_fs_extract_filename(const char *path, char *out, size_t out_size) +{ + const char *src = path; + size_t len; + size_t end; + size_t start; + size_t name_len; + + if (!out || out_size == 0) return ESP_ERR_INVALID_ARG; + if (!src || !src[0]) + { + out[0] = 0; + return ESP_OK; + } + + len = strlen(src); + end = len; + while (end > 0 && src[end - 1] == '/') + end--; + + if (end == 0) + { + out[0] = 0; + return ESP_OK; + } + + start = end; + while (start > 0 && src[start - 1] != '/') + start--; + + name_len = end - start; + if (name_len >= out_size) return CMD_ERR_ENTRY_TOO_LONG; + + memcpy(out, src + start, name_len); + out[name_len] = 0; + return ESP_OK; +} + +bool cmd_fs_path_has_root_prefix(const char *root_path, const char *path) +{ + size_t root_len; + + if (!root_path || !root_path[0]) return false; + if (!path || !path[0]) return false; + + root_len = strlen(root_path); + if (root_len == 1 && root_path[0] == '/') return path[0] == '/'; + if (strncmp(path, root_path, root_len) != 0) return false; + + return path[root_len] == 0 || path[root_len] == '/'; +} + +esp_err_t cmd_fs_driver_build_abs_path(const CmdFsDriver *driver, const char *path, char *out, size_t out_size) +{ + if (!driver || !driver->root_path || !driver->root_path[0]) return ESP_ERR_INVALID_ARG; + if (cmd_fs_path_has_root_prefix(driver->root_path, path)) + return cmd_fs_copy_path(path, out, out_size); + + return cmd_fs_join_path(driver->root_path, path, out, out_size); +} + +esp_err_t cmd_fs_check_root_path(const CmdFsDriver *driver) +{ + DIR *dir; + struct stat st = {}; + + if (!driver || !driver->root_path || !driver->root_path[0]) return ESP_ERR_INVALID_ARG; + + errno = 0; + dir = opendir(driver->root_path); + if (dir) + { + closedir(dir); + return ESP_OK; + } + + errno = 0; + if (stat(driver->root_path, &st) != 0) return cmd_fs_errno_to_err(errno); + if (!S_ISDIR(st.st_mode)) return ESP_ERR_INVALID_STATE; + + return ESP_OK; +} + +esp_err_t cmd_fs_driver_space_info(const CmdFsDriver *driver, CmdFsSpaceInfo *info) +{ + uint64_t total = 0; + uint64_t free = 0; + esp_err_t err; + + if (!driver || !driver->root_path || !driver->root_path[0]) return ESP_ERR_INVALID_ARG; + if (!info) return ESP_ERR_INVALID_ARG; + + memset(info, 0, sizeof(*info)); + + if (driver->device_id == CMD_DEVICE_SD) + { + esp_log_level_t old_sd_host_level = sd_host_log_suppress_begin(); + + err = sd_fs_mount_quiet(driver->root_path, NULL); + if (err == ESP_OK) + err = esp_vfs_fat_info(driver->root_path, &total, &free); + + sd_host_log_suppress_end(old_sd_host_level); + if (err != ESP_OK) return err; + + info->total_bytes = total; + info->free_bytes = free; + return ESP_OK; + } + + if (driver->device_id == CMD_DEVICE_FAT) + { + err = esp_vfs_fat_info(driver->root_path, &total, &free); + if (err != ESP_OK) return err; + + info->total_bytes = total; + info->free_bytes = free; + return ESP_OK; + } + + if (driver->device_id == CMD_DEVICE_TSF) + return tsf_storage_space_info(&info->total_bytes, &info->free_bytes); + + return CMD_ERR_INVALID_DEVICE; +} + +cmd_entry_type_t cmd_fs_entry_type_from_mode(mode_t mode) +{ + if (S_ISDIR(mode)) return CMD_ENTRY_DIR; + if (S_ISREG(mode)) return CMD_ENTRY_FILE; + return CMD_ENTRY_UNKNOWN; +} + +esp_err_t cmd_fs_fill_entry_from_stat(const char *name, const struct stat *st, cmd_file_entry_t *entry) +{ + if (!name || !st || !entry) return ESP_ERR_INVALID_ARG; + + memset(entry, 0, sizeof(*entry)); + size_t name_len = strlen(name); + if (name_len >= sizeof(entry->name)) return CMD_ERR_ENTRY_TOO_LONG; + memcpy(entry->name, name, name_len); + entry->name[name_len] = 0; + + entry->type = cmd_fs_entry_type_from_mode(st->st_mode); + entry->size = (uint64_t)st->st_size; + entry->mtime = (uint64_t)st->st_mtime; + entry->flags = CMD_ENTRY_FLAG_NONE; + return ESP_OK; +} + +esp_err_t cmd_fs_fill_parent_entry(cmd_file_entry_t *entry) +{ + if (!entry) return ESP_ERR_INVALID_ARG; + + memset(entry, 0, sizeof(*entry)); + entry->name[0] = '.'; + entry->name[1] = '.'; + entry->name[2] = 0; + + entry->type = CMD_ENTRY_PARENT; + entry->size = 0; + entry->mtime = 0; + entry->flags = CMD_ENTRY_FLAG_NONE; + return ESP_OK; +} + +esp_err_t cmd_fs_posix_list_begin(CmdFsDriver *driver, const char *path, CmdFsList *list) +{ + DIR *dir; + esp_err_t err; + + if (!driver || !list) return ESP_ERR_INVALID_ARG; + + memset(list, 0, sizeof(*list)); + list->device_id = driver->device_id; + + err = cmd_fs_copy_path(path, list->path, sizeof(list->path)); + if (err != ESP_OK) return err; + + err = cmd_fs_driver_build_abs_path(driver, list->path, list->abs_path, sizeof(list->abs_path)); + if (err != ESP_OK) return err; + + dir = opendir(list->abs_path); + if (!dir) return cmd_fs_errno_to_err(errno); + + list->dir = dir; + list->parent_pending = !cmd_fs_path_is_root(list->path); + list->index = 0; + list->flags = 0; + return ESP_OK; +} + +esp_err_t cmd_fs_posix_list_next(CmdFsDriver *driver, CmdFsList *list, cmd_file_entry_t *entry) +{ + DIR *dir; + struct dirent *de; + char item_path[CMD_PATH_MAX]; + struct stat st = {}; + esp_err_t err; + + if (!driver || !list || !entry) return ESP_ERR_INVALID_ARG; + if (list->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + + if (list->parent_pending) + { + list->parent_pending = false; + list->index++; + return cmd_fs_fill_parent_entry(entry); + } + + dir = (DIR *)list->dir; + if (!dir) return ESP_ERR_INVALID_STATE; + + for (;;) + { + errno = 0; + de = readdir(dir); + if (!de) + { + if (errno != 0) return cmd_fs_errno_to_err(errno); + return ESP_ERR_NOT_FOUND; + } + + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) + continue; + + err = cmd_fs_join_path(list->abs_path, de->d_name, item_path, sizeof(item_path)); + if (err != ESP_OK) return err; + + if (stat(item_path, &st) != 0) + { + memset(entry, 0, sizeof(*entry)); + err = cmd_fs_copy_path(de->d_name, entry->name, sizeof(entry->name)); + if (err != ESP_OK) return err; + entry->type = CMD_ENTRY_UNKNOWN; + entry->flags = CMD_ENTRY_FLAG_ERROR; + } + else + { + err = cmd_fs_fill_entry_from_stat(de->d_name, &st, entry); + if (err != ESP_OK) return err; + } + + list->index++; + return ESP_OK; + } +} + +void cmd_fs_posix_list_close(CmdFsDriver *driver, CmdFsList *list) +{ + if (!driver || !list) return; + if (list->device_id != driver->device_id) return; + + if (list->dir) + { + closedir((DIR *)list->dir); + list->dir = NULL; + } + + memset(list, 0, sizeof(*list)); +} + +esp_err_t cmd_fs_posix_stat(CmdFsDriver *driver, const char *path, cmd_file_entry_t *entry) +{ + char abs[CMD_PATH_MAX]; + struct stat st = {}; + esp_err_t err; + + if (!driver || !entry) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_driver_build_abs_path(driver, path, abs, sizeof(abs)); + if (err != ESP_OK) return err; + + if (stat(abs, &st) != 0) return cmd_fs_errno_to_err(errno); + + return cmd_fs_fill_entry_from_stat(cmd_fs_filename_ptr(abs), &st, entry); +} + +esp_err_t cmd_fs_posix_mkdir(CmdFsDriver *driver, const char *path) +{ + char abs[CMD_PATH_MAX]; + esp_err_t err; + + if (!driver) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_driver_build_abs_path(driver, path, abs, sizeof(abs)); + if (err != ESP_OK) return err; + + if (mkdir(abs, 0775) != 0) return cmd_fs_errno_to_err(errno); + return ESP_OK; +} + +esp_err_t cmd_fs_posix_remove(CmdFsDriver *driver, const char *path) +{ + char abs[CMD_PATH_MAX]; + esp_err_t err; + + if (!driver) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_driver_build_abs_path(driver, path, abs, sizeof(abs)); + if (err != ESP_OK) return err; + + if (remove(abs) != 0) return cmd_fs_errno_to_err(errno); + return ESP_OK; +} + +esp_err_t cmd_fs_posix_rename(CmdFsDriver *driver, const char *old_path, const char *new_path) +{ + char old_abs[CMD_PATH_MAX]; + char new_abs[CMD_PATH_MAX]; + esp_err_t err; + + if (!driver) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_driver_build_abs_path(driver, old_path, old_abs, sizeof(old_abs)); + if (err != ESP_OK) return err; + + err = cmd_fs_driver_build_abs_path(driver, new_path, new_abs, sizeof(new_abs)); + if (err != ESP_OK) return err; + + if (rename(old_abs, new_abs) != 0) return cmd_fs_errno_to_err(errno); + return ESP_OK; +} + +esp_err_t cmd_fs_posix_open(CmdFsDriver *driver, const char *path, const char *mode, CmdFsFile *file) +{ + char abs[CMD_PATH_MAX]; + esp_err_t err; + + if (!driver || !mode || !file) return ESP_ERR_INVALID_ARG; + + memset(file, 0, sizeof(*file)); + + err = cmd_fs_driver_build_abs_path(driver, path, abs, sizeof(abs)); + if (err != ESP_OK) return err; + + file->fp = fopen(abs, mode); + if (!file->fp) return cmd_fs_errno_to_err(errno); + + file->device_id = driver->device_id; + return ESP_OK; +} + +esp_err_t cmd_fs_posix_open_read(CmdFsDriver *driver, const char *path, CmdFsFile *file) +{ + return cmd_fs_posix_open(driver, path, "rb", file); +} + +esp_err_t cmd_fs_posix_open_write(CmdFsDriver *driver, const char *path, CmdFsFile *file) +{ + return cmd_fs_posix_open(driver, path, "wb", file); +} + +esp_err_t cmd_fs_posix_read(CmdFsDriver *driver, CmdFsFile *file, void *dst, size_t size, size_t *out_size) +{ + size_t got; + + if (!driver || !file || !dst) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->fp) return ESP_ERR_INVALID_STATE; + + got = fread(dst, 1, size, file->fp); + if (out_size) *out_size = got; + if (got < size && ferror(file->fp)) return ESP_FAIL; + + return ESP_OK; +} + +esp_err_t cmd_fs_posix_write(CmdFsDriver *driver, CmdFsFile *file, const void *src, size_t size, size_t *out_size) +{ + size_t done; + + if (!driver || !file || (!src && size)) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->fp) return ESP_ERR_INVALID_STATE; + + done = fwrite(src, 1, size, file->fp); + if (out_size) *out_size = done; + if (done != size) return ESP_FAIL; + + return ESP_OK; +} + +esp_err_t cmd_fs_posix_seek(CmdFsDriver *driver, CmdFsFile *file, int64_t offset, int whence) +{ + if (!driver || !file) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->fp) return ESP_ERR_INVALID_STATE; + if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) return ESP_ERR_INVALID_ARG; + if (offset < (int64_t)LONG_MIN || offset > (int64_t)LONG_MAX) return ESP_ERR_INVALID_ARG; + + if (fseek(file->fp, (long)offset, whence) != 0) return cmd_fs_errno_to_err(errno); + return ESP_OK; +} + +esp_err_t cmd_fs_posix_tell(CmdFsDriver *driver, CmdFsFile *file, uint64_t *out_pos) +{ + long pos; + + if (!driver || !file || !out_pos) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->fp) return ESP_ERR_INVALID_STATE; + + pos = ftell(file->fp); + if (pos < 0) return cmd_fs_errno_to_err(errno); + + *out_pos = (uint64_t)pos; + return ESP_OK; +} + +esp_err_t cmd_fs_posix_close(CmdFsDriver *driver, CmdFsFile *file) +{ + int rc; + + if (!driver || !file) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->fp) return ESP_OK; + + rc = fclose(file->fp); + file->fp = NULL; + file->device_id = CMD_DEVICE_INVALID; + if (rc != 0) return cmd_fs_errno_to_err(errno); + + return ESP_OK; +} + + +esp_err_t cmd_fs_tsf_require_volume(TSF_VOLUME **out_vol) +{ + esp_err_t err; + TSF_VOLUME *vol; + + if (!out_vol) return ESP_ERR_INVALID_ARG; + + err = tsf_storage_ensure_ready_quiet(); + if (err != ESP_OK) return err; + + vol = tsf_storage_volume(); + if (!vol) return ESP_ERR_INVALID_STATE; + + *out_vol = vol; + return ESP_OK; +} + +esp_err_t cmd_fs_tsf_fill_file_entry(const char *name, uint32_t size, cmd_file_entry_t *entry) +{ + esp_err_t err; + + if (!name || !entry) return ESP_ERR_INVALID_ARG; + + memset(entry, 0, sizeof(*entry)); + err = cmd_fs_copy_path(name, entry->name, sizeof(entry->name)); + if (err != ESP_OK) return err; + + entry->type = CMD_ENTRY_FILE; + entry->size = size; + entry->mtime = 0; + entry->flags = CMD_ENTRY_FLAG_NONE; + return ESP_OK; +} + +esp_err_t cmd_fs_tsf_list_begin(CmdFsDriver *driver, const char *path, CmdFsList *list) +{ + TSF_VOLUME *vol; + esp_err_t err; + TSF_RESULT res; + + if (!driver || !list) return ESP_ERR_INVALID_ARG; + if (!tsf_storage_path_is_root(path)) return ESP_ERR_NOT_SUPPORTED; + + err = cmd_fs_tsf_require_volume(&vol); + if (err != ESP_OK) return err; + + memset(list, 0, sizeof(*list)); + list->device_id = driver->device_id; + err = cmd_fs_copy_path(path, list->path, sizeof(list->path)); + if (err != ESP_OK) return err; + list->parent_pending = false; + list->index = 0; + + res = tsf_list(vol, TSF_LIST_START); + return tsf_storage_result_to_err(res); +} + +esp_err_t cmd_fs_tsf_list_next(CmdFsDriver *driver, CmdFsList *list, cmd_file_entry_t *entry) +{ + TSF_VOLUME *vol; + TSF_CONFIG *cfg; + TSF_FILE_STAT st = {}; + TSF_RESULT res; + esp_err_t err; + + if (!driver || !list || !entry) return ESP_ERR_INVALID_ARG; + if (list->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + + err = cmd_fs_tsf_require_volume(&vol); + if (err != ESP_OK) return err; + + cfg = vol->cfg; + if (!cfg || !cfg->buf) return ESP_ERR_INVALID_STATE; + + res = tsf_list(vol, TSF_LIST_NEXT); + if (res != TSF_RES_OK) return tsf_storage_result_to_err(res); + + res = tsf_stat(vol, &st, (const char *)cfg->buf); + if (res != TSF_RES_OK) return tsf_storage_result_to_err(res); + + list->index++; + return cmd_fs_tsf_fill_file_entry((const char *)cfg->buf, st.size, entry); +} + +void cmd_fs_tsf_list_close(CmdFsDriver *driver, CmdFsList *list) +{ + if (!driver || !list) return; + if (list->device_id != driver->device_id) return; + memset(list, 0, sizeof(*list)); +} + +esp_err_t cmd_fs_tsf_stat(CmdFsDriver *driver, const char *path, cmd_file_entry_t *entry) +{ + char name[CMD_FILE_NAME_MAX]; + TSF_VOLUME *vol; + TSF_FILE_STAT st = {}; + TSF_RESULT res; + esp_err_t err; + + if (!driver || !entry) return ESP_ERR_INVALID_ARG; + + if (tsf_storage_path_is_root(path)) + { + memset(entry, 0, sizeof(*entry)); + err = cmd_fs_copy_path("/", entry->name, sizeof(entry->name)); + if (err != ESP_OK) return err; + entry->type = CMD_ENTRY_DIR; + return ESP_OK; + } + + err = tsf_storage_name_from_path(path, name, sizeof(name)); + if (err != ESP_OK) return err; + + err = cmd_fs_tsf_require_volume(&vol); + if (err != ESP_OK) return err; + + res = tsf_stat(vol, &st, name); + if (res != TSF_RES_OK) return tsf_storage_result_to_err(res); + + return cmd_fs_tsf_fill_file_entry(name, st.size, entry); +} + +esp_err_t cmd_fs_tsf_mkdir(CmdFsDriver *driver, const char *path) +{ + if (!driver || !path) return ESP_ERR_INVALID_ARG; + return ESP_ERR_NOT_SUPPORTED; +} + +esp_err_t cmd_fs_tsf_remove(CmdFsDriver *driver, const char *path) +{ + char name[CMD_FILE_NAME_MAX]; + TSF_VOLUME *vol; + TSF_RESULT res; + esp_err_t err; + + if (!driver) return ESP_ERR_INVALID_ARG; + + err = tsf_storage_name_from_path(path, name, sizeof(name)); + if (err != ESP_OK) return err; + + err = cmd_fs_tsf_require_volume(&vol); + if (err != ESP_OK) return err; + + res = tsf_delete(vol, name); + return tsf_storage_result_to_err(res); +} + +esp_err_t cmd_fs_tsf_rename(CmdFsDriver *driver, const char *old_path, const char *new_path) +{ + if (!driver || !old_path || !new_path) return ESP_ERR_INVALID_ARG; + return ESP_ERR_NOT_SUPPORTED; +} + +esp_err_t cmd_fs_tsf_open_common(CmdFsDriver *driver, const char *path, u8 mode, CmdFsFile *file) +{ + char name[CMD_FILE_NAME_MAX]; + TSF_VOLUME *vol; + TSF_FILE *tsf_file; + TSF_RESULT res; + esp_err_t err; + + if (!driver || !file) return ESP_ERR_INVALID_ARG; + + err = tsf_storage_name_from_path(path, name, sizeof(name)); + if (err != ESP_OK) return err; + + err = cmd_fs_tsf_require_volume(&vol); + if (err != ESP_OK) return err; + + memset(file, 0, sizeof(*file)); + tsf_file = (TSF_FILE *)calloc(1, sizeof(TSF_FILE)); + if (!tsf_file) return ESP_ERR_NO_MEM; + + if (mode == TSF_MODE_CREATE_WRITE) + { + res = tsf_delete(vol, name); + if (res != TSF_RES_OK && res != TSF_RES_FILE_NOT_FOUND) + { + free(tsf_file); + return tsf_storage_result_to_err(res); + } + } + + res = tsf_open(vol, tsf_file, name, mode); + if (res != TSF_RES_OK) + { + free(tsf_file); + return tsf_storage_result_to_err(res); + } + + file->device_id = driver->device_id; + file->ctx = tsf_file; + file->flags = mode; + err = cmd_fs_copy_path(name, file->name, sizeof(file->name)); + if (err != ESP_OK) + { + tsf_close(tsf_file); + free(tsf_file); + memset(file, 0, sizeof(*file)); + return err; + } + + return ESP_OK; +} + +esp_err_t cmd_fs_tsf_open_read(CmdFsDriver *driver, const char *path, CmdFsFile *file) +{ + return cmd_fs_tsf_open_common(driver, path, TSF_MODE_READ, file); +} + +esp_err_t cmd_fs_tsf_open_write(CmdFsDriver *driver, const char *path, CmdFsFile *file) +{ + return cmd_fs_tsf_open_common(driver, path, TSF_MODE_CREATE_WRITE, file); +} + +esp_err_t cmd_fs_tsf_read(CmdFsDriver *driver, CmdFsFile *file, void *dst, size_t size, size_t *out_size) +{ + TSF_FILE *tsf_file; + TSF_RESULT res; + u32 before; + u32 todo; + + if (!driver || !file || !dst) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->ctx) return ESP_ERR_INVALID_STATE; + if (size > UINT32_MAX) return ESP_ERR_INVALID_SIZE; + + tsf_file = (TSF_FILE *)file->ctx; + before = tsf_file->seek; + todo = (u32)size; + + res = tsf_read(tsf_file, dst, todo); + if (out_size) *out_size = (size_t)(tsf_file->seek - before); + + return tsf_storage_result_to_err(res); +} + +esp_err_t cmd_fs_tsf_write(CmdFsDriver *driver, CmdFsFile *file, const void *src, size_t size, size_t *out_size) +{ + TSF_FILE *tsf_file; + TSF_RESULT res; + u32 before; + u32 todo; + + if (!driver || !file || (!src && size)) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->ctx) return ESP_ERR_INVALID_STATE; + if (size > UINT32_MAX) return ESP_ERR_INVALID_SIZE; + + tsf_file = (TSF_FILE *)file->ctx; + before = tsf_file->seek; + todo = (u32)size; + + res = tsf_write(tsf_file, src, todo); + if (out_size) *out_size = (size_t)(tsf_file->seek - before); + + return tsf_storage_result_to_err(res); +} + +esp_err_t cmd_fs_tsf_reopen_read(CmdFsDriver *driver, CmdFsFile *file) +{ + TSF_VOLUME *vol; + TSF_FILE *tsf_file; + TSF_RESULT res; + esp_err_t err; + + if (!driver || !file || !file->ctx) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_tsf_require_volume(&vol); + if (err != ESP_OK) return err; + + tsf_file = (TSF_FILE *)file->ctx; + memset(tsf_file, 0, sizeof(*tsf_file)); + res = tsf_open(vol, tsf_file, file->name, TSF_MODE_READ); + return tsf_storage_result_to_err(res); +} + +esp_err_t cmd_fs_tsf_seek(CmdFsDriver *driver, CmdFsFile *file, int64_t offset, int whence) +{ + TSF_FILE *tsf_file; + int64_t base; + int64_t target; + TSF_RESULT res; + esp_err_t err; + + if (!driver || !file) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->ctx) return ESP_ERR_INVALID_STATE; + if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) return ESP_ERR_INVALID_ARG; + + tsf_file = (TSF_FILE *)file->ctx; + if ((file->flags & TSF_MODE_WRITE) == TSF_MODE_WRITE) return ESP_ERR_NOT_SUPPORTED; + + if (whence == SEEK_SET) + base = 0; + else if (whence == SEEK_CUR) + base = (int64_t)tsf_file->seek; + else + base = (int64_t)tsf_file->size; + + target = base + offset; + if (target < 0 || target > (int64_t)tsf_file->size) return ESP_ERR_INVALID_ARG; + + if ((u32)target < tsf_file->seek) + { + err = cmd_fs_tsf_reopen_read(driver, file); + if (err != ESP_OK) return err; + tsf_file = (TSF_FILE *)file->ctx; + } + + res = tsf_seek(tsf_file, (u32)target - tsf_file->seek); + return tsf_storage_result_to_err(res); +} + +esp_err_t cmd_fs_tsf_tell(CmdFsDriver *driver, CmdFsFile *file, uint64_t *out_pos) +{ + TSF_FILE *tsf_file; + + if (!driver || !file || !out_pos) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->ctx) return ESP_ERR_INVALID_STATE; + + tsf_file = (TSF_FILE *)file->ctx; + *out_pos = tsf_file->seek; + return ESP_OK; +} + +esp_err_t cmd_fs_tsf_close(CmdFsDriver *driver, CmdFsFile *file) +{ + TSF_FILE *tsf_file; + TSF_RESULT res; + + if (!driver || !file) return ESP_ERR_INVALID_ARG; + if (file->device_id != driver->device_id) return CMD_ERR_INVALID_DEVICE; + if (!file->ctx) return ESP_OK; + + tsf_file = (TSF_FILE *)file->ctx; + res = tsf_close(tsf_file); + free(tsf_file); + memset(file, 0, sizeof(*file)); + file->device_id = CMD_DEVICE_INVALID; + + return tsf_storage_result_to_err(res); +} + +esp_err_t cmd_fs_sd_sense(CmdFsDriver *driver) +{ + if (!driver) return ESP_ERR_INVALID_ARG; + return sd_fs_mount_quiet(driver->root_path, NULL); +} + +esp_err_t cmd_fs_sd_mount_once() +{ + return sd_fs_mount_quiet(CMD_FS_SD_ROOT_PATH, NULL); +} + +esp_err_t cmd_fs_sd_mount(CmdFsDriver *driver) +{ + esp_err_t err; + + if (!driver) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_sd_mount_once(); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +esp_err_t cmd_fs_fat_mount(CmdFsDriver *driver) +{ + esp_err_t err; + + if (!driver) return ESP_ERR_INVALID_ARG; + + err = fs_ensure_ready_quiet(); + if (err != ESP_OK) return err; + + return cmd_fs_check_root_path(driver); +} + +esp_err_t cmd_fs_tsf_mount(CmdFsDriver *driver) +{ + if (!driver) return ESP_ERR_INVALID_ARG; + return tsf_storage_ensure_ready_quiet(); +} + +esp_err_t cmd_fs_sd_list_begin(CmdFsDriver *driver, const char *path, CmdFsList *list) +{ + esp_err_t err; + + if (!driver || !list) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + + return cmd_fs_posix_list_begin(driver, path, list); +} + +esp_err_t cmd_fs_sd_list_next(CmdFsDriver *driver, CmdFsList *list, cmd_file_entry_t *entry) +{ + esp_err_t err; + + err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + + return cmd_fs_posix_list_next(driver, list, entry); +} + +esp_err_t cmd_fs_sd_stat(CmdFsDriver *driver, const char *path, cmd_file_entry_t *entry) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_stat(driver, path, entry); +} + +esp_err_t cmd_fs_sd_mkdir(CmdFsDriver *driver, const char *path) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_mkdir(driver, path); +} + +esp_err_t cmd_fs_sd_remove(CmdFsDriver *driver, const char *path) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_remove(driver, path); +} + +esp_err_t cmd_fs_sd_rename(CmdFsDriver *driver, const char *old_path, const char *new_path) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_rename(driver, old_path, new_path); +} + +esp_err_t cmd_fs_sd_open_read(CmdFsDriver *driver, const char *path, CmdFsFile *file) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_open_read(driver, path, file); +} + +esp_err_t cmd_fs_sd_open_write(CmdFsDriver *driver, const char *path, CmdFsFile *file) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_open_write(driver, path, file); +} + +esp_err_t cmd_fs_sd_read(CmdFsDriver *driver, CmdFsFile *file, void *dst, size_t size, size_t *out_size) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_read(driver, file, dst, size, out_size); +} + +esp_err_t cmd_fs_sd_write(CmdFsDriver *driver, CmdFsFile *file, const void *src, size_t size, size_t *out_size) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_write(driver, file, src, size, out_size); +} + +esp_err_t cmd_fs_sd_seek(CmdFsDriver *driver, CmdFsFile *file, int64_t offset, int whence) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_seek(driver, file, offset, whence); +} + +esp_err_t cmd_fs_sd_tell(CmdFsDriver *driver, CmdFsFile *file, uint64_t *out_pos) +{ + esp_err_t err = cmd_fs_sd_sense(driver); + if (err != ESP_OK) return err; + return cmd_fs_posix_tell(driver, file, out_pos); +} + +esp_err_t cmd_fs_sd_unmount(CmdFsDriver *driver) +{ + if (!driver) return ESP_ERR_INVALID_ARG; + return ESP_OK; +} + +esp_err_t cmd_fs_noop_unmount(CmdFsDriver *driver) +{ + if (!driver) return ESP_ERR_INVALID_ARG; + return ESP_OK; +} + +CmdFsDriver cmd_fs_sd_driver = +{ + .device_id = CMD_DEVICE_SD, + .name = "sd", + .root_path = CMD_FS_SD_ROOT_PATH, + .ctx = NULL, + .mount = cmd_fs_sd_mount, + .unmount = cmd_fs_sd_unmount, + .list_begin = cmd_fs_sd_list_begin, + .list_next = cmd_fs_sd_list_next, + .list_close = cmd_fs_posix_list_close, + .stat = cmd_fs_sd_stat, + .mkdir = cmd_fs_sd_mkdir, + .remove = cmd_fs_sd_remove, + .rename = cmd_fs_sd_rename, + .open_read = cmd_fs_sd_open_read, + .open_write = cmd_fs_sd_open_write, + .read = cmd_fs_sd_read, + .write = cmd_fs_sd_write, + .seek = cmd_fs_sd_seek, + .tell = cmd_fs_sd_tell, + .close = cmd_fs_posix_close +}; + +CmdFsDriver cmd_fs_fat_driver = +{ + .device_id = CMD_DEVICE_FAT, + .name = "fat", + .root_path = FS_BASE_PATH, + .ctx = NULL, + .mount = cmd_fs_fat_mount, + .unmount = cmd_fs_noop_unmount, + .list_begin = cmd_fs_posix_list_begin, + .list_next = cmd_fs_posix_list_next, + .list_close = cmd_fs_posix_list_close, + .stat = cmd_fs_posix_stat, + .mkdir = cmd_fs_posix_mkdir, + .remove = cmd_fs_posix_remove, + .rename = cmd_fs_posix_rename, + .open_read = cmd_fs_posix_open_read, + .open_write = cmd_fs_posix_open_write, + .read = cmd_fs_posix_read, + .write = cmd_fs_posix_write, + .seek = cmd_fs_posix_seek, + .tell = cmd_fs_posix_tell, + .close = cmd_fs_posix_close +}; + +CmdFsDriver cmd_fs_tsf_driver = +{ + .device_id = CMD_DEVICE_TSF, + .name = "tsf", + .root_path = TSF_BASE_PATH, + .ctx = NULL, + .mount = cmd_fs_tsf_mount, + .unmount = cmd_fs_noop_unmount, + .list_begin = cmd_fs_tsf_list_begin, + .list_next = cmd_fs_tsf_list_next, + .list_close = cmd_fs_tsf_list_close, + .stat = cmd_fs_tsf_stat, + .mkdir = cmd_fs_tsf_mkdir, + .remove = cmd_fs_tsf_remove, + .rename = cmd_fs_tsf_rename, + .open_read = cmd_fs_tsf_open_read, + .open_write = cmd_fs_tsf_open_write, + .read = cmd_fs_tsf_read, + .write = cmd_fs_tsf_write, + .seek = cmd_fs_tsf_seek, + .tell = cmd_fs_tsf_tell, + .close = cmd_fs_tsf_close +}; + +void cmd_fs_manager_init(CmdFsManager *manager) +{ + if (!manager) return; + + memset(manager, 0, sizeof(*manager)); +} + +esp_err_t cmd_fs_manager_register_driver(CmdFsManager *manager, CmdFsDriver *driver) +{ + uint32_t bit; + + if (!manager || !driver) return ESP_ERR_INVALID_ARG; + if (!cmd_fs_is_valid_device_id(driver->device_id)) return CMD_ERR_INVALID_DEVICE; + if (!driver->root_path || !driver->root_path[0]) return ESP_ERR_INVALID_ARG; + + bit = 1u << (uint32_t)driver->device_id; + if (manager->registered_mask & bit) return ESP_ERR_INVALID_STATE; + + manager->drivers[driver->device_id] = driver; + manager->registered_mask |= bit; + return ESP_OK; +} + +esp_err_t cmd_fs_manager_unregister_driver(CmdFsManager *manager, cmd_device_id_t device_id) +{ + uint32_t bit; + + if (!manager) return ESP_ERR_INVALID_ARG; + if (!cmd_fs_is_valid_device_id(device_id)) return CMD_ERR_INVALID_DEVICE; + + bit = 1u << (uint32_t)device_id; + manager->drivers[device_id] = NULL; + manager->registered_mask &= ~bit; + return ESP_OK; +} + +CmdFsDriver *cmd_fs_manager_get_driver(CmdFsManager *manager, cmd_device_id_t device_id) +{ + if (!manager) return NULL; + if (!cmd_fs_is_valid_device_id(device_id)) return NULL; + + return manager->drivers[device_id]; +} + +const CmdFsDriver *cmd_fs_manager_get_driver_const(const CmdFsManager *manager, cmd_device_id_t device_id) +{ + if (!manager) return NULL; + if (!cmd_fs_is_valid_device_id(device_id)) return NULL; + + return manager->drivers[device_id]; +} + +esp_err_t cmd_fs_manager_register_default_drivers(CmdFsManager *manager) +{ + esp_err_t err; + + if (!manager) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_manager_register_driver(manager, &cmd_fs_sd_driver); + if (err != ESP_OK) return err; + + err = cmd_fs_manager_register_driver(manager, &cmd_fs_fat_driver); + if (err != ESP_OK) return err; + + return cmd_fs_manager_register_driver(manager, &cmd_fs_tsf_driver); +} + +esp_err_t cmd_fs_manager_build_abs_path(const CmdFsManager *manager, cmd_device_id_t device_id, const char *current_path, const char *filename, char *out, size_t out_size) +{ + const CmdFsDriver *driver; + char tmp[CMD_PATH_MAX]; + esp_err_t err; + + if (!out || out_size == 0) return ESP_ERR_INVALID_ARG; + + driver = cmd_fs_manager_get_driver_const(manager, device_id); + if (!driver) return CMD_ERR_INVALID_DEVICE; + + err = cmd_fs_driver_build_abs_path(driver, current_path, tmp, sizeof(tmp)); + if (err != ESP_OK) return err; + + if (!filename || !filename[0]) + return cmd_fs_copy_path(tmp, out, out_size); + + return cmd_fs_join_path(tmp, filename, out, out_size); +} + +esp_err_t cmd_fs_manager_mount(CmdFsManager *manager, cmd_device_id_t device_id) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + uint32_t bit; + esp_err_t err; + + if (!manager) return ESP_ERR_INVALID_ARG; + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->mount) return ESP_ERR_NOT_SUPPORTED; + + bit = 1u << (uint32_t)device_id; + if (manager->mounted_mask & bit) return ESP_OK; + + if (device_id != CMD_DEVICE_SD) + { + err = cmd_fs_check_root_path(driver); + if (err == ESP_OK) + { + manager->mounted_mask |= bit; + return ESP_OK; + } + } + + err = driver->mount(driver); + if (err == ESP_OK) + manager->mounted_mask |= bit; + + return err; +} + +esp_err_t cmd_fs_manager_unmount(CmdFsManager *manager, cmd_device_id_t device_id) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + uint32_t bit; + esp_err_t err = ESP_OK; + + if (!manager) return ESP_ERR_INVALID_ARG; + if (!driver) return CMD_ERR_INVALID_DEVICE; + + bit = 1u << (uint32_t)device_id; + if (!(manager->mounted_mask & bit)) return ESP_OK; + + if (driver->unmount) + err = driver->unmount(driver); + + if (err == ESP_OK) + manager->mounted_mask &= ~bit; + + return err; +} + +esp_err_t cmd_fs_manager_unmount_all(CmdFsManager *manager) +{ + esp_err_t first_err = ESP_OK; + + if (!manager) return ESP_ERR_INVALID_ARG; + + for (int i = 0; i < CMD_DEVICE_MAX; i++) + { + uint32_t bit = 1u << (uint32_t)i; + esp_err_t err; + + if (!(manager->mounted_mask & bit)) + continue; + + err = cmd_fs_manager_unmount(manager, (cmd_device_id_t)i); + if (err != ESP_OK && first_err == ESP_OK) + first_err = err; + } + + return first_err; +} + +esp_err_t cmd_fs_manager_list_begin(CmdFsManager *manager, cmd_device_id_t device_id, const char *path, CmdFsList *list) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->list_begin) return ESP_ERR_NOT_SUPPORTED; + return driver->list_begin(driver, path, list); +} + +esp_err_t cmd_fs_manager_list_next(CmdFsManager *manager, CmdFsList *list, cmd_file_entry_t *entry) +{ + CmdFsDriver *driver; + + if (!list) return ESP_ERR_INVALID_ARG; + + driver = cmd_fs_manager_get_driver(manager, list->device_id); + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->list_next) return ESP_ERR_NOT_SUPPORTED; + return driver->list_next(driver, list, entry); +} + +void cmd_fs_manager_list_close(CmdFsManager *manager, CmdFsList *list) +{ + CmdFsDriver *driver; + + if (!manager || !list) return; + + driver = cmd_fs_manager_get_driver(manager, list->device_id); + if (!driver || !driver->list_close) return; + driver->list_close(driver, list); +} + +esp_err_t cmd_fs_manager_stat(CmdFsManager *manager, cmd_device_id_t device_id, const char *path, cmd_file_entry_t *entry) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->stat) return ESP_ERR_NOT_SUPPORTED; + return driver->stat(driver, path, entry); +} + +esp_err_t cmd_fs_manager_mkdir(CmdFsManager *manager, cmd_device_id_t device_id, const char *path) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->mkdir) return ESP_ERR_NOT_SUPPORTED; + return driver->mkdir(driver, path); +} + +esp_err_t cmd_fs_manager_space_info(CmdFsManager *manager, cmd_device_id_t device_id, CmdFsSpaceInfo *info) +{ + CmdFsDriver *driver; + esp_err_t err; + + if (!manager || !info) return ESP_ERR_INVALID_ARG; + + driver = cmd_fs_manager_get_driver(manager, device_id); + if (!driver) return CMD_ERR_INVALID_DEVICE; + + err = cmd_fs_manager_mount(manager, device_id); + if (err != ESP_OK) return err; + + return cmd_fs_driver_space_info(driver, info); +} + +esp_err_t cmd_fs_manager_remove(CmdFsManager *manager, cmd_device_id_t device_id, const char *path) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->remove) return ESP_ERR_NOT_SUPPORTED; + return driver->remove(driver, path); +} + +esp_err_t cmd_fs_manager_rename(CmdFsManager *manager, cmd_device_id_t device_id, const char *old_path, const char *new_path) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->rename) return ESP_ERR_NOT_SUPPORTED; + return driver->rename(driver, old_path, new_path); +} + +esp_err_t cmd_fs_manager_open_read(CmdFsManager *manager, cmd_device_id_t device_id, const char *path, CmdFsFile *file) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->open_read) return ESP_ERR_NOT_SUPPORTED; + return driver->open_read(driver, path, file); +} + +esp_err_t cmd_fs_manager_open_write(CmdFsManager *manager, cmd_device_id_t device_id, const char *path, CmdFsFile *file) +{ + CmdFsDriver *driver = cmd_fs_manager_get_driver(manager, device_id); + + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->open_write) return ESP_ERR_NOT_SUPPORTED; + return driver->open_write(driver, path, file); +} + +esp_err_t cmd_fs_manager_read(CmdFsManager *manager, CmdFsFile *file, void *dst, size_t size, size_t *out_size) +{ + CmdFsDriver *driver; + + if (!file) return ESP_ERR_INVALID_ARG; + + driver = cmd_fs_manager_get_driver(manager, file->device_id); + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->read) return ESP_ERR_NOT_SUPPORTED; + return driver->read(driver, file, dst, size, out_size); +} + +esp_err_t cmd_fs_manager_write(CmdFsManager *manager, CmdFsFile *file, const void *src, size_t size, size_t *out_size) +{ + CmdFsDriver *driver; + + if (!file) return ESP_ERR_INVALID_ARG; + + driver = cmd_fs_manager_get_driver(manager, file->device_id); + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->write) return ESP_ERR_NOT_SUPPORTED; + return driver->write(driver, file, src, size, out_size); +} + +esp_err_t cmd_fs_manager_seek(CmdFsManager *manager, CmdFsFile *file, int64_t offset, int whence) +{ + CmdFsDriver *driver; + + if (!file) return ESP_ERR_INVALID_ARG; + + driver = cmd_fs_manager_get_driver(manager, file->device_id); + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->seek) return ESP_ERR_NOT_SUPPORTED; + return driver->seek(driver, file, offset, whence); +} + +esp_err_t cmd_fs_manager_tell(CmdFsManager *manager, CmdFsFile *file, uint64_t *out_pos) +{ + CmdFsDriver *driver; + + if (!file || !out_pos) return ESP_ERR_INVALID_ARG; + + driver = cmd_fs_manager_get_driver(manager, file->device_id); + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->tell) return ESP_ERR_NOT_SUPPORTED; + return driver->tell(driver, file, out_pos); +} + +esp_err_t cmd_fs_manager_close(CmdFsManager *manager, CmdFsFile *file) +{ + CmdFsDriver *driver; + + if (!file) return ESP_ERR_INVALID_ARG; + + driver = cmd_fs_manager_get_driver(manager, file->device_id); + if (!driver) return CMD_ERR_INVALID_DEVICE; + if (!driver->close) return ESP_ERR_NOT_SUPPORTED; + return driver->close(driver, file); +} + +// --------------- cmd_input.cpp --------------- + +#ifndef CONFIG_ESP_CONSOLE_UART_NUM +#define CONFIG_ESP_CONSOLE_UART_NUM UART_NUM_0 +#endif + +esp_err_t cmd_input_console_begin(CmdInputBackend *backend); +void cmd_input_console_end(CmdInputBackend *backend); +esp_err_t cmd_input_console_poll_event(CmdInputBackend *backend, cmd_event_t *event, uint32_t timeout_ms); + +CmdInputBackend g_cmd_input_console_backend = +{ + .name = "console-uart", + .ctx = NULL, + .begin = cmd_input_console_begin, + .end = cmd_input_console_end, + .poll_event = cmd_input_console_poll_event +}; + +void cmd_input_event_clear(cmd_event_t *event) +{ + if (!event) return; + + event->type = CMD_EVENT_NONE; + event->key = CMD_KEY_NONE; + event->ch = 0; + event->mods = CMD_KEY_MOD_NONE; +} + +void cmd_input_event_key(cmd_event_t *event, cmd_key_t key, uint32_t mods) +{ + if (!event) return; + + event->type = CMD_EVENT_KEY; + event->key = key; + event->ch = 0; + event->mods = mods; +} + +void cmd_input_event_char(cmd_event_t *event, uint32_t ch, uint32_t mods) +{ + if (!event) return; + + event->type = CMD_EVENT_KEY; + event->key = CMD_KEY_CHAR; + event->ch = ch; + event->mods = mods; +} + +void cmd_input_event_quit(cmd_event_t *event) +{ + if (!event) return; + + event->type = CMD_EVENT_QUIT; + event->key = CMD_KEY_NONE; + event->ch = 0; + event->mods = CMD_KEY_MOD_NONE; +} + +esp_err_t cmd_input_begin(CmdInputBackend *backend) +{ + if (!backend || !backend->begin) return ESP_ERR_INVALID_ARG; + return backend->begin(backend); +} + +void cmd_input_end(CmdInputBackend *backend) +{ + if (!backend || !backend->end) return; + backend->end(backend); +} + +esp_err_t cmd_input_poll_event(CmdInputBackend *backend, cmd_event_t *event, uint32_t timeout_ms) +{ + if (!backend || !backend->poll_event || !event) return ESP_ERR_INVALID_ARG; + return backend->poll_event(backend, event, timeout_ms); +} + +CmdInputBackend *cmd_input_console_backend() +{ + return &g_cmd_input_console_backend; +} + +CmdInputBackend *cmd_input_default_backend() +{ + return cmd_input_console_backend(); +} + +TickType_t cmd_input_timeout_to_ticks(uint32_t timeout_ms) +{ + if (timeout_ms == CMD_INPUT_WAIT_FOREVER) return portMAX_DELAY; + return pdMS_TO_TICKS(timeout_ms); +} + +int cmd_input_uart_read_byte(uint8_t *out, uint32_t timeout_ms) +{ + if (!out) return 0; + + return uart_read_bytes( + (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, + out, + 1, + cmd_input_timeout_to_ticks(timeout_ms)); +} + +uint32_t cmd_input_xterm_mods(int value) +{ + switch (value) + { + case 2: return CMD_KEY_MOD_SHIFT; + case 3: return CMD_KEY_MOD_ALT; + case 4: return CMD_KEY_MOD_SHIFT | CMD_KEY_MOD_ALT; + case 5: return CMD_KEY_MOD_CTRL; + case 6: return CMD_KEY_MOD_SHIFT | CMD_KEY_MOD_CTRL; + case 7: return CMD_KEY_MOD_ALT | CMD_KEY_MOD_CTRL; + case 8: return CMD_KEY_MOD_SHIFT | CMD_KEY_MOD_ALT | CMD_KEY_MOD_CTRL; + default: return CMD_KEY_MOD_NONE; + } +} + +uint32_t cmd_input_csi_mods(const char *seq) +{ + int value = 0; + int have_semicolon = 0; + + if (!seq) return CMD_KEY_MOD_NONE; + + for (size_t i = 0; seq[i]; i++) + { + if (seq[i] == ';') + { + have_semicolon = 1; + value = 0; + continue; + } + + if (have_semicolon && seq[i] >= '0' && seq[i] <= '9') + value = value * 10 + (seq[i] - '0'); + } + + if (!have_semicolon) return CMD_KEY_MOD_NONE; + return cmd_input_xterm_mods(value); +} + +int cmd_input_csi_first_number(const char *seq) +{ + int value = 0; + + if (!seq) return 0; + + for (size_t i = 0; seq[i]; i++) + { + if (seq[i] < '0' || seq[i] > '9') break; + value = value * 10 + (seq[i] - '0'); + } + + return value; +} + +cmd_key_t cmd_input_csi_tilde_key(int code) +{ + switch (code) + { + case 1: return CMD_KEY_HOME; + case 2: return CMD_KEY_INSERT; + case 3: return CMD_KEY_DELETE; + case 4: return CMD_KEY_END; + case 5: return CMD_KEY_PAGE_UP; + case 6: return CMD_KEY_PAGE_DOWN; + case 7: return CMD_KEY_HOME; + case 8: return CMD_KEY_END; + case 11: return CMD_KEY_F1; + case 12: return CMD_KEY_F2; + case 13: return CMD_KEY_F3; + case 14: return CMD_KEY_F4; + case 15: return CMD_KEY_F5; + case 17: return CMD_KEY_F6; + case 18: return CMD_KEY_F7; + case 19: return CMD_KEY_F8; + case 20: return CMD_KEY_F9; + case 21: return CMD_KEY_F10; + case 23: return CMD_KEY_F11; + case 24: return CMD_KEY_F12; + default: return CMD_KEY_UNKNOWN; + } +} + +cmd_key_t cmd_input_csi_final_key(char final) +{ + switch (final) + { + case 'P': return CMD_KEY_F1; + case 'Q': return CMD_KEY_F2; + case 'R': return CMD_KEY_F3; + case 'S': return CMD_KEY_F4; + case 'A': return CMD_KEY_UP; + case 'B': return CMD_KEY_DOWN; + case 'C': return CMD_KEY_RIGHT; + case 'D': return CMD_KEY_LEFT; + case 'H': return CMD_KEY_HOME; + case 'F': return CMD_KEY_END; + case 'Z': return CMD_KEY_TAB; + default: return CMD_KEY_UNKNOWN; + } +} + +cmd_key_t cmd_input_ss3_key(uint8_t c) +{ + switch (c) + { + case 'P': return CMD_KEY_F1; + case 'Q': return CMD_KEY_F2; + case 'R': return CMD_KEY_F3; + case 'S': return CMD_KEY_F4; + case 'A': return CMD_KEY_UP; + case 'B': return CMD_KEY_DOWN; + case 'C': return CMD_KEY_RIGHT; + case 'D': return CMD_KEY_LEFT; + case 'H': return CMD_KEY_HOME; + case 'F': return CMD_KEY_END; + default: return CMD_KEY_UNKNOWN; + } +} + +esp_err_t cmd_input_console_poll_csi(cmd_event_t *event) +{ + char seq[16]; + size_t len = 0; + + memset(seq, 0, sizeof(seq)); + + while (len + 1 < sizeof(seq)) + { + uint8_t c = 0; + if (cmd_input_uart_read_byte(&c, CMD_INPUT_ESC_TIMEOUT_MS) <= 0) + { + cmd_input_event_key(event, CMD_KEY_UNKNOWN, CMD_KEY_MOD_NONE); + return ESP_OK; + } + + seq[len++] = (char)c; + seq[len] = 0; + + if (c >= '@' && c <= '~') + break; + } + + char final = seq[len ? len - 1 : 0]; + uint32_t mods = cmd_input_csi_mods(seq); + cmd_key_t key; + + if (final == '~') + key = cmd_input_csi_tilde_key(cmd_input_csi_first_number(seq)); + else + key = cmd_input_csi_final_key(final); + + if (final == 'Z') + mods |= CMD_KEY_MOD_SHIFT; + + cmd_input_event_key(event, key, mods); + return ESP_OK; +} + +esp_err_t cmd_input_console_poll_ss3(cmd_event_t *event) +{ + uint8_t c = 0; + + if (cmd_input_uart_read_byte(&c, CMD_INPUT_ESC_TIMEOUT_MS) <= 0) + { + cmd_input_event_key(event, CMD_KEY_ESC, CMD_KEY_MOD_NONE); + return ESP_OK; + } + + cmd_input_event_key(event, cmd_input_ss3_key(c), CMD_KEY_MOD_NONE); + return ESP_OK; +} + +esp_err_t cmd_input_console_poll_escape(cmd_event_t *event) +{ + uint8_t c = 0; + esp_err_t err; + + if (cmd_input_uart_read_byte(&c, CMD_INPUT_ESC_TIMEOUT_MS) <= 0) + { + cmd_input_event_key(event, CMD_KEY_ESC, CMD_KEY_MOD_NONE); + return ESP_OK; + } + + if (c == 0x1b) + { + err = cmd_input_console_poll_escape(event); + if (err == ESP_OK && event->type == CMD_EVENT_KEY) + event->mods |= CMD_KEY_MOD_ALT; + return err; + } + + if (c == '[') + return cmd_input_console_poll_csi(event); + + if (c == 'O') + return cmd_input_console_poll_ss3(event); + + if (c >= 0x20) + { + cmd_input_event_char(event, c, CMD_KEY_MOD_ALT); + return ESP_OK; + } + + cmd_input_event_key(event, CMD_KEY_ESC, CMD_KEY_MOD_ALT); + return ESP_OK; +} + +esp_err_t cmd_input_console_byte_to_event(uint8_t c, cmd_event_t *event) +{ + if (c == 0x1b) + return cmd_input_console_poll_escape(event); + + if (c == '\r' || c == '\n') + { + cmd_input_event_key(event, CMD_KEY_ENTER, CMD_KEY_MOD_NONE); + return ESP_OK; + } + + if (c == '\t') + { + cmd_input_event_key(event, CMD_KEY_TAB, CMD_KEY_MOD_NONE); + return ESP_OK; + } + + if (c == 0x08 || c == 0x7f) + { + cmd_input_event_key(event, CMD_KEY_BACKSPACE, CMD_KEY_MOD_NONE); + return ESP_OK; + } + + if (c >= 0x20) + { + cmd_input_event_char(event, c, CMD_KEY_MOD_NONE); + return ESP_OK; + } + + cmd_input_event_key(event, CMD_KEY_UNKNOWN, CMD_KEY_MOD_NONE); + return ESP_OK; +} + +esp_err_t cmd_input_console_begin(CmdInputBackend *backend) +{ + if (!backend) return ESP_ERR_INVALID_ARG; + return ESP_OK; +} + +void cmd_input_console_end(CmdInputBackend *backend) +{ + if (!backend) return; +} + +esp_err_t cmd_input_console_poll_event(CmdInputBackend *backend, cmd_event_t *event, uint32_t timeout_ms) +{ + uint8_t c = 0; + + if (!backend || !event) return ESP_ERR_INVALID_ARG; + + cmd_input_event_clear(event); + + if (cmd_input_uart_read_byte(&c, timeout_ms) <= 0) + return ESP_ERR_TIMEOUT; + + return cmd_input_console_byte_to_event(c, event); +} + +const char *cmd_input_key_name(cmd_key_t key) +{ + switch (key) + { + case CMD_KEY_NONE: return "none"; + case CMD_KEY_CHAR: return "char"; + case CMD_KEY_ESC: return "esc"; + case CMD_KEY_ENTER: return "enter"; + case CMD_KEY_BACKSPACE: return "backspace"; + case CMD_KEY_TAB: return "tab"; + case CMD_KEY_UP: return "up"; + case CMD_KEY_DOWN: return "down"; + case CMD_KEY_LEFT: return "left"; + case CMD_KEY_RIGHT: return "right"; + case CMD_KEY_HOME: return "home"; + case CMD_KEY_END: return "end"; + case CMD_KEY_PAGE_UP: return "page_up"; + case CMD_KEY_PAGE_DOWN: return "page_down"; + case CMD_KEY_INSERT: return "insert"; + case CMD_KEY_DELETE: return "delete"; + case CMD_KEY_F1: return "f1"; + case CMD_KEY_F2: return "f2"; + case CMD_KEY_F3: return "f3"; + case CMD_KEY_F4: return "f4"; + case CMD_KEY_F5: return "f5"; + case CMD_KEY_F6: return "f6"; + case CMD_KEY_F7: return "f7"; + case CMD_KEY_F8: return "f8"; + case CMD_KEY_F9: return "f9"; + case CMD_KEY_F10: return "f10"; + case CMD_KEY_F11: return "f11"; + case CMD_KEY_F12: return "f12"; + case CMD_KEY_UNKNOWN: return "unknown"; + default: return "?"; + } +} + +// --------------- cmd_panel.cpp --------------- + +CmdFsList *g_cmd_panel_reload_list; + +esp_err_t cmd_panel_alloc_global_buffers() +{ + if (g_cmd_panel_reload_list) return ESP_OK; + + g_cmd_panel_reload_list = (CmdFsList *)heap_caps_calloc( + 1, + sizeof(CmdFsList), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + + if (!g_cmd_panel_reload_list) return ESP_ERR_NO_MEM; + return ESP_OK; +} + +void cmd_panel_free_global_buffers() +{ + if (!g_cmd_panel_reload_list) return; + + heap_caps_free(g_cmd_panel_reload_list); + g_cmd_panel_reload_list = NULL; +} + +esp_err_t cmd_panel_alloc_entries(CmdPanel *panel, size_t capacity) +{ + if (!panel || capacity == 0) return ESP_ERR_INVALID_ARG; + if (panel->entries && panel->capacity >= capacity) return ESP_OK; + + cmd_panel_free_entries(panel); + + panel->entries = (cmd_file_entry_t *)heap_caps_calloc( + capacity, + sizeof(cmd_file_entry_t), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + + if (!panel->entries) + { + panel->capacity = 0; + return ESP_ERR_NO_MEM; + } + + panel->capacity = capacity; + return ESP_OK; +} + +void cmd_panel_free_entries(CmdPanel *panel) +{ + if (!panel) return; + + if (panel->entries) + heap_caps_free(panel->entries); + + panel->entries = NULL; + panel->capacity = 0; + panel->count = 0; + panel->selected_count = 0; + panel->selected_size = 0; + panel->cursor = 0; + panel->scroll = 0; +} + +size_t cmd_panel_text_len(const char *s) +{ + size_t len = 0; + + if (!s) return 0; + + while (s[len]) + len++; + + return len; +} + +void cmd_panel_append_limited(char *out, size_t out_size, const char *text, size_t max_chars) +{ + size_t len; + size_t pos = 0; + + if (!out || out_size == 0 || !text) return; + + len = cmd_panel_text_len(out); + + while (text[pos] && pos < max_chars && len + 1 < out_size) + { + out[len] = text[pos]; + len++; + pos++; + } + + out[len] = 0; +} + +void cmd_panel_append_text(char *out, size_t out_size, const char *text) +{ + if (!text) return; + + cmd_panel_append_limited(out, out_size, text, cmd_panel_text_len(text)); +} + +void cmd_panel_make_title(char *out, size_t out_size, const char *device, const char *path) +{ + size_t used; + size_t reserve = 2; + size_t path_limit = 0; + + if (!out || out_size == 0) return; + + out[0] = 0; + cmd_panel_append_text(out, out_size, " "); + cmd_panel_append_text(out, out_size, device ? device : "?"); + cmd_panel_append_text(out, out_size, ":"); + + used = cmd_panel_text_len(out); + if (out_size > used + reserve) + path_limit = out_size - used - reserve; + + cmd_panel_append_limited(out, out_size, path ? path : "/", path_limit); + cmd_panel_append_text(out, out_size, " "); +} + +void cmd_panel_make_entry_line(const cmd_file_entry_t *entry, char *out, size_t out_size) +{ + size_t name_limit; + + if (!out || out_size == 0) return; + + out[0] = 0; + if (!entry) return; + + if (entry->type == CMD_ENTRY_PARENT) + { + cmd_panel_append_text(out, out_size, ".."); + return; + } + + if (entry->type == CMD_ENTRY_DIR || entry->type == CMD_ENTRY_FILE) + { + name_limit = out_size > 1 ? out_size - 1 : 0; + cmd_panel_append_limited(out, out_size, entry->name, name_limit); + return; + } + + cmd_panel_append_text(out, out_size, "? "); + name_limit = out_size > 3 ? out_size - 3 : 0; + cmd_panel_append_limited(out, out_size, entry->name, name_limit); +} + +int cmd_panel_entry_rank(cmd_entry_type_t type) +{ + if (type == CMD_ENTRY_PARENT) return -1; + if (type == CMD_ENTRY_DIR) return 0; + if (type == CMD_ENTRY_FILE) return 1; + return 2; +} + +int cmd_panel_entry_compare(const cmd_file_entry_t *a, const cmd_file_entry_t *b) +{ + int ar; + int br; + + if (!a || !b) return 0; + + ar = cmd_panel_entry_rank(a->type); + br = cmd_panel_entry_rank(b->type); + + if (ar < br) return -1; + if (ar > br) return 1; + return strcmp(a->name, b->name); +} + +void cmd_panel_sort_entries(CmdPanel *panel) +{ + size_t first = 0; + + if (!panel || !panel->entries || panel->count < 2) return; + + if (panel->entries[0].type == CMD_ENTRY_PARENT) + first = 1; + + if (first + 1 >= panel->count) return; + + std::sort(panel->entries + first, panel->entries + panel->count, + [](const cmd_file_entry_t &a, const cmd_file_entry_t &b) + { + return cmd_panel_entry_compare(&a, &b) < 0; + }); +} + +bool cmd_panel_find_entry(CmdPanel *panel, const char *name, size_t *out_index) +{ + if (!panel || !name) return false; + + for (size_t i = 0; i < panel->count; i++) + { + if (strcmp(panel->entries[i].name, name) == 0) + { + if (out_index) *out_index = i; + return true; + } + } + + return false; +} + +bool cmd_panel_entry_can_select(const cmd_file_entry_t *entry) +{ + if (!entry) return false; + if (entry->type == CMD_ENTRY_PARENT) return false; + if (entry->type != CMD_ENTRY_FILE && entry->type != CMD_ENTRY_DIR) return false; + return true; +} + +void cmd_panel_update_selection_stats(CmdPanel *panel) +{ + if (!panel) return; + + panel->selected_count = 0; + panel->selected_size = 0; + + if (!panel->entries) return; + + for (size_t i = 0; i < panel->count; i++) + { + cmd_file_entry_t *entry = &panel->entries[i]; + + if (!cmd_panel_entry_can_select(entry)) + { + entry->flags &= ~CMD_ENTRY_FLAG_SELECTED; + continue; + } + + if (!(entry->flags & CMD_ENTRY_FLAG_SELECTED)) continue; + + panel->selected_count++; + if (entry->type == CMD_ENTRY_FILE) + panel->selected_size += entry->size; + } +} + +void cmd_panel_clear_selection(CmdPanel *panel) +{ + if (!panel) return; + + if (panel->entries) + { + for (size_t i = 0; i < panel->count; i++) + panel->entries[i].flags &= ~CMD_ENTRY_FLAG_SELECTED; + } + + panel->selected_count = 0; + panel->selected_size = 0; +} + +bool cmd_panel_has_selection(const CmdPanel *panel) +{ + if (!panel) return false; + return panel->selected_count > 0; +} + +void cmd_panel_toggle_selection(CmdPanel *panel) +{ + cmd_file_entry_t *entry; + + if (!panel) return; + + if (panel->cursor < panel->count) + { + entry = &panel->entries[panel->cursor]; + if (cmd_panel_entry_can_select(entry)) + { + entry->flags ^= CMD_ENTRY_FLAG_SELECTED; + cmd_panel_update_selection_stats(panel); + } + } + + if (panel->cursor + 1 < panel->count) + panel->cursor++; + + cmd_panel_ensure_cursor_visible(panel); +} + +void cmd_panel_invert_selection(CmdPanel *panel) +{ + if (!panel || !panel->entries) return; + + for (size_t i = 0; i < panel->count; i++) + { + cmd_file_entry_t *entry = &panel->entries[i]; + + if (!cmd_panel_entry_can_select(entry)) + { + entry->flags &= ~CMD_ENTRY_FLAG_SELECTED; + continue; + } + + entry->flags ^= CMD_ENTRY_FLAG_SELECTED; + } + + cmd_panel_update_selection_stats(panel); +} + +void cmd_panel_clear_entries(CmdPanel *panel) +{ + if (!panel) return; + + panel->count = 0; + panel->selected_count = 0; + panel->selected_size = 0; + panel->flags &= ~CMD_PANEL_FLAG_TRUNCATED; + panel->cursor = 0; + panel->scroll = 0; +} + +void cmd_panel_init(CmdPanel *panel, CmdFsManager *fs, cmd_device_id_t device_id) +{ + if (!panel) return; + + memset(panel, 0, sizeof(*panel)); + panel->fs = fs; + panel->device_id = device_id; + panel->view_rows = CMD_PANEL_DEFAULT_PAGE_STEP; + panel->active = false; + panel->flags = CMD_PANEL_FLAG_NONE; + panel->last_error = ESP_OK; + cmd_fs_copy_path("/", panel->current_path, sizeof(panel->current_path)); +} + +void cmd_panel_reset(CmdPanel *panel) +{ + CmdFsManager *fs; + cmd_device_id_t device_id; + cmd_file_entry_t *entries; + size_t capacity; + + if (!panel) return; + + fs = panel->fs; + device_id = panel->device_id; + entries = panel->entries; + capacity = panel->capacity; + + memset(panel, 0, sizeof(*panel)); + panel->entries = entries; + panel->capacity = capacity; + panel->fs = fs; + panel->device_id = device_id; + panel->view_rows = CMD_PANEL_DEFAULT_PAGE_STEP; + panel->active = false; + panel->flags = CMD_PANEL_FLAG_NONE; + panel->last_error = ESP_OK; + cmd_fs_copy_path("/", panel->current_path, sizeof(panel->current_path)); +} + +void cmd_panel_set_active(CmdPanel *panel, bool active) +{ + if (!panel) return; + + panel->active = active; + if (active) + panel->flags |= CMD_PANEL_FLAG_ACTIVE; + else + panel->flags &= ~CMD_PANEL_FLAG_ACTIVE; +} + +bool cmd_panel_is_active(const CmdPanel *panel) +{ + if (!panel) return false; + return panel->active; +} + +esp_err_t cmd_panel_set_path(CmdPanel *panel, const char *path) +{ + esp_err_t err; + + if (!panel) return ESP_ERR_INVALID_ARG; + + err = cmd_fs_copy_path(path, panel->current_path, sizeof(panel->current_path)); + if (err != ESP_OK) return err; + + cmd_panel_clear_selection(panel); + panel->cursor = 0; + panel->scroll = 0; + return ESP_OK; +} + +void cmd_panel_clamp_cursor(CmdPanel *panel) +{ + if (!panel) return; + + if (panel->count == 0) + { + panel->cursor = 0; + panel->scroll = 0; + return; + } + + if (panel->cursor >= panel->count) + panel->cursor = panel->count - 1; + + cmd_panel_ensure_cursor_visible(panel); +} + +void cmd_panel_ensure_cursor_visible(CmdPanel *panel) +{ + size_t rows; + + if (!panel) return; + + rows = panel->view_rows ? panel->view_rows : CMD_PANEL_DEFAULT_PAGE_STEP; + if (rows == 0) rows = 1; + + if (panel->cursor < panel->scroll) + panel->scroll = panel->cursor; + + if (panel->cursor >= panel->scroll + rows) + panel->scroll = panel->cursor - rows + 1; +} + +esp_err_t cmd_panel_reload(CmdPanel *panel) +{ + CmdFsList *list = g_cmd_panel_reload_list; + cmd_file_entry_t entry; + size_t old_cursor; + bool truncated = false; + esp_err_t err; + + if (!panel || !panel->fs) return ESP_ERR_INVALID_ARG; + if (!panel->entries || panel->capacity == 0 || !list) return ESP_ERR_NO_MEM; + + memset(list, 0, sizeof(*list)); + memset(&panel->space_info, 0, sizeof(panel->space_info)); + panel->space_info_valid = false; + panel->space_info_error = ESP_ERR_INVALID_STATE; + + old_cursor = panel->cursor; + cmd_panel_clear_entries(panel); + + err = cmd_fs_manager_mount(panel->fs, panel->device_id); + if (err != ESP_OK) + { + panel->space_info_valid = true; + panel->space_info_error = err; + panel->last_error = err; + panel->flags |= CMD_PANEL_FLAG_ERROR; + return err; + } + + err = cmd_fs_manager_list_begin(panel->fs, panel->device_id, panel->current_path, list); + if (err != ESP_OK) + { + panel->space_info_valid = true; + panel->space_info_error = err; + panel->last_error = err; + panel->flags |= CMD_PANEL_FLAG_ERROR; + return err; + } + + for (;;) + { + err = cmd_fs_manager_list_next(panel->fs, list, &entry); + if (err == ESP_ERR_NOT_FOUND) break; + if (err != ESP_OK) + { + cmd_fs_manager_list_close(panel->fs, list); + panel->space_info_valid = true; + panel->space_info_error = err; + panel->last_error = err; + panel->flags |= CMD_PANEL_FLAG_ERROR; + return err; + } + + if (panel->count >= panel->capacity) + { + truncated = true; + continue; + } + + panel->entries[panel->count] = entry; + panel->count++; + } + + cmd_fs_manager_list_close(panel->fs, list); + cmd_panel_sort_entries(panel); + cmd_panel_update_selection_stats(panel); + + panel->space_info_error = cmd_fs_manager_space_info(panel->fs, panel->device_id, &panel->space_info); + panel->space_info_valid = true; + + panel->cursor = old_cursor; + panel->last_error = truncated ? CMD_ERR_DIR_FULL : ESP_OK; + panel->flags &= ~CMD_PANEL_FLAG_ERROR; + + if (truncated) + panel->flags |= CMD_PANEL_FLAG_TRUNCATED; + else + panel->flags &= ~CMD_PANEL_FLAG_TRUNCATED; + + cmd_panel_clamp_cursor(panel); + return ESP_OK; +} + +void cmd_panel_cursor_up(CmdPanel *panel) +{ + if (!panel) return; + if (panel->cursor > 0) panel->cursor--; + cmd_panel_ensure_cursor_visible(panel); +} + +void cmd_panel_cursor_down(CmdPanel *panel) +{ + if (!panel) return; + if (panel->cursor + 1 < panel->count) panel->cursor++; + cmd_panel_ensure_cursor_visible(panel); +} + +void cmd_panel_cursor_page_up(CmdPanel *panel) +{ + size_t step; + + if (!panel) return; + + step = panel->view_rows ? panel->view_rows : CMD_PANEL_DEFAULT_PAGE_STEP; + if (step == 0) step = 1; + + if (panel->cursor > step) + panel->cursor -= step; + else + panel->cursor = 0; + + cmd_panel_ensure_cursor_visible(panel); +} + +void cmd_panel_cursor_page_down(CmdPanel *panel) +{ + size_t step; + + if (!panel) return; + + step = panel->view_rows ? panel->view_rows : CMD_PANEL_DEFAULT_PAGE_STEP; + if (step == 0) step = 1; + + panel->cursor += step; + cmd_panel_clamp_cursor(panel); +} + +void cmd_panel_cursor_home(CmdPanel *panel) +{ + if (!panel) return; + + panel->cursor = 0; + cmd_panel_ensure_cursor_visible(panel); +} + +void cmd_panel_cursor_end(CmdPanel *panel) +{ + if (!panel) return; + + if (panel->count > 0) + panel->cursor = panel->count - 1; + else + panel->cursor = 0; + + cmd_panel_ensure_cursor_visible(panel); +} + +const cmd_file_entry_t *cmd_panel_get_selected_entry(const CmdPanel *panel) +{ + if (!panel) return NULL; + if (panel->cursor >= panel->count) return NULL; + return &panel->entries[panel->cursor]; +} + +esp_err_t cmd_panel_change_device(CmdPanel *panel, cmd_device_id_t device_id) +{ + esp_err_t err; + + if (!panel) return ESP_ERR_INVALID_ARG; + if (!cmd_fs_is_valid_device_id(device_id)) return CMD_ERR_INVALID_DEVICE; + + panel->device_id = device_id; + err = cmd_panel_set_path(panel, "/"); + if (err != ESP_OK) return err; + + return cmd_panel_reload(panel); +} + +esp_err_t cmd_panel_go_parent(CmdPanel *panel) +{ + char parent[CMD_PATH_MAX]; + char child_name[CMD_FILE_NAME_MAX]; + char old_path[CMD_PATH_MAX]; + size_t old_cursor; + size_t old_scroll; + size_t index; + esp_err_t err; + + if (!panel) return ESP_ERR_INVALID_ARG; + if (cmd_fs_path_is_root(panel->current_path)) return ESP_OK; + + err = cmd_fs_copy_path(panel->current_path, old_path, sizeof(old_path)); + if (err != ESP_OK) return err; + + old_cursor = panel->cursor; + old_scroll = panel->scroll; + + err = cmd_fs_extract_filename(panel->current_path, child_name, sizeof(child_name)); + if (err != ESP_OK) return err; + + err = cmd_fs_parent_path(panel->current_path, parent, sizeof(parent)); + if (err != ESP_OK) return err; + + err = cmd_panel_set_path(panel, parent); + if (err != ESP_OK) return err; + + err = cmd_panel_reload(panel); + if (err != ESP_OK) + { + cmd_fs_copy_path(old_path, panel->current_path, sizeof(panel->current_path)); + panel->cursor = old_cursor; + panel->scroll = old_scroll; + cmd_panel_reload(panel); + return err; + } + + if (cmd_panel_find_entry(panel, child_name, &index)) + { + panel->cursor = index; + cmd_panel_ensure_cursor_visible(panel); + } + + return ESP_OK; +} + +esp_err_t cmd_panel_enter_selected_dir(CmdPanel *panel) +{ + const cmd_file_entry_t *entry; + char path[CMD_PATH_MAX]; + char old_path[CMD_PATH_MAX]; + size_t old_cursor; + size_t old_scroll; + esp_err_t err; + + if (!panel) return ESP_ERR_INVALID_ARG; + + entry = cmd_panel_get_selected_entry(panel); + if (!entry) return ESP_ERR_NOT_FOUND; + + if (entry->type == CMD_ENTRY_PARENT) + return cmd_panel_go_parent(panel); + + if (entry->type != CMD_ENTRY_DIR) return ESP_ERR_NOT_SUPPORTED; + + err = cmd_fs_copy_path(panel->current_path, old_path, sizeof(old_path)); + if (err != ESP_OK) return err; + + old_cursor = panel->cursor; + old_scroll = panel->scroll; + + err = cmd_fs_join_path(panel->current_path, entry->name, path, sizeof(path)); + if (err != ESP_OK) return err; + + err = cmd_panel_set_path(panel, path); + if (err != ESP_OK) return err; + + err = cmd_panel_reload(panel); + if (err != ESP_OK) + { + cmd_fs_copy_path(old_path, panel->current_path, sizeof(panel->current_path)); + panel->cursor = old_cursor; + panel->scroll = old_scroll; + cmd_panel_reload(panel); + return err; + } + + return ESP_OK; +} + +void cmd_panel_draw_text_line(CmdDisplayBuffer *buffer, const cmd_rect_t *line_rect, const char *text, cmd_display_attr_t attr) +{ + if (!buffer || !line_rect) return; + + cmd_display_buffer_fill_rect(buffer, line_rect, ' ', attr); + if (text) + cmd_display_buffer_write_text(buffer, line_rect->x, line_rect->y, text, attr); +} + +void cmd_panel_draw_title(CmdPanel *panel, CmdDisplayBuffer *buffer, const cmd_rect_t *rect, cmd_display_attr_t attr) +{ + char title[CMD_DISPLAY_COLS + 1]; + char selected[48]; + const char *device; + + if (!panel || !buffer || !rect) return; + + device = cmd_device_name(panel->device_id); + cmd_panel_make_title(title, sizeof(title), device, panel->current_path); + + if (panel->selected_count > 0) + { + snprintf(selected, sizeof(selected), " [%u/%llu] ", + (unsigned)panel->selected_count, + (unsigned long long)panel->selected_size); + cmd_panel_append_text(title, sizeof(title), selected); + } + + cmd_display_buffer_write_text(buffer, rect->x + 2, rect->y, title, attr); +} + +void cmd_panel_draw_error(CmdPanel *panel, CmdDisplayBuffer *buffer, const cmd_rect_t *rect) +{ + char msg[CMD_DISPLAY_COLS + 1]; + cmd_rect_t line_rect; + + if (!panel || !buffer || !rect) return; + if (rect->w <= 2 || rect->h <= 2) return; + + line_rect.x = rect->x + 1; + line_rect.y = rect->y + 1; + line_rect.w = rect->w - 2; + line_rect.h = 1; + + snprintf(msg, sizeof(msg), "error: 0x%x", (unsigned)panel->last_error); + cmd_panel_draw_text_line(buffer, + &line_rect, + msg, + cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_RED, CMD_DISPLAY_COLOR_BLUE, CMD_DISPLAY_ATTR_FLAG_BOLD)); +} + +esp_err_t cmd_panel_draw(CmdPanel *panel, CmdDisplayBuffer *buffer, const cmd_rect_t *rect) +{ + cmd_display_attr_t normal_attr; + cmd_display_attr_t active_attr; + cmd_display_attr_t selected_attr; + cmd_display_attr_t marked_attr; + cmd_display_attr_t folder_attr; + cmd_display_attr_t frame_attr; + cmd_rect_t inner; + size_t rows; + + if (!panel || !buffer || !rect) return ESP_ERR_INVALID_ARG; + if (rect->w <= 0 || rect->h <= 0) return ESP_OK; + + normal_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_WHITE, CMD_DISPLAY_COLOR_BLUE, CMD_DISPLAY_ATTR_FLAG_NONE); + active_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_WHITE, CMD_DISPLAY_COLOR_BLUE, CMD_DISPLAY_ATTR_FLAG_NONE); + selected_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_BLACK, CMD_DISPLAY_COLOR_BRIGHT_YELLOW, + CMD_DISPLAY_ATTR_FLAG_BOLD | CMD_DISPLAY_ATTR_FLAG_SELECTED); + marked_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_WHITE, CMD_DISPLAY_COLOR_CYAN, CMD_DISPLAY_ATTR_FLAG_BOLD); + folder_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_WHITE, CMD_DISPLAY_COLOR_BLUE, CMD_DISPLAY_ATTR_FLAG_BOLD); + frame_attr = cmd_display_make_attr(CMD_DISPLAY_COLOR_BRIGHT_WHITE, CMD_DISPLAY_COLOR_BLUE, CMD_DISPLAY_ATTR_FLAG_BOLD); + + cmd_display_buffer_fill_rect(buffer, rect, ' ', panel->active ? active_attr : normal_attr); + cmd_display_buffer_draw_box(buffer, rect, frame_attr); + cmd_panel_draw_title(panel, buffer, rect, frame_attr); + + if (rect->w <= 2 || rect->h <= 2) return ESP_OK; + + inner.x = rect->x + 1; + inner.y = rect->y + 1; + inner.w = rect->w - 2; + inner.h = rect->h - 2; + rows = (size_t)inner.h; + panel->view_rows = rows; + cmd_panel_ensure_cursor_visible(panel); + + if (panel->flags & CMD_PANEL_FLAG_ERROR) + { + cmd_panel_draw_error(panel, buffer, rect); + return ESP_OK; + } + + for (size_t row = 0; row < rows; row++) + { + size_t idx = panel->scroll + row; + cmd_rect_t line_rect; + cmd_display_attr_t attr; + char line[CMD_DISPLAY_COLS + 1]; + + line_rect.x = inner.x; + line_rect.y = inner.y + (int)row; + line_rect.w = inner.w; + line_rect.h = 1; + if (panel->active && idx == panel->cursor) + attr = selected_attr; + else if (idx < panel->count && (panel->entries[idx].flags & CMD_ENTRY_FLAG_SELECTED)) + attr = marked_attr; + else if (idx < panel->count && (panel->entries[idx].type == CMD_ENTRY_DIR || panel->entries[idx].type == CMD_ENTRY_PARENT)) + attr = folder_attr; + else + attr = panel->active ? active_attr : normal_attr; + + if (idx < panel->count) + { + size_t line_size = sizeof(line); + if (line_rect.w > 2 && (size_t)(line_rect.w - 1) < line_size) + line_size = (size_t)(line_rect.w - 1); + cmd_panel_make_entry_line(&panel->entries[idx], line, line_size); + } + else + line[0] = 0; + + cmd_display_buffer_fill_rect(buffer, &line_rect, ' ', attr); + + if (line_rect.w > 1) + cmd_display_buffer_write_text(buffer, line_rect.x + 1, line_rect.y, line, attr); + else + cmd_display_buffer_write_text(buffer, line_rect.x, line_rect.y, line, attr); + } + + return ESP_OK; +} diff --git a/src/main/cmd.h b/src/main/cmd.h new file mode 100644 index 0000000..303e798 --- /dev/null +++ b/src/main/cmd.h @@ -0,0 +1,696 @@ +#pragma once + +#include +#include +#include +#include + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CmdApp CmdApp; +typedef struct CmdFsManager CmdFsManager; +typedef struct CmdPanel CmdPanel; + +void cmd_console_register_system_commands(); +void cmd_set_status(CmdApp *app, const char *fmt, ...); +void cmd_show_error(CmdApp *app, const char *title, esp_err_t err); + +#ifdef __cplusplus +} +#endif + +// --------------- cmd_types.h --------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define CMD_TEXT_COLS 80 +#define CMD_TEXT_ROWS 30 +#define CMD_FILE_NAME_MAX 256 +#define CMD_PATH_MAX 256 +#define CMD_PANEL_COUNT 2 + +#ifndef CMD_ERR_BASE +#define CMD_ERR_BASE 0x7000 +#endif + +typedef esp_err_t CmdErr; + +typedef enum +{ + CMD_DEVICE_SD = 0, + CMD_DEVICE_FAT, + CMD_DEVICE_TSF, + CMD_DEVICE_MAX, + CMD_DEVICE_INVALID = -1 +} cmd_device_id_t; + +typedef enum +{ + CMD_ENTRY_UNKNOWN = 0, + CMD_ENTRY_FILE, + CMD_ENTRY_DIR, + CMD_ENTRY_PARENT +} cmd_entry_type_t; + +typedef enum +{ + CMD_ENTRY_FLAG_NONE = 0, + CMD_ENTRY_FLAG_SELECTED = 1u << 0, + CMD_ENTRY_FLAG_ERROR = 1u << 1 +} cmd_entry_flags_t; + +typedef struct +{ + char name[CMD_FILE_NAME_MAX]; + cmd_entry_type_t type; + uint64_t size; + uint64_t mtime; + uint32_t flags; +} cmd_file_entry_t; + +typedef struct +{ + int x; + int y; +} cmd_point_t; + +typedef struct +{ + int w; + int h; +} cmd_size_t; + +typedef struct +{ + int x; + int y; + int w; + int h; +} cmd_rect_t; + +typedef enum +{ + CMD_KEY_NONE = 0, + CMD_KEY_CHAR, + CMD_KEY_ESC, + CMD_KEY_ENTER, + CMD_KEY_BACKSPACE, + CMD_KEY_TAB, + CMD_KEY_UP, + CMD_KEY_DOWN, + CMD_KEY_LEFT, + CMD_KEY_RIGHT, + CMD_KEY_HOME, + CMD_KEY_END, + CMD_KEY_PAGE_UP, + CMD_KEY_PAGE_DOWN, + CMD_KEY_INSERT, + CMD_KEY_DELETE, + CMD_KEY_F1, + CMD_KEY_F2, + CMD_KEY_F3, + CMD_KEY_F4, + CMD_KEY_F5, + CMD_KEY_F6, + CMD_KEY_F7, + CMD_KEY_F8, + CMD_KEY_F9, + CMD_KEY_F10, + CMD_KEY_F11, + CMD_KEY_F12, + CMD_KEY_UNKNOWN +} cmd_key_t; + +typedef enum +{ + CMD_EVENT_NONE = 0, + CMD_EVENT_KEY, + CMD_EVENT_QUIT +} cmd_event_type_t; + +typedef struct +{ + cmd_event_type_t type; + cmd_key_t key; + uint32_t ch; + uint32_t mods; +} cmd_event_t; + +typedef enum +{ + CMD_KEY_MOD_NONE = 0, + CMD_KEY_MOD_SHIFT = 1u << 0, + CMD_KEY_MOD_CTRL = 1u << 1, + CMD_KEY_MOD_ALT = 1u << 2 +} cmd_key_mod_t; + +typedef enum +{ + CMD_OK = ESP_OK, + CMD_ERR_INVALID_DEVICE = CMD_ERR_BASE, + CMD_ERR_NOT_MOUNTED, + CMD_ERR_PATH_TOO_LONG, + CMD_ERR_ENTRY_TOO_LONG, + CMD_ERR_DIR_FULL, + CMD_ERR_INPUT_UNAVAILABLE, + CMD_ERR_CANCELLED +} cmd_err_t; + +const char *cmd_device_name(cmd_device_id_t id); +const char *cmd_entry_type_name(cmd_entry_type_t type); + +#ifdef __cplusplus +} +#endif + +// --------------- cmd_display.h --------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define CMD_DISPLAY_DEFAULT_COLS CMD_TEXT_COLS +#define CMD_DISPLAY_DEFAULT_ROWS CMD_TEXT_ROWS +#define CMD_DISPLAY_MAX_COLS 160 +#define CMD_DISPLAY_MAX_ROWS 64 +#define CMD_DISPLAY_COLS CMD_DISPLAY_MAX_COLS +#define CMD_DISPLAY_ROWS CMD_DISPLAY_MAX_ROWS +#define CMD_DISPLAY_CELL_COUNT (CMD_DISPLAY_COLS * CMD_DISPLAY_ROWS) +#define CMD_DISPLAY_MUX_MAX_BACKENDS 4 +#define CMD_DISPLAY_BACKEND_FLAG_FORCE_PARTIAL 1u + +typedef uint16_t cmd_display_attr_t; + +typedef enum +{ + CMD_DISPLAY_COLOR_BLACK = 0, + CMD_DISPLAY_COLOR_BLUE, + CMD_DISPLAY_COLOR_GREEN, + CMD_DISPLAY_COLOR_CYAN, + CMD_DISPLAY_COLOR_RED, + CMD_DISPLAY_COLOR_MAGENTA, + CMD_DISPLAY_COLOR_YELLOW, + CMD_DISPLAY_COLOR_WHITE, + CMD_DISPLAY_COLOR_BRIGHT_BLACK, + CMD_DISPLAY_COLOR_BRIGHT_BLUE, + CMD_DISPLAY_COLOR_BRIGHT_GREEN, + CMD_DISPLAY_COLOR_BRIGHT_CYAN, + CMD_DISPLAY_COLOR_BRIGHT_RED, + CMD_DISPLAY_COLOR_BRIGHT_MAGENTA, + CMD_DISPLAY_COLOR_BRIGHT_YELLOW, + CMD_DISPLAY_COLOR_BRIGHT_WHITE +} cmd_display_color_t; + +typedef enum +{ + CMD_DISPLAY_ATTR_FLAG_NONE = 0, + CMD_DISPLAY_ATTR_FLAG_BOLD = 1u << 0, + CMD_DISPLAY_ATTR_FLAG_INVERSE = 1u << 1, + CMD_DISPLAY_ATTR_FLAG_UNDERLINE = 1u << 2, + CMD_DISPLAY_ATTR_FLAG_SELECTED = 1u << 3 +} cmd_display_attr_flag_t; + +typedef enum +{ + CMD_DISPLAY_MODE_CONSOLE = 0, + CMD_DISPLAY_MODE_FT812, + CMD_DISPLAY_MODE_MIRROR +} CmdDisplayMode; + +#define CMD_DISPLAY_ATTR_FG_MASK 0x000f +#define CMD_DISPLAY_ATTR_BG_MASK 0x00f0 +#define CMD_DISPLAY_ATTR_FLAGS_MASK 0xff00 +#define CMD_DISPLAY_ATTR_BG_SHIFT 4 +#define CMD_DISPLAY_ATTR_FLAGS_SHIFT 8 +#define CMD_DISPLAY_ATTR_DEFAULT ((cmd_display_attr_t)(CMD_DISPLAY_COLOR_WHITE | (CMD_DISPLAY_COLOR_BLACK << CMD_DISPLAY_ATTR_BG_SHIFT))) + +#define CMD_DISPLAY_BOX_TL ((char)0xC9) +#define CMD_DISPLAY_BOX_TR ((char)0xBB) +#define CMD_DISPLAY_BOX_BL ((char)0xC8) +#define CMD_DISPLAY_BOX_BR ((char)0xBC) +#define CMD_DISPLAY_BOX_H ((char)0xCD) +#define CMD_DISPLAY_BOX_V ((char)0xBA) + +typedef struct +{ + char ch; + cmd_display_attr_t attr; +} CmdDisplayCell; + +typedef struct +{ + cmd_size_t size; + CmdDisplayCell cells[CMD_DISPLAY_ROWS][CMD_DISPLAY_COLS]; +} CmdDisplayBuffer; + +typedef struct CmdDisplayBackend CmdDisplayBackend; +typedef struct CmdDisplayMux CmdDisplayMux; + +typedef esp_err_t (*CmdDisplayBackendInitFn)(CmdDisplayBackend *backend); +typedef void (*CmdDisplayBackendDeinitFn)(CmdDisplayBackend *backend); +typedef esp_err_t (*CmdDisplayBackendClearFn)(CmdDisplayBackend *backend); +typedef esp_err_t (*CmdDisplayBackendPresentFn)(CmdDisplayBackend *backend, const CmdDisplayBuffer *buffer); +typedef esp_err_t (*CmdDisplayBackendPutCharFn)(CmdDisplayBackend *backend, int x, int y, char ch, cmd_display_attr_t attr); +typedef esp_err_t (*CmdDisplayBackendWriteTextFn)(CmdDisplayBackend *backend, int x, int y, const char *text, cmd_display_attr_t attr); +typedef esp_err_t (*CmdDisplayBackendGetSizeFn)(CmdDisplayBackend *backend, cmd_size_t *size); + +struct CmdDisplayBackend +{ + const char *name; + void *ctx; + uint32_t flags; + + CmdDisplayBackendInitFn init; + CmdDisplayBackendDeinitFn deinit; + CmdDisplayBackendClearFn clear; + CmdDisplayBackendPresentFn present; + CmdDisplayBackendPutCharFn put_char; + CmdDisplayBackendWriteTextFn write_text; + CmdDisplayBackendGetSizeFn get_size; +}; + +struct CmdDisplayMux +{ + CmdDisplayBackend *backends[CMD_DISPLAY_MUX_MAX_BACKENDS]; + size_t count; +}; + +extern CmdDisplayBackend cmd_display_console_backend; +extern CmdDisplayBackend cmd_display_ft812_backend; + +cmd_display_attr_t cmd_display_make_attr(cmd_display_color_t fg, cmd_display_color_t bg, uint8_t flags); +cmd_display_color_t cmd_display_attr_fg(cmd_display_attr_t attr); +cmd_display_color_t cmd_display_attr_bg(cmd_display_attr_t attr); +uint8_t cmd_display_attr_flags(cmd_display_attr_t attr); + +const char *cmd_display_mode_name(CmdDisplayMode mode); +bool cmd_display_mode_parse(const char *text, CmdDisplayMode *mode); +bool cmd_display_mode_has_console(CmdDisplayMode mode); +bool cmd_display_mode_has_ft812(CmdDisplayMode mode); + +void cmd_display_buffer_init(CmdDisplayBuffer *buffer); +esp_err_t cmd_display_buffer_set_size(CmdDisplayBuffer *buffer, int w, int h); +void cmd_display_buffer_clear(CmdDisplayBuffer *buffer, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_buffer_put_char(CmdDisplayBuffer *buffer, int x, int y, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_buffer_write_text(CmdDisplayBuffer *buffer, int x, int y, const char *text, cmd_display_attr_t attr); +esp_err_t cmd_display_buffer_fill_rect(CmdDisplayBuffer *buffer, const cmd_rect_t *rect, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_buffer_draw_hline(CmdDisplayBuffer *buffer, int x, int y, int w, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_buffer_draw_vline(CmdDisplayBuffer *buffer, int x, int y, int h, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_buffer_draw_box(CmdDisplayBuffer *buffer, const cmd_rect_t *rect, cmd_display_attr_t attr); +CmdDisplayCell *cmd_display_buffer_cell(CmdDisplayBuffer *buffer, int x, int y); +const CmdDisplayCell *cmd_display_buffer_cell_const(const CmdDisplayBuffer *buffer, int x, int y); +bool cmd_display_point_inside(int x, int y); +bool cmd_display_buffer_point_inside(const CmdDisplayBuffer *buffer, int x, int y); + +esp_err_t cmd_display_backend_init(CmdDisplayBackend *backend); +void cmd_display_backend_deinit(CmdDisplayBackend *backend); +esp_err_t cmd_display_backend_clear(CmdDisplayBackend *backend); +esp_err_t cmd_display_backend_present(CmdDisplayBackend *backend, const CmdDisplayBuffer *buffer); +esp_err_t cmd_display_backend_put_char(CmdDisplayBackend *backend, int x, int y, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_backend_write_text(CmdDisplayBackend *backend, int x, int y, const char *text, cmd_display_attr_t attr); +esp_err_t cmd_display_backend_get_size(CmdDisplayBackend *backend, cmd_size_t *size); + +void cmd_display_mux_init(CmdDisplayMux *mux); +esp_err_t cmd_display_mux_add_backend(CmdDisplayMux *mux, CmdDisplayBackend *backend); +esp_err_t cmd_display_mux_add_mode(CmdDisplayMux *mux, CmdDisplayMode mode); +esp_err_t cmd_display_mux_remove_backend(CmdDisplayMux *mux, CmdDisplayBackend *backend); +esp_err_t cmd_display_mux_init_backends(CmdDisplayMux *mux); +esp_err_t cmd_display_mux_get_size(CmdDisplayMux *mux, cmd_size_t *size); +void cmd_display_mux_deinit_backends(CmdDisplayMux *mux); +esp_err_t cmd_display_mux_clear(CmdDisplayMux *mux); +esp_err_t cmd_display_mux_present(CmdDisplayMux *mux, const CmdDisplayBuffer *buffer); +esp_err_t cmd_display_mux_put_char(CmdDisplayMux *mux, int x, int y, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_mux_write_text(CmdDisplayMux *mux, int x, int y, const char *text, cmd_display_attr_t attr); + +esp_err_t cmd_display_console_init(CmdDisplayBackend *backend); +void cmd_display_console_deinit(CmdDisplayBackend *backend); +esp_err_t cmd_display_console_clear(CmdDisplayBackend *backend); +esp_err_t cmd_display_console_present(CmdDisplayBackend *backend, const CmdDisplayBuffer *buffer); +esp_err_t cmd_display_console_put_char(CmdDisplayBackend *backend, int x, int y, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_console_write_text(CmdDisplayBackend *backend, int x, int y, const char *text, cmd_display_attr_t attr); +esp_err_t cmd_display_console_get_size(CmdDisplayBackend *backend, cmd_size_t *size); + +esp_err_t cmd_display_ft812_begin(CmdDisplayBackend *backend); +void cmd_display_ft812_end(CmdDisplayBackend *backend); +esp_err_t cmd_display_ft812_clear(CmdDisplayBackend *backend); +esp_err_t cmd_display_ft812_present(CmdDisplayBackend *backend, const CmdDisplayBuffer *buffer); +esp_err_t cmd_display_ft812_put_char(CmdDisplayBackend *backend, int x, int y, char ch, cmd_display_attr_t attr); +esp_err_t cmd_display_ft812_write_text(CmdDisplayBackend *backend, int x, int y, const char *text, cmd_display_attr_t attr); +esp_err_t cmd_display_ft812_get_size(CmdDisplayBackend *backend, cmd_size_t *size); + +#ifdef __cplusplus +} +#endif + +// --------------- cmd_fileops.h --------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CMD_FILEOPS_BUFFER_SIZE +#define CMD_FILEOPS_BUFFER_SIZE 4096 +#endif + +#ifndef CMD_FILEOPS_MAX_DEPTH +#define CMD_FILEOPS_MAX_DEPTH 16 +#endif + +typedef enum +{ + CMD_FILEOPS_OP_COPY = 0, + CMD_FILEOPS_OP_MOVE, + CMD_FILEOPS_OP_DELETE +} cmd_fileops_op_t; + +typedef enum +{ + CMD_FILEOPS_FLAG_NONE = 0, + CMD_FILEOPS_FLAG_RECURSIVE = 1u << 0, + CMD_FILEOPS_FLAG_OVERWRITE = 1u << 1 +} cmd_fileops_flags_t; + +typedef struct +{ + cmd_fileops_op_t op; + const char *filename; + uint64_t bytes_done; + uint64_t bytes_total; + size_t files_done; + size_t files_total; + bool can_cancel; +} CmdFileopsProgress; + +typedef bool (*CmdFileopsProgressFn)(const CmdFileopsProgress *progress, void *ctx); + +typedef struct +{ + uint32_t flags; + CmdFileopsProgressFn progress; + void *progress_ctx; +} CmdFileopsOptions; + +esp_err_t cmd_fileops_alloc_global_buffers(); +void cmd_fileops_free_global_buffers(); + +esp_err_t cmd_fileops_copy_path(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + cmd_device_id_t dst_device, + const char *dst_path, + const CmdFileopsOptions *options); + +esp_err_t cmd_fileops_copy_file(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + cmd_device_id_t dst_device, + const char *dst_path, + const CmdFileopsOptions *options); + +esp_err_t cmd_fileops_move_path(CmdFsManager *fs, + cmd_device_id_t src_device, + const char *src_path, + cmd_device_id_t dst_device, + const char *dst_path, + const CmdFileopsOptions *options); + +esp_err_t cmd_fileops_delete_path(CmdFsManager *fs, + cmd_device_id_t device_id, + const char *path, + const CmdFileopsOptions *options); + +esp_err_t cmd_fileops_copy_selected(CmdPanel *active, + CmdPanel *passive, + const CmdFileopsOptions *options); + +esp_err_t cmd_fileops_move_selected(CmdPanel *active, + CmdPanel *passive, + const CmdFileopsOptions *options); + +esp_err_t cmd_fileops_delete_selected(CmdPanel *panel, + const CmdFileopsOptions *options); + +#ifdef __cplusplus +} +#endif + +// --------------- cmd_fs.h --------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define CMD_FS_DRIVER_MAX CMD_DEVICE_MAX + +#ifndef CMD_FS_SD_ROOT_PATH +#define CMD_FS_SD_ROOT_PATH "/sd" +#endif + +typedef struct CmdFsDriver CmdFsDriver; +typedef struct CmdFsManager CmdFsManager; +typedef struct CmdFsList CmdFsList; +typedef struct CmdFsFile CmdFsFile; + +typedef esp_err_t (*CmdFsMountFn)(CmdFsDriver *driver); +typedef esp_err_t (*CmdFsUnmountFn)(CmdFsDriver *driver); +typedef esp_err_t (*CmdFsListBeginFn)(CmdFsDriver *driver, const char *path, CmdFsList *list); +typedef esp_err_t (*CmdFsListNextFn)(CmdFsDriver *driver, CmdFsList *list, cmd_file_entry_t *entry); +typedef void (*CmdFsListCloseFn)(CmdFsDriver *driver, CmdFsList *list); +typedef esp_err_t (*CmdFsStatFn)(CmdFsDriver *driver, const char *path, cmd_file_entry_t *entry); +typedef esp_err_t (*CmdFsMkdirFn)(CmdFsDriver *driver, const char *path); +typedef esp_err_t (*CmdFsRemoveFn)(CmdFsDriver *driver, const char *path); +typedef esp_err_t (*CmdFsRenameFn)(CmdFsDriver *driver, const char *old_path, const char *new_path); +typedef esp_err_t (*CmdFsOpenFn)(CmdFsDriver *driver, const char *path, CmdFsFile *file); +typedef esp_err_t (*CmdFsReadFn)(CmdFsDriver *driver, CmdFsFile *file, void *dst, size_t size, size_t *out_size); +typedef esp_err_t (*CmdFsWriteFn)(CmdFsDriver *driver, CmdFsFile *file, const void *src, size_t size, size_t *out_size); +typedef esp_err_t (*CmdFsSeekFn)(CmdFsDriver *driver, CmdFsFile *file, int64_t offset, int whence); +typedef esp_err_t (*CmdFsTellFn)(CmdFsDriver *driver, CmdFsFile *file, uint64_t *out_pos); +typedef esp_err_t (*CmdFsCloseFn)(CmdFsDriver *driver, CmdFsFile *file); + +struct CmdFsList +{ + cmd_device_id_t device_id; + char path[CMD_PATH_MAX]; + char abs_path[CMD_PATH_MAX]; + void *dir; + size_t index; + bool parent_pending; + uint32_t flags; +}; + +struct CmdFsFile +{ + cmd_device_id_t device_id; + FILE *fp; + void *ctx; + char name[CMD_FILE_NAME_MAX]; + uint32_t flags; +}; + +typedef struct +{ + uint64_t total_bytes; + uint64_t free_bytes; +} +CmdFsSpaceInfo; + +struct CmdFsDriver +{ + cmd_device_id_t device_id; + const char *name; + const char *root_path; + void *ctx; + + CmdFsMountFn mount; + CmdFsUnmountFn unmount; + CmdFsListBeginFn list_begin; + CmdFsListNextFn list_next; + CmdFsListCloseFn list_close; + CmdFsStatFn stat; + CmdFsMkdirFn mkdir; + CmdFsRemoveFn remove; + CmdFsRenameFn rename; + CmdFsOpenFn open_read; + CmdFsOpenFn open_write; + CmdFsReadFn read; + CmdFsWriteFn write; + CmdFsSeekFn seek; + CmdFsTellFn tell; + CmdFsCloseFn close; +}; + +struct CmdFsManager +{ + CmdFsDriver *drivers[CMD_FS_DRIVER_MAX]; + uint32_t registered_mask; + uint32_t mounted_mask; +}; + +extern CmdFsDriver cmd_fs_sd_driver; +extern CmdFsDriver cmd_fs_fat_driver; +extern CmdFsDriver cmd_fs_tsf_driver; + +bool cmd_fs_is_valid_device_id(cmd_device_id_t device_id); + +void cmd_fs_manager_init(CmdFsManager *manager); +esp_err_t cmd_fs_manager_register_driver(CmdFsManager *manager, CmdFsDriver *driver); +esp_err_t cmd_fs_manager_unregister_driver(CmdFsManager *manager, cmd_device_id_t device_id); +CmdFsDriver *cmd_fs_manager_get_driver(CmdFsManager *manager, cmd_device_id_t device_id); +const CmdFsDriver *cmd_fs_manager_get_driver_const(const CmdFsManager *manager, cmd_device_id_t device_id); +esp_err_t cmd_fs_manager_register_default_drivers(CmdFsManager *manager); +esp_err_t cmd_fs_manager_build_abs_path(const CmdFsManager *manager, cmd_device_id_t device_id, const char *current_path, const char *filename, char *out, size_t out_size); + +esp_err_t cmd_fs_manager_mount(CmdFsManager *manager, cmd_device_id_t device_id); +esp_err_t cmd_fs_manager_unmount(CmdFsManager *manager, cmd_device_id_t device_id); +esp_err_t cmd_fs_manager_unmount_all(CmdFsManager *manager); +esp_err_t cmd_fs_manager_list_begin(CmdFsManager *manager, cmd_device_id_t device_id, const char *path, CmdFsList *list); +esp_err_t cmd_fs_manager_list_next(CmdFsManager *manager, CmdFsList *list, cmd_file_entry_t *entry); +void cmd_fs_manager_list_close(CmdFsManager *manager, CmdFsList *list); +esp_err_t cmd_fs_manager_stat(CmdFsManager *manager, cmd_device_id_t device_id, const char *path, cmd_file_entry_t *entry); +esp_err_t cmd_fs_manager_space_info(CmdFsManager *manager, cmd_device_id_t device_id, CmdFsSpaceInfo *info); +esp_err_t cmd_fs_manager_mkdir(CmdFsManager *manager, cmd_device_id_t device_id, const char *path); +esp_err_t cmd_fs_manager_remove(CmdFsManager *manager, cmd_device_id_t device_id, const char *path); +esp_err_t cmd_fs_manager_rename(CmdFsManager *manager, cmd_device_id_t device_id, const char *old_path, const char *new_path); +esp_err_t cmd_fs_manager_open_read(CmdFsManager *manager, cmd_device_id_t device_id, const char *path, CmdFsFile *file); +esp_err_t cmd_fs_manager_open_write(CmdFsManager *manager, cmd_device_id_t device_id, const char *path, CmdFsFile *file); +esp_err_t cmd_fs_manager_read(CmdFsManager *manager, CmdFsFile *file, void *dst, size_t size, size_t *out_size); +esp_err_t cmd_fs_manager_write(CmdFsManager *manager, CmdFsFile *file, const void *src, size_t size, size_t *out_size); +esp_err_t cmd_fs_manager_seek(CmdFsManager *manager, CmdFsFile *file, int64_t offset, int whence); +esp_err_t cmd_fs_manager_tell(CmdFsManager *manager, CmdFsFile *file, uint64_t *out_pos); +esp_err_t cmd_fs_manager_close(CmdFsManager *manager, CmdFsFile *file); + +esp_err_t cmd_fs_copy_path(const char *src, char *out, size_t out_size); +esp_err_t cmd_fs_join_path(const char *left, const char *right, char *out, size_t out_size); +esp_err_t cmd_fs_join3_path(const char *left, const char *middle, const char *right, char *out, size_t out_size); +esp_err_t cmd_fs_parent_path(const char *path, char *out, size_t out_size); +esp_err_t cmd_fs_extract_filename(const char *path, char *out, size_t out_size); +const char *cmd_fs_filename_ptr(const char *path); +bool cmd_fs_path_is_root(const char *path); + +#ifdef __cplusplus +} +#endif + +// --------------- cmd_input.h --------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define CMD_INPUT_WAIT_FOREVER UINT32_MAX +#define CMD_INPUT_ESC_TIMEOUT_MS 120 + +typedef struct CmdInputBackend CmdInputBackend; + +typedef esp_err_t (*cmd_input_begin_fn)(CmdInputBackend *backend); +typedef void (*cmd_input_end_fn)(CmdInputBackend *backend); +typedef esp_err_t (*cmd_input_poll_event_fn)(CmdInputBackend *backend, cmd_event_t *event, uint32_t timeout_ms); + +struct CmdInputBackend +{ + const char *name; + void *ctx; + cmd_input_begin_fn begin; + cmd_input_end_fn end; + cmd_input_poll_event_fn poll_event; +}; + +void cmd_input_event_clear(cmd_event_t *event); +void cmd_input_event_key(cmd_event_t *event, cmd_key_t key, uint32_t mods); +void cmd_input_event_char(cmd_event_t *event, uint32_t ch, uint32_t mods); +void cmd_input_event_quit(cmd_event_t *event); + +esp_err_t cmd_input_begin(CmdInputBackend *backend); +void cmd_input_end(CmdInputBackend *backend); +esp_err_t cmd_input_poll_event(CmdInputBackend *backend, cmd_event_t *event, uint32_t timeout_ms); + +CmdInputBackend *cmd_input_console_backend(); +CmdInputBackend *cmd_input_default_backend(); + +const char *cmd_input_key_name(cmd_key_t key); + +#ifdef __cplusplus +} +#endif + +// --------------- cmd_panel.h --------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CMD_PANEL_MAX_ENTRIES +#define CMD_PANEL_MAX_ENTRIES 1000 +#endif + +#ifndef CMD_PANEL_DEFAULT_PAGE_STEP +#define CMD_PANEL_DEFAULT_PAGE_STEP 10 +#endif + +typedef enum +{ + CMD_PANEL_FLAG_NONE = 0, + CMD_PANEL_FLAG_ACTIVE = 1u << 0, + CMD_PANEL_FLAG_ERROR = 1u << 1, + CMD_PANEL_FLAG_TRUNCATED = 1u << 2 +} cmd_panel_flags_t; + +struct CmdPanel +{ + CmdFsManager *fs; + cmd_device_id_t device_id; + char current_path[CMD_PATH_MAX]; + cmd_file_entry_t *entries; + size_t capacity; + size_t count; + size_t cursor; + size_t scroll; + size_t view_rows; + size_t selected_count; + uint64_t selected_size; + CmdFsSpaceInfo space_info; + esp_err_t space_info_error; + bool space_info_valid; + bool active; + uint32_t flags; + esp_err_t last_error; +}; + +esp_err_t cmd_panel_alloc_global_buffers(); +void cmd_panel_free_global_buffers(); +esp_err_t cmd_panel_alloc_entries(CmdPanel *panel, size_t capacity); +void cmd_panel_free_entries(CmdPanel *panel); +void cmd_panel_init(CmdPanel *panel, CmdFsManager *fs, cmd_device_id_t device_id); +void cmd_panel_reset(CmdPanel *panel); +void cmd_panel_set_active(CmdPanel *panel, bool active); +bool cmd_panel_is_active(const CmdPanel *panel); +esp_err_t cmd_panel_set_path(CmdPanel *panel, const char *path); +esp_err_t cmd_panel_reload(CmdPanel *panel); +esp_err_t cmd_panel_draw(CmdPanel *panel, CmdDisplayBuffer *buffer, const cmd_rect_t *rect); +void cmd_panel_cursor_up(CmdPanel *panel); +void cmd_panel_cursor_down(CmdPanel *panel); +void cmd_panel_cursor_page_up(CmdPanel *panel); +void cmd_panel_cursor_page_down(CmdPanel *panel); +void cmd_panel_cursor_home(CmdPanel *panel); +void cmd_panel_cursor_end(CmdPanel *panel); +const cmd_file_entry_t *cmd_panel_get_selected_entry(const CmdPanel *panel); +void cmd_panel_toggle_selection(CmdPanel *panel); +void cmd_panel_invert_selection(CmdPanel *panel); +void cmd_panel_clear_selection(CmdPanel *panel); +void cmd_panel_update_selection_stats(CmdPanel *panel); +bool cmd_panel_has_selection(const CmdPanel *panel); +esp_err_t cmd_panel_change_device(CmdPanel *panel, cmd_device_id_t device_id); +esp_err_t cmd_panel_enter_selected_dir(CmdPanel *panel); +esp_err_t cmd_panel_go_parent(CmdPanel *panel); +void cmd_panel_clamp_cursor(CmdPanel *panel); +void cmd_panel_ensure_cursor_visible(CmdPanel *panel); + +#ifdef __cplusplus +} +#endif diff --git a/src/main/console.cpp b/src/main/console.cpp new file mode 100644 index 0000000..c93d6c8 --- /dev/null +++ b/src/main/console.cpp @@ -0,0 +1,179 @@ +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "esp_system.h" +#include "esp_console.h" +#include "esp_log.h" +#include "esp_vfs_dev.h" // Old headers for the aliasing functions + +#include "driver/uart_vfs.h" + +#include "driver/uart.h" +#include "argtable3/argtable3.h" +#include "linenoise/linenoise.h" +#include "nvs.h" +#include "nvs_flash.h" + +#include "main.h" +#include "ft8xx.h" +#include "console.h" +#include "tracker.h" +#include "sfx.h" +#include "tsf.h" +#include "opl.h" +#include "fatfs.h" +#include "cmd.h" + +#if defined(CONFIG_ESP_WIFI_ENABLED) && CONFIG_ESP_WIFI_ENABLED +#include "wifi.h" +#endif + +#if SOC_SDMMC_HOST_SUPPORTED +#include "sdmmc.h" +#endif + +#define PROMPT_STR "zifi32" +#define CONSOLE_UART_RX_BUF_SIZE 1024 +#define CONSOLE_PROMPT_MAX_LEN 32 + +char prompt_buf[CONSOLE_PROMPT_MAX_LEN]; +const char *prompt = prompt_buf; + +void console_register_commands() +{ + esp_console_register_help_command(); + esp_console_register_system_commands(); +#if defined(CONFIG_ESP_WIFI_ENABLED) && CONFIG_ESP_WIFI_ENABLED + esp_console_register_wifi_commands(); +#endif + ft_console_register_system_commands(); +#if SOC_SDMMC_HOST_SUPPORTED + sdmmc_console_register_system_commands(); +#endif + xm_console_register_system_commands(); + sfx_console_register_system_commands(); + tsf_console_register_system_commands(); + opl_console_register_system_commands(); + fat_console_register_system_commands(); + cmd_console_register_system_commands(); +} + +void console_update_prompt() +{ + if (linenoiseIsDumbMode()) + { + snprintf(prompt_buf, sizeof(prompt_buf), PROMPT_STR "> "); + return; + } + +#if CONFIG_LOG_COLORS + snprintf(prompt_buf, sizeof(prompt_buf), LOG_COLOR_I PROMPT_STR "> " LOG_RESET_COLOR); +#else + snprintf(prompt_buf, sizeof(prompt_buf), PROMPT_STR "> "); +#endif +} + +void initialize_console() +{ + // Drain stdout before reconfiguring it + fflush(stdout); + fsync(fileno(stdout)); + + // Disable buffering on stdin + setvbuf(stdin, NULL, _IONBF, 0); + log_sram_used(__FILE_NAME__ ": setvbuf"); + + /* Minicom, screen, idf_monitor send CR when ENTER key is pressed */ + uart_vfs_dev_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); + + /* Move the caret to the beginning of the next line on '\n' */ + uart_vfs_dev_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); + + // Install UART driver for interrupt-driven reads and writes + ESP_ERROR_CHECK(uart_driver_install((uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, CONSOLE_UART_RX_BUF_SIZE, 0, 0, NULL, 0)); + log_sram_used(__FILE_NAME__ ": uart_driver_install"); + + // Tell VFS to use UART driver + uart_vfs_dev_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); + + // Initialize the console + esp_console_config_t console_config = + { + .max_cmdline_length = 256, + .max_cmdline_args = 128, +#if CONFIG_LOG_COLORS + .hint_color = atoi(LOG_COLOR_CYAN) +#endif + }; + ESP_ERROR_CHECK(esp_console_init(&console_config)); + + // Configure linenoise line completion library. + // Single-line mode sends less data on each key press and is much more stable on UART. + linenoiseSetMultiLine(0); + + // Detect whether the terminal supports escape sequences. + if (linenoiseProbe() != 0) + linenoiseSetDumbMode(1); + + // Tell linenoise where to get command completions. + linenoiseSetCompletionCallback(&esp_console_get_completion); + + // Hints trigger additional redraw traffic on every key press. + // Disabling them makes repeated backspace handling much more stable. + // linenoiseSetHintsCallback((linenoiseHintsCallback*)&esp_console_get_hint); + + // Set command history size + linenoiseHistorySetMaxLen(100); + + // Set command maximum length + linenoiseSetMaxLineLen(console_config.max_cmdline_length); + + // Don't return empty lines + linenoiseAllowEmpty(false); + + console_update_prompt(); + + // Register commands + console_register_commands(); + + log_sram_used(__FILE_NAME__ ": initialize_console end"); +} + +void console_task(void *arg) +{ + _delay_ms(30); + + printf("\n" + "Type 'help' to get the list of commands.\n" + "Use UP/DOWN arrows to navigate through command history.\n" + "Press TAB when typing command name to auto-complete.\n"); + + while (true) + { + char* line = linenoise(prompt); + + if (line == NULL) + continue; + + if (strlen(line) > 0) + linenoiseHistoryAdd(line); + + int ret; + esp_err_t err = esp_console_run(line, &ret); + + if (err == ESP_ERR_NOT_FOUND) + printf("Unrecognized command\n"); + else if (err == ESP_ERR_INVALID_ARG) + { + } + else if (err == ESP_OK && ret != ESP_OK) + printf("Command returned non-zero error code: 0x%x (%s)\n", ret, esp_err_to_name(ret)); + else if (err != ESP_OK) + printf("Internal error: %s\n", esp_err_to_name(err)); + + linenoiseFree(line); + } +} diff --git a/src/main/console.h b/src/main/console.h new file mode 100644 index 0000000..d73d1c8 --- /dev/null +++ b/src/main/console.h @@ -0,0 +1,6 @@ + +#pragma once + +void initialize_console(); +void console_task(void *arg); +void esp_console_register_system_commands(); diff --git a/src/main/depack.cpp b/src/main/depack.cpp new file mode 100644 index 0000000..40846fe --- /dev/null +++ b/src/main/depack.cpp @@ -0,0 +1,359 @@ + +#include "main.h" + +//------------------- DeHrust -------------------------- + +/* BBStream class */ +class BBStream +{ +private: + u8* base; + u8* p; + int idx; + int len; + bool eof; + u16 bits; + +public: + BBStream(u8* from, int blockSize) + { + base = p = from; + + len = blockSize; + idx = 0; + eof = false; + + bits = getByte(); + bits += 256 * getByte(); + } + + u8 getByte(void) + { + if (p - base == len) + { + eof = true; return 0; + } + return *p++; + } + + u8 getBit() + { + u16 mask[] = { 0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + + u8 bit = (bits & mask[idx]) ? 1 : 0; + + if (idx == 15) + { + bits = getByte(); + bits += 256 * getByte(); + } + + idx = (idx + 1) % 16; + return bit; + } + + u8 getBits(int n) + { + u8 r = 0; + + do + { + r = 2 * r + getBit(); + } while(--n); + return r; + } + + bool error(void) + { + return eof; + } +}; + +/* depacker */ +u16 dehrust(u8 *dst, u8 *src, int size) +{ + BBStream s(src, size); + + if (!dst || !src) + return 0; + + u8 *to = dst; + + *to++ = s.getByte(); + + u8 noBits = 2; + u8 mask[] = { 0, 0, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0 }; + + while (!s.error()) + { + while (s.getBit()) + *to++ = s.getByte(); + + u16 len = 0; + u8 bb /* = 0*/; + + do + { + bb = s.getBits(2); + len += bb; + } while(bb == 0x03 && len != 0x0f); + + short offset = 0; + + if (len == 0) + { + offset = 0xfff8 + s.getBits(3); + { u8 t = to[offset]; *to++ = t; } + continue; + } + + if (len == 1) + { + u8 code = s.getBits(2); + + if (code == 2) + { + u8 b = s.getByte(); + if (b >= 0xe0) + { + b <<= 1; ++b; // rlca + b ^= 2; // xor c + + if (b == 0xff) + { + ++noBits; continue; + } + + offset = 0xff00 + b - 0x0f; + + { u8 t = to[offset]; *to++ = t; } + *to++ = s.getByte(); + { u8 t = to[offset]; *to++ = t; } + continue; + } + offset = 0xff00 + b; + } + + if (code == 0 || code == 1) + { + offset = s.getByte(); + offset += 256 * (code ? 0xfe : 0xfd); + } + if (code == 3) + offset = 0xffe0 + s.getBits(5); + + for (u8 i = 0; i < 2; ++i) + { u8 t = to[offset]; *to++ = t; } + continue; + } + + if (len == 3) + { + if (s.getBit()) + { + offset = 0xfff0 + s.getBits(4); + { u8 t = to[offset]; *to++ = t; } + *to++ = s.getByte(); + { u8 t = to[offset]; *to++ = t; } + continue; + } + + if (s.getBit()) + { + u8 noBytes = 6 + s.getBits(4); + for (u8 i = 0; i < 2 * noBytes; ++i) + *to++ = s.getByte(); + continue; + } + + len = s.getBits(7); + if (len == 0x0f) + break; // EOF + if (len < 0x0f) + len = 256 * len + s.getByte(); + } + + if (len == 2) + ++len; + + u8 code = s.getBits(2); + + if (code == 1) + { + u8 b = s.getByte(); + + if (b >= 0xe0) + { + if (len > 3) + return false; + + b <<= 1; ++b; // rlca + b ^= 3; // xor c + + offset = 0xff00 + b - 0x0f; + + { u8 t = to[offset]; *to++ = t; } + *to++ = s.getByte(); + { u8 t = to[offset]; *to++ = t; } + continue; + } + offset = 0xff00 + b; + } + + if (code == 0) + offset = 0xfe00 + s.getByte(); + if (code == 2) + offset = 0xffe0 + s.getBits(5); + if (code == 3) + { + offset = 256 * (mask[noBits] + s.getBits(noBits)); + offset += s.getByte(); + } + + for (u16 i = 0; i < len; ++i) + { u8 t = to[offset]; *to++ = t; } + } + + return to - dst; +} + +//------------------- DeMegaLZ -------------------------- + +class deMLZ +{ +private: + u8 *from; + u8 *to; + u8 bitstream; + int bitcount; + +public: + deMLZ(u8 *dst, u8 *src) + { + from = src; + to = dst; + } + + void init_bitstream(void) + { + bitstream = get_byte(); + bitcount = 8; + } + + u8 get_byte(void) + { + return *from++; + } + + void put_byte(u8 val) + { + *to++ = val; + } + + void repeat(u32 disp, int num) + { + for (int i = 0; i < num; i++) + { + u8 val = *(to - disp); + put_byte(val); + } + } + + // gets specified number of bits from bitstream + // returns them LSB-aligned + u32 get_bits(int count) + { + u32 bits = 0; + + while (count--) + { + if (bitcount--) + { + bits <<= 1; + bits |= 1 & (bitstream >> 7); + bitstream <<= 1; + } + else + { + init_bitstream(); + count++; // repeat loop once more + } + } + + return bits; + } + + int get_bigdisp(void) + { + u32 bits; + + // inter displacement + if (get_bits(1)) + { + bits = get_bits(4); + return 0x1100 - (bits << 8) - get_byte(); + } + + // shorter displacement + else + return 256 - get_byte(); + } +}; + +// depacker +void demlz(u8 *dst, u8 *src, int size) +{ + deMLZ s(dst, src); + u32 done = 0; + int i; + + // get first byte of packed file and write to output + s.put_byte(s.get_byte()); + + // second byte goes to bitstream + s.init_bitstream(); + + // actual depacking loop! + do + { + // get 1st bit - either OUTBYTE or beginning of LZ code + // OUTBYTE + if (s.get_bits(1)) + s.put_byte(s.get_byte()); + + // LZ code + else + { + switch (s.get_bits(2)) + { + case 0: // 000 + s.repeat(8 - s.get_bits(3), 1); + break; + + case 1: // 001 + s.repeat(256 - s.get_byte(), 2); + break; + + case 2: // 010 + s.repeat(s.get_bigdisp(), 3); + break; + + case 3: // 011 + // extract num of length bits + for (i = 1; !s.get_bits(1); i++) + ; + + // check for exit code + if (i == 9) + done = 1; + else if (i <= 7) + { + // get length bits itself + int bits = s.get_bits(i); + s.repeat(s.get_bigdisp(), 2 + (1 << i) + bits); + } + break; + } + } + } while (!done); +} diff --git a/src/main/depack.h b/src/main/depack.h new file mode 100644 index 0000000..a3f75a7 --- /dev/null +++ b/src/main/depack.h @@ -0,0 +1,6 @@ + +#pragma once +#include "main.h" + +u16 dehrust(u8 *dst, u8 *src, int size); +void demlz(u8 *dst, u8 *src, int size); diff --git a/src/main/elf.cpp b/src/main/elf.cpp new file mode 100644 index 0000000..4a9be3d --- /dev/null +++ b/src/main/elf.cpp @@ -0,0 +1,244 @@ + +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "main.h" +#include "esp_spi_defs.h" +#include "mem_obj.h" +#include "elf.cpp.h" + +int load_elf(u8 *elf, MEM_OBJ *obj, int opt) +{ + enum + { + TYPE_NONE, + TYPE_TEXT, + TYPE_RODATA, + TYPE_DATA, + TYPE_BSS, + }; + + Elf32_Ehdr* elf_header = (Elf32_Ehdr*)elf; + Elf32_Shdr* section_headers = (Elf32_Shdr*)(elf + elf_header->e_shoff); +#ifdef VERBOSE + Elf32_Shdr* shstrtab_header = §ion_headers[elf_header->e_shstrndx]; + const char* shstrtab = (const char*)(elf + shstrtab_header->sh_offset); +#endif + u32 entry = 0; + int size = 0; + + int num_sec = elf_header->e_shnum; + + Elf32_Rela* rld = NULL; + int rld_num = 0; + + // Parse sections to determine type and find dynamic relocation section + for (int i = 0; i < num_sec; i++) + { + Elf32_Shdr* section = §ion_headers[i]; + + if (!section->sh_addr) continue; + + section->sh_info = TYPE_NONE; + section->sh_link = 0; + + switch (section->sh_type) + { + case SHT_RELA: + section->sh_type = TYPE_NONE; + rld = (Elf32_Rela*)&elf[section->sh_offset]; + rld_num = section->sh_size / sizeof(Elf32_Rela); + break; + + case SHT_NOBITS: + section->sh_type = TYPE_BSS; + break; + + case SHT_PROGBITS: + if (section->sh_flags & SHF_EXECINSTR) + { + section->sh_type = TYPE_TEXT; + section->sh_link = 1; // .text is always used if no symbol refere it + } + + else if (section->sh_flags & SHF_WRITE) + section->sh_type = TYPE_DATA; + + else + section->sh_type = TYPE_RODATA; + break; + + default: + section->sh_type = TYPE_NONE; + } + } + + // Parse relocation symbols to find used sections + for (int i = 0; i < rld_num; i++) + { + u32 rld_offs = rld[i].r_offset; + u32 *sym_offs = (u32*)&elf[rld_offs]; + u32 sym_val = *sym_offs; + + for (int j = 0; j < num_sec; j++) + { + Elf32_Shdr* section = §ion_headers[j]; + + if (section->sh_addr) + { + if ((sym_val >= section->sh_addr) && (sym_val <= (section->sh_addr + section->sh_size - 1))) + { + section->sh_link++; + break; + } + } + } + } + + // Allocate memory for sections +#ifdef VERBOSE + printf("\nSections used:\n"); +#endif + + for (int i = 0; i < num_sec; i++) + { + Elf32_Shdr* section = §ion_headers[i]; + + if (!section->sh_addr) continue; + if (!section->sh_link) continue; + + section->sh_info = 0; + + switch (section->sh_type) + { + case TYPE_TEXT: + section->sh_info = (u32)heap_caps_aligned_alloc(section->sh_addralign, section->sh_size, MALLOC_CAP_INTERNAL); + if (!section->sh_info) goto cleanup; + entry = elf_header->e_entry - section->sh_offset + section->sh_info + 0x6F0000; + obj->text = (void*)section->sh_info; + obj->sz_text = section->sh_size; + obj->entry = (void*)entry; + size += section->sh_size; + break; + + case TYPE_BSS: +#ifdef CONFIG_SPIRAM + section->sh_info = (u32)heap_caps_aligned_alloc(section->sh_addralign, section->sh_size, (opt & ESP_OPT_BSS_SRAM) ? MALLOC_CAP_INTERNAL : MALLOC_CAP_SPIRAM); +#else + section->sh_info = (u32)heap_caps_aligned_alloc(section->sh_addralign, section->sh_size, MALLOC_CAP_INTERNAL); +#endif + if (!section->sh_info) goto cleanup; + obj->bss = (void*)section->sh_info; + obj->sz_bss = section->sh_size; + size += section->sh_size; + break; + + case TYPE_DATA: +#ifdef CONFIG_SPIRAM + section->sh_info = (u32)heap_caps_aligned_alloc(section->sh_addralign, section->sh_size, (opt & ESP_OPT_DATA_SRAM) ? MALLOC_CAP_INTERNAL : MALLOC_CAP_SPIRAM); +#else + section->sh_info = (u32)heap_caps_aligned_alloc(section->sh_addralign, section->sh_size, MALLOC_CAP_INTERNAL); +#endif + if (!section->sh_info) goto cleanup; + obj->data = (void*)section->sh_info; + obj->sz_data = section->sh_size; + size += section->sh_size; + break; + + case TYPE_RODATA: +#ifdef CONFIG_SPIRAM + section->sh_info = (u32)heap_caps_aligned_alloc(section->sh_addralign, section->sh_size, (opt & ESP_OPT_RODATA_SRAM) ? MALLOC_CAP_INTERNAL : MALLOC_CAP_SPIRAM); +#else + section->sh_info = (u32)heap_caps_aligned_alloc(section->sh_addralign, section->sh_size, MALLOC_CAP_INTERNAL); +#endif + if (!section->sh_info) goto cleanup; + obj->rodata = (void*)section->sh_info; + obj->sz_rodata = section->sh_size; + size += section->sh_size; + break; + } + +#ifdef VERBOSE + const char* section_name = shstrtab + section->sh_name; + printf("%-10s Addr: %06lX Size: %-5ld Symbols: %-3ld Alloc: %lX Align: %ld\n", section_name, section->sh_addr, section->sh_size, section->sh_link, section->sh_info, section->sh_addralign); +#endif + } + + // Relocate dynamic symbols +#ifdef VERBOSE + printf("\nRelocated symbols:\n"); +#endif + + for (int i = 0; i < rld_num; i++) + { + u32 rld_offs = rld[i].r_offset; + u32 *sym_offs = (u32*)&elf[rld_offs]; + u32 sym_val = *sym_offs; + u32 sym_addr = 0; +#ifdef VERBOSE + const char* name = ""; +#endif + + for (int j = 0; j < num_sec; j++) + { + Elf32_Shdr* section = §ion_headers[j]; + + if (section->sh_addr) + { + if ((sym_val >= section->sh_addr) && (sym_val <= (section->sh_addr + section->sh_size - 1))) + { + sym_addr = sym_val - section->sh_offset + section->sh_info + ((section->sh_type == TYPE_TEXT) ? 0x6F0000 : 0); + *sym_offs = sym_addr; +#ifdef VERBOSE + name = shstrtab + section->sh_name; +#endif + break; + } + } + } + +#ifdef VERBOSE + printf("%-4d Offs: %-5lX Value: %-6lX Addr: %lX Section: %s\n", i, rld_offs, sym_val, sym_addr, name); +#endif + } + + // Initialize memory for sections + for (int i = 0; i < num_sec; i++) + { + Elf32_Shdr* section = §ion_headers[i]; + + if (!section->sh_addr) continue; + if (!section->sh_link) continue; + + switch (section->sh_type) + { + case TYPE_TEXT: + case TYPE_DATA: + case TYPE_RODATA: + if (section->sh_info) memcpy((void*)section->sh_info, &elf[section->sh_offset], section->sh_size); + break; + + case TYPE_BSS: + if (section->sh_info) memset((void*)section->sh_info, 0, section->sh_size); + break; + } + } + +#ifdef VERBOSE + printf("\nEntry: %lX\n", entry); +#endif + + return size; + +cleanup: + if (obj->text) free(obj->text); + if (obj->rodata) free(obj->rodata); + if (obj->data) free(obj->data); + if (obj->bss) free(obj->bss); + + return -1; +} diff --git a/src/main/elf.cpp.h b/src/main/elf.cpp.h new file mode 100644 index 0000000..8b61a19 --- /dev/null +++ b/src/main/elf.cpp.h @@ -0,0 +1,4 @@ + +#pragma once + +int load_elf(u8 *elf, MEM_OBJ *obj, int opt); diff --git a/src/main/esp_spi_defs.h b/src/main/esp_spi_defs.h new file mode 100644 index 0000000..108e83d --- /dev/null +++ b/src/main/esp_spi_defs.h @@ -0,0 +1,375 @@ +#pragma once + +#define ZIFI_STR_HELPER(x) #x +#define ZIFI_STR(x) ZIFI_STR_HELPER(x) + +#define PROD_VER0 0 +#define PROD_VER1 6 +#define PROD_VER2 4 +#define PROD_VER_STRING ZIFI_STR(PROD_VER0) "." ZIFI_STR(PROD_VER1) "." ZIFI_STR(PROD_VER2) +#define CP_STRING "ESP32 SPI WiFi Module, ver." PROD_VER_STRING ", (c) TS-Labs" + +#define API_VER 1 +#define FEAT_VER 10 +#define API_VER_STRING ZIFI_STR(API_VER) +#define FEAT_VER_STRING ZIFI_STR(FEAT_VER) +#define API_STRING "API version: " API_VER_STRING ", feature version: " FEAT_VER_STRING + +// Registers +enum +{ + ESP_REG_COMMAND = 0x00, // 1 byte + ESP_REG_STATUS = 0x01, // 1 byte + + // String commands + ESP_REG_STRING_TYPE = 0x02, // 1 byte + ESP_REG_STRING_SIZE = 0x02, // 1 byte + ESP_REG_STRING_DATA = 0x03, // byte array + + // Version commands + ESP_REG_API = 0x02, // 1 byte + ESP_REG_FEAT = 0x03, // 2 bytes + ESP_REG_VER0 = 0x05, // 1 byte + ESP_REG_VER1 = 0x06, // 1 byte + ESP_REG_VER2 = 0x07, // 1 byte + + // Object commands and data transmission commands + ESP_REG_OBJ_TYPE = 0x02, // 1 byte + ESP_REG_DATA_SIZE = 0x03, // 4 bytes + ESP_REG_DATA_OFFSET = 0x07, // 4 bytes + ESP_REG_OBJ_HANDLE = 0x0B, // 1 byte + + // Lib commands + ESP_REG_FUNC = 0x02, // 1 byte + ESP_REG_OPT = 0x03, // 1 byte + ESP_REG_ARG = 0x03, // 4 bytes + ESP_REG_RETVAL = 0x07, // 4 bytes + ESP_REG_ARR1_HANDLE = 0x0C, // 1 byte + ESP_REG_ARR2_HANDLE = 0x0D, // 1 byte + ESP_REG_ARR3_HANDLE = 0x0E, // 1 byte + ESP_REG_LIB_HANDLE = 0x0F, // 1 byte + + // Network commands + ESP_REG_NETSTATE = 0x02, + ESP_REG_IP = 0x2C, // 4 bytes + ESP_REG_OWN_IP = 0x30, // 4 bytes + ESP_REG_MASK = 0x34, // 4 bytes + ESP_REG_GATE = 0x38, // 4 bytes + + // Stats commands + ESP_EXEC_TIME = 0x3C, // 4 bytes + + // SFX commands + ESP_REG_SFX_CHANNEL = 0x02, // 1 byte + ESP_REG_SFX_GROUP = 0x03, // 1 byte + ESP_REG_SFX_VOLUME = 0x04, // 1 byte + ESP_REG_SFX_PAN = 0x05, // 1 byte + ESP_REG_SFX_PITCH = 0x06, // 2 bytes, Q4.8 little-endian + + ESP_REG_SFX_STATE_ACTIVE = 0x10, // 1 byte + ESP_REG_SFX_STATE_HANDLE = 0x11, // 1 byte + ESP_REG_SFX_STATE_GROUP = 0x12, // 1 byte + ESP_REG_SFX_STATE_ORDER = 0x13, // 1 byte + ESP_REG_SFX_STATE_VOLUME = 0x14, // 1 byte + ESP_REG_SFX_STATE_PAN = 0x15, // 1 byte + ESP_REG_SFX_STATE_PITCH = 0x16, // 2 bytes, Q4.8 little-endian + ESP_REG_SFX_STATE_RATE = 0x18, // 4 bytes + ESP_REG_SFX_STATE_FRAMES = 0x1C, // 4 bytes + ESP_REG_SFX_STATE_POSITION = 0x20, // 4 bytes + ESP_REG_SFX_STATE_BITS = 0x24, // 2 bytes + ESP_REG_SFX_STATE_CHANNELS = 0x26, // 1 byte + ESP_REG_SFX_STATE_SIGNED = 0x27, // 1 byte + + // Track (XM/MOD/S3M) get-state/get-info commands + ESP_REG_TRACK_STATUS = 0x28, // 1 byte: TRACK_OBJ_ST_STOPPED / TRACK_OBJ_ST_PLAYING + ESP_REG_TRACK_IS_CURRENT = 0x29, // 1 byte: 1 if this handle is the one currently loaded in the player + ESP_REG_TRACK_PATTERN_INDEX = 0x2A, // 1 byte: position in the order/pattern-table list + ESP_REG_TRACK_PATTERN = 0x2B, // 1 byte: pattern number + ESP_REG_TRACK_ROW = 0x2C, // 1 byte: current row within the pattern + ESP_REG_TRACK_SAMPLES = 0x2D, // 4 bytes: samples elapsed since track start + ESP_REG_TRACK_BPM = 0x31, // 2 bytes + ESP_REG_TRACK_TEMPO = 0x33, // 2 bytes + ESP_REG_TRACK_LOOP_COUNT = 0x35, // 1 byte + ESP_REG_TRACK_TOTAL_SAMPLES = 0x36, // 4 bytes: length of one full pass through the song, computed once at load time + ESP_REG_TRACK_MAX_LOOP_COUNT = 0x3A, // 1 byte: see ESP_CMD_TRACK_SET_PARAMS + + // VFS bridge commands (SMB2 network share <-> Wild Commander local storage) + ESP_REG_VFS_PENDING = 0x02, // 1 byte: 1 if a request is waiting, else 0 + // NOTE: ESP_CMD_VFS_POLL's output also includes ESP_REG_DATA_SIZE (0x03, + // 4 bytes) - VFS_OP must not overlap that range, unlike most register + // reuse in this header, since both are read back from the SAME command. + ESP_REG_VFS_OP = 0x36, // 1 byte: VFS_OP_* (see below) - meaning of the payload from ESP_CMD_VFS_GET_REQUEST_DATA + ESP_REG_VFS_STATUS = 0x02, // 1 byte: i: 0=success, nonzero=error (ESP_CMD_VFS_SUBMIT_RESULT) +}; + +// Commands +enum +{ + ESP_CMD_NOP = 0x00, // (no parameters) + ESP_CMD_GET_INFO_STR = 0x01, // i: ESP_REG_STRING_TYPE + // o: ESP_REG_STRING_SIZE, ESP_REG_STRING_DATA + ESP_CMD_GET_VER = 0x02, // o: ESP_REG_API, ESP_REG_FEAT, ESP_REG_VER0..2 + ESP_CMD_GET_CHIP_INFO = 0x03, // +++ + + ESP_CMD_GET_NETSTATE = 0x11, // o: ESP_REG_NETSTATE + ESP_CMD_WSCAN = 0x12, // (no parameters) + ESP_CMD_SET_AP_NAME = 0x13, // i: ESP_REG_STRING_SIZE, ESP_REG_STRING_DATA + ESP_CMD_SET_AP_PWD = 0x14, // i: ESP_REG_STRING_SIZE, ESP_REG_STRING_DATA + ESP_CMD_AP_CONNECT = 0x16, // (no parameters) + ESP_CMD_AP_DISCONNECT = 0x17, // (no parameters) + ESP_CMD_SET_URL = 0x18, // (no parameters) + ESP_CMD_GET_IP = 0x19, // o: ESP_REG_IP + ESP_CMD_HTTP_GET = 0x20, // +++ + ESP_CMD_HTTPS_GET = 0x21, // (no parameters) + // o: ESP_REG_OBJ_HANDLE, ESP_REG_DATA_SIZE + ESP_CMD_GOPHER_GET = 0x22, // (no parameters) + // o: ESP_REG_OBJ_HANDLE, ESP_REG_DATA_SIZE + ESP_CMD_HTTP_STREAM_START = 0x23, // (no parameters) + // o: ESP_REG_DATA_SIZE (total size) + ESP_CMD_HTTPS_STREAM_START = 0x24, // (no parameters) + // o: ESP_REG_DATA_SIZE (total size) + ESP_CMD_GOPHER_STREAM_START = 0x25, // (no parameters) + // o: ESP_REG_DATA_SIZE (total size) + ESP_CMD_STREAM_READ = 0x26, // (no parameters) + // o: ESP_REG_DATA_SIZE (chunk size) + // (DMA read like ESP_CMD_READ_OBJECT) + ESP_CMD_STREAM_CLOSE = 0x27, // (no parameters) + + // VFS bridge: a small generic pipe, not one opcode per filesystem + // operation - the actual op (VFS_OP_STAT/READDIR/OPEN/READ/WRITE/CLOSE/ + // DELETE/MKDIR/RMDIR) travels inside the request payload, mirroring how + // the fake filesystem's own Vfs_Dispatch works. The Z80 side polls + // ESP_CMD_VFS_POLL on every idle tick; when a request is pending it + // fetches the payload, does the real filesystem op locally through WC, + // and posts the result back. + ESP_CMD_VFS_SERVER_START = 0x28, // i: ESP_REG_STRING_SIZE, ESP_REG_STRING_DATA (share name) + ESP_CMD_VFS_SERVER_STOP = 0x29, // (no parameters) + ESP_CMD_VFS_POLL = 0x2A, // o: ESP_REG_VFS_PENDING, ESP_REG_VFS_OP, ESP_REG_DATA_SIZE (request payload length, if pending) + ESP_CMD_VFS_GET_REQUEST_DATA = 0x2B, // o: ESP_REG_DATA_SIZE (DMA read like ESP_CMD_READ_OBJECT) + ESP_CMD_VFS_SUBMIT_RESULT = 0x2C, // i: ESP_REG_VFS_STATUS, ESP_REG_DATA_SIZE (DMA write like ESP_CMD_WRITE_OBJECT) + + ESP_CMD_WEATHER_GET = 0x2D, // i: OBJ_HANDLE -> country\0zip\0 (DATA/DATAF) + // o: new OBJ_HANDLE, DATA_OFFSET=0, DATA_SIZE=90 + + ESP_CMD_TRACK_INIT = 0xA0, // i: ESP_REG_OBJ_HANDLE + ESP_CMD_TRACK_PLAY = 0xA1, // i: ESP_REG_OBJ_HANDLE + ESP_CMD_TRACK_STOP = 0xA2, // (no parameters) + ESP_CMD_TRACK_RESET = 0xA3, // i: ESP_REG_OBJ_HANDLE, stop playback and reset XMC context to start + ESP_CMD_TRACK_SET_VOLUME = 0xA4, // +++ + ESP_CMD_TRACK_SET_S_RATE = 0xA5, // +++ + ESP_CMD_TRACK_SET_PARAMS = 0xA6, // i: ESP_REG_OBJ_HANDLE, ESP_REG_TRACK_MAX_LOOP_COUNT + // (0 = loop forever, the default; N = stop playback after N loops) + ESP_CMD_TRACK_SET_POS = 0xA7, // +++ + ESP_CMD_TRACK_GET_INFO = 0xA8, // i: ESP_REG_OBJ_HANDLE + // o: ESP_REG_TRACK_STATUS, ESP_REG_TRACK_IS_CURRENT, + // ESP_REG_TRACK_PATTERN_INDEX, ESP_REG_TRACK_PATTERN, ESP_REG_TRACK_ROW, + // ESP_REG_TRACK_SAMPLES, ESP_REG_TRACK_BPM, ESP_REG_TRACK_TEMPO, + // ESP_REG_TRACK_LOOP_COUNT, ESP_REG_TRACK_TOTAL_SAMPLES + // (position/speed reflect the object's own context - live if + // ESP_REG_TRACK_IS_CURRENT is set, otherwise a frozen snapshot from + // when it last played or was reset) + ESP_CMD_TRACK_GET_STATE = 0xA9, // i: ESP_REG_OBJ_HANDLE + // o: ESP_REG_TRACK_STATUS, ESP_REG_TRACK_IS_CURRENT + ESP_CMD_TRACK_GET_STATS = 0xAA, // +++ + + ESP_CMD_XM_STREAM_LOAD = 0xAB, // i: ESP_REG_DATA_SIZE (tx chunk, aligned), ESP_REG_DATA_OFFSET (total on first chunk, 0 on next chunks) + // o: ESP_REG_DATA_OFFSET (chunk offset), ESP_REG_DATA_SIZE (chunk size), ESP_REG_OBJ_HANDLE + ESP_CMD_MOD_STREAM_LOAD = 0xAC, // i: ESP_REG_DATA_SIZE (tx chunk, aligned), ESP_REG_DATA_OFFSET (total on first chunk, 0 on next chunks) + // o: ESP_REG_DATA_OFFSET (chunk offset), ESP_REG_DATA_SIZE (chunk size), ESP_REG_OBJ_HANDLE + ESP_CMD_S3M_STREAM_LOAD = 0xAD, // i: ESP_REG_DATA_SIZE (tx chunk, aligned), ESP_REG_DATA_OFFSET (total on first chunk, 0 on next chunks) + // o: ESP_REG_DATA_OFFSET (chunk offset), ESP_REG_DATA_SIZE (chunk size), ESP_REG_OBJ_HANDLE + + ESP_CMD_SFX_PLAY = 0xB0, // i: ESP_REG_OBJ_HANDLE, ESP_REG_SFX_GROUP; o: ESP_REG_SFX_CHANNEL + ESP_CMD_SFX_PLAY_EX = 0xB1, // i: ESP_REG_OBJ_HANDLE, ESP_REG_SFX_GROUP, ESP_REG_SFX_VOLUME, ESP_REG_SFX_PAN, ESP_REG_SFX_PITCH; o: ESP_REG_SFX_CHANNEL + ESP_CMD_SFX_STOP = 0xB2, // i: ESP_REG_SFX_CHANNEL + ESP_CMD_SFX_SET_PARAMS = 0xB3, // i: ESP_REG_SFX_CHANNEL, ESP_REG_SFX_VOLUME, ESP_REG_SFX_PAN, ESP_REG_SFX_PITCH + ESP_CMD_SFX_SET_VOLUME = 0xB4, // i: ESP_REG_SFX_VOLUME + ESP_CMD_SFX_GET_STATE = 0xB5, // i: ESP_REG_SFX_CHANNEL; o: ESP_REG_SFX_STATE_* + ESP_CMD_SFX_STOP_GROUP = 0xB6, // i: ESP_REG_SFX_GROUP + + ESP_CMD_CONFIG_SPI = 0xC0, // +++ + + ESP_CMD_LOAD_ELF = 0xD0, // i: ESP_REG_OBJ_HANDLE + // o: ESP_REG_LIB_HANDLE + ESP_CMD_LOAD_ELF_OPT = 0xD1, // i: ESP_REG_OBJ_HANDLE, ESP_REG_OPT + // o: ESP_REG_LIB_HANDLE + ESP_CMD_RUN_FUNC0 = 0xD2, // i: ESP_REG_LIB_HANDLE, ESP_REG_FUNC, ESP_REG_ARG, + // o: ESP_REG_RETVAL + ESP_CMD_RUN_FUNC1 = 0xD3, // i: ESP_REG_LIB_HANDLE, ESP_REG_FUNC, ESP_REG_ARG, ESP_REG_ARR1_HANDLE + // o: ESP_REG_RETVAL + ESP_CMD_RUN_FUNC2 = 0xD4, // i: ESP_REG_LIB_HANDLE, ESP_REG_FUNC, ESP_REG_ARG, ESP_REG_ARR1_HANDLE, ESP_REG_ARR2_HANDLE + // o: ESP_REG_RETVAL + ESP_CMD_RUN_FUNC3 = 0xD5, // i: ESP_REG_LIB_HANDLE, ESP_REG_FUNC, ESP_REG_ARG, ESP_REG_ARR1_HANDLE, ESP_REG_ARR2_HANDLE, ESP_REG_ARR3_HANDLE + // o: ESP_REG_RETVAL + + ESP_CMD_MAKE_OBJECT = 0xE0, // i: ESP_REG_DATA_SIZE, ESP_REG_OBJ_TYPE + // o: ESP_REG_OBJ_HANDLE, ESP_REG_DATA_OFFSET, ESP_REG_DATA_SIZE + ESP_CMD_WRITE_OBJECT = 0xE1, // i: ESP_REG_OBJ_HANDLE, ESP_REG_DATA_OFFSET, ESP_REG_DATA_SIZE + // o: ESP_REG_DATA_OFFSET, ESP_REG_DATA_SIZE + ESP_CMD_READ_OBJECT = 0xE2, // i: ESP_REG_OBJ_HANDLE, ESP_REG_DATA_OFFSET, ESP_REG_DATA_SIZE + // o: ESP_REG_DATA_OFFSET, ESP_REG_DATA_SIZE + ESP_CMD_DELETE_OBJECT = 0xE3, // i: ESP_REG_OBJ_HANDLE + ESP_CMD_KILL_OBJECTS = 0xE4, // (no parameters) + ESP_CMD_FILL_OBJECT = 0xE5, // +++ + ESP_CMD_COPY_OBJECT = 0xE6, // +++ + ESP_CMD_GET_OBJECT_INFO = 0xE7, // +++ + ESP_CMD_REBOOT = 0xED, // (no parameters) + ESP_CMD_RESET = 0xEE, // (no parameters) + ESP_CMD_BREAK = 0xEF, // abort active host tracker stream state, READY if idle + + ESP_CMD_GET_RND = 0xF0, // i: ESP_REG_DATA_SIZE + ESP_CMD_DEHST = 0xF1, // i: ESP_REG_OBJ_HANDLE, ESP_REG_DATA_SIZE, ESP_REG_OBJ_TYPE + // o: ESP_REG_DATA_OFFSET, ESP_REG_DATA_SIZE + ESP_CMD_UNZIP = 0xF2, // i: ESP_REG_OBJ_HANDLE, ESP_REG_DATA_SIZE, ESP_REG_OBJ_TYPE + // o: ESP_REG_DATA_OFFSET, ESP_REG_DATA_SIZE + ESP_CMD_STREAM_UNZIP = 0xF3, // i: ESP_REG_OBJ_TYPE + // o: ESP_REG_OBJ_HANDLE +}; + +enum +{ + ESP_OPT_DATA_SRAM = 0x01, + ESP_OPT_RODATA_SRAM = 0x02, + ESP_OPT_BSS_SRAM = 0x04, + + ESP_OPT_SPI_1BIT = 0x00, + ESP_OPT_SPI_2BIT = 0x40, + ESP_OPT_SPI_4BIT = 0x80, +}; + +enum +{ + // Status codes + ESP_ST_IDLE = 0x00, // Idle + ESP_ST_READY = 0x01, // Command completed + ESP_ST_BUSY = 0x02, // Busy executing command or initializing + ESP_ST_DATA_M2S = 0x03, // Ready to receive data from Master to Slave + ESP_ST_DATA_S2M = 0x04, // Ready to send data from Slave to Master + + ESP_ST_RESET = 0x7E, // Reset performed, ready + + // Error codes + ESP_ERR_INV_COMMAND = 0x80, + ESP_ERR_INV_PARAM , + ESP_ERR_INV_STATE , + ESP_ERR_INV_STR_LEN , + ESP_ERR_INV_SIZE , // 84 + ESP_ERR_INV_OBJ_TYPE , + ESP_ERR_INV_ARR_NUM , + ESP_ERR_INV_HANDLE , + ESP_ERR_INV_XM_HANDLE , // 88 + ESP_ERR_INV_LIB_HANDLE , + ESP_ERR_INV_ELF_HANDLE , + ESP_ERR_INV_HST_HANDLE , + ESP_ERR_INV_BSS_HANDLE , // 8C + ESP_ERR_INV_ARG_HANDLE , + ESP_ERR_INV_SRC_HANDLE , + ESP_ERR_INV_DST_HANDLE , + ESP_ERR_INV_XM , // 90, + ESP_ERR_INV_LIB , + ESP_ERR_INV_ELF , + ESP_ERR_INV_HST , + ESP_ERR_INV_ZIP , // 94 + ESP_ERR_INV_MOD , + ESP_ERR_INV_MOD_HANDLE , + ESP_ERR_INV_S3M , + ESP_ERR_INV_S3M_HANDLE , // 98 + ESP_ERR_OUT_OF_MEMORY , + ESP_ERR_OUT_OF_HANDLES , + ESP_ERR_OBJ_NOT_DELETED , + + ESP_ERR_AP_NOT_CONNECTED = 0xB0, + ESP_ERR_NET_BUSY , + ESP_ERR_WEATHER = 0xB5, // weather HTTP/JSON failure; details in log + + ESP_ERR_VFS_NO_REQUEST = 0x9C, // ESP_CMD_VFS_GET_REQUEST_DATA/SUBMIT_RESULT with nothing pending + ESP_ERR_VFS_TIMEOUT = 0x9D, // no VFS client waiting for a result (e.g. it gave up) +}; + +// VFS bridge request opcodes - travel inside the ESP_CMD_VFS_GET_REQUEST_DATA +// payload, not as separate ESP_CMD_* values (see ESP_CMD_VFS_POLL comment). +enum +{ + VFS_OP_STAT = 0x40, + VFS_OP_READDIR = 0x41, + VFS_OP_OPEN = 0x42, + VFS_OP_READ = 0x43, + VFS_OP_WRITE = 0x44, + VFS_OP_CLOSE = 0x45, + VFS_OP_DELETE = 0x46, + VFS_OP_MKDIR = 0x47, + VFS_OP_RMDIR = 0x48, + // 2026-09-08: real filesystem-size/free-space query, via Wild Commander + // Improved's FILEX_OP_GET_FS_INFO (needs FILEX.WMF installed) - see + // do_statfs() in smbvfs/src/main.c. No request payload. Result: u32 + // total_clusters, u32 free_clusters, u8 sectors_per_cluster, u16 + // bytes_per_sector (11 bytes) - status=0 on success. Was previously + // faked as a hardcoded 512MB/32MB in vfs_bridge.cpp, see + // project_smbvfs_plugin.md. + VFS_OP_STATFS = 0x49, +}; + +// Info type (ESP_CMD_GET_INFO_STR) +enum +{ + GET_INFO_COPYRIGHT = 0x00, + GET_INFO_API = 0x01, + GET_INFO_BUILD = 0x02, + GET_INFO_IDF = 0x03, +}; + +// Memory object types (add new types to mem_obj.cpp) +enum +{ + OBJ_TYPE_NONE = 0, + OBJ_TYPE_DATA = 1, // SPIRAM + OBJ_TYPE_DATAF = 2, // SRAM + OBJ_TYPE_ELF = 3, // SPIRAM + OBJ_TYPE_LIB = 4, // Virtual + OBJ_TYPE_XM = 5, // SPIRAM + OBJ_TYPE_WAV = 6, // SPIRAM + OBJ_TYPE_HST = 7, // SPIRAM + OBJ_TYPE_ZIP = 8, // SPIRAM + OBJ_TYPE_XMC = 9, // SPIRAM + OBJ_TYPE_MOD = 10, // SPIRAM + OBJ_TYPE_MDC = 11, // SPIRAM + OBJ_TYPE_S3M = 12, // SPIRAM + OBJ_TYPE_S3C = 13, // SPIRAM + OBJ_TYPE_MBC = 14, // SPIRAM +}; + +// Network state +enum +{ + NETWORK_CLOSED = 0x00, + NETWORK_OPENING = 0x01, + NETWORK_OPEN = 0x02, + NETWORK_CLOSING = 0x03, + NETWORK_UNKNOWN = 0xFF +}; + +// SPI Slave Commands (ESP32) +enum +{ + ESP_SPI_CMD_WR_REGS = 0x01, + ESP_SPI_CMD_RD_REGS = 0x02, + ESP_SPI_CMD_WR_DATA = 0x03, + ESP_SPI_CMD_RD_DATA = 0x04, + ESP_SPI_CMD_W_END = 0x07, + ESP_SPI_CMD_R_END = 0x08, +}; + +enum +{ + OBJ_ST_NONE = 0, + + LIB_OBJ_ST_READY = 0x10, // Library loaded + + TRACK_OBJ_ST_STOPPED = 0x20, // Tracker object context created, idling + TRACK_OBJ_ST_PLAYING = 0x21, // Tracker object playing + + WAV_OBJ_ST_PLAYING = 0x30, // WAV object is used by SFX renderer + + OBJ_ST_DELETING = 0xFE, // Object is being deleted, new users must not attach + OBJ_ST_ERROR = 0xFF // Reserved +}; diff --git a/src/main/fatfs.cpp b/src/main/fatfs.cpp new file mode 100644 index 0000000..8fafdd1 --- /dev/null +++ b/src/main/fatfs.cpp @@ -0,0 +1,618 @@ +#include +#include +#include +#include +#include +#include +#include "esp_console.h" +#include "esp_partition.h" +#include "esp_vfs_fat.h" +#include "diskio_impl.h" +#include "diskio_wl.h" +#include "ff.h" +#include "wear_levelling.h" +#include "fatfs.h" + +bool fs_initialized = false; +bool fs_fs_mounted = false; +char fs_fs_base_path[32] = { 0 }; +char fs_part_label[16] = { 0 }; +wl_handle_t fs_wl_handle = WL_INVALID_HANDLE; +FATFS *fs_fs_fatfs = NULL; +BYTE fs_fs_pdrv = FF_DRV_NOT_USED; +bool fs_fs_vfs_registered = false; +bool fs_fs_diskio_registered = false; +bool fs_fs_fat_mounted = false; +bool fs_fs_no_filesystem = false; +FRESULT fs_fs_last_mount_result = FR_OK; + +#define FS_VFS_MAX_FILES 4 + +int fs_build_full_path(const char *base_path, const char *path, char *full, size_t full_size) +{ + int n; + + if (!base_path || !base_path[0] || !full || full_size < 2) return 0; + + if (!path || !path[0] || strcmp(path, "/") == 0) + { + n = snprintf(full, full_size, "%s", base_path); + return n >= 0 && (size_t)n < full_size; + } + + if (path[0] == '/') + { + n = snprintf(full, full_size, "%s%s", base_path, path); + return n >= 0 && (size_t)n < full_size; + } + + n = snprintf(full, full_size, "%s/%s", base_path, path); + return n >= 0 && (size_t)n < full_size; +} + +const esp_partition_t *fs_find_partition() +{ + return esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_DATA_FAT, + FS_PART_LABEL); +} + +void fs_clear_mount_state() +{ + fs_initialized = false; + fs_fs_mounted = false; + fs_fs_fatfs = NULL; + fs_fs_pdrv = FF_DRV_NOT_USED; + fs_fs_vfs_registered = false; + fs_fs_diskio_registered = false; + fs_fs_fat_mounted = false; + fs_fs_base_path[0] = 0; + fs_part_label[0] = 0; + fs_wl_handle = WL_INVALID_HANDLE; +} + +void fs_unmount_force() +{ + char drv[3]; + + if (fs_fs_pdrv != FF_DRV_NOT_USED) + { + drv[0] = (char)('0' + fs_fs_pdrv); + drv[1] = ':'; + drv[2] = 0; + + if (fs_fs_fat_mounted) + f_mount(NULL, drv, 0); + } + + if (fs_fs_diskio_registered && fs_fs_pdrv != FF_DRV_NOT_USED) + { + ff_diskio_unregister(fs_fs_pdrv); + if (fs_wl_handle != WL_INVALID_HANDLE) + ff_diskio_clear_pdrv_wl(fs_wl_handle); + } + + if (fs_fs_vfs_registered) + esp_vfs_fat_unregister_path(fs_fs_base_path[0] ? fs_fs_base_path : FS_BASE_PATH); + + if (fs_wl_handle != WL_INVALID_HANDLE) + wl_unmount(fs_wl_handle); + + fs_clear_mount_state(); +} + +esp_err_t fs_register_fat(const esp_partition_t *part, const esp_vfs_fat_mount_config_t *mount_cfg) +{ + char drv[3]; + esp_err_t err; + + if (!part || !mount_cfg) return ESP_ERR_INVALID_ARG; + + err = wl_mount(part, &fs_wl_handle); + if (err != ESP_OK) return err; + + err = ff_diskio_get_drive(&fs_fs_pdrv); + if (err != ESP_OK || fs_fs_pdrv == FF_DRV_NOT_USED) + return ESP_ERR_NO_MEM; + + err = ff_diskio_register_wl_partition(fs_fs_pdrv, fs_wl_handle); + if (err != ESP_OK) return err; + fs_fs_diskio_registered = true; + + drv[0] = (char)('0' + fs_fs_pdrv); + drv[1] = ':'; + drv[2] = 0; + + esp_vfs_fat_conf_t fs_fatfs_conf = { + .base_path = FS_BASE_PATH, + .fat_drive = drv, + .max_files = (size_t)mount_cfg->max_files, + }; + err = esp_vfs_fat_register(&fs_fatfs_conf, &fs_fs_fatfs); + if (err != ESP_OK) return err; + fs_fs_vfs_registered = true; + + fs_fs_last_mount_result = f_mount(fs_fs_fatfs, drv, 1); + if (fs_fs_last_mount_result != FR_OK) + { + fs_fs_no_filesystem = fs_fs_last_mount_result == FR_NO_FILESYSTEM; + return ESP_FAIL; + } + + fs_fs_fat_mounted = true; + return ESP_OK; +} + +size_t fs_get_allocation_unit_size(size_t part_size) +{ + if (part_size >= (16u * 1024u * 1024u)) return 16u * 1024u; + if (part_size >= (4u * 1024u * 1024u)) return 4u * 1024u; + return 4096; +} + +void fs_fill_mount_cfg(esp_vfs_fat_mount_config_t *cfg, bool format_if_mount_failed) +{ + const esp_partition_t *part = fs_find_partition(); + size_t part_size = part ? part->size : 0; + + memset(cfg, 0, sizeof(*cfg)); + cfg->format_if_mount_failed = format_if_mount_failed; + cfg->max_files = FS_VFS_MAX_FILES; + cfg->allocation_unit_size = fs_get_allocation_unit_size(part_size); + cfg->disk_status_check_enable = false; + cfg->use_one_fat = true; +} + + +const char *fs_fat_type_name(BYTE fs_type) +{ + switch (fs_type) + { + case FS_FAT12: return "FAT12"; + case FS_FAT16: return "FAT16"; + case FS_FAT32: return "FAT32"; +#if defined(FF_FS_EXFAT) && FF_FS_EXFAT + case FS_EXFAT: return "exFAT"; +#endif + default: return "unknown"; + } +} + +uint32_t fs_fat_sector_size(FATFS *fat) +{ + if (!fat) return 0; + +#if FF_MAX_SS != FF_MIN_SS + return fat->ssize; +#else + return FF_MIN_SS; +#endif +} + +FRESULT fs_get_mounted_fatfs(FATFS **out_fat, DWORD *out_free_clusters) +{ + if (!out_fat || !out_free_clusters) return FR_INVALID_PARAMETER; + + *out_fat = NULL; + *out_free_clusters = 0; + + FRESULT res = f_getfree("", out_free_clusters, out_fat); + if (res == FR_OK) return res; + + return f_getfree("0:", out_free_clusters, out_fat); +} + +void fs_print_fatfs_details(uint64_t total_bytes, uint64_t free_bytes, esp_err_t usage_err) +{ + FATFS *fat = NULL; + DWORD free_clusters_fatfs = 0; + FRESULT res = fs_get_mounted_fatfs(&fat, &free_clusters_fatfs); + + if (res != FR_OK || !fat) + { + printf(" fatfs : unavailable (FRESULT=%u)\r\n", (unsigned)res); + return; + } + + uint32_t sector_size = fs_fat_sector_size(fat); + uint32_t cluster_size = (uint32_t)fat->csize * sector_size; + uint32_t total_clusters = fat->n_fatent >= 2 ? fat->n_fatent - 2 : 0; + uint32_t free_clusters = (uint32_t)free_clusters_fatfs; + + if (free_clusters > total_clusters) + free_clusters = total_clusters; + + uint32_t used_clusters = total_clusters >= free_clusters ? total_clusters - free_clusters : 0; + uint64_t data_bytes = (uint64_t)total_clusters * cluster_size; + uint64_t fat_bytes = (uint64_t)fat->fsize * sector_size; + + printf(" fat type : %s (%u)\r\n", fs_fat_type_name(fat->fs_type), (unsigned)fat->fs_type); + printf(" fat copies : %u\r\n", (unsigned)fat->n_fats); + printf(" sector : %u bytes\r\n", (unsigned)sector_size); + printf(" cluster : %u sectors, %u bytes\r\n", (unsigned)fat->csize, (unsigned)cluster_size); + printf(" clusters : total=%u used=%u free=%u\r\n", (unsigned)total_clusters, (unsigned)used_clusters, (unsigned)free_clusters); + printf(" data area : %llu bytes\r\n", (unsigned long long)data_bytes); + printf(" fat size : %u sectors, %llu bytes each\r\n", (unsigned)fat->fsize, (unsigned long long)fat_bytes); + printf(" root ents : %u\r\n", (unsigned)fat->n_rootdir); + printf(" vol base : %llu\r\n", (unsigned long long)fat->volbase); + printf(" fat base : %llu\r\n", (unsigned long long)fat->fatbase); + printf(" dir base : %llu\r\n", (unsigned long long)fat->dirbase); + printf(" data base : %llu\r\n", (unsigned long long)fat->database); + + if (usage_err == ESP_OK && total_bytes != data_bytes) + printf(" vfs total : %llu bytes\r\n", (unsigned long long)total_bytes); + + if (usage_err == ESP_OK && cluster_size > 0 && free_bytes != (uint64_t)free_clusters * cluster_size) + printf(" vfs free : %llu bytes\r\n", (unsigned long long)free_bytes); +} + +esp_err_t fs_mount_impl(bool quiet) +{ + const esp_partition_t *part; + esp_err_t err; + + if (fs_fs_mounted) + { + fs_initialized = true; + return ESP_OK; + } + + fs_fs_no_filesystem = false; + fs_fs_last_mount_result = FR_OK; + part = fs_find_partition(); + if (!part) return ESP_ERR_NOT_FOUND; + + esp_vfs_fat_mount_config_t mount_cfg; + fs_fill_mount_cfg(&mount_cfg, false); + + err = fs_register_fat(part, &mount_cfg); + if (err != ESP_OK) + { + fs_unmount_force(); + + if (fs_fs_no_filesystem) + return ESP_ERR_INVALID_STATE; + + if (!quiet) + { + if (fs_fs_last_mount_result != FR_OK) + printf("E: FAT f_mount failed: FRESULT=%u\r\n", (unsigned)fs_fs_last_mount_result); + else + printf("E: FAT mount failed: %s\r\n", esp_err_to_name(err)); + } + return err; + } + + fs_initialized = true; + fs_fs_mounted = true; + fs_fs_no_filesystem = false; + fs_fs_last_mount_result = FR_OK; + snprintf(fs_fs_base_path, sizeof(fs_fs_base_path), "%s", FS_BASE_PATH); + snprintf(fs_part_label, sizeof(fs_part_label), "%s", FS_PART_LABEL); + + return ESP_OK; +} + +esp_err_t fs_mount() +{ + return fs_mount_impl(false); +} + +esp_err_t fs_mount_quiet() +{ + return fs_mount_impl(true); +} + +esp_err_t fs_format() +{ + const esp_partition_t *part = fs_find_partition(); + if (!part) return ESP_ERR_NOT_FOUND; + + if (fs_fs_mounted) + fs_deinit(); + + esp_vfs_fat_mount_config_t format_cfg; + fs_fill_mount_cfg(&format_cfg, true); + + esp_err_t err = esp_vfs_fat_spiflash_format_cfg_rw_wl( + FS_BASE_PATH, + FS_PART_LABEL, + &format_cfg); + if (err != ESP_OK) + { + printf("E: esp_vfs_fat_spiflash_format_cfg_rw_wl failed: %s\r\n", esp_err_to_name(err)); + return err; + } + + return fs_mount(); +} + +esp_err_t fs_delete() +{ + const esp_partition_t *part = fs_find_partition(); + + if (!part) return ESP_ERR_NOT_FOUND; + + fs_deinit(); + esp_err_t err = esp_partition_erase_range(part, 0, part->size); + if (err == ESP_OK) + { + fs_fs_no_filesystem = true; + fs_fs_last_mount_result = FR_NO_FILESYSTEM; + } + + return err; +} + +void fs_deinit() +{ + fs_unmount_force(); + fs_fs_no_filesystem = false; + fs_fs_last_mount_result = FR_OK; +} + +esp_err_t fs_ensure_ready() +{ + return fs_mount(); +} + +esp_err_t fs_ensure_ready_quiet() +{ + return fs_mount_quiet(); +} + +esp_err_t fs_list_dir(const char *base_path, const char *path) +{ + char full[256]; + + if (!fs_build_full_path(base_path, path, full, sizeof(full))) + return ESP_ERR_INVALID_ARG; + + errno = 0; + DIR *d = opendir(full); + if (!d) + { + int saved_errno = errno; + printf("E: opendir('%s') failed, errno=%d\r\n", full, saved_errno); + return ESP_FAIL; + } + + printf("Listing: %s\r\n", full); + + for (;;) + { + struct dirent *e = readdir(d); + if (!e) break; + + if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) + continue; + + char p[256]; + int n = snprintf(p, sizeof(p), "%s/%s", full, e->d_name); + if (n < 0 || (size_t)n >= sizeof(p)) + { + printf(" ? ? %s (path too long)\r\n", e->d_name); + continue; + } + + struct stat st = {}; + if (stat(p, &st) == 0) + { + const char *t = S_ISDIR(st.st_mode) ? "DIR " : "FILE"; + printf(" %s %10" PRIu32 " %s\r\n", t, (uint32_t)st.st_size, e->d_name); + } + else + { + printf(" ? ? %s\r\n", e->d_name); + } + } + + closedir(d); + return ESP_OK; +} + +int fs_info(int argc, char **argv) +{ + const esp_partition_t *part; + uint64_t total = 0; + uint64_t free = 0; + uint64_t used = 0; + esp_err_t err; + + if (argc < 0 || !argv) return 1; + + err = fs_ensure_ready_quiet(); + part = fs_find_partition(); + + printf("FAT info\r\n"); + printf(" label : %s\r\n", FS_PART_LABEL); + printf(" base path : %s\r\n", FS_BASE_PATH); + + if (err != ESP_OK) + { + if (err == ESP_ERR_NOT_FOUND) + { + printf(" state : partition not found\r\n"); + return 0; + } + + if (fs_fs_no_filesystem) + { + printf(" state : no FAT filesystem\r\n"); + if (part) + { + printf(" address : 0x%08" PRIX32 "\r\n", part->address); + printf(" size : 0x%08lx (%lu bytes)\r\n", (unsigned long)part->size, (unsigned long)part->size); + } + return 0; + } + + if (fs_fs_last_mount_result != FR_OK) + printf(" state : unavailable (FRESULT=%u)\r\n", (unsigned)fs_fs_last_mount_result); + else + printf(" state : unavailable (%s)\r\n", esp_err_to_name(err)); + return 1; + } + + err = esp_vfs_fat_info(FS_BASE_PATH, &total, &free); + if (err == ESP_OK) + used = total - free; + + printf(" mounted : %s\r\n", fs_fs_mounted ? "yes" : "no"); + + esp_vfs_fat_mount_config_t cfg; + fs_fill_mount_cfg(&cfg, false); + printf(" cfg alloc : %u bytes\r\n", (unsigned)cfg.allocation_unit_size); + printf(" cfg fats : %u on next format\r\n", cfg.use_one_fat ? 1u : 2u); + printf(" max files : %d\r\n", cfg.max_files); + + if (err == ESP_OK) + { + printf(" total : %llu bytes\r\n", (unsigned long long)total); + printf(" used : %llu bytes\r\n", (unsigned long long)used); + printf(" free : %llu bytes\r\n", (unsigned long long)free); + } + else + { + printf(" usage : unavailable (%s)\r\n", esp_err_to_name(err)); + } + + fs_print_fatfs_details(total, free, err); + + if (part) + { + printf(" address : 0x%08" PRIX32 "\r\n", part->address); + printf(" size : 0x%08lx (%lu bytes)\r\n", (unsigned long)part->size, (unsigned long)part->size); + } + else + { + printf(" partition : not found\r\n"); + } + + if (fs_wl_handle != WL_INVALID_HANDLE) + { + size_t wl_bytes = wl_size(fs_wl_handle); + size_t wl_sector = wl_sector_size(fs_wl_handle); + printf(" wl size : %u bytes\r\n", (unsigned)wl_bytes); + printf(" wl sector : %u bytes\r\n", (unsigned)wl_sector); + printf(" wl handle : %d\r\n", (int)fs_wl_handle); + } + + return 0; +} + +esp_err_t fs_init() +{ + return fs_format(); +} + +int fs_format_cmd(int argc, char **argv) +{ + if (argc < 0 || !argv) return 1; + + const esp_partition_t *part = fs_find_partition(); + if (!part) + { + printf("E: partition '%s' not found\r\n", FS_PART_LABEL); + return 1; + } + + esp_vfs_fat_mount_config_t format_cfg; + fs_fill_mount_cfg(&format_cfg, true); + + esp_err_t err = fs_format(); + if (err != ESP_OK) return 1; + + printf("FAT formatted and mounted: %s -> %s\r\n", FS_PART_LABEL, FS_BASE_PATH); + printf(" address : 0x%08" PRIX32 "\r\n", part->address); + printf(" size : 0x%08lx (%lu bytes)\r\n", (unsigned long)part->size, (unsigned long)part->size); + printf(" alloc unit : %u bytes\r\n", (unsigned)format_cfg.allocation_unit_size); + printf(" fat copies : %u\r\n", format_cfg.use_one_fat ? 1u : 2u); + return 0; +} + +int fs_delete_cmd(int argc, char **argv) +{ + const esp_partition_t *part; + esp_err_t err; + + if (argc < 0 || !argv) return 1; + + part = fs_find_partition(); + if (!part) + { + printf("E: partition '%s' not found\r\n", FS_PART_LABEL); + return 1; + } + + err = fs_delete(); + if (err != ESP_OK) + { + printf("E: FAT erase failed: %s\r\n", esp_err_to_name(err)); + return 1; + } + + printf("FAT erased: %s\r\n", FS_PART_LABEL); + printf(" address : 0x%08" PRIX32 "\r\n", part->address); + printf(" size : 0x%08lx (%lu bytes)\r\n", (unsigned long)part->size, (unsigned long)part->size); + return 0; +} + +int fs_ls(int argc, char **argv) +{ + const char *path = "/"; + + if (argc >= 3) + path = argv[2]; + + esp_err_t err = fs_ensure_ready(); + if (err != ESP_OK) return 1; + + err = fs_list_dir(FS_BASE_PATH, path); + return (err == ESP_OK) ? 0 : 1; +} + +int fs_cmd(int argc, char **argv) +{ + if (argc < 2 || !argv[1]) + { + printf("Usage:\r\n"); + printf(" fat format\r\n"); + printf(" fat info\r\n"); + printf(" fat del\r\n"); + printf(" fat ls [path]\r\n"); + return 0; + } + + const char *op = argv[1]; + + if (!strcmp(op, "format")) + return fs_format_cmd(argc, argv); + + if (!strcmp(op, "info")) + return fs_info(argc, argv); + + if (!strcmp(op, "del")) + return fs_delete_cmd(argc, argv); + + if (!strcmp(op, "ls")) + return fs_ls(argc, argv); + + printf("Unknown subcommand: %s\r\n", op); + return 1; +} + +void fat_console_register_system_commands() +{ + const esp_console_cmd_t cmd = + { + .command = "fat", + .help = "FATFS commands: format/info/del/ls", + .hint = NULL, + .func = &fs_cmd, + .argtable = NULL + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} diff --git a/src/main/fatfs.h b/src/main/fatfs.h new file mode 100644 index 0000000..00000d3 --- /dev/null +++ b/src/main/fatfs.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include "esp_err.h" +#include "wear_levelling.h" + +#define FS_PART_LABEL "fat" +#define FS_BASE_PATH "/fs" + +extern bool fs_initialized; +extern bool fs_fs_mounted; +extern char fs_fs_base_path[32]; +extern char fs_part_label[16]; +extern wl_handle_t fs_wl_handle; + +esp_err_t fs_mount(); +esp_err_t fs_mount_quiet(); +esp_err_t fs_format(); +esp_err_t fs_delete(); +esp_err_t fs_init(); +esp_err_t fs_ensure_ready(); +esp_err_t fs_ensure_ready_quiet(); +void fs_deinit(); +esp_err_t fs_list_dir(const char *base_path, const char *path); +int fs_build_full_path(const char *base_path, const char *path, char *full, size_t full_size); + +int fs_info(int argc, char **argv); +int fs_format_cmd(int argc, char **argv); +int fs_delete_cmd(int argc, char **argv); +int fs_ls(int argc, char **argv); +int fs_cmd(int argc, char **argv); + +void fat_console_register_system_commands(); diff --git a/src/main/font.h b/src/main/font.h new file mode 100644 index 0000000..dd68391 --- /dev/null +++ b/src/main/font.h @@ -0,0 +1,174 @@ +const u8 code_866_fnt[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0xaa, 0x82, + 0x82, 0xba, 0x92, 0x7c, 0x7c, 0xfe, 0xd6, 0xfe, 0xfe, 0xc6, 0xee, 0x7c, + 0x44, 0xee, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x10, 0x38, 0x7c, 0xfe, + 0x7c, 0x38, 0x10, 0x00, 0x38, 0x38, 0xd6, 0xfe, 0xd6, 0x10, 0x38, 0x00, + 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x10, 0x38, 0x00, 0x00, 0x00, 0x38, 0x7c, + 0x7c, 0x38, 0x00, 0x00, 0xfe, 0xfe, 0xc6, 0x82, 0x82, 0xc6, 0xfe, 0xfe, + 0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0xfe, 0xfe, 0xc6, 0xba, + 0xba, 0xc6, 0xfe, 0xfe, 0x00, 0x0e, 0x06, 0x7a, 0xd8, 0x88, 0xd8, 0x70, + 0x38, 0x6c, 0x44, 0x6c, 0x38, 0x10, 0x38, 0x10, 0x1e, 0x12, 0x1e, 0x10, + 0x10, 0x70, 0xe0, 0x40, 0x3e, 0x22, 0x3e, 0x22, 0x22, 0x2e, 0xe4, 0x40, + 0x92, 0x7c, 0x6c, 0xc6, 0x6c, 0x7c, 0x92, 0x00, 0x80, 0xe0, 0xf8, 0xfe, + 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, + 0x10, 0x38, 0x7c, 0x10, 0x10, 0x7c, 0x38, 0x10, 0x6c, 0x6c, 0x6c, 0x6c, + 0x6c, 0x00, 0x6c, 0x00, 0x7e, 0xb6, 0xb6, 0x76, 0x36, 0x36, 0x36, 0x00, + 0x3c, 0x60, 0x3c, 0x66, 0x3c, 0x06, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x7c, 0x7c, 0x00, 0x10, 0x38, 0x7c, 0x10, 0x7c, 0x38, 0x10, 0x7c, + 0x10, 0x38, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, + 0x7c, 0x38, 0x10, 0x00, 0x00, 0x08, 0x04, 0x7e, 0x04, 0x08, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x7e, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, + 0x40, 0x7e, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, + 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0x00, 0xfe, 0x7c, 0x7c, 0x38, + 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x00, 0x00, 0x6c, 0x24, 0x48, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7e, 0x24, 0x24, 0x7e, 0x24, 0x00, + 0x18, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x18, 0x00, 0x63, 0x66, 0x0c, 0x18, + 0x30, 0x66, 0xc6, 0x00, 0x00, 0x18, 0x34, 0x18, 0x2c, 0x66, 0x3a, 0x00, + 0x00, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x18, + 0x18, 0x0c, 0x06, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, + 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00, + 0x00, 0x3c, 0x66, 0x6e, 0x76, 0x66, 0x3c, 0x00, 0x00, 0x18, 0x38, 0x18, + 0x18, 0x18, 0x18, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x3c, 0x60, 0x7e, 0x00, + 0x00, 0x3c, 0x66, 0x0c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x66, 0x66, 0x66, + 0x7e, 0x06, 0x06, 0x00, 0x00, 0x7e, 0x60, 0x7c, 0x06, 0x66, 0x3c, 0x00, + 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x7e, 0x06, 0x06, + 0x0c, 0x18, 0x18, 0x00, 0x00, 0x3c, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x10, 0x20, + 0x06, 0x0c, 0x18, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x3c, 0x66, 0x06, 0x1c, 0x00, 0x18, 0x00, 0x00, 0x3c, 0x66, 0x5a, + 0x5e, 0x60, 0x3c, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x00, + 0x00, 0x7c, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x3c, 0x66, 0x60, + 0x60, 0x66, 0x3c, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, + 0x00, 0x7e, 0x60, 0x78, 0x60, 0x60, 0x7e, 0x00, 0x00, 0x7e, 0x60, 0x60, + 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x3e, 0x00, + 0x00, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x3c, 0x18, 0x18, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, + 0x00, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0x00, 0x00, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x7e, 0x00, 0x00, 0x82, 0xc6, 0xee, 0xd6, 0xc6, 0xc6, 0x00, + 0x00, 0x46, 0x66, 0x76, 0x6e, 0x66, 0x62, 0x00, 0x00, 0x3c, 0x66, 0x66, + 0x66, 0x66, 0x3c, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, + 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6e, 0x3c, 0x06, 0x00, 0x7c, 0x66, 0x66, + 0x7c, 0x66, 0x66, 0x00, 0x00, 0x3c, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, + 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x3c, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x24, 0x18, 0x00, + 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xee, 0x44, 0x00, 0x00, 0x66, 0x66, 0x3c, + 0x66, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x00, + 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, 0x1e, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1e, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x00, 0x18, 0x3c, 0x66, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x18, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, + 0x3e, 0x66, 0x3e, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x06, 0x06, 0x3e, + 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, + 0x00, 0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00, 0x3e, 0x66, + 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x0c, 0x00, 0x0c, + 0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00, 0xfc, 0xd6, + 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x7c, 0x66, + 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x06, + 0x00, 0x00, 0x3c, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3c, 0x60, + 0x3c, 0x06, 0x7c, 0x00, 0x00, 0x30, 0x78, 0x30, 0x30, 0x30, 0x1c, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x66, 0x66, + 0x66, 0x24, 0x18, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xee, 0x44, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, + 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, + 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x00, 0x70, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x70, 0x00, + 0x00, 0x34, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x99, 0xa1, + 0xa1, 0x99, 0x42, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x00, + 0x00, 0x7c, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x7c, 0x66, 0x7c, + 0x66, 0x66, 0x7c, 0x00, 0x00, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, + 0x00, 0x1e, 0x36, 0x66, 0x66, 0x66, 0xff, 0xc3, 0x00, 0x7e, 0x60, 0x78, + 0x60, 0x60, 0x7e, 0x00, 0x00, 0xd6, 0xd6, 0x7c, 0x7c, 0xd6, 0xd6, 0x00, + 0x00, 0x3c, 0x66, 0x0c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x62, 0x66, 0x6e, + 0x76, 0x66, 0x46, 0x00, 0x04, 0x6a, 0x66, 0x6e, 0x76, 0x66, 0x46, 0x00, + 0x00, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0x00, 0x00, 0x1e, 0x36, 0x66, + 0x66, 0x66, 0x66, 0x00, 0x00, 0x82, 0xc6, 0xee, 0xd6, 0xc6, 0xc6, 0x00, + 0x00, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x3c, 0x66, 0x66, + 0x66, 0x66, 0x3c, 0x00, 0x00, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3c, 0x66, 0x60, + 0x60, 0x66, 0x3c, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x00, 0x7c, 0xd6, 0xd6, + 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x01, 0x00, 0x66, 0x66, 0x66, + 0x3e, 0x06, 0x06, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, + 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x01, 0x00, 0xe0, 0x60, 0x7c, + 0x66, 0x66, 0x7c, 0x00, 0x00, 0xc6, 0xc6, 0xf6, 0xde, 0xde, 0xf6, 0x00, + 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x3c, 0x66, 0x0e, + 0x06, 0x66, 0x3c, 0x00, 0x00, 0xce, 0xdb, 0xfb, 0xdb, 0xdb, 0xce, 0x00, + 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3c, 0x06, + 0x3e, 0x66, 0x3e, 0x00, 0x00, 0x3c, 0x60, 0x3c, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0x7c, 0x66, 0x7c, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x3c, 0x06, + 0x3c, 0x60, 0x3e, 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x00, 0x00, 0xd6, 0x7c, + 0x7c, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x0c, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0x62, 0x66, 0x6e, 0x76, 0x66, 0x00, 0x00, 0x04, 0x6a, 0x66, + 0x6e, 0x76, 0x66, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x00, + 0x00, 0x00, 0x1e, 0x36, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x82, 0xc6, + 0xee, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x7e, 0x66, + 0x66, 0x66, 0x66, 0x00, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x77, 0xdd, 0x77, 0xdd, + 0x77, 0xdd, 0x77, 0xdd, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, + 0xf8, 0x18, 0x18, 0x18, 0x66, 0x66, 0x66, 0xe6, 0x66, 0x66, 0x66, 0x66, + 0x00, 0x00, 0x00, 0xfe, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0xf8, 0x18, + 0xf8, 0x18, 0x18, 0x18, 0x66, 0x66, 0xe6, 0x06, 0xe6, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0xfe, 0x06, + 0xe6, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0xfe, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0xf8, 0x18, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x66, 0x66, 0x66, 0x67, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x60, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x60, 0x67, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe7, 0x00, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xe7, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x67, 0x60, 0x67, 0x66, 0x66, 0x66, 0x00, 0x00, 0xff, 0x00, + 0xff, 0x00, 0x00, 0x00, 0x66, 0x66, 0xe7, 0x00, 0xe7, 0x66, 0x66, 0x66, + 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x7f, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, + 0x18, 0x18, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, + 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x7e, 0x18, + 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, + 0x00, 0x00, 0x7c, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x66, 0x66, + 0x3c, 0x66, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x01, + 0x00, 0x00, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0xd6, 0xd6, + 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x01, + 0x00, 0x00, 0xe0, 0x60, 0x7c, 0x66, 0x7c, 0x00, 0x00, 0x00, 0xc6, 0xc6, + 0xf6, 0xde, 0xf6, 0x00, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x7c, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x0e, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xce, 0xdb, + 0xfb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x3e, 0x66, 0x66, 0x00, + 0x24, 0x7e, 0x60, 0x78, 0x60, 0x60, 0x7e, 0x00, 0x00, 0x24, 0x3c, 0x66, + 0x7e, 0x60, 0x3c, 0x00, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x00, 0x00, 0x0e, 0x1b, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, + 0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0e, 0x0e, 0x0c, 0x0c, 0x6c, 0x3c, 0x1c, 0x00, + 0x8f, 0xcd, 0xef, 0xfc, 0xdc, 0xcc, 0xcc, 0x00, 0x38, 0x6c, 0x18, 0x30, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, + 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x00 +}; diff --git a/src/main/ft8xx.cpp b/src/main/ft8xx.cpp new file mode 100644 index 0000000..d602563 --- /dev/null +++ b/src/main/ft8xx.cpp @@ -0,0 +1,8408 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "miniz.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_timer.h" +#include "esp_check.h" +#include "esp_console.h" +#include "esp_err.h" +#include "esp_heap_caps.h" +#include "driver/uart.h" + +#include "main.h" +#include "font.h" +#include "spi_slave.h" +#include "ft8xx.h" +#include "sdmmc.h" +#include "zx_screen.h" +#include "esp_jpeg_dec.h" + +const char TAG[] = "ft8xx"; + +extern const u8 code_866_fnt[]; + +void hexdump(const void *data, size_t len, uint64_t base_off); + +#define CHUNK_PAYLOAD DMA_BUF_SIZE + +// #define FT_DEMO_PIX_W 640 +// #define FT_DEMO_PIX_H 480 +#define FT_DEMO_PIX_W 320 +#define FT_DEMO_PIX_H 240 +#define FT_DEMO_PIX_SIZE (FT_DEMO_PIX_W * FT_DEMO_PIX_H) +#define FT_DEMO_PIX0_ADDR FT_RAM_G +#define FT_DEMO_PIX1_ADDR (FT_RAM_G + FT_DEMO_PIX_SIZE) +#define FT_DEMO_PALETTE_ADDR (FT_DEMO_PIX1_ADDR + FT_DEMO_PIX_SIZE) +#define FT_DEMO_PALETTE_SIZE (256UL * 4UL) + +#define FT_DEMO_TEXT_COLS 80 +#define FT_DEMO_TEXT_ROWS 30 +#define FT_TEXT_ATTR_MAX_COLS 160 +#define FT_TEXT_ATTR_MAX_ROWS 64 +#define FT_TEXT_ATTR_GROUP_ROWS 32 + +#define FT_DEMO_PAL4_PIX_ADDR FT_RAM_G +#define FT_DEMO_PAL4_PAL_HI_ADDR (FT_DEMO_PAL4_PIX_ADDR + ((FT_DEMO_TEXT_COLS * 4UL) * (FT_DEMO_TEXT_ROWS * 8UL))) +#define FT_DEMO_PAL4_PAL_LO_ADDR (FT_DEMO_PAL4_PAL_HI_ADDR + 512UL) +#define FT_DEMO_PAL4_MASK_ADDR 0x002FF82C // Font area, value = 0x10 + +#define FT_TEXT_ATTR_GROUPS_FOR(rows) ((((u32)(rows)) + FT_TEXT_ATTR_GROUP_ROWS - 1U) / FT_TEXT_ATTR_GROUP_ROWS) +#define FT_TEXT_ATTR_GFX_SIZE_FOR(cols, rows) ((u32)(cols) * 256UL * FT_TEXT_ATTR_GROUPS_FOR(rows)) +#define FT_TEXT_ATTR_COLOR_SIZE_FOR(rows) ((u32)(rows) * 256UL) +#define FT_TEXT_ATTR_UPLOAD_SIZE_FOR(cols, rows) (FT_TEXT_ATTR_GFX_SIZE_FOR(cols, rows) + FT_TEXT_ATTR_COLOR_SIZE_FOR(rows)) +#define FT_TEXT_ATTR_GFX_SIZE FT_TEXT_ATTR_GFX_SIZE_FOR(FT_DEMO_TEXT_COLS, FT_DEMO_TEXT_ROWS) +#define FT_TEXT_ATTR_COLOR_SIZE FT_TEXT_ATTR_COLOR_SIZE_FOR(FT_DEMO_TEXT_ROWS) +#define FT_TEXT_ATTR_UPLOAD_SIZE FT_TEXT_ATTR_UPLOAD_SIZE_FOR(FT_DEMO_TEXT_COLS, FT_DEMO_TEXT_ROWS) + +#define FT_DEMO_PIX_GROUP_ADDR(group, col, cols) (FT_RAM_G + ((((u32)(group) * (u32)(cols)) + (u32)(col)) << 8)) +#define FT_DEMO_PIX_ADDR(col) FT_DEMO_PIX_GROUP_ADDR(0, col, FT_DEMO_TEXT_COLS) +#define FT_DEMO_ATTR_ADDR_FOR(cols, rows) (FT_RAM_G + FT_TEXT_ATTR_GFX_SIZE_FOR(cols, rows)) +#define FT_DEMO_ATTR_ADDR FT_DEMO_ATTR_ADDR_FOR(FT_DEMO_TEXT_COLS, FT_DEMO_TEXT_ROWS) +#define FT_TEXT_ATTR_PAL_HI_ADDR_FOR(cols, rows) (FT_RAM_G + FT_TEXT_ATTR_UPLOAD_SIZE_FOR(cols, rows)) +#define FT_TEXT_ATTR_PAL_LO_ADDR_FOR(cols, rows) (FT_TEXT_ATTR_PAL_HI_ADDR_FOR(cols, rows) + 512UL) + +#define FT_DEMO_ZX_SCREEN_X 16 +#define FT_DEMO_ZX_SCREEN_Y 16 +#define FT_DEMO_ZX_PIX_ADDR FT_RAM_G +#define FT_DEMO_ZX_ATTR_ADDR (FT_DEMO_ZX_PIX_ADDR + 6144) +#define FT_DEMO_ZX_PAL_PAPER_ADDR (FT_DEMO_ZX_PIX_ADDR + 0x2000) +#define FT_DEMO_ZX_PAL_INK_ADDR (FT_DEMO_ZX_PAL_PAPER_ADDR + 512) + +#define FT_RGB888_640_480_W 640 +#define FT_RGB888_640_480_H 480 +#define FT_RGB888_640_480_BPP 3UL +#define FT_RGB888_640_480_STRIDE FT_RGB888_640_480_W +#define FT_RGB888_640_480_PLANE_SIZE (FT_RGB888_640_480_STRIDE * FT_RGB888_640_480_H) +#define FT_RGB888_640_480_SIZE (FT_RGB888_640_480_PLANE_SIZE * FT_RGB888_640_480_BPP) +#define FT_RGB888_640_480_ADDR FT_RAM_G + ((1024U * 1024) - (FT_RGB888_640_480_W * FT_RGB888_640_480_H * FT_RGB888_640_480_BPP)) + +#define FT_JPG_MAX_PATH 256 +#define FT_JPG_SCAN_MAX_DEPTH 8 +#define FT_DXP_HEADER_SIZE 8 +#define FT_DXP_RAM_G_SIZE (1024UL * 1024UL) + +typedef struct +{ + char **items; + int count; + int cap; +} FT_JPG_LIST; + +typedef struct +{ + u8 type; + u16 w; + u16 h; + u16 mask_format; + u32 raw_size; +} +FT_DXP_INFO; + +enum +{ + FT_DXP_TYPE_RAW_L2 = 0, + FT_DXP_TYPE_ZLIB_L2, + FT_DXP_TYPE_ZLIB_L4, + FT_DXP_TYPE_RAW_L4 +}; + +enum +{ + FT_JPG_KEY_EXIT = 0, + FT_JPG_KEY_NEXT, + FT_JPG_KEY_PREV +}; + +// ------------- Profiler ------------- + +typedef struct +{ + uint64_t ts_loop_start; + uint64_t ts_show_start; + uint64_t ts_show_end; + uint64_t ts_wait_swap_start; + uint64_t ts_wait_swap_end; + uint64_t ts_upload_start; + uint64_t ts_upload_end; + uint64_t ts_upload_done; + uint64_t ts_render_start; + uint64_t ts_render_end; + uint64_t ts_idle_wait_start; + uint64_t ts_idle_wait_end; + u32 ft_frames_before_wait; + u32 ft_frames_after_wait; + int stop; +} PROFILER_LINE; + +u32 *ft_ccmdb = nullptr; +u16 ft_ccmdp = 0; +EXT_RAM_BSS_ATTR u8 cmdl[8192]; + +#define FT_F_DL_MAX_DWORDS (8192 / 4) + +EXT_RAM_BSS_ATTR u32 ft_f_dl[FT_F_DL_MAX_DWORDS]; +EXT_RAM_BSS_ATTR u16 ft_f_dl_words[FT_F_DL_MAX_DWORDS]; +u16 ft_f_dl_count = 0; +u16 ft_f_dl_items = 0; +u8 ft_f_dl_ready = 0; + +u8 ft_spi_width = 2; +u32 ft_spi_freq_hz = 20000000UL; +int ft_current_mode = -1; + +const FT_MODE ft_modes[] = // | # | visible | Fpll MHz | Fpix MHz | clocks/dl | clocks/line | lines/frame | line kHz | frame Hz | +{ // | -- | -------- | -------- | -------- | --------- | ----------- | ----------- | -------- | -------- | + {6, 2, 16, 96, 48, 640, 11, 2, 31, 480}, // | 0 | 640x480 | 48 | 24 | 1600 | 800 | 524 | 30.000 | 57.252 | + {8, 2, 24, 40, 128, 640, 9, 3, 28, 480}, // | 1 | 640x480 | 64 | 32 | 1664 | 832 | 520 | 38.462 | 73.964 | + {8, 2, 16, 96, 48, 640, 11, 2, 31, 480}, // | 2 | 640x480 | 64 | 32 | 1600 | 800 | 524 | 40.000 | 76.336 | + {5, 1, 40, 128, 88, 800, 1, 4, 23, 600}, // | 3 | 800x600 | 40 | 40 | 1056 | 1056 | 628 | 37.879 | 60.317 | + {10, 2, 40, 128, 88, 800, 1, 4, 23, 600}, // | 4 | 800x600 | 80 | 40 | 2112 | 1056 | 628 | 37.879 | 60.317 | + {6, 1, 56, 120, 64, 800, 37, 6, 23, 600}, // | 5 | 800x600 | 48 | 48 | 1040 | 1040 | 666 | 46.154 | 69.300 | + {7, 1, 32, 64, 152, 800, 1, 3, 27, 600}, // | 6 | 800x600 | 56 | 56 | 1048 | 1048 | 631 | 53.435 | 84.683 | + {8, 1, 24, 136, 160, 1024, 3, 6, 29, 768}, // | 7 | 1024x768 | 64 | 64 | 1344 | 1344 | 806 | 47.619 | 59.081 | + {9, 1, 24, 136, 144, 1024, 3, 6, 29, 768}, // | 8 | 1024x768 | 72 | 72 | 1328 | 1328 | 806 | 54.217 | 67.267 | + {10, 1, 16, 96, 176, 1024, 1, 3, 28, 768}, // | 9 | 1024x768 | 80 | 80 | 1312 | 1312 | 800 | 60.976 | 76.220 | + {7, 1, 24, 56, 124, 640, 1, 3, 38, 1024}, // | 10 | 640x1024 | 56 | 56 | 844 | 844 | 1066 | 66.351 | 62.243 | + {9, 1, 110, 40, 220, 1280, 5, 5, 20, 720}, // | 11 | 1280x720 | 72 | 72 | 1650 | 1650 | 750 | 43.636 | 58.182 | + {9, 1, 93, 40, 187, 1280, 5, 5, 20, 720}, // | 12 | 1280x720 | 72 | 72 | 1600 | 1600 | 750 | 45.000 | 60.000 | +}; + +const u16 sintab[257] = +{ + 0, 402, 804, 1206, 1608, 2010, 2412, 2813, 3215, 3617, 4018, 4419, 4821, 5221, 5622, 6023, + 6423, 6823, 7223, 7622, 8022, 8421, 8819, 9218, 9615, 10013, 10410, 10807, 11203, 11599, 11995, 12390, + 12785, 13179, 13573, 13966, 14358, 14750, 15142, 15533, 15923, 16313, 16702, 17091, 17479, 17866, 18252, 18638, + 19023, 19408, 19791, 20174, 20557, 20938, 21319, 21699, 22078, 22456, 22833, 23210, 23585, 23960, 24334, 24707, + 25079, 25450, 25820, 26189, 26557, 26924, 27290, 27655, 28019, 28382, 28744, 29105, 29465, 29823, 30181, 30537, + 30892, 31247, 31599, 31951, 32302, 32651, 32999, 33346, 33691, 34035, 34378, 34720, 35061, 35400, 35737, 36074, + 36409, 36742, 37075, 37406, 37735, 38063, 38390, 38715, 39039, 39361, 39682, 40001, 40319, 40635, 40950, 41263, + 41574, 41885, 42193, 42500, 42805, 43109, 43411, 43711, 44010, 44307, 44603, 44896, 45189, 45479, 45768, 46055, + 46340, 46623, 46905, 47185, 47463, 47739, 48014, 48287, 48558, 48827, 49094, 49360, 49623, 49885, 50145, 50403, + 50659, 50913, 51165, 51415, 51664, 51910, 52155, 52397, 52638, 52876, 53113, 53347, 53580, 53810, 54039, 54265, + 54490, 54712, 54933, 55151, 55367, 55581, 55793, 56003, 56211, 56416, 56620, 56821, 57021, 57218, 57413, 57606, + 57796, 57985, 58171, 58355, 58537, 58717, 58894, 59069, 59242, 59413, 59582, 59748, 59912, 60074, 60234, 60391, + 60546, 60699, 60849, 60997, 61143, 61287, 61428, 61567, 61704, 61838, 61970, 62100, 62227, 62352, 62474, 62595, + 62713, 62828, 62941, 63052, 63161, 63267, 63370, 63472, 63570, 63667, 63761, 63853, 63942, 64029, 64114, 64196, + 64275, 64353, 64427, 64500, 64570, 64637, 64702, 64765, 64825, 64883, 64938, 64991, 65042, 65090, 65135, 65178, + 65219, 65257, 65293, 65326, 65357, 65385, 65411, 65435, 65456, 65474, 65490, 65504, 65515, 65523, 65530, 65533, + 65535 +}; + +// ---------- Profiler ----------- + +QueueHandle_t profiler_queue = nullptr; +TaskHandle_t profiler_task_handle = nullptr; +TaskHandle_t profiler_done_task = nullptr; + +uint64_t profiler_now() +{ + return (uint64_t)esp_timer_get_time(); +} + +void profiler_task(void *arg) +{ + PROFILER_LINE line; + uint64_t prev_loop_start = 0; + uint64_t loop_dt; + uint64_t dt_upload; + uint64_t dt_render; + + (void)arg; + + while (1) + { + if (xQueueReceive(profiler_queue, &line, portMAX_DELAY) != pdTRUE) + continue; + + if (line.stop) + break; + + loop_dt = prev_loop_start ? (line.ts_loop_start - prev_loop_start) : 0; + prev_loop_start = line.ts_loop_start; + + dt_upload = (line.ts_upload_start && line.ts_upload_done) ? (line.ts_upload_done - line.ts_upload_start) : 0; + dt_render = (line.ts_render_start && line.ts_render_end) ? (line.ts_render_end - line.ts_render_start) : 0; + + printf("us, frame=%llu ", (unsigned long long)loop_dt); + printf("render=%llu ", (unsigned long long)dt_render); + printf("xfer=%llu", (unsigned long long)dt_upload); + printf("\r\n"); + } + + if (profiler_done_task) + xTaskNotifyGive(profiler_done_task); + + vTaskDelete(nullptr); +} + +esp_err_t profiler_start() +{ + if (profiler_queue) + return ESP_OK; + + profiler_queue = xQueueCreate(64, sizeof(PROFILER_LINE)); + if (!profiler_queue) + return ESP_ERR_NO_MEM; + + profiler_done_task = xTaskGetCurrentTaskHandle(); + + if (xTaskCreatePinnedToCore(profiler_task, "profiler_log", 4096, nullptr, tskIDLE_PRIORITY + 1, &profiler_task_handle, 1) != pdPASS) + { + vQueueDelete(profiler_queue); + profiler_queue = nullptr; + profiler_done_task = nullptr; + profiler_task_handle = nullptr; + return ESP_FAIL; + } + + return ESP_OK; +} + +void profiler_push(const PROFILER_LINE *line) +{ + if (!profiler_queue || !line) + return; + + xQueueSend(profiler_queue, line, 0); +} + +void profiler_stop() +{ + PROFILER_LINE line = {}; + QueueHandle_t queue = profiler_queue; + + if (!queue) + return; + + line.stop = 1; + xQueueSend(queue, &line, pdMS_TO_TICKS(1000)); + + if (!ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) && profiler_task_handle) + vTaskDelete(profiler_task_handle); + + profiler_queue = nullptr; + profiler_task_handle = nullptr; + profiler_done_task = nullptr; + + vQueueDelete(queue); +} + +// -------- Aux math --------- + +i16 rsin(i16 r, u16 th) +{ + i16 th4; + u16 s; + i16 p; + + th >>= 6; + th4 = (i16)(th & 511); + + if (th4 & 256) + th4 = 512 - th4; + + s = sintab[(u16)th4]; + p = (i16)(((u32)s * (u32)r) >> 16); + + if (th & 512) + p = -p; + + return p; +} + +i16 rcos(i16 r, u16 th) +{ + return rsin(r, (u16)(th + 0x4000)); +} + +u32 ft_argb32(u8 a, u8 r, u8 g, u8 b) +{ + return ((u32)a << 24) | ((u32)r << 16) | ((u32)g << 8) | (u32)b; +} + +// -------- Display list --------- + +void ft_AlphaFunc(u8 func, u8 ref) +{ + ft_ccmd((9UL << 24) | ((func & 7L) << 8) | ((ref & 255L) << 0)); +} + +void ft_Begin(u8 prim) +{ + ft_ccmd((31UL << 24) | prim); +} + +void ft_BitmapHandle(u8 handle) +{ + ft_ccmd((5UL << 24) | handle); +} + +void ft_BitmapLayout(u8 format, u16 linestride, u16 height) +{ + ft_ccmd((0x28UL << 24) | ((linestride >> 8) & 12L) | ((height >> 9) & 3L)); + ft_ccmd((7UL << 24) | ((format & 31L) << 19) | ((linestride & 1023L) << 9) | ((height & 511L) << 0)); +} + +void ft_BitmapSize(u8 filter, u8 wrapx, u8 wrapy, u16 width, u16 height) +{ + u8 fxy = (filter << 2) | (wrapx << 1) | (wrapy); + ft_ccmd((0x29UL << 24) | ((width >> 7) & 12L) | ((height>> 9) & 3L)); + ft_ccmd((8UL << 24) | ((u32)fxy << 18) | ((width & 511L) << 9) | ((height & 511L) << 0)); +} + +void ft_BitmapSource(u32 addr) +{ + ft_ccmd((1UL << 24) | ((addr & 0x3FFFFFL) << 0)); +} + +void ft_BitmapTransformA(i32 a) +{ + ft_ccmd((21UL << 24) | ((a & 131071L) << 0)); +} + +void ft_BitmapTransformB(i32 b) +{ + ft_ccmd((22UL << 24) | ((b & 131071L) << 0)); +} + +void ft_BitmapTransformC(i32 c) +{ + ft_ccmd((23UL << 24) | ((c & 16777215L) << 0)); +} + +void ft_BitmapTransformD(i32 d) +{ + ft_ccmd((24UL << 24) | ((d & 131071L) << 0)); +} + +void ft_BitmapTransformE(i32 e) +{ + ft_ccmd((25UL << 24) | ((e & 131071L) << 0)); +} + +void ft_BitmapTransformF(i32 f) +{ + ft_ccmd((26UL << 24) | ((f & 16777215L) << 0)); +} + +void ft_BlendFunc(u8 src, u8 dst) +{ + ft_ccmd((11UL << 24) | ((src & 7L) << 3) | ((dst & 7L) << 0)); +} + +void ft_Call(u16 dest) +{ + ft_ccmd((29UL << 24) | ((dest & 2047L) << 0)); +} + +void ft_Cell(u8 cell) +{ + ft_ccmd((6UL << 24) | ((cell & 127L) << 0)); +} + +void ft_ClearColorA(u8 alpha) +{ + ft_ccmd((15UL << 24) | ((alpha & 255L) << 0)); +} + +void ft_ClearColorRGB(u8 red, u8 green, u8 blue) +{ + ft_ccmd((2UL << 24) | ((red & 255L) << 16) | ((green & 255L) << 8) | ((blue & 255L) << 0)); +} + +void ft_ClearColorRGB32(u32 rgb) +{ + ft_ccmd((2UL << 24) | (rgb & 0xffffffL)); +} + +void ft_Clear(u8 c, u8 s, u8 t) +{ + u8 m = (c << 2) | (s << 1) | t; + ft_ccmd((38UL << 24) | m); +} + +void ft_ClearAll() +{ + ft_ccmd((38UL << 24) | 7); +} + +void ft_ClearStencil(u8 s) +{ + ft_ccmd((17UL << 24) | ((s & 255L) << 0)); +} + +void ft_ClearTag(u8 s) +{ + ft_ccmd((18UL << 24) | ((s & 255L) << 0)); +} + +void ft_ColorA(u8 alpha) +{ + ft_ccmd((16UL << 24) | ((alpha & 255L) << 0)); +} + +void ft_ColorMask(u8 r, u8 g, u8 b, u8 a) +{ + ft_ccmd((32UL << 24) | ((r & 1L) << 3) | ((g & 1L) << 2) | ((b & 1L) << 1) | ((a & 1L) << 0)); +} + +void ft_ColorRGB(u8 red, u8 green, u8 blue) +{ + ft_ccmd((4UL << 24) | ((red & 255L) << 16) | ((green & 255L) << 8) | ((blue & 255L) << 0)); +} + +void ft_ColorRGB32(u32 rgb) +{ + ft_ccmd((4UL << 24) | (rgb & 0xffffffL)); +} + +void ft_Display(void) +{ + ft_ccmd(0UL << 24); +} + +void ft_Nop() +{ + ft_ccmd(0x2DUL << 24); +} + +void ft_End(void) +{ + ft_ccmd(33UL << 24); +} + +void ft_Jump(u16 dest) +{ + ft_ccmd((30UL << 24) | ((dest & 2047L) << 0)); +} + +void ft_LineWidth(u16 width) +{ + ft_ccmd((14UL << 24) | ((width & 4095L) << 0)); +} + +void ft_Macro(u8 m) +{ + ft_ccmd((37UL << 24) | ((m & 1L) << 0)); +} + +void ft_PaletteSource(u32 addr) +{ + ft_ccmd((0x2AUL << 24) | ((addr & 0x3FFFFFL) << 0)); +} + +void ft_PointSize(u16 size) +{ + ft_ccmd((13UL << 24) | ((size & 8191L) << 0)); +} + +void ft_RestoreContext(void) +{ + ft_ccmd(35UL << 24); +} + +void ft_Return(void) +{ + ft_ccmd(36UL << 24); +} + +void ft_SaveContext(void) +{ + ft_ccmd(34UL << 24); +} + +void ft_ScissorSize(u16 width, u16 height) +{ + ft_ccmd((28UL << 24) | ((width & 4095L) << 12) | ((height & 4095L) << 0)); +} + +void ft_ScissorXY(u16 x, u16 y) +{ + ft_ccmd((27UL << 24) | ((x & 511L) << 9) | ((y & 511L) << 0)); +} + +void ft_StencilFunc(u8 func, u8 ref, u8 mask) +{ + ft_ccmd((10UL << 24) | ((func & 7L) << 16) | ((ref & 255L) << 8) | ((mask & 255L) << 0)); +} + +void ft_StencilMask(u8 mask) +{ + ft_ccmd((19UL << 24) | ((mask & 255L) << 0)); +} + +void ft_StencilOp(u8 sfail, u8 spass) +{ + ft_ccmd((12UL << 24) | ((sfail & 7L) << 3) | ((spass & 7L) << 0)); +} + +void ft_TagMask(u8 mask) +{ + ft_ccmd((20UL << 24) | ((mask & 1L) << 0)); +} + +void ft_Tag(u8 s) +{ + ft_ccmd((3UL << 24) | s); +} + +void ft_Vertex2f(i16 x, i16 y) +{ + ft_ccmd((1UL << 30) | ((x & 32767L) << 15) | ((y & 32767L) << 0)); +} + +void ft_Vertex2ii(u16 x, u16 y, u8 handle, u8 cell) +{ + ft_ccmd((2UL << 30) | ((x & 511L) << 21) | ((y & 511L) << 12) | ((handle & 31L) << 7) | ((cell & 127L) << 0)); +} + +void ft_VertexFormat(u8 f) +{ + ft_ccmd((0x27UL << 24) | (f & 7L)); +} + +void ft_VertexTranslateX(i32 v) +{ + ft_ccmd((0x2BUL << 24) | ((u32)v & 0x1FFFF)); +} + +void ft_VertexTranslateY(i32 v) +{ + ft_ccmd((0x2CUL << 24) | ((u32)v & 0x1FFFF)); +} + +// Co-processor +void ft_SetBitmap(u32 source, u16 fmt, u16 w, u16 h) +{ + ft_ccmd(FT_CCMD_SETBITMAP); + ft_ccmd(source); + ft_ccmd((((u32)w << 16) | (fmt & 0xffff))); + ft_ccmd(h); +} + +void ft_SetScratch(u32 handle) +{ + ft_ccmd(FT_CCMD_SETSCRATCH); + ft_ccmd(handle); +} + +void ft_Text(i16 x, i16 y, i16 font, u16 options, const char *s) +{ + ft_ccmd(FT_CCMD_TEXT); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)options << 16) | (font & 0xffff))); + ft_cstr(s); +} + +void ft_Number(i16 x, i16 y, i16 font, u16 options, i32 n) +{ + ft_ccmd(FT_CCMD_NUMBER); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)options << 16) | (font & 0xffff))); + ft_ccmd(n); +} + +void ft_LoadIdentity() +{ + ft_ccmd(FT_CCMD_LOADIDENTITY); +} + +void ft_Toggle(i16 x, i16 y, i16 w, i16 font, u16 options, u16 state, const char *s) +{ + ft_ccmd(FT_CCMD_TOGGLE); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)font << 16) | (w & 0xffff))); + ft_ccmd((((u32)state << 16) | options)); + ft_cstr(s); +} + +void ft_Gauge(i16 x, i16 y, i16 r, u16 options, u16 major, u16 minor, u16 val, u16 range) +{ + ft_ccmd(FT_CCMD_GAUGE); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)options << 16) | (r & 0xffff))); + ft_ccmd((((u32)minor << 16) | (major & 0xffff))); + ft_ccmd((((u32)range << 16) | (val & 0xffff))); +} + +void ft_RegRead(u32 ptr, u32 result) +{ + ft_ccmd(FT_CCMD_REGREAD); + ft_ccmd(ptr); + ft_ccmd(result); +} + +void ft_VideoStart() +{ + ft_ccmd(FT_CCMD_VIDEOSTART); +} + +void ft_GetProps(u32 ptr, u32 w, u32 h) +{ + ft_ccmd(FT_CCMD_GETPROPS); + ft_ccmd(ptr); + ft_ccmd(w); + ft_ccmd(h); +} + +void ft_Memcpy(u32 dest, u32 src, u32 num) +{ + ft_ccmd(FT_CCMD_MEMCPY); + ft_ccmd(dest); + ft_ccmd(src); + ft_ccmd(num); +} + +void ft_Spinner(i16 x, i16 y, u16 style, u16 scale) +{ + ft_ccmd(FT_CCMD_SPINNER); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)scale << 16) | (style & 0xffff))); +} + +void ft_BgColor(u32 c) +{ + ft_ccmd(FT_CCMD_BGCOLOR); + ft_ccmd(c); +} + +void ft_Swap() +{ + ft_ccmd(FT_CCMD_SWAP); +} + +void ft_Inflate(u32 ptr) +{ + ft_ccmd(FT_CCMD_INFLATE); + ft_ccmd(ptr); +} + +void ft_Translate(i32 tx, i32 ty) +{ + ft_ccmd(FT_CCMD_TRANSLATE); + ft_ccmd(tx); + ft_ccmd(ty); +} + +void ft_Stop() +{ + ft_ccmd(FT_CCMD_STOP); +} + +void ft_SetBase(u32 base) +{ + ft_ccmd(FT_CCMD_SETBASE); + ft_ccmd(base); +} + +void ft_Slider(i16 x, i16 y, i16 w, i16 h, u16 options, u16 val, u16 range) +{ + ft_ccmd(FT_CCMD_SLIDER); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)h << 16) | (w & 0xffff))); + ft_ccmd((((u32)val << 16) | (options & 0xffff))); + ft_ccmd(range); +} + +void ft_VideoFrame(u32 dst, u32 ptr) +{ + ft_ccmd(FT_CCMD_VIDEOFRAME); + ft_ccmd(dst); + ft_ccmd(ptr); +} + +void ft_TouchTransform(i32 x0, i32 y0, i32 x1, i32 y1, i32 x2, i32 y2, i32 tx0, i32 ty0, i32 tx1, i32 ty1, i32 tx2, i32 ty2, u16 result) +{ + ft_ccmd(FT_CCMD_TOUCH_TRANSFORM); + ft_ccmd(x0); + ft_ccmd(y0); + ft_ccmd(x1); + ft_ccmd(y1); + ft_ccmd(x2); + ft_ccmd(y2); + ft_ccmd(tx0); + ft_ccmd(ty0); + ft_ccmd(tx1); + ft_ccmd(ty1); + ft_ccmd(tx2); + ft_ccmd(ty2); + ft_ccmd(result); +} + +void ft_Interrupt(u32 ms) +{ + ft_ccmd(FT_CCMD_INTERRUPT); + ft_ccmd(ms); +} + +void ft_FgColor(u32 c) +{ + ft_ccmd(FT_CCMD_FGCOLOR); + ft_ccmd(c); +} + +void ft_Rotate(i32 a) +{ + ft_ccmd(FT_CCMD_ROTATE); + ft_ccmd(a); +} + +void ft_Button(i16 x, i16 y, i16 w, i16 h, i16 font, u16 options, const char *s) +{ + ft_ccmd(FT_CCMD_BUTTON); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)h << 16) | (w & 0xffff))); + ft_ccmd((((u32)options << 16) | (font & 0xffff))); + ft_cstr(s); +} + +void ft_MemWrite(u32 ptr, u32 num) +{ + ft_ccmd(FT_CCMD_MEMWRITE); + ft_ccmd(ptr); + ft_ccmd(num); +} + +void ft_Scrollbar(i16 x, i16 y, i16 w, i16 h, u16 options, u16 val, u16 size, u16 range) +{ + ft_ccmd(FT_CCMD_SCROLLBAR); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)h << 16) | (w & 0xffff))); + ft_ccmd((((u32)val << 16) | (options & 0xffff))); + ft_ccmd((((u32)range << 16) | (size & 0xffff))); +} + +void ft_GetMatrix(i32 a, i32 b, i32 c, i32 d, i32 e, i32 f) +{ + ft_ccmd(FT_CCMD_GETMATRIX); + ft_ccmd(a); + ft_ccmd(b); + ft_ccmd(c); + ft_ccmd(d); + ft_ccmd(e); + ft_ccmd(f); +} + +void ft_Sketch(i16 x, i16 y, u16 w, u16 h, u32 ptr, u16 format) +{ + ft_ccmd(FT_CCMD_SKETCH); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)h << 16) | (w & 0xffff))); + ft_ccmd(ptr); + ft_ccmd(format); +} + +void ft_RomFont(u32 font, u32 romslot) +{ + ft_ccmd(FT_CCMD_ROMFONT); + ft_ccmd(font); + ft_ccmd(romslot); +} + +void ft_PlayVideo(u32 options) +{ + ft_ccmd(FT_CCMD_PLAYVIDEO); + ft_ccmd(options); +} + +void ft_MemSet(u32 ptr, u32 value, u32 num) +{ + ft_ccmd(FT_CCMD_MEMSET); + ft_ccmd(ptr); + ft_ccmd(value); + ft_ccmd(num); +} + +void ft_GradColor(u32 c) +{ + ft_ccmd(FT_CCMD_GRADCOLOR); + ft_ccmd(c); +} + +void ft_Sync() +{ + ft_ccmd(FT_CCMD_SYNC); +} + +void ft_BitmapTransform(i32 x0, i32 y0, i32 x1, i32 y1, i32 x2, i32 y2, i32 tx0, i32 ty0, i32 tx1, i32 ty1, i32 tx2, i32 ty2, u16 result) +{ + ft_ccmd(FT_CCMD_BITMAP_TRANSFORM); + ft_ccmd(x0); + ft_ccmd(y0); + ft_ccmd(x1); + ft_ccmd(y1); + ft_ccmd(x2); + ft_ccmd(y2); + ft_ccmd(tx0); + ft_ccmd(ty0); + ft_ccmd(tx1); + ft_ccmd(ty1); + ft_ccmd(tx2); + ft_ccmd(ty2); + ft_ccmd(result); +} + +void ft_Calibrate(u32 result) +{ + ft_ccmd(FT_CCMD_CALIBRATE); + ft_ccmd(result); +} + +void ft_SetFont(u32 font, u32 ptr) +{ + ft_ccmd(FT_CCMD_SETFONT); + ft_ccmd(font); + ft_ccmd(ptr); +} + +void ft_Logo() +{ + ft_ccmd(FT_CCMD_LOGO); +} + +void ft_Append(u32 ptr, u32 num) +{ + ft_ccmd(FT_CCMD_APPEND); + ft_ccmd(ptr); + ft_ccmd(num); +} + +void ft_MemZero(u32 ptr, u32 num) +{ + ft_ccmd(FT_CCMD_MEMZERO); + ft_ccmd(ptr); + ft_ccmd(num); +} + +void ft_Scale(i32 sx, i32 sy) +{ + ft_ccmd(FT_CCMD_SCALE); + ft_ccmd(sx); + ft_ccmd(sy); +} + +void ft_Clock(i16 x, i16 y, i16 r, u16 options, u16 h, u16 m, u16 s, u16 ms) +{ + ft_ccmd(FT_CCMD_CLOCK); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)options << 16) | (r & 0xffff))); + ft_ccmd((((u32)m << 16) | (h & 0xffff))); + ft_ccmd((((u32)ms << 16) | (s & 0xffff))); +} + +void ft_Gradient(i16 x0, i16 y0, u32 rgb0, i16 x1, i16 y1, u32 rgb1) +{ + ft_ccmd(FT_CCMD_GRADIENT); + ft_ccmd((((u32)y0 << 16) | (x0 & 0xffff))); + ft_ccmd(rgb0); + ft_ccmd((((u32)y1 << 16) | (x1 & 0xffff))); + ft_ccmd(rgb1); +} + +void ft_SetMatrix() +{ + ft_ccmd(FT_CCMD_SETMATRIX); +} + +void ft_Track(i16 x, i16 y, i16 w, i16 h, i16 tag) +{ + ft_ccmd(FT_CCMD_TRACK); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)h << 16) | (w & 0xffff))); + ft_ccmd(tag); +} + +void ft_Int_RAMShared(u32 ptr) +{ + ft_ccmd(FT_CCMD_INT_RAMSHARED); + ft_ccmd(ptr); +} + +void ft_Int_SWLoadImage(u32 ptr, u32 options) +{ + ft_ccmd(FT_CCMD_INT_SWLOADIMAGE); + ft_ccmd(ptr); + ft_ccmd(options); +} + +void ft_GetPtr(u32 result) +{ + ft_ccmd(FT_CCMD_GETPTR); + ft_ccmd(result); +} + +void ft_Progress(i16 x, i16 y, i16 w, i16 h, u16 options, u16 val, u16 range) +{ + ft_ccmd(FT_CCMD_PROGRESS); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)h << 16) | (w & 0xffff))); + ft_ccmd((((u32)val << 16) | (options & 0xffff))); + ft_ccmd(range); +} + +void ft_ColdStart() +{ + ft_ccmd(FT_CCMD_COLDSTART); +} + +void ft_MediaFifo(u32 ptr, u32 size) +{ + ft_ccmd(FT_CCMD_MEDIAFIFO); + ft_ccmd(ptr); + ft_ccmd(size); +} + +void ft_Keys(i16 x, i16 y, i16 w, i16 h, i16 font, u16 options, const char *s) +{ + ft_ccmd(FT_CCMD_KEYS); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)h << 16) | (w & 0xffff))); + ft_ccmd((((u32)options << 16) | (font & 0xffff))); + ft_cstr(s); +} + +void ft_Dial(i16 x, i16 y, i16 r, u16 options, u16 val) +{ + ft_ccmd(FT_CCMD_DIAL); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)options << 16) | (r & 0xffff))); + ft_ccmd(val); +} + +void ft_Snapshot2(u32 fmt, u32 ptr, i16 x, i16 y, i16 w, i16 h) +{ + ft_ccmd(FT_CCMD_SNAPSHOT2); + ft_ccmd(fmt); + ft_ccmd(ptr); + ft_ccmd((((u32)y << 16) | (x & 0xffff))); + ft_ccmd((((u32)h << 16) | (w & 0xffff))); +} + +void ft_LoadImage(u32 ptr, u32 options) +{ + ft_ccmd(FT_CCMD_LOADIMAGE); + ft_ccmd(ptr); + ft_ccmd(options); +} + +void ft_SetFont2(u32 font, u32 ptr, u32 firstchar) +{ + ft_ccmd(FT_CCMD_SETFONT2); + ft_ccmd(font); + ft_ccmd(ptr); + ft_ccmd(firstchar); +} + +void ft_SetRotate(u32 r) +{ + ft_ccmd(FT_CCMD_SETROTATE); + ft_ccmd(r); +} + +void ft_Dlstart() +{ + ft_ccmd(FT_CCMD_DLSTART); +} + +void ft_Snapshot(u32 ptr) +{ + ft_ccmd(FT_CCMD_SNAPSHOT); + ft_ccmd(ptr); +} + +void ft_ScreenSaver() +{ + ft_ccmd(FT_CCMD_SCREENSAVER); +} + +void ft_MemCrc(u32 ptr, u32 num, u32 result) +{ + ft_ccmd(FT_CCMD_MEMCRC); + ft_ccmd(ptr); + ft_ccmd(num); + ft_ccmd(result); +} + +void ft_FlashAttach() +{ + ft_ccmd(FT_CCMD_FLASHATTACH); +} + +void ft_FlashDetach() +{ + ft_ccmd(FT_CCMD_FLASHDETACH); +} + +void ft_FlashFast(u32 rc) +{ + ft_ccmd(FT_CCMD_FLASHFAST); + ft_ccmd(rc); +} + +void ft_FlashSpiDesel() +{ + ft_ccmd(FT_CCMD_FLASHSPIDESEL); +} + +void ft_FlashTx(u32 num) +{ + ft_ccmd(FT_CCMD_FLASHTX); + ft_ccmd(num); +} + +void ft_FlashRx(u32 ptr, u32 num) +{ + ft_ccmd(FT_CCMD_FLASHRX); + ft_ccmd(ptr); + ft_ccmd(num); +} + +void ft_FlashErase() +{ + ft_ccmd(FT_CCMD_FLASHERASE); +} + +void ft_FlashUpdate(u32 dest, u32 src, u32 num) +{ + ft_ccmd(FT_CCMD_FLASHUPDATE); + ft_ccmd(dest); + ft_ccmd(src); + ft_ccmd(num); +} + +// ------------- System layer --------------- + +void init_ft8xx() +{ +} + +// ------------- Hardware layer --------------- + +esp_err_t ft_apply_spi_width(u8 width) +{ + switch (width) + { + case 1: + ft_wreg8(FT_REG_SPI_WIDTH, FT_SPI_WIDTH_SINGLE); + return spi_master_set_data_lines(1); + + case 2: + ft_wreg8(FT_REG_SPI_WIDTH, FT_SPI_WIDTH_DUAL); + return spi_master_set_data_lines(2); + + case 4: + ft_wreg8(FT_REG_SPI_WIDTH, FT_SPI_WIDTH_QUAD | 4); + return spi_master_set_data_lines(4); + } + + return ESP_ERR_INVALID_ARG; +} + +esp_err_t ft_switch_spi_to_1_bit() +{ + return ft_apply_spi_width(1); +} + +esp_err_t ft_switch_spi_to_2_bit() +{ + return ft_apply_spi_width(2); +} + +esp_err_t ft_switch_spi_to_4_bit() +{ + return ft_apply_spi_width(4); +} + +esp_err_t ft_open_session() +{ + esp_err_t err; + + spi_master_set_clock_hz(ft_spi_freq_hz); + + err = spi_switch_to_master(); + if (err != ESP_OK) return err; + + err = spi_master_set_data_lines(1); + if (err != ESP_OK) + { + spi_switch_to_slave(); + return err; + } + + err = ft_apply_spi_width(ft_spi_width); + if (err != ESP_OK) + { + spi_switch_to_slave(); + return err; + } + + return ESP_OK; +} + +esp_err_t ft_close_session() +{ + esp_err_t err; + esp_err_t err2; + + err = ft_switch_spi_to_1_bit(); + + err2 = spi_switch_to_slave(); + if (err == ESP_OK) + err = err2; + + return err; +} + +esp_err_t ft_xfer(const void *tx, void *rx, size_t size) +{ + return spi_master_xfer((void*)tx, rx, size); +} + +inline void wr16le(u8 *p, u16 v) +{ + p[0] = (u8)(v & 0xFF); + p[1] = (u8)((v >> 8) & 0xFF); +} + +inline void wr32le(u8 *p, u32 v) +{ + p[0] = (u8)(v & 0xFF); + p[1] = (u8)((v >> 8) & 0xFF); + p[2] = (u8)((v >> 16) & 0xFF); + p[3] = (u8)((v >> 24) & 0xFF); +} + +esp_err_t ft_cmdp(u8 a, u8 v) +{ + return spi_master_host_cmd_inline(a, v); +} + +esp_err_t ft_cmd(u8 a) +{ + return ft_cmdp(a, 0); +} + +void ft_wreg8(u32 a, u8 v) +{ + spi_master_write_inline((u8)((FT_RAM_REG >> 16) | 0x80), (u16)a, v, 1); +} + +void ft_wreg16(u32 a, u16 v) +{ + spi_master_write_inline((u8)((FT_RAM_REG >> 16) | 0x80), (u16)a, v, 2); +} + +void ft_wreg32(u32 a, u32 v) +{ + spi_master_write_inline((u8)((FT_RAM_REG >> 16) | 0x80), (u16)a, v, 4); +} + +u8 ft_rreg8(u32 a) +{ + u32 v = 0; + spi_master_read_inline((u8)(FT_RAM_REG >> 16), (u16)a, &v, 1); + return (u8)v; +} + +u16 ft_rreg16(u32 a) +{ + u32 v = 0; + spi_master_read_inline((u8)(FT_RAM_REG >> 16), (u16)a, &v, 2); + return (u16)v; +} + +u32 ft_rreg32(u32 a) +{ + u32 v = 0; + spi_master_read_inline((u8)(FT_RAM_REG >> 16), (u16)a, &v, 4); + return v; +} + +esp_err_t ft_write(const void *addr, u32 ft_addr, u32 size) +{ + if (!addr && size) return ESP_ERR_INVALID_ARG; + if (!size) return ESP_OK; + + const u8 *src = (const u8*)addr; + esp_err_t err = ESP_OK; + u32 a = ft_addr; + u32 left = size; + + while (left) + { + u32 n = left > CHUNK_PAYLOAD ? CHUNK_PAYLOAD : left; + + err = spi_master_write_buf((u8)(((a >> 16) & 0x3F) | 0x80), (u16)a, src, n); + if (err != ESP_OK) + break; + + src += n; + a += n; + left -= n; + } + + return err; +} + +esp_err_t ft_read(void *addr, u32 ft_addr, u32 size) +{ + if (!addr && size) return ESP_ERR_INVALID_ARG; + if (!size) return ESP_OK; + + u8 *dst = (u8*)addr; + esp_err_t err = ESP_OK; + u32 a = ft_addr; + u32 left = size; + + while (left) + { + u32 n = left > CHUNK_PAYLOAD ? CHUNK_PAYLOAD : left; + + err = spi_master_read_buf((u8)((a >> 16) & 0x3F), (u16)a, dst, n); + if (err != ESP_OK) + break; + + dst += n; + a += n; + left -= n; + } + + return err; +} + +esp_err_t ft_write_dl(const void *addr, u32 size_dwords) +{ + return ft_write(addr, FT_RAM_DL, size_dwords << 2); +} + +void ft_ccmd_start(void *addr) +{ + ft_ccmdb = (u32*)addr; + ft_ccmdp = 0; +} + +void ft_ccmd(u32 a) +{ + ft_ccmdb[ft_ccmdp++] = a; +} + +void ft_cstr(const char *s) +{ + u8 *p = (u8*)&ft_ccmdb[ft_ccmdp]; + u16 c = 0; + + while ((p[c++] = (u8)*s++) != 0) + {} + + ft_ccmdp += (c + 3) >> 2; +} + +esp_err_t ft_ccmd_write() +{ + return ft_write((const void*)ft_ccmdb, FT_REG_CMDB_WRITE, (u32)ft_ccmdp << 2); +} + +esp_err_t ft_cp_wait(uint32_t timeout_ms) +{ + int64_t t0 = esp_timer_get_time(); + while (1) + { + u16 space = ft_rreg16(FT_REG_CMDB_SPACE); + + if (space == 0x0FFC) + return ESP_OK; + + if (((esp_timer_get_time() - t0) / 1000) >= (int64_t)timeout_ms) + return ESP_ERR_TIMEOUT; + + vTaskDelay(pdMS_TO_TICKS(1)); + } +} + +esp_err_t ft_cp_reset() +{ + ft_wreg8(FT_REG_CPURESET, 1); + ft_wreg32(FT_REG_CMD_READ, 0); + ft_wreg32(FT_REG_CMD_WRITE, 0); + ft_wreg8(FT_REG_CPURESET, 0); + + return ESP_OK; +} + +void ft_swap() +{ + return ft_wreg8(FT_REG_DLSWAP, FT_DLSWAP_FRAME); +} + +esp_err_t ft_wait_swap(uint32_t timeout_ms) +{ + int64_t t0 = esp_timer_get_time(); + while (1) + { + u8 dlswap = ft_rreg8(FT_REG_DLSWAP); + + if (dlswap == FT_DLSWAP_DONE) + return ESP_OK; + + if (((esp_timer_get_time() - t0) / 1000) >= (int64_t)timeout_ms) + return ESP_ERR_TIMEOUT; + + vTaskDelay(pdMS_TO_TICKS(1)); + } +} + +esp_err_t ft_set_mode(u8 m) +{ + static int last_f_mul = -1; + + if (m > FT_MODE_MAX) + return ESP_ERR_INVALID_ARG; + + const FT_MODE *mode = &ft_modes[m]; + esp_err_t err; + + + err = ft_switch_spi_to_1_bit(); + if (err != ESP_OK) return err; + + if (last_f_mul != mode->f_mul) + { + ft_current_mode = -1; + last_f_mul = -1; + + ft_cmd(FT_CMD_PWRDOWN); + ft_cmd(FT_CMD_ACTIVE); + ft_cmd(FT_CMD_SLEEP); + ft_cmd(FT_CMD_CLKEXT); + ft_cmdp(FT_CMD_CLKSEL, mode->f_mul | 0xC0); + ft_cmd(FT_CMD_ACTIVE); + + int64_t t0 = esp_timer_get_time(); + while (1) + { + u8 id = ft_rreg8(FT_REG_ID); + if (id == FT_ID) break; + + if ((esp_timer_get_time() - t0) > 100000) + { + err = ESP_ERR_TIMEOUT; + goto fail; + } + + vTaskDelay(pdMS_TO_TICKS(1)); + } + + last_f_mul = mode->f_mul; + } + + ft_wreg16(FT_REG_HSYNC0, mode->h_fporch); + ft_wreg16(FT_REG_HSYNC1, mode->h_fporch + mode->h_sync); + ft_wreg16(FT_REG_HOFFSET, mode->h_fporch + mode->h_sync + mode->h_bporch); + ft_wreg16(FT_REG_HCYCLE, mode->h_fporch + mode->h_sync + mode->h_bporch + mode->h_visible); + ft_wreg16(FT_REG_HSIZE, mode->h_visible); + ft_wreg16(FT_REG_VSYNC0, mode->v_fporch - 1); + ft_wreg16(FT_REG_VSYNC1, mode->v_fporch + mode->v_sync - 1); + ft_wreg16(FT_REG_VOFFSET, mode->v_fporch + mode->v_sync + mode->v_bporch - 1); + ft_wreg16(FT_REG_VCYCLE, mode->v_fporch + mode->v_sync + mode->v_bporch + mode->v_visible); + ft_wreg16(FT_REG_VSIZE, mode->v_visible); + ft_wreg8(FT_REG_PCLK_POL, 0); + ft_wreg8(FT_REG_CSPREAD, 0); + ft_wreg8(FT_REG_PCLK, mode->f_div); + ft_wreg8(FT_REG_INT_MASK, FT_INT_SWAP); + ft_wreg8(FT_REG_INT_EN, 1); + + vTaskDelay(pdMS_TO_TICKS(30)); + ft_wreg32(FT_REG_FREQUENCY, mode->f_mul * 8000000UL); + + err = ft_apply_spi_width(ft_spi_width); + if (err != ESP_OK) return err; + + ft_current_mode = m; + return ESP_OK; + +fail: + ft_apply_spi_width(ft_spi_width); + return err; +} + +esp_err_t ft_read_detect(u8 &chip_id, u8 chip_type[4], char datestamp[17]) +{ + chip_id = ft_rreg8(FT_REG_ID); + ft_read(chip_type, FT_ROM_CHIPID, 4); + ft_read(datestamp, FT_REG_DATESTAMP, 16); + datestamp[16] = 0; + + return ESP_OK; +} + +esp_err_t ft_reset_chip() +{ + ft_current_mode = -1; + + esp_err_t err = ft_switch_spi_to_1_bit(); + if (err != ESP_OK) return err; + + ft_cmd(FT_CMD_PWRDOWN); + ft_cmd(FT_CMD_ACTIVE); + ft_cmd(FT_CMD_SLEEP); + ft_cmd(FT_CMD_CLKEXT); + ft_cmd(FT_CMD_ACTIVE); + ft_cmd(FT_CMD_RST_PULSE); + + u8 chip_id; + int64_t t0 = esp_timer_get_time(); + + while ((esp_timer_get_time() - t0) < 100000) + { + chip_id = ft_rreg8(FT_REG_ID); + if (chip_id == FT_ID) break; + vTaskDelay(pdMS_TO_TICKS(1)); + } + + vTaskDelay(pdMS_TO_TICKS(30)); + ft_wreg32(FT_REG_FREQUENCY, 40000000UL); + + err = ft_apply_spi_width(ft_spi_width); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +// ------------- Console --------------- + +u32 ft_parse_num_arg(const char *s, const char *name, int *ok); + +void ft_print_string(const char *s, u16 x, u16 y) +{ + int i = 0; + char c; + + while ((c = s[i++]) != 0) + { + ft_Cell((u8)c); + ft_Vertex2f((i16)x, (i16)y); + x += 9; + } +} + +void ft_print_spi_freq(const char *label, u32 hz) +{ + printf("%s: %lu.%03lu MHz (%lu Hz)\r\n", + label, + (unsigned long)(hz / 1000000UL), + (unsigned long)((hz % 1000000UL) / 1000UL), + (unsigned long)hz); +} + +void ft_print_current_mode() +{ + if (ft_current_mode < 0) + { + printf("FT mode: none\r\n"); + return; + } + + const FT_MODE *mode = &ft_modes[ft_current_mode]; + printf("FT mode: %d, %ux%u\r\n", + ft_current_mode, + (unsigned int)mode->h_visible, + (unsigned int)mode->v_visible); +} + +int ft_mode_cmd(int argc, char **argv) +{ + esp_err_t err; + esp_err_t err2; + u32 mode; + int ok; + + if (argc != 3) + { + printf("Usage:\r\n"); + printf(" ft mode <0-%lu>\r\n", (unsigned long)FT_MODE_MAX); + ft_print_current_mode(); + return 1; + } + + mode = ft_parse_num_arg(argv[2], "mode", &ok); + if (!ok) + return 1; + + if (mode > FT_MODE_MAX) + { + printf("Bad : %lu, allowed 0-%lu\r\n", + (unsigned long)mode, + (unsigned long)FT_MODE_MAX); + return 1; + } + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + err = ft_set_mode((u8)mode); + if (err == ESP_OK) + err = ft_cp_reset(); + + err2 = ft_close_session(); + if (err == ESP_OK && err2 != ESP_OK) + err = err2; + + if (err != ESP_OK) + { + printf("FT mode failed: %d\r\n", (int)err); + return 1; + } + + printf("FT mode set: %lu\r\n", (unsigned long)mode); + return 0; +} + +u32 ft_parse_freq_arg_hz(const char *s, const char *name, int *ok) +{ + char buf[32]; + size_t n; + char *endp = nullptr; + double mhz; + uint64_t hz; + + *ok = 0; + + if (!s) + { + printf("Missing <%s>\r\n", name); + return 0; + } + + n = strlen(s); + if (n >= sizeof(buf)) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + memcpy(buf, s, n + 1); + + if (n && buf[n - 1] == ',') + buf[n - 1] = 0; + + mhz = strtod(buf, &endp); + if (!endp || *endp || mhz <= 0.0) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + hz = (uint64_t)(mhz * 1000000.0 + 0.5); + if (!hz || hz > 0xFFFFFFFFULL) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + *ok = 1; + return (u32)hz; +} + +int ft_spi_cmd(int argc, char **argv) +{ + int ok; + u32 width; + + if (argc < 3) + { + printf("Usage:\r\n"); + printf(" ft spi <1|2|4>\r\n"); + printf("Current FT SPI width: %u-bit\r\n", (unsigned int)ft_spi_width); + return 0; + } + + width = ft_parse_num_arg(argv[2], "width", &ok); + if (!ok) + return 1; + + if (width != 1 && width != 2 && width != 4) + { + printf("Bad : %lu\r\n", (unsigned long)width); + printf("Allowed: 1, 2, 4\r\n"); + return 1; + } + + ft_spi_width = (u8)width; + + printf("FT SPI width set to %u-bit\r\n", (unsigned int)ft_spi_width); + return 0; +} + +int ft_freq_cmd(int argc, char **argv) +{ + esp_err_t err; + esp_err_t err2; + int ok; + u32 actual_hz; + + if (argc > 3) + { + printf("Usage:\r\n"); + printf(" ft freq\r\n"); + printf(" ft freq \r\n"); + return 1; + } + + if (argc == 3) + { + ft_spi_freq_hz = ft_parse_freq_arg_hz(argv[2], "freq", &ok); + if (!ok) return 1; + + ft_print_spi_freq("FT SPI req", ft_spi_freq_hz); + } + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + actual_hz = spi_master_get_actual_freq_hz(); + if (actual_hz) + ft_print_spi_freq("FT SPI actual", actual_hz); + else + printf("FT SPI actual: unavailable\r\n"); + + err2 = ft_close_session(); + if (err2 != ESP_OK) + { + printf("FT close failed: %d\r\n", (int)err2); + return 1; + } + + return 0; +} + +u32 ft_parse_num_arg(const char *s, const char *name, int *ok) +{ + char buf[32]; + size_t n; + char *endp = nullptr; + uint64_t v; + + *ok = 0; + + if (!s) + { + printf("Missing <%s>\r\n", name); + return 0; + } + + n = strlen(s); + if (n >= sizeof(buf)) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + memcpy(buf, s, n + 1); + + if (n && buf[n - 1] == ',') + buf[n - 1] = 0; + + v = strtoull(buf, &endp, 0); + if (!endp || *endp) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + if (v > 0xFFFFFFFFULL) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + *ok = 1; + return (u32)v; +} + +const char *ft_chip_type_name(const u8 chip_type[4]) +{ + if (chip_type[0] != 0x08) return "Unknown"; + + switch (chip_type[1]) + { + case 0x10: return "FT810"; + case 0x11: return "FT811"; + case 0x12: return "FT812"; + case 0x13: return "FT813"; + case 0x15: return "BT815"; + case 0x16: return "BT816"; + case 0x17: return "BT817"; + case 0x18: return "BT818"; + default: return "Unknown"; + } +} + +void ft_print_detect(const u8 chip_id, const u8 chip_type[4], const char *datestamp) +{ + const char *type = ft_chip_type_name(chip_type); + + printf("Chip ID : %02X\r\n", chip_id); + printf("Chip type : %s (%02X %02X %02X %02X)\r\n", + type, + chip_type[0], chip_type[1], chip_type[2], chip_type[3]); + printf("Chip datestamp : %s\r\n", datestamp); +} + +esp_err_t ft_print_info() +{ + u8 chip_id = 0; + u8 chip_type[4] = {}; + char datestamp[17] = {}; + ft_read_detect(chip_id, chip_type, datestamp); + + u8 cpureset = ft_rreg8(FT_REG_CPURESET); + u8 pclk = ft_rreg8(FT_REG_PCLK); + u8 int_en = ft_rreg8(FT_REG_INT_EN); + u8 int_mask = ft_rreg8(FT_REG_INT_MASK); + u8 int_flags = ft_rreg8(FT_REG_INT_FLAGS); + + u16 hcycle = ft_rreg16(FT_REG_HCYCLE); + u16 hoffset = ft_rreg16(FT_REG_HOFFSET); + u16 hsize = ft_rreg16(FT_REG_HSIZE); + u16 hsync0 = ft_rreg16(FT_REG_HSYNC0); + u16 hsync1 = ft_rreg16(FT_REG_HSYNC1); + u16 vcycle = ft_rreg16(FT_REG_VCYCLE); + u16 voffset = ft_rreg16(FT_REG_VOFFSET); + u16 vsize = ft_rreg16(FT_REG_VSIZE); + u16 vsync0 = ft_rreg16(FT_REG_VSYNC0); + u16 vsync1 = ft_rreg16(FT_REG_VSYNC1); + u16 cmdb_space = ft_rreg16(FT_REG_CMDB_SPACE); + + u32 frames = ft_rreg32(FT_REG_FRAMES); + u32 clock = ft_rreg32(FT_REG_CLOCK); + u32 frequency = ft_rreg32(FT_REG_FREQUENCY); + u8 spi_width = ft_rreg8(FT_REG_SPI_WIDTH); + u32 esp_spi_clock = spi_master_get_actual_freq_hz(); + + u16 hfront = hsync0; + u16 hsync = hsync1 - hsync0; + u16 hback = hoffset - hsync1; + + u16 vfront = vsync0 + 1; + u16 vsync = vsync1 - vsync0; + u16 vback = voffset - vsync1; + + u32 pixel_clock = 0; + float line_rate_hz = 0.0f; + float line_rate_khz = 0.0f; + float frame_rate_hz = 0.0f; + + if (pclk) + { + pixel_clock = frequency / pclk; + + if (hcycle) + { + line_rate_hz = (float)pixel_clock / (float)hcycle; + line_rate_khz = line_rate_hz / 1000.0f; + } + + if (hcycle && vcycle) + frame_rate_hz = line_rate_hz / (float)vcycle; + } + + printf("FT812 information:\r\n"); + printf(" Chip ID : %02X\r\n", chip_id); + printf(" Chip type : %s\r\n", ft_chip_type_name(chip_type)); + printf(" Datestamp : %s\r\n", datestamp); + + printf(" PLL frequency : %lu Hz\r\n", (unsigned long)frequency); + printf(" Pixel clock : %lu Hz\r\n", (unsigned long)pixel_clock); + printf(" Pixel divider : %u\r\n", (unsigned)pclk); + + printf(" Resolution : %u x %u\r\n", (unsigned)hsize, (unsigned)vsize); + printf(" Total frame : %u x %u\r\n", (unsigned)hcycle, (unsigned)vcycle); + printf(" Frame rate : %.3f Hz\r\n", frame_rate_hz); + printf(" Line rate : %.3f kHz\r\n", line_rate_khz); + printf(" Horizontal : front=%u sync=%u back=%u active=%u\r\n", (unsigned)hfront, (unsigned)hsync, (unsigned)hback, (unsigned)hsize); + printf(" Vertical : front=%u sync=%u back=%u active=%u\r\n", (unsigned)vfront, (unsigned)vsync, (unsigned)vback, (unsigned)vsize); + + switch (spi_width & 3) + { + case FT_SPI_WIDTH_SINGLE: printf(" Bus width : 1-bit SPI\r\n"); break; + case FT_SPI_WIDTH_DUAL: printf(" Bus width : 2-bit SPI\r\n"); break; + case FT_SPI_WIDTH_QUAD: printf(" Bus width : 4-bit SPI\r\n"); break; + default: printf(" Bus width : ? (%u)\r\n", (unsigned)(spi_width & 3)); break; + } + + printf(" ESP SPI clock : %lu Hz\r\n", (unsigned long)esp_spi_clock); + + printf(" Frame counter : %lu\r\n", (unsigned long)frames); + printf(" Clock counter : %lu\r\n", (unsigned long)clock); + + printf(" Interrupts : enable=%u mask=%02X flags=%02X\r\n", (unsigned)int_en, (unsigned)int_mask, (unsigned)int_flags); + printf(" Command space : %u\r\n", (unsigned)cmdb_space); + printf(" CPU reset flags : %u\r\n", (unsigned)cpureset); + + return ESP_OK; +} + +esp_err_t ft_perf_run(void *buf, int is_read, u32 chunk_size, u32 total_size, int64_t *elapsed_us) +{ + if (!buf || !elapsed_us) return ESP_ERR_INVALID_ARG; + if (!chunk_size || chunk_size > CHUNK_PAYLOAD) return ESP_ERR_INVALID_ARG; + + u32 left = total_size; + int64_t t0 = esp_timer_get_time(); + + while (left) + { + u32 n = left > chunk_size ? chunk_size : left; + esp_err_t err; + + if (is_read) + err = ft_read(buf, FT_RAM_G, n); + else + err = ft_write(buf, FT_RAM_G, n); + + if (err != ESP_OK) return err; + + left -= n; + } + + *elapsed_us = esp_timer_get_time() - t0; + return ESP_OK; +} + +void ft_perf_fill_pattern(u8 *buf, u32 size) +{ + for (u32 i = 0; i < size; ++i) + buf[i] = (u8)(i ^ (i >> 8) ^ 0x5A); +} + +double ft_perf_mb_per_s(u32 bytes, int64_t elapsed_us) +{ + if (elapsed_us <= 0) return 0.0; + + return ((double)bytes * 1000000.0) / ((double)elapsed_us * 1024.0 * 1024.0); +} + +int ft_perf_one(void *buf, const char *name, int is_read, u32 chunk_size, u32 total_size) +{ + if (chunk_size > CHUNK_PAYLOAD) + { + printf("%-20s : skipped, chunk=%lu > CHUNK_PAYLOAD=%u\r\n", + name, + (unsigned long)chunk_size, + (unsigned int)CHUNK_PAYLOAD); + return 0; + } + + if (is_read) + { + esp_err_t err = ft_write(buf, FT_RAM_G, chunk_size); + if (err != ESP_OK) + { + printf("%-20s : prep failed: %s (0x%x)\r\n", + name, + esp_err_to_name(err), + (unsigned int)err); + return 1; + } + } + + int64_t elapsed_us = 0; + esp_err_t err = ft_perf_run(buf, is_read, chunk_size, total_size, &elapsed_us); + if (err != ESP_OK) + { + printf("%-20s : failed: %s (0x%x)\r\n", + name, + esp_err_to_name(err), + (unsigned int)err); + return 1; + } + + printf("%-20s : %7.3f MB/s (%8llu us, chunk=%5lu)\r\n", + name, + ft_perf_mb_per_s(total_size, elapsed_us), + (unsigned long long)elapsed_us, + (unsigned long)chunk_size); + + return 0; +} + +int ft_perf_suite(void *buf, const char *mem_name, u32 total_size) +{ + int failed = 0; + char name[32]; + + printf("\r\n[%s]\r\n", mem_name); + + snprintf(name, sizeof(name), "%s", "write max"); + if (ft_perf_one(buf, name, 0, CHUNK_PAYLOAD, total_size)) failed = 1; + + snprintf(name, sizeof(name), "%s", "write 1024"); + if (ft_perf_one(buf, name, 0, 1024, total_size)) failed = 1; + + snprintf(name, sizeof(name), "%s", "write 128"); + if (ft_perf_one(buf, name, 0, 128, total_size)) failed = 1; + + snprintf(name, sizeof(name), "%s", "write 16"); + if (ft_perf_one(buf, name, 0, 16, total_size)) failed = 1; + + snprintf(name, sizeof(name), "%s", "read max"); + if (ft_perf_one(buf, name, 1, CHUNK_PAYLOAD, total_size)) failed = 1; + + snprintf(name, sizeof(name), "%s", "read 1024"); + if (ft_perf_one(buf, name, 1, 1024, total_size)) failed = 1; + + snprintf(name, sizeof(name), "%s", "read 128"); + if (ft_perf_one(buf, name, 1, 128, total_size)) failed = 1; + + snprintf(name, sizeof(name), "%s", "read 16"); + if (ft_perf_one(buf, name, 1, 16, total_size)) failed = 1; + + return failed; +} + +int ft_perf_cmd(int argc, char **argv) +{ + const u32 total_size = 1024 * 1024; + esp_err_t err; + esp_err_t err2; + int failed = 0; + u8 *perf_buf_int = nullptr; + u8 *perf_buf_spiram = nullptr; + + (void)argv; + + if (argc != 2) + { + printf("Usage:\r\n"); + printf(" ft perf\r\n"); + return 1; + } + + perf_buf_int = (u8*)heap_caps_malloc(CHUNK_PAYLOAD, MALLOC_CAP_INTERNAL); + if (!perf_buf_int) + { + printf("FT perf internal buffer alloc failed, size=%u\r\n", (unsigned int)CHUNK_PAYLOAD); + return 1; + } + + perf_buf_spiram = (u8*)heap_caps_malloc(CHUNK_PAYLOAD, MALLOC_CAP_SPIRAM); + if (!perf_buf_spiram) + { + printf("FT perf SPIRAM buffer alloc failed, size=%u\r\n", (unsigned int)CHUNK_PAYLOAD); + heap_caps_free(perf_buf_int); + return 1; + } + + ft_perf_fill_pattern(perf_buf_int, CHUNK_PAYLOAD); + ft_perf_fill_pattern(perf_buf_spiram, CHUNK_PAYLOAD); + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + heap_caps_free(perf_buf_spiram); + heap_caps_free(perf_buf_int); + return 1; + } + + printf("FT perf: total=%lu bytes, addr=0x%06lX, max_chunk=%u, spi=%u-bit, clk=%lu Hz\r\n", + (unsigned long)total_size, + (unsigned long)FT_RAM_G, + (unsigned int)CHUNK_PAYLOAD, + (unsigned int)ft_spi_width, + (unsigned long)spi_master_get_actual_freq_hz()); + + if (ft_perf_suite(perf_buf_int, "internal", total_size)) failed = 1; + if (ft_perf_suite(perf_buf_spiram, "spiram", total_size)) failed = 1; + + err2 = ft_close_session(); + heap_caps_free(perf_buf_spiram); + heap_caps_free(perf_buf_int); + + if (err2 != ESP_OK) + { + printf("FT close failed: %d\r\n", (int)err2); + return 1; + } + + return failed ? 1 : 0; +} + +int ft_res_cmd(int argc, char **argv) +{ + (void)argc; + (void)argv; + + esp_err_t err; + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + err = ft_reset_chip(); + if (err != ESP_OK) + { + ft_close_session(); + printf("FT reset failed: %d\r\n", (int)err); + return 1; + } + printf("\r\nFT reset done\r\n"); + + u8 chip_id = 0; + u8 chip_type[4] = {}; + char datestamp[17] = {}; + ft_read_detect(chip_id, chip_type, datestamp); + ft_print_detect(chip_id, chip_type, datestamp); + + err = ft_close_session(); + if (err != ESP_OK) + { + printf("FT close failed: %d\r\n", (int)err); + return 1; + } + + return 0; +} + +int ft_wreg_cmd(int argc, char **argv) +{ + esp_err_t err; + u32 addr; + u32 actual_addr; + u32 value; + int ok; + + if (argc != 4) + { + printf("Usage:\r\n"); + printf(" ft wreg \r\n"); + return 1; + } + + addr = ft_parse_num_arg(argv[2], "addr", &ok); + if (!ok) + return 1; + + value = ft_parse_num_arg(argv[3], "value", &ok); + if (!ok) + return 1; + + actual_addr = ((FT_RAM_REG >> 16) << 16) | (addr & 0xFFFFUL); + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + ft_wreg32(addr, value); + err = ft_close_session(); + + if (err != ESP_OK) + { + printf("FT close failed: %d\r\n", (int)err); + return 1; + } + + printf("FT write: [0x%06lX] = 0x%08lX (%lu)\r\n", + (unsigned long)actual_addr, + (unsigned long)value, + (unsigned long)value); + + return 0; +} + +int ft_wr_cmd(int argc, char **argv) +{ + esp_err_t err; + esp_err_t err2; + u32 addr; + u32 actual_addr; + u32 value; + u32 width = 0; + u8 data[4]; + int ok; + + if (argc != 4) + { + printf("Usage:\r\n"); + printf(" ft wr \r\n"); + printf(" ft wr8 \r\n"); + printf(" ft wr16 \r\n"); + printf(" ft wr32 \r\n"); + return 1; + } + + if (!strcmp(argv[1], "wr8")) + width = 1; + else if (!strcmp(argv[1], "wr16")) + width = 2; + else if (!strcmp(argv[1], "wr32")) + width = 4; + else if (strcmp(argv[1], "wr")) + return 1; + + addr = ft_parse_num_arg(argv[2], "addr", &ok); + if (!ok) + return 1; + + value = ft_parse_num_arg(argv[3], "value", &ok); + if (!ok) + return 1; + + if (!width) + { + width = 1; + if (value > 0xFFUL) + width = 2; + if (value > 0xFFFFUL) + width = 4; + } + + if (width == 1 && value > 0xFFUL) + { + printf("Bad : 0x%08lX > 0xFF\r\n", (unsigned long)value); + return 1; + } + + if (width == 2 && value > 0xFFFFUL) + { + printf("Bad : 0x%08lX > 0xFFFF\r\n", (unsigned long)value); + return 1; + } + + actual_addr = addr & 0x3FFFFFUL; + data[0] = (u8)(value & 0xFF); + if (width >= 2) + wr16le(data, (u16)value); + if (width == 4) + wr32le(data, value); + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + err = ft_write(data, addr, width); + err2 = ft_close_session(); + if (err == ESP_OK && err2 != ESP_OK) + err = err2; + + if (err != ESP_OK) + { + printf("FT write failed: %d\r\n", (int)err); + return 1; + } + + printf("FT write%lu: [0x%06lX] = 0x%08lX (%lu)\r\n", + (unsigned long)(width * 8), + (unsigned long)actual_addr, + (unsigned long)value, + (unsigned long)value); + + return 0; +} + +int ft_info_cmd(int argc, char **argv) +{ + (void)argc; + (void)argv; + + esp_err_t err; + esp_err_t err2; + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + u8 chip_id = 0; + u8 chip_type[4] = {}; + char datestamp[17] = {}; + err = ft_read_detect(chip_id, chip_type, datestamp); + if (err == ESP_OK) + { + printf("\r\n"); + err = ft_print_info(); + } + + err2 = ft_close_session(); + if (err == ESP_OK && err2 != ESP_OK) + err = err2; + + if (err != ESP_OK) + { + printf("FT info read failed: %d\r\n", (int)err); + return 1; + } + + return 0; +} + +int ft_dump_cmd(int argc, char **argv) +{ + esp_err_t err; + esp_err_t err2; + u8 chip_id = 0; + u8 chip_type[4] = {}; + char datestamp[17] = {}; + u8 b[256]; + u32 addr = 0; + u32 actual_addr; + int ok; + + if (argc > 3) + { + printf("Usage:\r\n"); + printf(" ft dump [addr]\r\n"); + return 1; + } + + if (argc == 3) + { + addr = ft_parse_num_arg(argv[2], "addr", &ok); + if (!ok) + return 1; + } + + actual_addr = addr & 0x3FFFFFUL; + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + err = ft_read_detect(chip_id, chip_type, datestamp); + if (err != ESP_OK) printf("FT detect failed: %d\r\n", (int)err); + + printf("\r\nFT hexdump @ 0x%06lX:\r\n\r\n", (unsigned long)actual_addr); + printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\r\n"); + err = ft_read(b, addr, sizeof(b)); + if (err == ESP_OK) + hexdump(b, sizeof(b), actual_addr); + + err2 = ft_close_session(); + if (err == ESP_OK && err2 != ESP_OK) + err = err2; + + if (err != ESP_OK) + { + printf("FT dump failed: %d\r\n", (int)err); + return 1; + } + + return 0; +} + +esp_err_t ft_draw_calib_frame() +{ + const char *mode_txt = "1024x768@59Hz (64MHz)"; + esp_err_t err; + esp_err_t err2; + u16 i; + u16 j; + + err = ft_open_session(); + if (err != ESP_OK) + return err; + + if (err == ESP_OK) + { + ft_rreg8(FT_REG_INT_FLAGS); + + ft_ccmd_start(cmdl); + ft_Dlstart(); + + ft_VertexFormat(0); + ft_ClearColorRGB(0, 0, 0); + ft_Clear(1, 1, 1); + + ft_ColorRGB(255, 255, 255); + ft_LineWidth(24); + + ft_Begin(FT_LINE_STRIP); + ft_Vertex2f(0, 0); + ft_Vertex2f(1023, 0); + ft_Vertex2f(1023, 767); + ft_Vertex2f(0, 767); + ft_Vertex2f(0, 0); + + ft_Begin(FT_LINE_STRIP); + ft_Vertex2f(0, 0); + ft_Vertex2f(799, 0); + ft_Vertex2f(799, 599); + ft_Vertex2f(0, 599); + ft_Vertex2f(0, 0); + + ft_Begin(FT_LINE_STRIP); + ft_Vertex2f(0, 0); + ft_Vertex2f(639, 0); + ft_Vertex2f(639, 479); + ft_Vertex2f(0, 479); + ft_Vertex2f(0, 0); + + ft_Begin(FT_BITMAPS); + ft_BitmapHandle(18); + + ft_ColorRGB(100, 220, 200); + ft_print_string("Mode:", 10, 8); + + ft_ColorRGB(120, 100, 255); + ft_print_string(mode_txt, 66, 8); + + ft_ColorRGB(120, 100, 255); + ft_print_string("640x480", 572, 461); + ft_print_string("800x600", 732, 581); + ft_print_string("1024x768", 947, 749); + + ft_ColorA(255); + ft_Begin(FT_POINTS); + ft_PointSize(100 << 4); + ft_BlendFunc(FT_SRC_ALPHA, FT_ONE); + + ft_ColorRGB(255, 0, 0); + ft_Vertex2f(rsin(80, 32768) + 320, rcos(80, 32768) + 240); + + ft_ColorRGB(0, 255, 0); + ft_Vertex2f(rsin(80, 21845 + 32768) + 320, rcos(80, 21845 + 32768) + 240); + + ft_ColorRGB(0, 0, 255); + ft_Vertex2f(rsin(80, 43690 - 32768) + 320, rcos(80, 43690 - 32768) + 240); + + ft_ClearColorA(32); + ft_ColorMask(0, 0, 0, 1); + ft_Clear(1, 1, 1); + + ft_BlendFunc(FT_ONE, FT_ONE); + ft_ColorA(20); + + for (i = 120, j = 0; j <= 255; i -= 5, j += 20) + { + ft_PointSize(i << 4); + ft_Vertex2f(320, 240); + } + + ft_ColorRGB(0, 0, 0); + ft_ColorMask(1, 1, 1, 1); + ft_BlendFunc(FT_ONE_MINUS_DST_ALPHA, FT_DST_ALPHA); + ft_Begin(FT_RECTS); + ft_Vertex2f(100, 50); + ft_Vertex2f(539, 429); + + ft_Display(); + ft_Swap(); + + err = ft_ccmd_write(); + if (err == ESP_OK) + err = ft_cp_wait(1000); + + if (err == ESP_OK) + err = ft_wait_swap(1000); + } + + err2 = ft_close_session(); + if (err == ESP_OK && err2 != ESP_OK) + err = err2; + + return err; +} + +int ft_demo_bases_cmd() +{ + esp_err_t err; + + const i16 x_pos = 350; + const i16 y_pos = 250; + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + if (err == ESP_OK) + { + ft_rreg8(FT_REG_INT_FLAGS); + + while (1) + { + u32 clock = ft_rreg32(FT_REG_CLOCK); + u32 frames = ft_rreg32(FT_REG_FRAMES); + + ft_ccmd_start(cmdl); + + ft_Dlstart(); + ft_VertexFormat(0); + + ft_ClearColorRGB(0, 0, 0); + ft_ClearColorA(255); + ft_Clear(1, 1, 1); + + ft_ColorA(255); + ft_Begin(FT_POINTS); + + ft_PointSize(100 << 4); + ft_BlendFunc(FT_SRC_ALPHA, FT_ONE); + + ft_ColorRGB(255, 0, 0); + ft_Vertex2f(rsin(80, 0) + x_pos, rcos(80, 0) + y_pos); + + ft_ColorRGB(0, 255, 0); + ft_Vertex2f(rsin(80, 21845) + x_pos, rcos(80, 21845) + y_pos); + + ft_ColorRGB(0, 0, 255); + ft_Vertex2f(rsin(80, 43690) + x_pos, rcos(80, 43690) + y_pos); + + ft_ClearColorA(32); + ft_ColorMask(0, 0, 0, 1); + ft_Clear(1, 1, 1); + + ft_BlendFunc(FT_ONE, FT_ONE); + ft_ColorA(20); + + for (int i = 120, j = 0; j <= 255; i -= 5, j += 20) + { + ft_PointSize(i << 4); + ft_Vertex2f(x_pos, y_pos); + } + + ft_ColorRGB(0, 0, 0); + ft_ColorMask(1, 1, 1, 1); + ft_BlendFunc(FT_ONE_MINUS_DST_ALPHA, FT_DST_ALPHA); + ft_Begin(FT_RECTS); + ft_Vertex2f(0, 0); + ft_Vertex2f(799, 599); + + ft_ColorA(255); + ft_BlendFunc(FT_SRC_ALPHA, FT_ONE_MINUS_SRC_ALPHA); + ft_RomFont(14, 34); + + ft_ColorRGB(255, 0, 0); + ft_Number(100, 80, 14, 0, (i32)clock); + + ft_ColorRGB(0, 200, 240); + ft_Number(100, 220, 14, 0, (i32)frames); + + ft_ColorRGB(0, 200, 0); + ft_Text(100, 50, 31, 0, "Clocks:"); + ft_Text(100, 190, 31, 0, "Frames:"); + + ft_ColorRGB(255, 120, 0); + ft_Text(190, 500, 31, 0, "All your base are belong to us!"); + + ft_Display(); + ft_Swap(); + + err = ft_ccmd_write(); + if (err != ESP_OK) + { + printf("FT demo0 error: ft_ccmd_write() failed: %s (0x%x)\r\n", + esp_err_to_name(err), (unsigned int)err); + break; + } + + err = ft_cp_wait(1000); + if (err != ESP_OK) + { + printf("FT demo0 error: ft_cp_wait(1000) failed: %s (0x%x)\r\n", + esp_err_to_name(err), (unsigned int)err); + break; + } + + err = ft_wait_swap(1000); + if (err != ESP_OK) + { + printf("FT demo0 error: ft_wait_swap(1000) failed: %s (0x%x)\r\n", + esp_err_to_name(err), (unsigned int)err); + break; + } + + char c; + if (uart_read_bytes(UART_NUM_0, &c, 1, 0) > 0) + { + printf("FT demo stopped\r\n"); + break; + } + } + } + + err = ft_close_session(); + if (err != ESP_OK) + { + printf("FT close failed: %d\r\n", (int)err); + return 1; + } + + return 0; +} + +void ft_demo_frac_make_palette(u32 *pal) +{ + if (!pal) return; + + pal[0] = ft_argb32(255, 0, 0, 0); + + for (u32 i = 1; i < 256; i++) + { + u8 r; + u8 g; + u8 b; + + if (i < 64) + { + r = 0; + g = 0; + b = (u8)(i << 2); + } + + else if (i < 128) + { + u8 t = (u8)((i - 64) << 2); + r = 0; + g = t; + b = 255; + } + + else if (i < 192) + { + u8 t = (u8)((i - 128) << 2); + r = t; + g = 255; + b = (u8)(255 - t); + } + + else + { + u8 t = (u8)((i - 192) << 2); + r = 255; + g = (u8)(255 - t); + b = 0; + } + + pal[i] = ft_argb32(255, r, g, b); + } +} + +typedef struct +{ + float *zr; + float *zi; + u8 *alive; +} FT_DEMO_FRAC_STATE; + +int ft_demo_frac_state_init(FT_DEMO_FRAC_STATE *st, u8 *dst) +{ + u32 pixels = FT_DEMO_PIX_W * FT_DEMO_PIX_H; + + if (!st || !dst) + return 0; + + memset(st, 0, sizeof(*st)); + + st->zr = (float*)malloc_spiram(pixels * sizeof(float)); + st->zi = (float*)malloc_spiram(pixels * sizeof(float)); + st->alive = (u8*)malloc_spiram(pixels); + + if (!st->zr || !st->zi || !st->alive) + { + if (st->zr) free(st->zr); + if (st->zi) free(st->zi); + if (st->alive) free(st->alive); + + st->zr = nullptr; + st->zi = nullptr; + st->alive = nullptr; + return 0; + } + + memset(st->zr, 0, pixels * sizeof(float)); + memset(st->zi, 0, pixels * sizeof(float)); + memset(st->alive, 1, pixels); + memset(dst, 0, pixels); + + return 1; +} + +void ft_demo_frac_state_free(FT_DEMO_FRAC_STATE *st) +{ + if (!st) return; + + if (st->zr) free(st->zr); + if (st->zi) free(st->zi); + if (st->alive) free(st->alive); + + st->zr = nullptr; + st->zi = nullptr; + st->alive = nullptr; +} + +void ft_demo_frac_render(FT_DEMO_FRAC_STATE *st, u8 *dst, u32 frame_no) +{ + static u8 offs = 0; + + for (u32 y = 0; y < FT_DEMO_PIX_H; y++) + { + for (u32 x = 0; x < FT_DEMO_PIX_W; x++) + { + u32 idx = y * FT_DEMO_PIX_W + x; + dst[idx] = x * 256 / FT_DEMO_PIX_W + offs; + } + } + + offs++; +} + +void ft_demo_frac_render1(FT_DEMO_FRAC_STATE *st, u8 *dst, u32 frame_no) +{ + if (!st || !dst) return; + if (!frame_no) return; + + u32 iter_mark = frame_no; + + for (u32 y = 0; y < FT_DEMO_PIX_H; y++) + { + float ci = -1.5f + (float)y * 3.0f / (float)FT_DEMO_PIX_H; + + for (u32 x = 0; x < FT_DEMO_PIX_W; x++) + { + u32 idx = y * FT_DEMO_PIX_W + x; + + if (!st->alive[idx]) + continue; + + float cr = -2.0f + (float)x * 3.0f / (float)FT_DEMO_PIX_W; + float zr = st->zr[idx]; + float zi = st->zi[idx]; + + float zr_new = zr * zr - zi * zi + cr; + float zi_new = 2.0f * zr * zi + ci; + float mag2 = zr_new * zr_new + zi_new * zi_new; + + if (mag2 > 4.0f) + { + st->alive[idx] = 0; + dst[idx] = (u8)iter_mark; + } + else + { + st->zr[idx] = zr_new; + st->zi[idx] = zi_new; + } + } + } +} + +esp_err_t ft_demo_frac_upload_bitmap(const void *src, u32 ft_addr) +{ + return ft_write(src, ft_addr, FT_DEMO_PIX_SIZE); +} + +esp_err_t ft_demo_frac_upload_bitmap_bg(const void *src, u32 ft_addr) +{ + return spi_master_write_buf_bg((u8)(((ft_addr >> 16) & 0x3F) | 0x80), (u16)ft_addr, src, FT_DEMO_PIX_SIZE); +} + +esp_err_t ft_demo_frac_show_bitmap(u32 bmp_addr, u32 frame_no) +{ + esp_err_t err; + u32 iters = frame_no; + const u16 screen_w = 800; + const u16 screen_h = 600; + const i32 scale_x = ((i32)FT_DEMO_PIX_W << 8) / screen_w; + const i32 scale_y = ((i32)FT_DEMO_PIX_H << 8) / screen_h; + const u8 bitmap_filter = FT_NEAREST; + // const u8 bitmap_filter = FT_BILINEAR; + + ft_ccmd_start(cmdl); + + ft_Dlstart(); + ft_VertexFormat(0); + + ft_ClearColorRGB(0, 0, 0); + ft_ClearColorA(255); + ft_Clear(1, 1, 1); + + ft_SaveContext(); + + ft_BitmapHandle(0); + ft_BitmapSource(bmp_addr); + ft_BitmapLayout(FT_PALETTED8, (u16)FT_DEMO_PIX_W, (u16)FT_DEMO_PIX_H); + ft_BitmapSize(bitmap_filter, FT_BORDER, FT_BORDER, screen_w, screen_h); + ft_BitmapTransformA(scale_x); + ft_BitmapTransformB(0); + ft_BitmapTransformC(0); + ft_BitmapTransformD(0); + ft_BitmapTransformE(scale_y); + ft_BitmapTransformF(0); + + ft_Begin(FT_BITMAPS); + + ft_BlendFunc(FT_ONE, FT_ZERO); + + ft_ColorMask(0, 0, 0, 1); + ft_PaletteSource(FT_DEMO_PALETTE_ADDR + 3); + ft_Vertex2ii(0, 0, 0, 0); + + ft_BlendFunc(FT_DST_ALPHA, FT_ONE_MINUS_DST_ALPHA); + + ft_ColorMask(1, 0, 0, 0); + ft_PaletteSource(FT_DEMO_PALETTE_ADDR + 2); + ft_Vertex2ii(0, 0, 0, 0); + + ft_ColorMask(0, 1, 0, 0); + ft_PaletteSource(FT_DEMO_PALETTE_ADDR + 1); + ft_Vertex2ii(0, 0, 0, 0); + + ft_ColorMask(0, 0, 1, 0); + ft_PaletteSource(FT_DEMO_PALETTE_ADDR + 0); + ft_Vertex2ii(0, 0, 0, 0); + + ft_RestoreContext(); + + ft_ColorMask(1, 1, 1, 1); + ft_BlendFunc(FT_SRC_ALPHA, FT_ONE_MINUS_SRC_ALPHA); + + ft_ColorRGB(0, 255, 255); + ft_Text(8, screen_h - 32, 18, 0, "Frame:"); + ft_Number(120, screen_h - 32, 18, 0, (i32)frame_no); + + ft_Text(8, screen_h - 16, 18, 0, "Iters:"); + ft_Number(120, screen_h - 16, 18, 0, (i32)iters); + + ft_Display(); + ft_Swap(); + + err = ft_ccmd_write(); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +int ft_demo_frac_cmd() +{ + esp_err_t err; + esp_err_t err2; + FT_DEMO_FRAC_STATE st = {}; + u8 *render_bufs[2] = + { + nullptr, + nullptr + }; + u32 palette[256]; + u32 active_addr = FT_DEMO_PIX0_ADDR; + u32 inactive_addr = FT_DEMO_PIX1_ADDR; + u32 shown_frame = 1; + u32 prepared_frame = 2; + int upload_buf_idx = 1; + + render_bufs[0] = (u8*)heap_caps_malloc(FT_DEMO_PIX_SIZE, MALLOC_CAP_INTERNAL); + render_bufs[1] = (u8*)heap_caps_malloc(FT_DEMO_PIX_SIZE, MALLOC_CAP_INTERNAL); + + if (!render_bufs[0] || !render_bufs[1]) + { + printf("FT demo render buffer alloc failed, size=%lu\r\n", (unsigned long)FT_DEMO_PIX_SIZE); + if (render_bufs[0]) free(render_bufs[0]); + if (render_bufs[1]) free(render_bufs[1]); + return 1; + } + + if (!ft_demo_frac_state_init(&st, render_bufs[0])) + { + printf("FT demo state alloc failed\r\n"); + free(render_bufs[0]); + free(render_bufs[1]); + return 1; + } + + memset(render_bufs[1], 0, FT_DEMO_PIX_SIZE); + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + ft_demo_frac_state_free(&st); + free(render_bufs[0]); + free(render_bufs[1]); + return 1; + } + + ft_demo_frac_make_palette(palette); + err = ft_write(palette, FT_DEMO_PALETTE_ADDR, FT_DEMO_PALETTE_SIZE); + + if (err == ESP_OK) + { + ft_demo_frac_render(&st, render_bufs[0], shown_frame); + ft_demo_frac_render(&st, render_bufs[1], prepared_frame); + err = ft_demo_frac_upload_bitmap_bg(render_bufs[0], active_addr); + } + + if (err == ESP_OK) + err = spi_master_bg_wait_done(portMAX_DELAY); + + if (err == ESP_OK) + err = ft_demo_frac_show_bitmap(active_addr, shown_frame); + + if (err == ESP_OK) + { + ft_rreg8(FT_REG_INT_FLAGS); + err = profiler_start(); + + if (err == ESP_OK) + { + while (1) + { + PROFILER_LINE line = {}; + int render_buf_idx = upload_buf_idx ^ 1; + u32 future_frame = prepared_frame + 1; + int64_t t0 = esp_timer_get_time(); + + while (1) + { + if (ft_rreg8(FT_REG_INT_FLAGS) & FT_INT_SWAP) + break; + + if (((esp_timer_get_time() - t0) / 1000) >= 1000) + { + err = ESP_ERR_TIMEOUT; + break; + } + + vTaskDelay(pdMS_TO_TICKS(1)); + } + if (err != ESP_OK) break; + + line.ts_loop_start = profiler_now(); + + line.ts_upload_start = profiler_now(); + err = ft_demo_frac_upload_bitmap_bg(render_bufs[upload_buf_idx], inactive_addr); + if (err != ESP_OK) break; + + line.ts_render_start = profiler_now(); + ft_demo_frac_render(&st, render_bufs[render_buf_idx], future_frame); + line.ts_render_end = profiler_now(); + + err = spi_master_bg_wait_done(portMAX_DELAY); + line.ts_upload_done = profiler_now(); + if (err != ESP_OK) break; + + err = ft_demo_frac_show_bitmap(inactive_addr, prepared_frame); + if (err != ESP_OK) break; + + profiler_push(&line); + + shown_frame = prepared_frame; + prepared_frame = future_frame; + upload_buf_idx = render_buf_idx; + + u32 tmp = active_addr; + active_addr = inactive_addr; + inactive_addr = tmp; + + char c; + if (uart_read_bytes(UART_NUM_0, &c, 1, 0) > 0) + { + printf("FT demo stopped\r\n"); + break; + } + } + + profiler_stop(); + } + else + printf("Profiler start failed: %s (0x%x)\r\n", esp_err_to_name(err), (unsigned int)err); + } + + err2 = ft_close_session(); + if (err == ESP_OK) + err = err2; + + ft_demo_frac_state_free(&st); + free(render_bufs[0]); + free(render_bufs[1]); + + if (err != ESP_OK) + { + printf("FT demo_frac failed: %d\r\n", (int)err); + return 1; + } + + return 0; +} + +u8 ft_text_cur_ink = 15; +u8 ft_text_cur_paper = 0; +u8 *ft_text_chars_addr = nullptr; +u8 *ft_text_attrs_addr = nullptr; + +u8 *ft_text_attr_mode_upload = nullptr; +u8 *ft_text_attr_mode_blank_chars = nullptr; +u8 *ft_text_attr_mode_blank_attrs = nullptr; +u16 ft_text_attr_mode_cols = FT_DEMO_TEXT_COLS; +u16 ft_text_attr_mode_rows = FT_DEMO_TEXT_ROWS; +bool ft_text_attr_mode_open = false; +bool ft_text_attr_mode_palette_dirty = false; + +void ft_text_set_attr(u8 ink, u8 paper) +{ + ft_text_cur_ink = (u8)(ink & 15U); + ft_text_cur_paper = (u8)(paper & 15U); +} + +void ft_text_set_addrs(u8 *chars, u8 *attrs) +{ + ft_text_chars_addr = chars; + ft_text_attrs_addr = attrs; +} + +u8 ft_text_attr(u8 ink, u8 paper) +{ + return (u8)(((paper & 15U) << 4) | (ink & 15U)); +} + +void ft_text_clear(u8 ch, u8 attr) +{ + if (!ft_text_chars_addr || !ft_text_attrs_addr) return; + + for (u32 i = 0; i < ((u32)FT_DEMO_TEXT_COLS * (u32)FT_DEMO_TEXT_ROWS); i++) + { + ft_text_chars_addr[i] = ch; + ft_text_attrs_addr[i] = attr; + } +} + +void ft_text_put_raw(int x, int y, u8 ch, u8 attr) +{ + u32 off; + + if (!ft_text_chars_addr || !ft_text_attrs_addr) return; + if (x < 0 || x >= FT_DEMO_TEXT_COLS) return; + if (y < 0 || y >= FT_DEMO_TEXT_ROWS) return; + + off = (u32)y * FT_DEMO_TEXT_COLS + (u32)x; + ft_text_chars_addr[off] = ch; + ft_text_attrs_addr[off] = attr; +} + +void ft_text_putc(int x, int y, u8 ch) +{ + ft_text_put_raw(x, y, ch, ft_text_attr(ft_text_cur_ink, ft_text_cur_paper)); +} + +void ft_text_fill_rect(int x, int y, int w, int h, u8 ch, u8 attr) +{ + if (w <= 0 || h <= 0) return; + + for (int yy = 0; yy < h; yy++) + { + int py = y + yy; + + if (py < 0 || py >= FT_DEMO_TEXT_ROWS) + continue; + + for (int xx = 0; xx < w; xx++) + ft_text_put_raw(x + xx, py, ch, attr); + } +} + +void ft_text_fill_paper(int x, int y, int w, int h, u8 paper) +{ + ft_text_fill_rect(x, y, w, h, ' ', ft_text_attr(15, paper)); +} + +void ft_text_draw_box2(int x, int y, int w, int h) +{ + if (w < 2 || h < 2) return; + + ft_text_putc(x, y, 0xC9); + ft_text_putc(x + w - 1, y, 0xBB); + ft_text_putc(x, y + h - 1, 0xC8); + ft_text_putc(x + w - 1, y + h - 1, 0xBC); + + for (int xx = 1; xx < (w - 1); xx++) + { + ft_text_putc(x + xx, y, 0xCD); + ft_text_putc(x + xx, y + h - 1, 0xCD); + } + + for (int yy = 1; yy < (h - 1); yy++) + { + ft_text_putc(x, y + yy, 0xBA); + ft_text_putc(x + w - 1, y + yy, 0xBA); + } +} + +void ft_text_puts(int x, int y, const char *s) +{ + if (!ft_text_chars_addr || !ft_text_attrs_addr || !s) return; + if (y < 0 || y >= FT_DEMO_TEXT_ROWS) return; + + while (*s && x < FT_DEMO_TEXT_COLS) + { + if (x >= 0) + ft_text_putc(x, y, (u8)*s); + + x++; + s++; + } +} + +char ft_hex_digit(u8 v) +{ + v &= 15; + + if (v < 10) + return (char)('0' + v); + + return (char)('A' + (v - 10)); +} + +void ft_text_put_hex1(int x, int y, u8 v) +{ + ft_text_putc(x, y, (u8)ft_hex_digit(v)); +} + +void ft_text_to_attr_render_size(u8 *gfx, const u8 *chars, u8 *color, const u8 *attrs, u16 cols, u16 rows) +{ + u32 column_pitch = 256; + u32 row_pitch = 256; + int col_count; + int row_count; + + if (!gfx || !chars) return; + + if (cols == 0) cols = FT_DEMO_TEXT_COLS; + if (rows == 0) rows = FT_DEMO_TEXT_ROWS; + if (cols > FT_TEXT_ATTR_MAX_COLS) cols = FT_TEXT_ATTR_MAX_COLS; + if (rows > FT_TEXT_ATTR_MAX_ROWS) rows = FT_TEXT_ATTR_MAX_ROWS; + + col_count = (int)cols; + row_count = (int)rows; + + memset(gfx, 0, (size_t)FT_TEXT_ATTR_GFX_SIZE_FOR(cols, rows)); + + for (int cy = 0; cy < row_count; cy++) + { + u32 group = (u32)cy / FT_TEXT_ATTR_GROUP_ROWS; + u32 local_y = (u32)cy % FT_TEXT_ATTR_GROUP_ROWS; + + for (int cx = 0; cx < col_count; cx++) + { + u32 col_index = group * (u32)cols + (u32)cx; + u8 *col_dst = gfx + col_index * column_pitch; + u8 ch = chars[(u32)cy * (u32)cols + (u32)cx]; + + for (int gy = 0; gy < 8; gy++) + col_dst[local_y * 8U + (u32)gy] = code_866_fnt[(u32)ch * 8U + (u32)gy]; + } + } + + if (!color || !attrs) return; + + memset(color, 0, (size_t)((u32)rows * row_pitch)); + + for (int cy = 0; cy < row_count; cy++) + { + u8 *row_dst = color + (u32)cy * row_pitch; + + for (int cx = 0; cx < col_count; cx++) + row_dst[cx] = attrs[(u32)cy * (u32)cols + (u32)cx]; + } +} + +void ft_text_to_attr_render(u8 *gfx, const u8 *chars, u8 *color, const u8 *attrs) +{ + ft_text_to_attr_render_size(gfx, chars, color, attrs, FT_DEMO_TEXT_COLS, FT_DEMO_TEXT_ROWS); +} + +void ft_text_to_4bpp_render(u8 *dst, const u8 *chars, const u8 *attrs) +{ + if (!dst || !chars || !attrs) return; + + for (int cy = 0; cy < FT_DEMO_TEXT_ROWS; cy++) + { + for (int gy = 0; gy < 8; gy++) + { + u8 *drow = dst + (u32)(cy * 8 + gy) * ((u32)FT_DEMO_TEXT_COLS * 4U); + + for (int cx = 0; cx < FT_DEMO_TEXT_COLS; cx++) + { + u32 off = (u32)cy * FT_DEMO_TEXT_COLS + (u32)cx; + u8 ch = chars[off]; + u8 attr = attrs[off]; + u8 ink = (u8)(attr & 15U); + u8 paper = (u8)((attr >> 4) & 15U); + u8 bits = code_866_fnt[(u32)ch * 8U + (u32)gy]; + u8 *dp = drow + (u32)cx * 4U; + + for (int i = 0; i < 4; i++) + { + u8 p0 = (bits & 0x80U) ? ink : paper; + bits <<= 1; + u8 p1 = (bits & 0x80U) ? ink : paper; + bits <<= 1; + dp[i] = (u8)((p0 << 4) | p1); + } + } + } + } +} + +u16 ft_attr_to_rgb565(u8 c) +{ + u8 level = (c & 8U) ? 255U : 191U; + u8 b = (c & 1U) ? level : 0U; + u8 r = (c & 2U) ? level : 0U; + u8 g = (c & 4U) ? level : 0U; + + return (u16)(((u16)(r & 0xF8U) << 8) | ((u16)(g & 0xFCU) << 3) | ((u16)b >> 3)); +} + +void ft_text_make_palettes(u16 *pal_hi, u16 *pal_lo) +{ + u16 pal4[16]; + + if (!pal_hi || !pal_lo) return; + + for (u32 c = 0; c < 16; c++) + { + u8 intensity = (c & 8U) ? 85U : 0U; + u8 b = (c & 1U) ? (u8)(intensity + 170U) : intensity; + u8 r = (c & 2U) ? (u8)(intensity + 170U) : intensity; + u8 g = (c & 4U) ? (u8)(intensity + 170U) : intensity; + + pal4[c] = (u16)(((u16)(r & 0xF8U) << 8) | ((u16)(g & 0xFCU) << 3) | ((u16)b >> 3)); + } + + for (u32 i = 0; i < 256; i++) + { + pal_hi[i] = pal4[i >> 4]; + pal_lo[i] = pal4[i & 15U]; + } +} + +esp_err_t ft_text_palette_init_at(u32 pal_hi_addr, u32 pal_lo_addr) +{ + esp_err_t err; + u16 pal_hi[256]; + u16 pal_lo[256]; + + ft_text_make_palettes(pal_hi, pal_lo); + + err = ft_write(pal_hi, pal_hi_addr, sizeof(pal_hi)); + if (err != ESP_OK) return err; + + err = ft_write(pal_lo, pal_lo_addr, sizeof(pal_lo)); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +esp_err_t ft_text_palette_init() +{ + return ft_text_palette_init_at(FT_DEMO_PAL4_PAL_HI_ADDR, FT_DEMO_PAL4_PAL_LO_ADDR); +} + +esp_err_t ft_text_attr_mode_palette_init() +{ + esp_err_t err; + + err = ft_text_palette_init_at( + FT_TEXT_ATTR_PAL_HI_ADDR_FOR(ft_text_attr_mode_cols, ft_text_attr_mode_rows), + FT_TEXT_ATTR_PAL_LO_ADDR_FOR(ft_text_attr_mode_cols, ft_text_attr_mode_rows)); + if (err != ESP_OK) return err; + + ft_text_attr_mode_palette_dirty = false; + return ESP_OK; +} + +esp_err_t ft_4bpp_show() +{ + esp_err_t err; + u16 bitmap_w_bytes = (u16)(FT_DEMO_TEXT_COLS * 4); + u16 bitmap_h = (u16)(FT_DEMO_TEXT_ROWS * 8); + u16 screen_w = (u16)(FT_DEMO_TEXT_COLS * 8); + u16 screen_h = (u16)(FT_DEMO_TEXT_ROWS * 16); + u16 screen_x = (u16)((800 - screen_w) / 2); + u16 screen_y = (u16)((600 - screen_h) / 2); + + ft_ccmd_start(cmdl); + + ft_Dlstart(); + + ft_ClearColorRGB(0, 0, 32); + ft_ClearColorA(255); + ft_ClearStencil(0); + ft_Clear(1, 1, 1); + + ft_BitmapHandle(0); + ft_BitmapSource(FT_DEMO_PAL4_PIX_ADDR); + ft_BitmapLayout(FT_PALETTED565, bitmap_w_bytes, bitmap_h); + ft_BitmapSize(FT_NEAREST, FT_BORDER, FT_BORDER, screen_w, screen_h); + + ft_BitmapHandle(1); + ft_BitmapSource(FT_DEMO_PAL4_MASK_ADDR); + ft_BitmapLayout(FT_L4, 1, 1); + ft_BitmapSize(FT_NEAREST, FT_REPEAT, FT_REPEAT, screen_w, screen_h); + + ft_BitmapTransformB(0); + ft_BitmapTransformC(0); + ft_BitmapTransformD(0); + ft_BitmapTransformF(0); + + ft_BitmapTransformA(256); + ft_BitmapTransformE(256); + + ft_ColorMask(0, 0, 0, 0); + ft_StencilMask(255); + ft_AlphaFunc(FT_GREATER, 0); + ft_StencilFunc(FT_ALWAYS, 1, 255); + ft_StencilOp(FT_KEEP, FT_REPLACE); + ft_Begin(FT_BITMAPS); + ft_Vertex2ii(screen_x, screen_y, 1, 0); + + ft_ColorMask(1, 1, 1, 0); + ft_StencilMask(0); + ft_AlphaFunc(FT_ALWAYS, 0); + ft_BlendFunc(FT_ONE, FT_ZERO); + + ft_BitmapTransformA(128); + ft_BitmapTransformE(128); + + ft_StencilFunc(FT_EQUAL, 1, 255); + ft_PaletteSource(FT_DEMO_PAL4_PAL_HI_ADDR); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_StencilFunc(FT_EQUAL, 0, 255); + ft_PaletteSource(FT_DEMO_PAL4_PAL_LO_ADDR); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_Display(); + ft_Swap(); + + err = ft_ccmd_write(); + if (err != ESP_OK) return err; + + err = ft_cp_wait(1000); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +esp_err_t ft_attr_show() +{ + esp_err_t err; + u16 bitmap_h = FT_DEMO_TEXT_ROWS; + u16 screen_w = (u16)(FT_DEMO_TEXT_COLS * 8); + u16 screen_h = (u16)(FT_DEMO_TEXT_ROWS * 16); + u16 screen_x = (u16)((800 - screen_w) / 2); + u16 screen_y = (u16)((600 - screen_h) / 2); + + ft_ccmd_start(cmdl); + + ft_Dlstart(); + + ft_ClearColorRGB(0, 0, 32); + ft_ClearColorA(255); + ft_ClearStencil(0); + ft_Clear(1, 1, 1); + + ft_BitmapHandle(0); + ft_BitmapSource(FT_DEMO_ATTR_ADDR); + ft_BitmapLayout(FT_PALETTED565, 256, bitmap_h); + ft_BitmapSize(FT_NEAREST, FT_BORDER, FT_BORDER, screen_w, screen_h); + + ft_BitmapHandle(1); + ft_BitmapSource(FT_DEMO_PIX_ADDR(0)); + ft_BitmapLayout(FT_L1, 1, 256); + ft_BitmapSize(FT_NEAREST, FT_BORDER, FT_BORDER, 8, screen_h); + + ft_BitmapTransformB(0); + ft_BitmapTransformC(0); + ft_BitmapTransformD(0); + ft_BitmapTransformF(0); + + ft_BitmapTransformA(256); + ft_BitmapTransformE(128); + + ft_ColorMask(0, 0, 0, 0); + ft_StencilMask(255); + ft_AlphaFunc(FT_GREATER, 0); + ft_StencilFunc(FT_ALWAYS, 1, 255); + ft_StencilOp(FT_KEEP, FT_REPLACE); + + ft_Begin(FT_BITMAPS); + + ft_VertexTranslateX((i32)screen_x * 16); + ft_VertexTranslateY((i32)screen_y * 16); + + for (int cx = 0; cx < 64; cx++) + ft_Vertex2ii((u16)(cx * 8), 0, 1, (u8)cx); + + ft_VertexTranslateX((i32)(screen_x + 64 * 8) * 16); + + for (int cx = 64; cx < FT_DEMO_TEXT_COLS; cx++) + ft_Vertex2ii((u16)((cx - 64) * 8), 0, 1, (u8)cx); + + ft_VertexTranslateX(0); + ft_VertexTranslateY(0); + + ft_ColorMask(1, 1, 1, 0); + ft_StencilMask(0); + ft_AlphaFunc(FT_ALWAYS, 0); + ft_BlendFunc(FT_ONE, FT_ZERO); + + ft_BitmapTransformA(32); + ft_BitmapTransformE(16); + + ft_StencilFunc(FT_EQUAL, 0, 255); + ft_PaletteSource(FT_DEMO_PAL4_PAL_HI_ADDR); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_StencilFunc(FT_EQUAL, 1, 255); + ft_PaletteSource(FT_DEMO_PAL4_PAL_LO_ADDR); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_Display(); + ft_Swap(); + + err = ft_ccmd_write(); + if (err != ESP_OK) return err; + + err = ft_cp_wait(1000); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +void ft_text_attr_mode_calc_size(u16 *cols, u16 *rows, u16 *visible_w, u16 *visible_h) +{ + u16 w = 640; + u16 h = 480; + u16 c; + u16 r; + + if (ft_current_mode >= 0 && ft_current_mode < FT_MODE_MAX) + { + w = ft_modes[ft_current_mode].h_visible; + h = ft_modes[ft_current_mode].v_visible; + } + + c = (u16)(w / 8U); + r = (u16)(h / 16U); + + if (c == 0) c = FT_DEMO_TEXT_COLS; + if (r == 0) r = FT_DEMO_TEXT_ROWS; + if (c > FT_TEXT_ATTR_MAX_COLS) c = FT_TEXT_ATTR_MAX_COLS; + if (r > FT_TEXT_ATTR_MAX_ROWS) r = FT_TEXT_ATTR_MAX_ROWS; + + if (cols) *cols = c; + if (rows) *rows = r; + if (visible_w) *visible_w = w; + if (visible_h) *visible_h = h; +} + +void ft_text_attr_mode_get_size(uint16_t *cols, uint16_t *rows) +{ + u16 c; + u16 r; + + if (ft_text_attr_mode_open) + { + c = ft_text_attr_mode_cols; + r = ft_text_attr_mode_rows; + } + else + ft_text_attr_mode_calc_size(&c, &r, nullptr, nullptr); + + if (cols) *cols = c; + if (rows) *rows = r; +} + +esp_err_t ft_text_attr_mode_show() +{ + esp_err_t err; + u16 cols = ft_text_attr_mode_cols; + u16 rows = ft_text_attr_mode_rows; + u16 bitmap_h = rows; + u16 text_w = (u16)(cols * 8U); + u16 text_h = (u16)(rows * 16U); + u16 visible_w; + u16 visible_h; + u16 screen_x = 0; + u16 screen_y = 0; + int col_count = (int)cols; + + ft_text_attr_mode_calc_size(nullptr, nullptr, &visible_w, &visible_h); + + if (ft_text_attr_mode_palette_dirty) + { + err = ft_text_attr_mode_palette_init(); + if (err != ESP_OK) return err; + } + + if (visible_w > text_w) + screen_x = (u16)((visible_w - text_w) / 2U); + + if (visible_h > text_h) + screen_y = (u16)((visible_h - text_h) / 2U); + + ft_ccmd_start(cmdl); + + ft_Dlstart(); + + ft_ClearColorRGB(0, 0, 32); + ft_ClearColorA(255); + ft_ClearStencil(0); + ft_Clear(1, 1, 1); + + ft_BitmapHandle(0); + ft_BitmapSource(FT_DEMO_ATTR_ADDR_FOR(cols, rows)); + ft_BitmapLayout(FT_PALETTED565, 256, bitmap_h); + ft_BitmapSize(FT_NEAREST, FT_BORDER, FT_BORDER, text_w, text_h); + + ft_BitmapHandle(1); + + ft_BitmapTransformB(0); + ft_BitmapTransformC(0); + ft_BitmapTransformD(0); + ft_BitmapTransformF(0); + + ft_BitmapTransformA(256); + ft_BitmapTransformE(128); + + ft_ColorMask(0, 0, 0, 0); + ft_StencilMask(255); + ft_AlphaFunc(FT_GREATER, 0); + ft_StencilFunc(FT_ALWAYS, 1, 255); + ft_StencilOp(FT_KEEP, FT_REPLACE); + + ft_Begin(FT_BITMAPS); + + for (u32 group = 0; group < FT_TEXT_ATTR_GROUPS_FOR(rows); group++) + { + u32 row0 = group * FT_TEXT_ATTR_GROUP_ROWS; + u32 group_rows = (u32)rows - row0; + u16 group_text_h; + + if (group_rows > FT_TEXT_ATTR_GROUP_ROWS) + group_rows = FT_TEXT_ATTR_GROUP_ROWS; + + group_text_h = (u16)(group_rows * 16U); + + ft_BitmapLayout(FT_L1, 1, 256); + ft_BitmapSize(FT_NEAREST, FT_BORDER, FT_BORDER, 8, group_text_h); + + for (int start = 0; start < col_count; start += 64) + { + int count = col_count - start; + if (count > 64) count = 64; + + ft_BitmapSource(FT_DEMO_PIX_GROUP_ADDR(group, start, cols)); + ft_VertexTranslateX((i32)(screen_x + start * 8) * 16); + ft_VertexTranslateY((i32)(screen_y + row0 * 16U) * 16); + + for (int cx = 0; cx < count; cx++) + ft_Vertex2ii((u16)(cx * 8), 0, 1, (u8)cx); + } + } + + ft_VertexTranslateX(0); + ft_VertexTranslateY(0); + + ft_ColorMask(1, 1, 1, 0); + ft_StencilMask(0); + ft_AlphaFunc(FT_ALWAYS, 0); + ft_BlendFunc(FT_ONE, FT_ZERO); + + ft_BitmapTransformA(32); + ft_BitmapTransformE(16); + + ft_BitmapHandle(0); + ft_BitmapSource(FT_DEMO_ATTR_ADDR_FOR(cols, rows)); + + ft_StencilFunc(FT_EQUAL, 0, 255); + ft_PaletteSource(FT_TEXT_ATTR_PAL_HI_ADDR_FOR(cols, rows)); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_StencilFunc(FT_EQUAL, 1, 255); + ft_PaletteSource(FT_TEXT_ATTR_PAL_LO_ADDR_FOR(cols, rows)); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_Display(); + ft_Swap(); + + err = ft_ccmd_write(); + if (err != ESP_OK) return err; + + err = ft_cp_wait(1000); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +esp_err_t ft_text_attr_mode_present(const u8 *chars, const u8 *attrs) +{ + esp_err_t err; + u32 gfx_size; + u32 upload_size; + + if (!chars || !attrs) return ESP_ERR_INVALID_ARG; + if (!ft_text_attr_mode_open) return ESP_ERR_INVALID_STATE; + if (!ft_text_attr_mode_upload) return ESP_ERR_INVALID_STATE; + + gfx_size = FT_TEXT_ATTR_GFX_SIZE_FOR(ft_text_attr_mode_cols, ft_text_attr_mode_rows); + upload_size = FT_TEXT_ATTR_UPLOAD_SIZE_FOR(ft_text_attr_mode_cols, ft_text_attr_mode_rows); + + u8 *gfx = ft_text_attr_mode_upload; + u8 *color = ft_text_attr_mode_upload + gfx_size; + + ft_text_to_attr_render_size(gfx, chars, color, attrs, ft_text_attr_mode_cols, ft_text_attr_mode_rows); + + err = ft_write(ft_text_attr_mode_upload, FT_DEMO_PIX_ADDR(0), upload_size); + if (err != ESP_OK) return err; + + if (ft_text_attr_mode_palette_dirty) + return ft_text_attr_mode_palette_init(); + + return ESP_OK; +} + +esp_err_t ft_text_attr_mode_clear(u8 ch, u8 attr) +{ + u32 text_cells = (u32)ft_text_attr_mode_cols * (u32)ft_text_attr_mode_rows; + + if (!ft_text_attr_mode_open) return ESP_ERR_INVALID_STATE; + if (!ft_text_attr_mode_blank_chars || !ft_text_attr_mode_blank_attrs) return ESP_ERR_INVALID_STATE; + + if (ch == 0) + ch = ' '; + + memset(ft_text_attr_mode_blank_chars, ch, text_cells); + memset(ft_text_attr_mode_blank_attrs, attr, text_cells); + + return ft_text_attr_mode_present(ft_text_attr_mode_blank_chars, ft_text_attr_mode_blank_attrs); +} + +void ft_text_attr_mode_free() +{ + if (ft_text_attr_mode_upload) free(ft_text_attr_mode_upload); + if (ft_text_attr_mode_blank_chars) free(ft_text_attr_mode_blank_chars); + if (ft_text_attr_mode_blank_attrs) free(ft_text_attr_mode_blank_attrs); + + ft_text_attr_mode_upload = nullptr; + ft_text_attr_mode_blank_chars = nullptr; + ft_text_attr_mode_blank_attrs = nullptr; + ft_text_attr_mode_cols = FT_DEMO_TEXT_COLS; + ft_text_attr_mode_rows = FT_DEMO_TEXT_ROWS; + ft_text_attr_mode_palette_dirty = false; +} + +esp_err_t ft_text_attr_mode_begin() +{ + esp_err_t err; + u32 text_cells; + u32 upload_size; + + if (ft_text_attr_mode_open) return ESP_OK; + + ft_text_attr_mode_calc_size(&ft_text_attr_mode_cols, &ft_text_attr_mode_rows, nullptr, nullptr); + text_cells = (u32)ft_text_attr_mode_cols * (u32)ft_text_attr_mode_rows; + upload_size = FT_TEXT_ATTR_UPLOAD_SIZE_FOR(ft_text_attr_mode_cols, ft_text_attr_mode_rows); + + ft_text_attr_mode_upload = (u8*)heap_caps_malloc(upload_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + ft_text_attr_mode_blank_chars = (u8*)heap_caps_malloc(text_cells, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + ft_text_attr_mode_blank_attrs = (u8*)heap_caps_malloc(text_cells, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + + if (!ft_text_attr_mode_upload || !ft_text_attr_mode_blank_chars || !ft_text_attr_mode_blank_attrs) + { + ft_text_attr_mode_free(); + return ESP_ERR_NO_MEM; + } + + err = ft_open_session(); + if (err != ESP_OK) + { + ft_text_attr_mode_free(); + return err; + } + + ft_text_attr_mode_open = true; + + err = ft_text_attr_mode_palette_init(); + if (err == ESP_OK) + err = ft_text_attr_mode_clear(' ', 0x0f); + + if (err == ESP_OK) + err = ft_text_attr_mode_show(); + + if (err == ESP_OK) + err = ft_wait_swap(1000); + + if (err != ESP_OK) + { + ft_text_attr_mode_open = false; + ft_close_session(); + ft_text_attr_mode_free(); + return err; + } + + return ESP_OK; +} + +void ft_text_attr_mode_end() +{ + if (ft_text_attr_mode_open) + ft_close_session(); + + ft_text_attr_mode_open = false; + ft_text_attr_mode_free(); +} + +void ft_demo_text_fill(const char *title, const char *subtitle) +{ + const int left_x = 2; + const int right_x = 42; + + if (!ft_text_chars_addr || !ft_text_attrs_addr) return; + + ft_text_clear(' ', ft_text_attr(15, 0)); + ft_text_fill_paper(0, 0, FT_DEMO_TEXT_COLS, FT_DEMO_TEXT_ROWS, 0); + + ft_text_set_attr(15, 0); + ft_text_draw_box2(0, 0, FT_DEMO_TEXT_COLS, FT_DEMO_TEXT_ROWS); + + ft_text_set_attr(14, 0); + ft_text_puts(left_x, 1, title); + + ft_text_set_attr(11, 0); + ft_text_puts(left_x, 2, subtitle); + + { + int x0 = left_x; + int y0 = 11; + + ft_text_set_attr(15, 0); + for (int ink = 0; ink < 16; ink++) + ft_text_put_hex1(x0 + 4 + ink * 2, y0, (u8)ink); + + for (int paper = 0; paper < 16; paper++) + { + ft_text_set_attr(15, (u8)paper); + ft_text_put_hex1(x0 + 1, y0 + 1 + paper, (u8)paper); + + for (int ink = 0; ink < 16; ink++) + { + ft_text_set_attr((u8)ink, (u8)paper); + ft_text_putc(x0 + 4 + ink * 2, y0 + 1 + paper, 'A'); + } + } + } + + { + int x0 = right_x; + int y0 = 11; + + ft_text_set_attr(15, 0); + for (int col = 0; col < 16; col++) + ft_text_put_hex1(x0 + 3 + col * 2, y0, (u8)col); + + for (int row = 0; row < 16; row++) + { + ft_text_put_hex1(x0 + 1, y0 + 1 + row, (u8)row); + + ft_text_set_attr(7, 0); + for (int col = 0; col < 16; col++) + ft_text_putc(x0 + 3 + col * 2, y0 + 1 + row, (u8)(row * 16 + col)); + + ft_text_set_attr(15, 0); + } + } +} + +esp_err_t ft_rgb888_640x480_load_mode(u32 rgb_addr, bool stretch, bool swap); +esp_err_t ft_rgb888_640x480_show_mode(u32 rgb_addr, bool stretch); +esp_err_t ft_dxp_show_mode(const FT_DXP_INFO *info); + +int ft_jpg_ext_match(const char *name) +{ + const char *dot = strrchr(name, '.'); + if (!dot) return 0; + + char ext[6] = {}; + size_t n = strlen(dot); + if (n >= sizeof(ext)) return 0; + + for (size_t i = 0; i < n; i++) + ext[i] = (char)tolower((unsigned char)dot[i]); + + return !strcmp(ext, ".jpg") || !strcmp(ext, ".jpeg"); +} + +int ft_dxp_ext_match(const char *name) +{ + const char *dot = strrchr(name, '.'); + if (!dot) return 0; + + char ext[6] = {}; + size_t n = strlen(dot); + if (n >= sizeof(ext)) return 0; + + for (size_t i = 0; i < n; i++) + ext[i] = (char)tolower((unsigned char)dot[i]); + + return !strcmp(ext, ".dxp"); +} + +char *ft_jpg_strdup(const char *s) +{ + if (!s) return nullptr; + + size_t len = strlen(s) + 1; + char *d = (char*)malloc(len); + if (!d) return nullptr; + + memcpy(d, s, len); + return d; +} + +void ft_jpg_list_free(FT_JPG_LIST *lst) +{ + if (!lst) return; + + for (int i = 0; i < lst->count; i++) + free(lst->items[i]); + + free(lst->items); + lst->items = nullptr; + lst->count = 0; + lst->cap = 0; +} + +int ft_jpg_list_add(FT_JPG_LIST *lst, const char *path) +{ + if (!lst || !path || !path[0]) return 0; + + if (lst->count >= lst->cap) + { + int new_cap = lst->cap ? lst->cap * 2 : 16; + char **new_items = (char**)realloc(lst->items, (size_t)new_cap * sizeof(char*)); + if (!new_items) return 0; + + lst->items = new_items; + lst->cap = new_cap; + } + + lst->items[lst->count] = ft_jpg_strdup(path); + if (!lst->items[lst->count]) return 0; + + lst->count++; + return 1; +} + +int ft_jpg_list_cmp(const void *a, const void *b) +{ + const char *pa = *(const char * const *)a; + const char *pb = *(const char * const *)b; + return strcmp(pa, pb); +} + +int ft_jpg_join_rel(char *dst, size_t dst_size, const char *dir, const char *name) +{ + int n; + + if (!dst || !dst_size || !name || !name[0]) return 0; + + if (!dir || !dir[0] || !strcmp(dir, "/")) + n = snprintf(dst, dst_size, "/%s", name); + else if (dir[strlen(dir) - 1] == '/') + n = snprintf(dst, dst_size, "%s%s", dir, name); + else + n = snprintf(dst, dst_size, "%s/%s", dir, name); + + return n >= 0 && (size_t)n < dst_size; +} + +esp_err_t ft_jpg_scan_dir(const char *base, const char *rel, FT_JPG_LIST *lst, int depth) +{ + char full[FT_JPG_MAX_PATH]; + + if (depth > FT_JPG_SCAN_MAX_DEPTH) return ESP_OK; + + if (!sd_fs_build_full_path(base, rel, full, sizeof(full))) + { + printf("E: path too long: %s\r\n", rel ? rel : "-"); + return ESP_ERR_INVALID_ARG; + } + + DIR *d = opendir(full); + if (!d) + { + int saved_errno = errno; + printf("E: opendir('%s') failed, errno=%d\r\n", full, saved_errno); + if (sd_has_retryable_errno(saved_errno)) return ESP_ERR_INVALID_STATE; + return ESP_FAIL; + } + + for (;;) + { + struct dirent *e = readdir(d); + if (!e) break; + + if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, "..")) + continue; + + char child_rel[FT_JPG_MAX_PATH]; + char child_full[FT_JPG_MAX_PATH]; + + if (!ft_jpg_join_rel(child_rel, sizeof(child_rel), rel, e->d_name)) + { + printf("W: skip long path: %s/%s\r\n", rel ? rel : "", e->d_name); + continue; + } + + if (!sd_fs_build_full_path(base, child_rel, child_full, sizeof(child_full))) + { + printf("W: skip long full path: %s\r\n", child_rel); + continue; + } + + struct stat st = {}; + if (stat(child_full, &st) != 0) + { + printf("W: stat('%s') failed, errno=%d\r\n", child_full, errno); + continue; + } + + if (S_ISDIR(st.st_mode)) + { + esp_err_t err = ft_jpg_scan_dir(base, child_rel, lst, depth + 1); + if (err != ESP_OK) + { + closedir(d); + return err; + } + continue; + } + + if (!S_ISREG(st.st_mode)) continue; + if (!ft_jpg_ext_match(e->d_name)) continue; + + if (!ft_jpg_list_add(lst, child_rel)) + { + closedir(d); + return ESP_ERR_NO_MEM; + } + } + + closedir(d); + return ESP_OK; +} + +esp_err_t ft_jpg_collect(const char *path, FT_JPG_LIST *lst) +{ + const char *base = "/sd"; + char full[FT_JPG_MAX_PATH]; + sdmmc_card_t *card = nullptr; + + if (!path || !path[0]) return ESP_ERR_INVALID_ARG; + if (!lst) return ESP_ERR_INVALID_ARG; + + esp_err_t err = sd_fs_mount(base, &card); + if (err != ESP_OK && sd_error_needs_reinit(err)) + { + printf("W: SD mount failed: %s, retry\r\n", esp_err_to_name(err)); + sd_deinit(); + err = sd_fs_mount(base, &card); + } + if (err != ESP_OK) return err; + + if (!sd_fs_build_full_path(base, path, full, sizeof(full))) + { + sd_fs_unmount(base, card); + return ESP_ERR_INVALID_ARG; + } + + struct stat st = {}; + if (stat(full, &st) != 0) + { + int saved_errno = errno; + printf("E: stat('%s') failed, errno=%d\r\n", full, saved_errno); + sd_fs_unmount(base, card); + if (sd_has_retryable_errno(saved_errno)) return ESP_ERR_INVALID_STATE; + return ESP_FAIL; + } + + if (S_ISDIR(st.st_mode)) + err = ft_jpg_scan_dir(base, path, lst, 0); + else if (S_ISREG(st.st_mode) && ft_jpg_ext_match(path)) + err = ft_jpg_list_add(lst, path) ? ESP_OK : ESP_ERR_NO_MEM; + else + { + printf("E: no JPEG files at '%s'\r\n", path); + err = ESP_ERR_NOT_FOUND; + } + + sd_fs_unmount(base, card); + + if (err == ESP_OK && lst->count > 1) + qsort(lst->items, (size_t)lst->count, sizeof(char*), ft_jpg_list_cmp); + + return err; +} + + +int ft_jpg_is_sof_marker(u8 marker) +{ + if (marker < 0xC0 || marker > 0xCF) return 0; + if (marker == 0xC4 || marker == 0xC8 || marker == 0xCC) return 0; + return 1; +} + +int ft_jpg_read_sof(const u8 *jpg, size_t size, u8 *out_marker, u16 *out_w, u16 *out_h) +{ + if (!jpg || size < 4) return 0; + if (jpg[0] != 0xFF || jpg[1] != 0xD8) return 0; + + size_t pos = 2; + while (pos + 4 <= size) + { + if (jpg[pos] != 0xFF) + { + pos++; + continue; + } + + while (pos < size && jpg[pos] == 0xFF) + pos++; + + if (pos >= size) return 0; + + u8 marker = jpg[pos++]; + if (marker == 0x00) continue; + if (marker == 0xD9 || marker == 0xDA) return 0; + if (marker >= 0xD0 && marker <= 0xD7) continue; + if (pos + 2 > size) return 0; + + size_t seg_len = ((size_t)jpg[pos] << 8) | jpg[pos + 1]; + if (seg_len < 2 || pos + seg_len > size) return 0; + + if (ft_jpg_is_sof_marker(marker)) + { + if (seg_len < 8) return 0; + if (out_marker) *out_marker = marker; + if (out_h) *out_h = ((u16)jpg[pos + 3] << 8) | jpg[pos + 4]; + if (out_w) *out_w = ((u16)jpg[pos + 5] << 8) | jpg[pos + 6]; + return 1; + } + + pos += seg_len; + } + + return 0; +} + +void ft_jpg_copy_to_screen(u8 *screen, const u8 *img, u16 img_w, u16 img_h) +{ + if (!screen || !img) return; + + memset(screen, 0, FT_RGB888_640_480_SIZE); + + u16 copy_w = img_w > FT_RGB888_640_480_W ? FT_RGB888_640_480_W : img_w; + u16 copy_h = img_h > FT_RGB888_640_480_H ? FT_RGB888_640_480_H : img_h; + u16 dst_x = img_w < FT_RGB888_640_480_W ? (u16)((FT_RGB888_640_480_W - img_w) / 2U) : 0; + u16 dst_y = img_h < FT_RGB888_640_480_H ? (u16)((FT_RGB888_640_480_H - img_h) / 2U) : 0; + + u8 *dst_r0 = screen; + u8 *dst_g0 = screen + FT_RGB888_640_480_PLANE_SIZE; + u8 *dst_b0 = screen + (FT_RGB888_640_480_PLANE_SIZE * 2UL); + + for (u16 y = 0; y < copy_h; y++) + { + const u8 *src = img + ((size_t)y * img_w * FT_RGB888_640_480_BPP); + u8 *dst_r = dst_r0 + (((size_t)dst_y + y) * FT_RGB888_640_480_STRIDE) + dst_x; + u8 *dst_g = dst_g0 + (((size_t)dst_y + y) * FT_RGB888_640_480_STRIDE) + dst_x; + u8 *dst_b = dst_b0 + (((size_t)dst_y + y) * FT_RGB888_640_480_STRIDE) + dst_x; + + for (u16 x = 0; x < copy_w; x++) + { + const u8 *px = src + ((size_t)x * FT_RGB888_640_480_BPP); + dst_r[x] = px[0]; + dst_g[x] = px[1]; + dst_b[x] = px[2]; + } + } +} + +esp_err_t ft_jpg_read_whole_file(const char *path, u8 **out_data, size_t *out_size) +{ + FILE *fp; + long file_size; + u8 *data; + size_t got; + size_t sd_size = 0; + esp_err_t err; + + if (!path || !out_data || !out_size) return ESP_ERR_INVALID_ARG; + + *out_data = nullptr; + *out_size = 0; + + fp = fopen(path, "rb"); + if (fp) + { + if (fseek(fp, 0, SEEK_END) != 0) + { + fclose(fp); + return ESP_FAIL; + } + + file_size = ftell(fp); + if (file_size <= 0 || file_size > INT_MAX) + { + fclose(fp); + return ESP_ERR_INVALID_SIZE; + } + + if (fseek(fp, 0, SEEK_SET) != 0) + { + fclose(fp); + return ESP_FAIL; + } + + data = (u8*)heap_caps_malloc((size_t)file_size, MALLOC_CAP_SPIRAM); + if (!data) + { + fclose(fp); + return ESP_ERR_NO_MEM; + } + + got = fread(data, 1, (size_t)file_size, fp); + if (got != (size_t)file_size) + { + free(data); + fclose(fp); + return ESP_FAIL; + } + + fclose(fp); + *out_data = data; + *out_size = (size_t)file_size; + return ESP_OK; + } + + err = sd_fs_read_file("/sd", path, NULL, 0, &sd_size); + if (err != ESP_OK) return err; + if (sd_size == 0 || sd_size > INT_MAX) return ESP_ERR_INVALID_SIZE; + + data = (u8*)heap_caps_malloc(sd_size, MALLOC_CAP_SPIRAM); + if (!data) return ESP_ERR_NO_MEM; + + err = sd_fs_read_file("/sd", path, data, sd_size, NULL); + if (err != ESP_OK) + { + free(data); + return err; + } + + *out_data = data; + *out_size = sd_size; + return ESP_OK; +} + +esp_err_t ft_jpg_decode_to_screen(const char *path, u8 *screen, u16 *out_w, u16 *out_h, bool quiet) +{ + size_t jpg_size = 0; + u8 *jpg = nullptr; + u8 *decoded = nullptr; + jpeg_dec_handle_t dec = NULL; + jpeg_dec_io_t *io = NULL; + jpeg_dec_header_info_t *info = NULL; + jpeg_dec_config_t cfg = DEFAULT_JPEG_DEC_CONFIG(); + jpeg_error_t jerr = JPEG_ERR_OK; + int output_len = 0; + u8 sof_marker = 0; + u16 sof_w = 0; + u16 sof_h = 0; + + if (!path || !screen) return ESP_ERR_INVALID_ARG; + + esp_err_t err = ft_jpg_read_whole_file(path, &jpg, &jpg_size); + if (err != ESP_OK) return err; + + if (ft_jpg_read_sof(jpg, jpg_size, &sof_marker, &sof_w, &sof_h)) + { + if (sof_marker == 0xC2) + { + if (!quiet) + { + printf("E: progressive JPEG is not supported by esp_new_jpeg: '%s' (%ux%u, SOF2)\r\n", + path, (unsigned)sof_w, (unsigned)sof_h); + } + free(jpg); + return ESP_ERR_NOT_SUPPORTED; + } + + if (sof_marker != 0xC0) + { + if (!quiet) + { + printf("E: unsupported JPEG SOF marker 0x%02X: '%s' (%ux%u)\r\n", + (unsigned)sof_marker, path, (unsigned)sof_w, (unsigned)sof_h); + } + free(jpg); + return ESP_ERR_NOT_SUPPORTED; + } + } + + cfg.output_type = JPEG_PIXEL_FORMAT_RGB888; + cfg.rotate = JPEG_ROTATE_0D; + + jerr = jpeg_dec_open(&cfg, &dec); + if (jerr != JPEG_ERR_OK) + { + if (!quiet) + printf("E: jpeg_dec_open failed for '%s': %d\r\n", path, (int)jerr); + free(jpg); + return jerr == JPEG_ERR_NO_MEM ? ESP_ERR_NO_MEM : ESP_FAIL; + } + + io = (jpeg_dec_io_t*)calloc(1, sizeof(jpeg_dec_io_t)); + info = (jpeg_dec_header_info_t*)calloc(1, sizeof(jpeg_dec_header_info_t)); + if (!io || !info) + { + if (!quiet) + printf("E: JPEG decoder helper alloc failed\r\n"); + err = ESP_ERR_NO_MEM; + goto done; + } + + io->inbuf = jpg; + io->inbuf_len = (int)jpg_size; + + jerr = jpeg_dec_parse_header(dec, io, info); + if (jerr != JPEG_ERR_OK) + { + if (!quiet) + printf("E: JPEG header parse failed for '%s': %d\r\n", path, (int)jerr); + err = jerr == JPEG_ERR_NO_MEM ? ESP_ERR_NO_MEM : ESP_FAIL; + goto done; + } + + if (info->width == 0 || info->height == 0) + { + if (!quiet) + { + printf("E: bad JPEG info for '%s': %ux%u\r\n", + path, (unsigned)info->width, (unsigned)info->height); + } + err = ESP_FAIL; + goto done; + } + + jerr = jpeg_dec_get_outbuf_len(dec, &output_len); + if (jerr != JPEG_ERR_OK || output_len <= 0) + { + if (!quiet) + { + printf("E: JPEG outbuf len failed for '%s': %d len=%d\r\n", + path, (int)jerr, output_len); + } + err = jerr == JPEG_ERR_NO_MEM ? ESP_ERR_NO_MEM : ESP_FAIL; + goto done; + } + + decoded = (u8*)jpeg_calloc_align((size_t)output_len, 16); + if (!decoded) + { + if (!quiet) + { + printf("E: JPEG output alloc failed: %ux%u, size=%d\r\n", + (unsigned)info->width, (unsigned)info->height, output_len); + } + err = ESP_ERR_NO_MEM; + goto done; + } + + io->outbuf = decoded; + + jerr = jpeg_dec_process(dec, io); + if (jerr != JPEG_ERR_OK) + { + if (!quiet) + printf("E: JPEG decode failed for '%s': %d\r\n", path, (int)jerr); + err = jerr == JPEG_ERR_NO_MEM ? ESP_ERR_NO_MEM : ESP_FAIL; + goto done; + } + + ft_jpg_copy_to_screen(screen, decoded, info->width, info->height); + + if (out_w) *out_w = info->width; + if (out_h) *out_h = info->height; + + err = ESP_OK; + +done: + if (dec) jpeg_dec_close(dec); + if (decoded) jpeg_free_align(decoded); + if (info) free(info); + if (io) free(io); + if (jpg) free(jpg); + return err; +} + +u16 ft_dxp_read_le16(const u8 *p) +{ + return (u16)p[0] | ((u16)p[1] << 8); +} + +esp_err_t ft_dxp_parse_header(const u8 *data, size_t size, FT_DXP_INFO *info, bool quiet) +{ + u32 color_size; + u32 mask_stride; + u32 mask_size; + + if (!data || !info) return ESP_ERR_INVALID_ARG; + if (size < FT_DXP_HEADER_SIZE) return ESP_ERR_INVALID_SIZE; + if (data[0] != 'D' || data[1] != 'X' || data[2] != 'P') return ESP_ERR_INVALID_RESPONSE; + + memset(info, 0, sizeof(*info)); + info->type = data[3]; + info->w = ft_dxp_read_le16(&data[4]); + info->h = ft_dxp_read_le16(&data[6]); + + if (info->w == 0 || info->h == 0) return ESP_ERR_INVALID_SIZE; + if ((info->w & 3) || (info->h & 3)) return ESP_ERR_INVALID_SIZE; + + switch (info->type) + { + case FT_DXP_TYPE_RAW_L2: + case FT_DXP_TYPE_ZLIB_L2: + info->mask_format = FT_L2; + mask_stride = (u32)info->w >> 2; + break; + + case FT_DXP_TYPE_ZLIB_L4: + case FT_DXP_TYPE_RAW_L4: + info->mask_format = FT_L4; + mask_stride = (u32)info->w >> 1; + break; + + default: + if (!quiet) + printf("E: unsupported DXP type %u\r\n", (unsigned)info->type); + return ESP_ERR_NOT_SUPPORTED; + } + + color_size = ((u32)info->w >> 2) * ((u32)info->h >> 2) * 2UL; + mask_size = mask_stride * (u32)info->h; + info->raw_size = color_size + color_size + mask_size; + + if (info->raw_size == 0 || info->raw_size > FT_DXP_RAM_G_SIZE) return ESP_ERR_INVALID_SIZE; + return ESP_OK; +} + +bool ft_dxp_type_is_raw(u8 type) +{ + return type == FT_DXP_TYPE_RAW_L2 || type == FT_DXP_TYPE_RAW_L4; +} + +esp_err_t ft_dxp_inflate_zlib(const u8 *src, size_t src_size, u8 *dst, size_t dst_size, bool quiet) +{ + tinfl_decompressor *decomp; + size_t inbytes; + size_t outbytes; + tinfl_status decomp_status; + esp_err_t err = ESP_OK; + + if (!src || !dst) return ESP_ERR_INVALID_ARG; + if (!src_size || !dst_size) return ESP_ERR_INVALID_SIZE; + + decomp = (tinfl_decompressor*)heap_caps_malloc( + sizeof(tinfl_decompressor), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!decomp) return ESP_ERR_NO_MEM; + + inbytes = src_size; + outbytes = dst_size; + + tinfl_init(decomp); + + decomp_status = tinfl_decompress( + decomp, + src, + &inbytes, + dst, + dst, + &outbytes, + TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + +#ifdef VERBOSE + printf("DXP inflate status=%d, inbytes=%u, outbytes=%u\r\n", + (int)decomp_status, + (unsigned)inbytes, + (unsigned)outbytes); +#endif + + if (decomp_status != TINFL_STATUS_DONE || outbytes != dst_size) + { + if (!quiet) + { + printf("E: DXP inflate failed: status=%d in=%u/%u out=%u/%u\r\n", + (int)decomp_status, + (unsigned)inbytes, + (unsigned)src_size, + (unsigned)outbytes, + (unsigned)dst_size); + } + err = ESP_FAIL; + } + + free(decomp); + return err; +} + +esp_err_t ft_dxp_prepare_raw(const u8 *data, size_t size, const FT_DXP_INFO *info, + const u8 **out_raw, u8 **out_alloc, bool quiet) +{ + const u8 *payload; + size_t payload_size; + esp_err_t err; + + if (!data || !info || !out_raw || !out_alloc) return ESP_ERR_INVALID_ARG; + if (size < FT_DXP_HEADER_SIZE) return ESP_ERR_INVALID_SIZE; + + *out_raw = nullptr; + *out_alloc = nullptr; + payload = data + FT_DXP_HEADER_SIZE; + payload_size = size - FT_DXP_HEADER_SIZE; + + if (ft_dxp_type_is_raw(info->type)) + { + if (payload_size < info->raw_size) return ESP_ERR_INVALID_SIZE; + *out_raw = payload; + return ESP_OK; + } + + u8 *raw = (u8*)heap_caps_malloc(info->raw_size, MALLOC_CAP_SPIRAM); + if (!raw) return ESP_ERR_NO_MEM; + + err = ft_dxp_inflate_zlib(payload, payload_size, raw, info->raw_size, quiet); + if (err != ESP_OK) + { + free(raw); + return err; + } + + *out_raw = raw; + *out_alloc = raw; + return ESP_OK; +} + +void ft_dxp_dl(const FT_DXP_INFO *info, u16 x, u16 y) +{ + u32 mask_addr; + + if (!info) return; + + mask_addr = FT_RAM_G + ((u32)info->w * ((u32)info->h >> 2)); + + ft_BitmapHandle(0); + ft_SetBitmap(mask_addr, info->mask_format, info->w, info->h); + ft_BitmapHandle(1); + ft_SetBitmap(FT_RAM_G, FT_RGB565, info->w >> 2, info->h >> 2); + ft_BitmapSize(FT_NEAREST, FT_BORDER, FT_BORDER, info->w, info->h); + + ft_Begin(FT_BITMAPS); + ft_ColorA(255); + ft_BlendFunc(FT_ONE, FT_ZERO); + ft_Vertex2ii(x, y, 0, 0); + + ft_ColorMask(1, 1, 1, 0); + ft_BitmapTransformA(64); + ft_BitmapTransformE(64); + ft_BlendFunc(FT_ONE_MINUS_DST_ALPHA, FT_ZERO); + ft_Vertex2ii(x, y, 1, 0); + ft_BlendFunc(FT_DST_ALPHA, FT_ONE); + ft_Vertex2ii(x, y, 1, 1); +} + +esp_err_t ft_dxp_show_mode(const FT_DXP_INFO *info) +{ + esp_err_t err; + u16 screen_w = 1024; + u16 screen_h = 768; + u16 x = 0; + u16 y = 0; + + if (!info) return ESP_ERR_INVALID_ARG; + + if (ft_current_mode >= 0 && ft_current_mode < FT_MODE_MAX) + { + screen_w = ft_modes[ft_current_mode].h_visible; + screen_h = ft_modes[ft_current_mode].v_visible; + } + + if (screen_w > info->w) + x = (u16)((screen_w - info->w) >> 1); + + if (screen_h > info->h) + y = (u16)((screen_h - info->h) >> 1); + + ft_ccmd_start(cmdl); + ft_Dlstart(); + ft_ClearColorRGB(0, 0, 0); + ft_ClearColorA(255); + ft_Clear(1, 1, 1); + + ft_dxp_dl(info, x, y); + + ft_Display(); + ft_Swap(); + + err = ft_ccmd_write(); + if (err != ESP_OK) return err; + + err = ft_cp_wait(1000); + if (err != ESP_OK) return err; + + return ft_wait_swap(1000); +} + +esp_err_t ft_dxp_show_file_mode(const char *path, bool quiet) +{ + u8 *data = nullptr; + size_t size = 0; + const u8 *raw = nullptr; + u8 *raw_alloc = nullptr; + FT_DXP_INFO info; + esp_err_t err; + esp_err_t err2; + bool keep_session = false; + + if (!path) return ESP_ERR_INVALID_ARG; + + int64_t t0 = esp_timer_get_time(); + err = ft_jpg_read_whole_file(path, &data, &size); + if (err != ESP_OK) return err; + + err = ft_dxp_parse_header(data, size, &info, quiet); + if (err != ESP_OK) goto done_no_session; + + err = ft_dxp_prepare_raw(data, size, &info, &raw, &raw_alloc, quiet); + if (err != ESP_OK) goto done_no_session; + + keep_session = ft_text_attr_mode_open; + + err = ft_open_session(); + if (err != ESP_OK) + { + if (!quiet) + printf("FT open failed: %d\r\n", (int)err); + goto done_no_session; + } + + err = ft_dxp_show_mode(&info); + if (err == ESP_OK) + { + err = ft_write(raw, FT_RAM_G, info.raw_size); + if (err == ESP_OK) ft_text_attr_mode_palette_dirty = true; + } + + if (!keep_session) + { + err2 = ft_close_session(); + if (err == ESP_OK) err = err2; + } + + if (err == ESP_OK && !quiet) + { + int64_t t1 = esp_timer_get_time(); + printf("DXP: %s %ux%u type=%u raw=%lu load=%lldus\r\n", + path, (unsigned)info.w, (unsigned)info.h, (unsigned)info.type, + (unsigned long)info.raw_size, (long long)(t1 - t0)); + } + +done_no_session: + if (raw_alloc) free(raw_alloc); + if (data) free(data); + return err; +} + +esp_err_t ft_dxp_show_file(const char *path) +{ + return ft_dxp_show_file_mode(path, false); +} + +esp_err_t ft_jpg_show_file_mode(const char *path, bool stretch, bool quiet) +{ + esp_err_t err; + esp_err_t err2; + u16 img_w = 0; + u16 img_h = 0; + + u8 *screen = (u8*)heap_caps_malloc(FT_RGB888_640_480_SIZE, MALLOC_CAP_SPIRAM); + if (!screen) + { + if (!quiet) + printf("E: RGB888 screen alloc failed, size=%lu\r\n", (unsigned long)FT_RGB888_640_480_SIZE); + return ESP_ERR_NO_MEM; + } + + int64_t t0 = esp_timer_get_time(); + err = ft_jpg_decode_to_screen(path, screen, &img_w, &img_h, quiet); + int64_t t1 = esp_timer_get_time(); + if (err != ESP_OK) + { + free(screen); + return err; + } + + bool keep_session = ft_text_attr_mode_open; + + err = ft_open_session(); + if (err != ESP_OK) + { + if (!quiet) + printf("FT open failed: %d\r\n", (int)err); + free(screen); + return err; + } + + err = ft_rgb888_640x480_show_mode(FT_RGB888_640_480_ADDR, stretch); + if (err == ESP_OK) + { + err = ft_write(screen, FT_RGB888_640_480_ADDR, FT_RGB888_640_480_SIZE); + if (err == ESP_OK) ft_text_attr_mode_palette_dirty = true; + } + + if (!keep_session) + { + err2 = ft_close_session(); + if (err == ESP_OK) + err = err2; + } + + free(screen); + + if (err != ESP_OK) + return err; + + if (!quiet) + { + printf("JPEG: %s %ux%u -> 640x480 decode=%lldus\r\n", + path, (unsigned)img_w, (unsigned)img_h, (long long)(t1 - t0)); + } + + return ESP_OK; +} + +esp_err_t ft_jpg_show_file(const char *path) +{ + return ft_jpg_show_file_mode(path, false, false); +} + +int ft_jpg_wait_key() +{ + u8 c; + + if (uart_read_bytes(UART_NUM_0, &c, 1, portMAX_DELAY) <= 0) + return FT_JPG_KEY_EXIT; + + if (c != 0x1B) + return FT_JPG_KEY_EXIT; + + u8 seq[2] = {}; + if (uart_read_bytes(UART_NUM_0, &seq[0], 1, pdMS_TO_TICKS(50)) <= 0) + return FT_JPG_KEY_EXIT; + + if (seq[0] != '[') + return FT_JPG_KEY_EXIT; + + if (uart_read_bytes(UART_NUM_0, &seq[1], 1, pdMS_TO_TICKS(50)) <= 0) + return FT_JPG_KEY_EXIT; + + if (seq[1] == 'C') return FT_JPG_KEY_NEXT; + if (seq[1] == 'D') return FT_JPG_KEY_PREV; + + return FT_JPG_KEY_EXIT; +} + +int ft_dxp_cmd(int argc, char **argv) +{ + if (argc != 3) + { + printf("Usage:\r\n"); + printf(" ft dxp \r\n"); + return 1; + } + + esp_err_t err = ft_dxp_show_file(argv[2]); + if (err != ESP_OK) + { + printf("E: DXP show failed: %s (0x%x)\r\n", esp_err_to_name(err), (unsigned int)err); + return 1; + } + + return 0; +} + +int ft_jpg_cmd(int argc, char **argv) +{ + if (argc != 3) + { + printf("Usage:\r\n"); + printf(" ft jpg \r\n"); + return 1; + } + + FT_JPG_LIST lst = {}; + esp_err_t err = ft_jpg_collect(argv[2], &lst); + if (err != ESP_OK) + { + ft_jpg_list_free(&lst); + return 1; + } + + if (lst.count <= 0) + { + printf("No JPEG files found: %s\r\n", argv[2]); + ft_jpg_list_free(&lst); + return 1; + } + + printf("JPEG files: %d\r\n", lst.count); + printf("Controls: Right=next, Left=prev, other key=exit\r\n"); + + int idx = 0; + for (;;) + { + printf("[%d/%d] %s\r\n", idx + 1, lst.count, lst.items[idx]); + + err = ft_jpg_show_file(lst.items[idx]); + if (err != ESP_OK) + printf("E: show failed: %s\r\n", esp_err_to_name(err)); + + int key = ft_jpg_wait_key(); + if (key == FT_JPG_KEY_NEXT) + { + idx++; + if (idx >= lst.count) idx = 0; + continue; + } + + if (key == FT_JPG_KEY_PREV) + { + idx--; + if (idx < 0) idx = lst.count - 1; + continue; + } + + break; + } + + ft_jpg_list_free(&lst); + return 0; +} + +void ft_rgb888_640x480_dl(u32 rgb_addr, u16 screen_x, u16 screen_y, u16 draw_w, u16 draw_h, u8 filter) +{ + i32 scale_x; + i32 scale_y; + + if (draw_w == 0) draw_w = FT_RGB888_640_480_W; + if (draw_h == 0) draw_h = FT_RGB888_640_480_H; + + scale_x = (i32)(((u32)FT_RGB888_640_480_W * 256U + ((u32)draw_w / 2U)) / draw_w); + scale_y = (i32)(((u32)FT_RGB888_640_480_H * 256U + ((u32)draw_h / 2U)) / draw_h); + + ft_SaveContext(); + + ft_BitmapHandle(0); + ft_BitmapLayout(FT_L8, (u16)FT_RGB888_640_480_STRIDE, FT_RGB888_640_480_H); + ft_BitmapSize(filter, FT_BORDER, FT_BORDER, draw_w, draw_h); + + ft_BitmapTransformA(scale_x); + ft_BitmapTransformB(0); + ft_BitmapTransformC(0); + ft_BitmapTransformD(0); + ft_BitmapTransformE(scale_y); + ft_BitmapTransformF(0); + + ft_BlendFunc(FT_SRC_ALPHA, FT_ONE); + ft_ColorA(255); + ft_ColorMask(1, 1, 1, 0); + ft_Begin(FT_BITMAPS); + + ft_ColorRGB(255, 0, 0); + ft_BitmapSource(rgb_addr); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_ColorRGB(0, 255, 0); + ft_BitmapSource(rgb_addr + FT_RGB888_640_480_PLANE_SIZE); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_ColorRGB(0, 0, 255); + ft_BitmapSource(rgb_addr + (FT_RGB888_640_480_PLANE_SIZE * 2UL)); + ft_Vertex2ii(screen_x, screen_y, 0, 0); + + ft_End(); + + ft_RestoreContext(); +} + +esp_err_t ft_rgb888_640x480_load_mode(u32 rgb_addr, bool stretch, bool swap) +{ + esp_err_t err; + u16 screen_x = 0; + u16 screen_y = 0; + u16 screen_w = FT_RGB888_640_480_W; + u16 screen_h = FT_RGB888_640_480_H; + u16 draw_w = FT_RGB888_640_480_W; + u16 draw_h = FT_RGB888_640_480_H; + u8 filter = FT_NEAREST; + + if (ft_current_mode >= 0 && ft_current_mode < FT_MODE_MAX) + { + screen_w = ft_modes[ft_current_mode].h_visible; + screen_h = ft_modes[ft_current_mode].v_visible; + } + + if (stretch) + { + draw_w = screen_w; + draw_h = screen_h; + filter = FT_BILINEAR; + } + else + { + if (screen_w > FT_RGB888_640_480_W) + screen_x = (u16)((screen_w - FT_RGB888_640_480_W) / 2); + + if (screen_h > FT_RGB888_640_480_H) + screen_y = (u16)((screen_h - FT_RGB888_640_480_H) / 2); + } + + ft_ccmd_start(cmdl); + + ft_Dlstart(); + ft_ClearColorRGB(0, 0, 0); + ft_ClearColorA(255); + ft_Clear(1, 1, 1); + + ft_rgb888_640x480_dl(rgb_addr, screen_x, screen_y, draw_w, draw_h, filter); + + ft_Display(); + if (swap) ft_Swap(); + + err = ft_ccmd_write(); + if (err != ESP_OK) return err; + + err = ft_cp_wait(1000); + if (err != ESP_OK) return err; + + if (!swap) return ESP_OK; + + return ft_wait_swap(1000); +} + +esp_err_t ft_rgb888_640x480_show_mode(u32 rgb_addr, bool stretch) +{ + return ft_rgb888_640x480_load_mode(rgb_addr, stretch, true); +} + +esp_err_t ft_rgb888_640x480_show(u32 rgb_addr) +{ + return ft_rgb888_640x480_show_mode(rgb_addr, false); +} + +esp_err_t ft_rgb888_640x480_show_current(bool stretch) +{ + esp_err_t err; + esp_err_t err2; + bool keep_session = ft_text_attr_mode_open; + + err = ft_open_session(); + if (err != ESP_OK) return err; + + err = ft_rgb888_640x480_show_mode(FT_RGB888_640_480_ADDR, stretch); + + if (!keep_session) + { + err2 = ft_close_session(); + if (err == ESP_OK) err = err2; + } + + return err; +} + +int ft_demo_rgb888_cmd() +{ + esp_err_t err; + esp_err_t err2; + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + err = ft_rgb888_640x480_show_mode(FT_RGB888_640_480_ADDR, false); + + err2 = ft_close_session(); + if (err == ESP_OK) + err = err2; + + if (err != ESP_OK) + { + printf("FT demo RGB888 failed: %d\r\n", (int)err); + return 1; + } + + printf("FT RGB888 640x480 shown from 0x%06lX, size=%lu\r\n", + (unsigned long)FT_RGB888_640_480_ADDR, + (unsigned long)FT_RGB888_640_480_SIZE); + + return 0; +} + +int ft_demo_attr_mode_cmd() +{ + esp_err_t err; + esp_err_t err2; + u8 *chars = nullptr; + u8 *attrs = nullptr; + u8 *gfx = nullptr; + u8 *color = nullptr; + u32 text_cells = (u32)FT_DEMO_TEXT_COLS * (u32)FT_DEMO_TEXT_ROWS; + u32 gfx_size = (u32)FT_DEMO_TEXT_COLS * 256U; + u32 color_size = (u32)FT_DEMO_TEXT_ROWS * 256U; + + chars = (u8*)heap_caps_malloc(text_cells, MALLOC_CAP_SPIRAM); + attrs = (u8*)heap_caps_malloc(text_cells, MALLOC_CAP_SPIRAM); + gfx = (u8*)heap_caps_malloc(gfx_size, MALLOC_CAP_SPIRAM); + color = (u8*)heap_caps_malloc(color_size, MALLOC_CAP_SPIRAM); + + if (!chars || !attrs || !gfx || !color) + { + printf("FT demo_attr_mode alloc failed: chars=%u attrs=%u gfx=%lu color=%lu\r\n", + (unsigned int)text_cells, + (unsigned int)text_cells, + (unsigned long)gfx_size, + (unsigned long)color_size); + if (chars) free(chars); + if (attrs) free(attrs); + if (gfx) free(gfx); + if (color) free(color); + return 1; + } + + ft_text_set_addrs(chars, attrs); + ft_demo_text_fill("Attribute mode text demo", "80x30 chars -> FT812 640x480"); + ft_text_to_attr_render(gfx, chars, color, attrs); + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + free(chars); + free(attrs); + free(gfx); + free(color); + return 1; + } + + if (err == ESP_OK) + err = ft_write(gfx, FT_DEMO_PIX_ADDR(0), gfx_size); + + if (err == ESP_OK) + err = ft_write(color, FT_DEMO_ATTR_ADDR, color_size); + + if (err == ESP_OK) + err = ft_text_palette_init(); + + if (err == ESP_OK) + { + ft_rreg8(FT_REG_INT_FLAGS); + err = ft_attr_show(); + } + + if (err == ESP_OK) + err = ft_wait_swap(1000); + + err2 = ft_close_session(); + if (err == ESP_OK) + err = err2; + + free(chars); + free(attrs); + free(gfx); + free(color); + + if (err != ESP_OK) + { + printf("FT demo_attr_mode failed: %d\r\n", (int)err); + return 1; + } + + return 0; +} + +int ft_demo_4bpp_mode_cmd() +{ + esp_err_t err; + esp_err_t err2; + u8 *chars = nullptr; + u8 *attrs = nullptr; + u8 *bitmap = nullptr; + + u32 text_cells = (u32)FT_DEMO_TEXT_COLS * (u32)FT_DEMO_TEXT_ROWS; + u32 bitmap_size = ((u32)FT_DEMO_TEXT_COLS * 4U) * ((u32)FT_DEMO_TEXT_ROWS * 8U); + + chars = (u8*)heap_caps_malloc(text_cells, MALLOC_CAP_SPIRAM); + attrs = (u8*)heap_caps_malloc(text_cells, MALLOC_CAP_SPIRAM); + bitmap = (u8*)heap_caps_malloc(bitmap_size, MALLOC_CAP_SPIRAM); + + if (!chars || !attrs || !bitmap) + { + printf("FT demo_4bpp_mode alloc failed: chars=%u attrs=%u bitmap=%lu\r\n", + (unsigned int)text_cells, + (unsigned int)text_cells, + (unsigned long)bitmap_size); + if (chars) free(chars); + if (attrs) free(attrs); + if (bitmap) free(bitmap); + return 1; + } + + ft_text_set_addrs(chars, attrs); + ft_demo_text_fill("4bpp paletted text demo", "80x30 chars -> FT812 640x480"); + ft_text_to_4bpp_render(bitmap, chars, attrs); + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + free(chars); + free(attrs); + free(bitmap); + return 1; + } + + if (err == ESP_OK) + err = ft_write(bitmap, FT_DEMO_PAL4_PIX_ADDR, bitmap_size); + + if (err == ESP_OK) + err = ft_text_palette_init(); + + if (err == ESP_OK) + { + ft_rreg8(FT_REG_INT_FLAGS); + err = ft_4bpp_show(); + } + + if (err == ESP_OK) + err = ft_wait_swap(1000); + + err2 = ft_close_session(); + if (err == ESP_OK) + err = err2; + + free(chars); + free(attrs); + free(bitmap); + + if (err != ESP_OK) + { + printf("FT demo_4bpp_mode failed: %d\r\n", (int)err); + return 1; + } + + return 0; +} + +u8 ft_zx_color_from_attr(u8 attr, u8 paper) +{ + u8 color; + u8 bright; + + attr &= 0x7FU; + bright = (attr & 0x40U) ? 8U : 0U; + + if (paper) + color = (u8)((attr >> 3) & 7U); + else + color = (u8)(attr & 7U); + + if (color) + color |= bright; + + return color; +} + +esp_err_t ft_zx_palette_init() +{ + esp_err_t err; + u16 pal_paper[256]; + u16 pal_ink[256]; + + for (u32 attr = 0; attr < 256; attr++) + { + pal_paper[attr] = ft_attr_to_rgb565(ft_zx_color_from_attr((u8)attr, 1)); + pal_ink[attr] = ft_attr_to_rgb565(ft_zx_color_from_attr((u8)attr, 0)); + } + + err = ft_write(pal_paper, FT_DEMO_ZX_PAL_PAPER_ADDR, sizeof(pal_paper)); + if (err != ESP_OK) return err; + + err = ft_write(pal_ink, FT_DEMO_ZX_PAL_INK_ADDR, sizeof(pal_ink)); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +esp_err_t ft_zx_show(u8 scale = 2) +{ + esp_err_t err; + u16 screen_x = FT_DEMO_ZX_SCREEN_X; + u16 screen_y = FT_DEMO_ZX_SCREEN_Y; + + ft_ccmd_start(cmdl); + + ft_Dlstart(); + + ft_ClearColorRGB(0, 0, 32); + ft_ClearColorA(255); + ft_ClearStencil(0); + ft_Clear(1, 1, 1); + + for (int h = 0; h < 8; h++) + { + ft_BitmapHandle(h); + ft_BitmapSource(FT_DEMO_ZX_PIX_ADDR + h * 32); + ft_BitmapLayout(FT_L1, 256, 8); + ft_BitmapSize(FT_NEAREST, FT_BORDER, FT_BORDER, 256 * scale, 8 * scale); + } + + ft_BitmapHandle(8); + ft_BitmapSource(FT_DEMO_ZX_ATTR_ADDR); + ft_BitmapLayout(FT_PALETTED565, 32, 24); + ft_BitmapSize(FT_NEAREST, FT_BORDER, FT_BORDER, 256 * scale, 192 * scale); + + ft_BitmapTransformB(0); + ft_BitmapTransformC(0); + ft_BitmapTransformD(0); + ft_BitmapTransformF(0); + + ft_BitmapTransformA(256 / scale); + ft_BitmapTransformE(256 / scale); + + ft_ColorMask(0, 0, 0, 0); + ft_StencilMask(255); + ft_AlphaFunc(FT_GREATER, 0); + ft_StencilFunc(FT_ALWAYS, 1, 255); + ft_StencilOp(FT_KEEP, FT_REPLACE); + + ft_Begin(FT_BITMAPS); + + ft_VertexTranslateX((i32)screen_x * 16); + ft_VertexTranslateY((i32)screen_y * 16); + + for (u8 bank = 0; bank < 3; bank++) + for (u8 row = 0; row < 8; row++) + ft_Vertex2ii(0, (bank * 64 + row * 8) * scale, row, bank); + + ft_ColorMask(1, 1, 1, 0); + ft_StencilMask(0); + ft_AlphaFunc(FT_ALWAYS, 0); + ft_BlendFunc(FT_ONE, FT_ZERO); + + ft_BitmapTransformA(32 / scale); + ft_BitmapTransformE(32 / scale); + + ft_StencilFunc(FT_EQUAL, 0, 255); + ft_PaletteSource(FT_DEMO_ZX_PAL_PAPER_ADDR); + ft_Vertex2ii(0, 0, 8, 0); + + ft_StencilFunc(FT_EQUAL, 1, 255); + ft_PaletteSource(FT_DEMO_ZX_PAL_INK_ADDR); + ft_Vertex2ii(0, 0, 8, 0); + + ft_Display(); + ft_Swap(); + + err = ft_ccmd_write(); + if (err != ESP_OK) return err; + + err = ft_cp_wait(1000); + if (err != ESP_OK) return err; + + return ESP_OK; +} + +int ft_demo_zx_mode_cmd() +{ + esp_err_t err; + esp_err_t err2; + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + err = ft_write(zx_screen, FT_DEMO_ZX_PIX_ADDR, 6912); + + if (err == ESP_OK) + err = ft_zx_palette_init(); + + if (err == ESP_OK) + { + ft_rreg8(FT_REG_INT_FLAGS); + err = ft_zx_show(); + } + + if (err == ESP_OK) + err = ft_wait_swap(1000); + + err2 = ft_close_session(); + if (err == ESP_OK) + err = err2; + + if (err != ESP_OK) + { + printf("FT demo_zx_mode failed: %d\r\n", (int)err); + return 1; + } + + return 0; +} + +// -------- Display list decoder --------- + +#define FT_DL_READ_SIZE FT_DL_SIZE +#define FT_DL_DEFAULT_VERTEX_FORMAT 4 +#define FT_DL_CONTEXT_STACK_SIZE 4 + +u32 ft_rd32le(const u8 *p) +{ + return (u32)p[0] | ((u32)p[1] << 8) | ((u32)p[2] << 16) | ((u32)p[3] << 24); +} + +i32 ft_dl_sx(u32 v, u8 bits) +{ + u32 m = 1UL << (bits - 1); + return (i32)((v ^ m) - m); +} + + +typedef struct +{ + u8 vertex_format; + u8 stack[FT_DL_CONTEXT_STACK_SIZE]; + u8 stack_depth; +} FT_DL_DECODE_CONTEXT; + +void ft_dl_context_init(FT_DL_DECODE_CONTEXT *ctx) +{ + ctx->vertex_format = FT_DL_DEFAULT_VERTEX_FORMAT; + ctx->stack_depth = 0; +} + +void ft_dl_context_save(FT_DL_DECODE_CONTEXT *ctx) +{ + if (ctx->stack_depth < FT_DL_CONTEXT_STACK_SIZE) + { + ctx->stack[ctx->stack_depth++] = ctx->vertex_format; + return; + } + + for (u32 i = 1; i < FT_DL_CONTEXT_STACK_SIZE; i++) + ctx->stack[i - 1] = ctx->stack[i]; + + ctx->stack[FT_DL_CONTEXT_STACK_SIZE - 1] = ctx->vertex_format; +} + +void ft_dl_context_restore(FT_DL_DECODE_CONTEXT *ctx) +{ + if (ctx->stack_depth) + { + ctx->vertex_format = ctx->stack[--ctx->stack_depth]; + return; + } + + ctx->vertex_format = FT_DL_DEFAULT_VERTEX_FORMAT; +} + +void ft_dl_print_fixed(i32 v, u8 frac) +{ + u32 uv; + u32 ip; + u32 rem; + u32 den; + u32 dec; + char dec_txt[16]; + int n; + + if (frac > 4) + frac = 4; + + if (v < 0) + { + printf("-"); + uv = (u32)(-(v + 1)) + 1UL; + } + else + { + uv = (u32)v; + } + + den = 1UL << frac; + ip = uv >> frac; + rem = uv & (den - 1); + + printf("%lu", (unsigned long)ip); + + if (!frac || !rem) + return; + + dec = (rem * 10000UL) / den; + snprintf(dec_txt, sizeof(dec_txt), "%04lu", (unsigned long)dec); + + n = 3; + while (n > 0 && dec_txt[n] == '0') + dec_txt[n--] = 0; + + printf(".%s", dec_txt); +} + +void ft_dl_print_fixed_cmd_1(u32 line, const char *name, i32 v, u8 frac) +{ + printf("%04lX %s(", (unsigned long)line, name); + ft_dl_print_fixed(v, frac); + printf(")\r\n"); +} + +const char *ft_dl_format_name(u32 v) +{ + switch (v) + { + case FT_ARGB1555: return "ARGB1555"; + case FT_L1: return "L1"; + case FT_L4: return "L4"; + case FT_L8: return "L8"; + case FT_RGB332: return "RGB332"; + case FT_ARGB2: return "ARGB2"; + case FT_ARGB4: return "ARGB4"; + case FT_RGB565: return "RGB565"; + case FT_TEXT8X8: return "TEXT8X8"; + case FT_TEXTVGA: return "TEXTVGA"; + case FT_BARGRAPH: return "BARGRAPH"; + case FT_PALETTED565: return "PALETTED565"; + case FT_PALETTED4444: return "PALETTED4444"; + case FT_PALETTED8: return "PALETTED8"; + case FT_L2: return "L2"; + default: return "?"; + } +} + +const char *ft_dl_blend_name(u32 v) +{ + switch (v) + { + case FT_ZERO: return "ZERO"; + case FT_ONE: return "ONE"; + case FT_SRC_ALPHA: return "SRC_ALPHA"; + case FT_DST_ALPHA: return "DST_ALPHA"; + case FT_ONE_MINUS_SRC_ALPHA: return "ONE_MINUS_SRC_ALPHA"; + case FT_ONE_MINUS_DST_ALPHA: return "ONE_MINUS_DST_ALPHA"; + default: return "?"; + } +} + +const char *ft_dl_test_name(u32 v) +{ + switch (v) + { + case FT_NEVER: return "NEVER"; + case FT_LESS: return "LESS"; + case FT_LEQUAL: return "LEQUAL"; + case FT_GREATER: return "GREATER"; + case FT_GEQUAL: return "GEQUAL"; + case FT_EQUAL: return "EQUAL"; + case FT_NOTEQUAL: return "NOTEQUAL"; + case FT_ALWAYS: return "ALWAYS"; + default: return "?"; + } +} + +const char *ft_dl_stencil_op_name(u32 v) +{ + switch (v) + { + case 0: return "ZERO"; + case FT_KEEP: return "KEEP"; + case FT_REPLACE: return "REPLACE"; + case FT_INCR: return "INCR"; + case FT_DECR: return "DECR"; + case FT_INVERT: return "INVERT"; + case FT_INCR_WRAP: return "INCR_WRAP"; + case FT_DECR_WRAP: return "DECR_WRAP"; + default: return "?"; + } +} + +const char *ft_dl_filter_name(u32 v) +{ + switch (v) + { + case FT_NEAREST: return "NEAREST"; + case FT_BILINEAR: return "BILINEAR"; + default: return "?"; + } +} + +const char *ft_dl_wrap_name(u32 v) +{ + switch (v) + { + case FT_BORDER: return "BORDER"; + case FT_REPEAT: return "REPEAT"; + default: return "?"; + } +} + +const char *ft_dl_prim_name(u32 v) +{ + switch (v) + { + case FT_BITMAPS: return "BITMAPS"; + case FT_POINTS: return "POINTS"; + case FT_LINES: return "LINES"; + case FT_LINE_STRIP: return "LINE_STRIP"; + case FT_EDGE_STRIP_R: return "EDGE_STRIP_R"; + case FT_EDGE_STRIP_L: return "EDGE_STRIP_L"; + case FT_EDGE_STRIP_A: return "EDGE_STRIP_A"; + case FT_EDGE_STRIP_B: return "EDGE_STRIP_B"; + case FT_RECTS: return "RECTS"; + default: return "?"; + } +} + +void ft_dl_print_num_or_name(const char *name, u32 v) +{ + if (name && strcmp(name, "?")) + printf("%s", name); + else + printf("%lu", (unsigned long)v); +} + +void ft_dl_print_bitmap_layout(u32 line, u32 w, u32 hi, int has_hi) +{ + u32 format = (w >> 19) & 31UL; + u32 stride = (w >> 9) & 1023UL; + u32 height = w & 511UL; + + if (has_hi) + { + stride |= (hi & 12UL) << 8; + height |= (hi & 3UL) << 9; + } + + printf("%04lX BITMAP_LAYOUT(", (unsigned long)line); + ft_dl_print_num_or_name(ft_dl_format_name(format), format); + printf(", %lu, %lu)\r\n", (unsigned long)stride, (unsigned long)height); +} + +void ft_dl_print_bitmap_size(u32 line, u32 w, u32 hi, int has_hi) +{ + u32 fxy = (w >> 18) & 7UL; + u32 filter = (fxy >> 2) & 1UL; + u32 wrapx = (fxy >> 1) & 1UL; + u32 wrapy = fxy & 1UL; + u32 width = (w >> 9) & 511UL; + u32 height = w & 511UL; + + if (has_hi) + { + width |= (hi & 12UL) << 7; + height |= (hi & 3UL) << 9; + } + + printf("%04lX BITMAP_SIZE(", (unsigned long)line); + ft_dl_print_num_or_name(ft_dl_filter_name(filter), filter); + printf(", "); + ft_dl_print_num_or_name(ft_dl_wrap_name(wrapx), wrapx); + printf(", "); + ft_dl_print_num_or_name(ft_dl_wrap_name(wrapy), wrapy); + printf(", %lu, %lu)\r\n", (unsigned long)width, (unsigned long)height); +} + +void ft_dl_print_bitmap_layout_h(u32 line, u32 w) +{ + printf("%04lX BITMAP_LAYOUT_H(%lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w & 12UL) >> 2), + (unsigned long)(w & 3UL)); +} + +void ft_dl_print_bitmap_size_h(u32 line, u32 w) +{ + printf("%04lX BITMAP_SIZE_H(%lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w & 12UL) >> 2), + (unsigned long)(w & 3UL)); +} + +int ft_dl_print_word(FT_DL_DECODE_CONTEXT *ctx, u32 line, u32 w) +{ + u32 op = w >> 24; + u32 v; + + if ((w & 0xC0000000UL) == 0x40000000UL) + { + printf("%04lX VERTEX2F(", (unsigned long)line); + ft_dl_print_fixed(ft_dl_sx((w >> 15) & 32767UL, 15), ctx->vertex_format); + printf(", "); + ft_dl_print_fixed(ft_dl_sx(w & 32767UL, 15), ctx->vertex_format); + printf(")\r\n"); + return 0; + } + + if ((w & 0xC0000000UL) == 0x80000000UL) + { + printf("%04lX VERTEX2II(%lu, %lu, %lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w >> 21) & 511UL), + (unsigned long)((w >> 12) & 511UL), + (unsigned long)((w >> 7) & 31UL), + (unsigned long)(w & 127UL)); + return 0; + } + + switch (op) + { + case 0: + printf("%04lX DISPLAY()\r\n", (unsigned long)line); + return 1; + + case 1: + printf("%04lX BITMAP_SOURCE(0x%06lX)\r\n", (unsigned long)line, (unsigned long)(w & 0x3FFFFFUL)); + return 0; + + case 2: + printf("%04lX CLEAR_COLOR_RGB(%lu, %lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w >> 16) & 255UL), + (unsigned long)((w >> 8) & 255UL), + (unsigned long)(w & 255UL)); + return 0; + + case 3: + printf("%04lX TAG(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 255UL)); + return 0; + + case 4: + printf("%04lX COLOR_RGB(%lu, %lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w >> 16) & 255UL), + (unsigned long)((w >> 8) & 255UL), + (unsigned long)(w & 255UL)); + return 0; + + case 5: + printf("%04lX BITMAP_HANDLE(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 31UL)); + return 0; + + case 6: + printf("%04lX CELL(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 127UL)); + return 0; + + case 7: + ft_dl_print_bitmap_layout(line, w, 0, 0); + return 0; + + case 8: + ft_dl_print_bitmap_size(line, w, 0, 0); + return 0; + + case 9: + printf("%04lX ALPHA_FUNC(", (unsigned long)line); + ft_dl_print_num_or_name(ft_dl_test_name((w >> 8) & 7UL), (w >> 8) & 7UL); + printf(", %lu)\r\n", (unsigned long)(w & 255UL)); + return 0; + + case 10: + printf("%04lX STENCIL_FUNC(", (unsigned long)line); + ft_dl_print_num_or_name(ft_dl_test_name((w >> 16) & 7UL), (w >> 16) & 7UL); + printf(", %lu, %lu)\r\n", (unsigned long)((w >> 8) & 255UL), (unsigned long)(w & 255UL)); + return 0; + + case 11: + printf("%04lX BLEND_FUNC(", (unsigned long)line); + ft_dl_print_num_or_name(ft_dl_blend_name((w >> 3) & 7UL), (w >> 3) & 7UL); + printf(", "); + ft_dl_print_num_or_name(ft_dl_blend_name(w & 7UL), w & 7UL); + printf(")\r\n"); + return 0; + + case 12: + printf("%04lX STENCIL_OP(", (unsigned long)line); + ft_dl_print_num_or_name(ft_dl_stencil_op_name((w >> 3) & 7UL), (w >> 3) & 7UL); + printf(", "); + ft_dl_print_num_or_name(ft_dl_stencil_op_name(w & 7UL), w & 7UL); + printf(")\r\n"); + return 0; + + case 13: + ft_dl_print_fixed_cmd_1(line, "POINT_SIZE", (i32)(w & 8191UL), 4); + return 0; + + case 14: + ft_dl_print_fixed_cmd_1(line, "LINE_WIDTH", (i32)(w & 4095UL), 4); + return 0; + + case 15: + printf("%04lX CLEAR_COLOR_A(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 255UL)); + return 0; + + case 16: + printf("%04lX COLOR_A(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 255UL)); + return 0; + + case 17: + printf("%04lX CLEAR_STENCIL(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 255UL)); + return 0; + + case 18: + printf("%04lX CLEAR_TAG(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 255UL)); + return 0; + + case 19: + printf("%04lX STENCIL_MASK(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 255UL)); + return 0; + + case 20: + printf("%04lX TAG_MASK(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 1UL)); + return 0; + + case 21: + printf("%04lX BITMAP_TRANSFORM_A(%ld)\r\n", (unsigned long)line, (long)ft_dl_sx(w & 131071UL, 17)); + return 0; + + case 22: + printf("%04lX BITMAP_TRANSFORM_B(%ld)\r\n", (unsigned long)line, (long)ft_dl_sx(w & 131071UL, 17)); + return 0; + + case 23: + printf("%04lX BITMAP_TRANSFORM_C(%ld)\r\n", (unsigned long)line, (long)ft_dl_sx(w & 16777215UL, 24)); + return 0; + + case 24: + printf("%04lX BITMAP_TRANSFORM_D(%ld)\r\n", (unsigned long)line, (long)ft_dl_sx(w & 131071UL, 17)); + return 0; + + case 25: + printf("%04lX BITMAP_TRANSFORM_E(%ld)\r\n", (unsigned long)line, (long)ft_dl_sx(w & 131071UL, 17)); + return 0; + + case 26: + printf("%04lX BITMAP_TRANSFORM_F(%ld)\r\n", (unsigned long)line, (long)ft_dl_sx(w & 16777215UL, 24)); + return 0; + + case 27: + printf("%04lX SCISSOR_XY(%lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w >> 9) & 511UL), + (unsigned long)(w & 511UL)); + return 0; + + case 28: + printf("%04lX SCISSOR_SIZE(%lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w >> 12) & 4095UL), + (unsigned long)(w & 4095UL)); + return 0; + + case 29: + printf("%04lX CALL(0x%03lX)\r\n", (unsigned long)line, (unsigned long)(w & 2047UL)); + return 0; + + case 30: + printf("%04lX JUMP(0x%03lX)\r\n", (unsigned long)line, (unsigned long)(w & 2047UL)); + return 0; + + case 31: + v = w & 15UL; + printf("%04lX BEGIN(", (unsigned long)line); + ft_dl_print_num_or_name(ft_dl_prim_name(v), v); + printf(")\r\n"); + return 0; + + case 32: + printf("%04lX COLOR_MASK(%lu, %lu, %lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w >> 3) & 1UL), + (unsigned long)((w >> 2) & 1UL), + (unsigned long)((w >> 1) & 1UL), + (unsigned long)(w & 1UL)); + return 0; + + case 33: + printf("%04lX END()\r\n", (unsigned long)line); + return 0; + + case 34: + ft_dl_context_save(ctx); + printf("%04lX SAVE_CONTEXT()\r\n", (unsigned long)line); + return 0; + + case 35: + ft_dl_context_restore(ctx); + printf("%04lX RESTORE_CONTEXT()\r\n", (unsigned long)line); + return 0; + + case 36: + printf("%04lX RETURN()\r\n", (unsigned long)line); + return 0; + + case 37: + printf("%04lX MACRO(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 1UL)); + return 0; + + case 38: + printf("%04lX CLEAR(%lu, %lu, %lu)\r\n", + (unsigned long)line, + (unsigned long)((w >> 2) & 1UL), + (unsigned long)((w >> 1) & 1UL), + (unsigned long)(w & 1UL)); + return 0; + + case 39: + ctx->vertex_format = (u8)(w & 7UL); + printf("%04lX VERTEX_FORMAT(%lu)\r\n", (unsigned long)line, (unsigned long)(w & 7UL)); + return 0; + + case 40: + ft_dl_print_bitmap_layout_h(line, w); + return 0; + + case 41: + ft_dl_print_bitmap_size_h(line, w); + return 0; + + case 42: + printf("%04lX PALETTE_SOURCE(0x%06lX)\r\n", (unsigned long)line, (unsigned long)(w & 0x3FFFFFUL)); + return 0; + + case 43: + ft_dl_print_fixed_cmd_1(line, "VERTEX_TRANSLATE_X", ft_dl_sx(w & 131071UL, 17), 4); + return 0; + + case 44: + ft_dl_print_fixed_cmd_1(line, "VERTEX_TRANSLATE_Y", ft_dl_sx(w & 131071UL, 17), 4); + return 0; + + case 45: + printf("%04lX NOP()\r\n", (unsigned long)line); + return 0; + } + + printf("%04lX UNKNOWN(0x%08lX)\r\n", (unsigned long)line, (unsigned long)w); + return 0; +} + +void ft_dl_flush_pending(u32 *line, int *has_layout_hi, u32 layout_hi, int *has_size_hi, u32 size_hi) +{ + if (*has_layout_hi) + { + ft_dl_print_bitmap_layout_h(*line, layout_hi); + (*line)++; + *has_layout_hi = 0; + } + + if (*has_size_hi) + { + ft_dl_print_bitmap_size_h(*line, size_hi); + (*line)++; + *has_size_hi = 0; + } +} + +void ft_dl_decode(const u8 *buf, u32 bytes) +{ + FT_DL_DECODE_CONTEXT ctx; + u32 out_line = 0; + u32 raw_line; + u32 layout_hi = 0; + u32 size_hi = 0; + int has_layout_hi = 0; + int has_size_hi = 0; + + ft_dl_context_init(&ctx); + + for (raw_line = 0; raw_line < bytes / 4; raw_line++) + { + u32 w = ft_rd32le(buf + raw_line * 4); + u32 op = w >> 24; + + if (op == 40) + { + if (has_layout_hi) + ft_dl_flush_pending(&out_line, &has_layout_hi, layout_hi, &has_size_hi, size_hi); + + layout_hi = w; + has_layout_hi = 1; + continue; + } + + if (op == 41) + { + if (has_size_hi) + ft_dl_flush_pending(&out_line, &has_layout_hi, layout_hi, &has_size_hi, size_hi); + + size_hi = w; + has_size_hi = 1; + continue; + } + + if (op == 7 && has_layout_hi) + { + if (has_size_hi) + ft_dl_flush_pending(&out_line, &has_layout_hi, layout_hi, &has_size_hi, size_hi); + + ft_dl_print_bitmap_layout(out_line, w, layout_hi, 1); + out_line++; + has_layout_hi = 0; + continue; + } + + if (op == 8 && has_size_hi) + { + if (has_layout_hi) + ft_dl_flush_pending(&out_line, &has_layout_hi, layout_hi, &has_size_hi, size_hi); + + ft_dl_print_bitmap_size(out_line, w, size_hi, 1); + out_line++; + has_size_hi = 0; + continue; + } + + ft_dl_flush_pending(&out_line, &has_layout_hi, layout_hi, &has_size_hi, size_hi); + + if (ft_dl_print_word(&ctx, out_line, w)) + break; + + out_line++; + } +} + +esp_err_t ft_dl_line_swap_wait() +{ + ft_wreg8(FT_REG_DLSWAP, FT_DLSWAP_LINE); + return ft_wait_swap(1000); +} + +esp_err_t ft_dl_read_current(void *buf, u32 bytes) +{ + esp_err_t err; + esp_err_t err_restore; + + err = ft_dl_line_swap_wait(); + if (err != ESP_OK) return err; + + err = ft_read(buf, FT_RAM_DL, bytes); + + err_restore = ft_dl_line_swap_wait(); + if (err == ESP_OK) + err = err_restore; + + return err; +} + +int ft_swap_cmd(int argc, char **) +{ + esp_err_t err; + esp_err_t err2; + + if (argc != 2) + { + printf("Usage:\r\n"); + printf(" ft swap\r\n"); + return 1; + } + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + ft_wreg8(FT_REG_DLSWAP, FT_DLSWAP_FRAME); + + err2 = ft_close_session(); + if (err == ESP_OK && err2 != ESP_OK) + err = err2; + + if (err != ESP_OK) + { + printf("FT swap failed: %d\r\n", (int)err); + return 1; + } + + printf("FT swap: DLSWAP=%u\r\n", (unsigned)FT_DLSWAP_FRAME); + return 0; +} + +int ft_dl_cmd(int argc, char **argv) +{ + esp_err_t err; + esp_err_t err2; + u32 dl = 0; + int current = 1; + int ok; + + if (argc > 3) + { + printf("Usage:\r\n"); + printf(" ft dl\r\n"); + printf(" ft dl 0\r\n"); + printf(" ft dl 1\r\n"); + return 1; + } + + if (argc == 3) + { + dl = ft_parse_num_arg(argv[2], "dl", &ok); + if (!ok) + return 1; + + if (dl > 1) + { + printf("Bad
: %lu, allowed 0-1\r\n", (unsigned long)dl); + return 1; + } + + current = dl == 0; + } + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return 1; + } + + if (current) + err = ft_dl_read_current(cmdl, FT_DL_READ_SIZE); + else + err = ft_read(cmdl, FT_RAM_DL, FT_DL_READ_SIZE); + + err2 = ft_close_session(); + if (err == ESP_OK && err2 != ESP_OK) + err = err2; + + if (err != ESP_OK) + { + printf("FT dl read failed: %d\r\n", (int)err); + return 1; + } + + if (current) + printf("\r\nFT DL current:\r\n"); + else + printf("\r\nFT DL staging:\r\n"); + + ft_dl_decode(cmdl, FT_DL_READ_SIZE); + + return 0; +} + +typedef struct +{ + const char *name; + u32 value; +} +FT_F_VALUE_DEF; + +typedef struct +{ + const char *name; + const char *aliases; + u8 id; + u8 min_args; + u8 max_args; +} +FT_F_CMD_DEF; + +enum +{ + FT_F_ALPHA_FUNC = 0, + FT_F_BEGIN, + FT_F_BITMAPS_CMD, + FT_F_POINTS_CMD, + FT_F_LINES_CMD, + FT_F_LINE_STRIP_CMD, + FT_F_EDGE_STRIP_R_CMD, + FT_F_EDGE_STRIP_L_CMD, + FT_F_EDGE_STRIP_A_CMD, + FT_F_EDGE_STRIP_B_CMD, + FT_F_RECTS_CMD, + FT_F_BITMAP_HANDLE, + FT_F_BITMAP_LAYOUT, + FT_F_BITMAP_SIZE, + FT_F_BITMAP_SOURCE, + FT_F_BITMAP_TRANSFORM_A, + FT_F_BITMAP_TRANSFORM_B, + FT_F_BITMAP_TRANSFORM_C, + FT_F_BITMAP_TRANSFORM_D, + FT_F_BITMAP_TRANSFORM_E, + FT_F_BITMAP_TRANSFORM_F, + FT_F_BLEND_FUNC, + FT_F_CALL, + FT_F_CELL, + FT_F_CLEAR_COLOR_A, + FT_F_CLEAR_COLOR_RGB, + FT_F_CLEAR, + FT_F_CLEAR_ALL, + FT_F_CLEAR_STENCIL, + FT_F_CLEAR_TAG, + FT_F_COLOR_A, + FT_F_COLOR_MASK, + FT_F_COLOR_RGB, + FT_F_NOP, + FT_F_DISPLAY, + FT_F_END, + FT_F_JUMP, + FT_F_LINE_WIDTH, + FT_F_MACRO, + FT_F_PALETTE_SOURCE, + FT_F_POINT_SIZE, + FT_F_RESTORE_CONTEXT, + FT_F_RETURN, + FT_F_SAVE_CONTEXT, + FT_F_SCISSOR_SIZE, + FT_F_SCISSOR_XY, + FT_F_STENCIL_FUNC, + FT_F_STENCIL_MASK, + FT_F_STENCIL_OP, + FT_F_TAG_MASK, + FT_F_TAG, + FT_F_VERTEX_2F, + FT_F_VERTEX_2II, + FT_F_VERTEX_FORMAT, + FT_F_VERTEX_TRANSLATE_X, + FT_F_VERTEX_TRANSLATE_Y +}; + +const FT_F_VALUE_DEF ft_f_values[] = +{ + {"bitmaps", FT_BITMAPS}, {"b", FT_BITMAPS}, + {"points", FT_POINTS}, {"p", FT_POINTS}, + {"rects", FT_RECTS}, {"r", FT_RECTS}, + {"lines", FT_LINES}, {"l", FT_LINES}, + {"line_strip", FT_LINE_STRIP}, {"ls", FT_LINE_STRIP}, + {"edge_strip_r", FT_EDGE_STRIP_R}, {"esr", FT_EDGE_STRIP_R}, + {"edge_strip_l", FT_EDGE_STRIP_L}, {"esl", FT_EDGE_STRIP_L}, + {"edge_strip_a", FT_EDGE_STRIP_A}, {"esa", FT_EDGE_STRIP_A}, + {"edge_strip_b", FT_EDGE_STRIP_B}, {"esb", FT_EDGE_STRIP_B}, + {"l1", FT_L1}, + {"l2", FT_L2}, + {"l4", FT_L4}, + {"l8", FT_L8}, + {"argb1555", FT_ARGB1555}, + {"rgb332", FT_RGB332}, + {"argb2", FT_ARGB2}, + {"argb4", FT_ARGB4}, + {"rgb565", FT_RGB565}, + {"paletted565", FT_PALETTED565}, {"p565", FT_PALETTED565}, + {"paletted4444", FT_PALETTED4444}, {"p4444", FT_PALETTED4444}, + {"paletted8", FT_PALETTED8}, {"p8", FT_PALETTED8}, + {"text8x8", FT_TEXT8X8}, {"t8", FT_TEXT8X8}, + {"textvga", FT_TEXTVGA}, {"tv", FT_TEXTVGA}, + {"bargraph", FT_BARGRAPH}, + {"zero", FT_ZERO}, + {"one", FT_ONE}, + {"src_alpha", FT_SRC_ALPHA}, + {"dst_alpha", FT_DST_ALPHA}, + {"one_minus_src_alpha", FT_ONE_MINUS_SRC_ALPHA}, + {"one_minus_dst_alpha", FT_ONE_MINUS_DST_ALPHA}, + {"never", FT_NEVER}, + {"less", FT_LESS}, + {"lequal", FT_LEQUAL}, + {"greater", FT_GREATER}, + {"gequal", FT_GEQUAL}, + {"equal", FT_EQUAL}, + {"notequal", FT_NOTEQUAL}, + {"always", FT_ALWAYS}, + {"keep", FT_KEEP}, + {"replace", FT_REPLACE}, + {"incr", FT_INCR}, + {"decr", FT_DECR}, + {"invert", FT_INVERT}, + {"incr_wrap", FT_INCR_WRAP}, + {"decr_wrap", FT_DECR_WRAP}, + {"repeat", FT_REPEAT}, + {"border", FT_BORDER}, + {"nearest", FT_NEAREST}, + {"bilinear", FT_BILINEAR} +}; + +const FT_F_CMD_DEF ft_f_cmds[] = +{ + {"alpha_func", "af", FT_F_ALPHA_FUNC, 2, 2}, + {"begin", "bg", FT_F_BEGIN, 1, 1}, + {"bitmap", "b", FT_F_BITMAPS_CMD, 0, 0}, + {"points", "p", FT_F_POINTS_CMD, 0, 0}, + {"lines", "l", FT_F_LINES_CMD, 0, 0}, + {"line_strip", "ls", FT_F_LINE_STRIP_CMD, 0, 0}, + {"edge_strip_r", "esr", FT_F_EDGE_STRIP_R_CMD, 0, 0}, + {"edge_strip_l", "esl", FT_F_EDGE_STRIP_L_CMD, 0, 0}, + {"edge_strip_a", "esa", FT_F_EDGE_STRIP_A_CMD, 0, 0}, + {"edge_strip_b", "esb", FT_F_EDGE_STRIP_B_CMD, 0, 0}, + {"rects", "r", FT_F_RECTS_CMD, 0, 0}, + {"bitmap_handle", "bh", FT_F_BITMAP_HANDLE, 1, 1}, + {"bitmap_layout", "bl", FT_F_BITMAP_LAYOUT, 3, 3}, + {"bitmap_size", "bsz", FT_F_BITMAP_SIZE, 5, 5}, + {"bitmap_source", "bs", FT_F_BITMAP_SOURCE, 1, 1}, + {"bitmap_transform_a", "bta", FT_F_BITMAP_TRANSFORM_A, 1, 1}, + {"bitmap_transform_b", "btb", FT_F_BITMAP_TRANSFORM_B, 1, 1}, + {"bitmap_transform_c", "btc", FT_F_BITMAP_TRANSFORM_C, 1, 1}, + {"bitmap_transform_d", "btd", FT_F_BITMAP_TRANSFORM_D, 1, 1}, + {"bitmap_transform_e", "bte", FT_F_BITMAP_TRANSFORM_E, 1, 1}, + {"bitmap_transform_f", "btf", FT_F_BITMAP_TRANSFORM_F, 1, 1}, + {"blend_func", "bf", FT_F_BLEND_FUNC, 2, 2}, + {"call", "cal", FT_F_CALL, 1, 1}, + {"cell", "c", FT_F_CELL, 1, 1}, + {"clear_color_a", "cca", FT_F_CLEAR_COLOR_A, 1, 1}, + {"clear_color_rgb", "ccr", FT_F_CLEAR_COLOR_RGB, 1, 3}, + {"clear", "cl", FT_F_CLEAR, 3, 3}, + {"clear_all", "cla", FT_F_CLEAR_ALL, 0, 0}, + {"clear_stencil", "cls", FT_F_CLEAR_STENCIL, 1, 1}, + {"clear_tag", "clt", FT_F_CLEAR_TAG, 1, 1}, + {"color_a", "ca", FT_F_COLOR_A, 1, 1}, + {"color_mask", "cm", FT_F_COLOR_MASK, 4, 4}, + {"color_rgb", "cr", FT_F_COLOR_RGB, 1, 3}, + {"nop", "n", FT_F_NOP, 0, 0}, + {"display", "d", FT_F_DISPLAY, 0, 0}, + {"end", "e", FT_F_END, 0, 0}, + {"jump", "j", FT_F_JUMP, 1, 1}, + {"line_width", "lw", FT_F_LINE_WIDTH, 1, 1}, + {"macro", "m", FT_F_MACRO, 1, 1}, + {"palette_source", "ps", FT_F_PALETTE_SOURCE, 1, 1}, + {"point_size", "psz", FT_F_POINT_SIZE, 1, 1}, + {"restore_context", "rc", FT_F_RESTORE_CONTEXT, 0, 0}, + {"return", "ret", FT_F_RETURN, 0, 0}, + {"save_context", "sc", FT_F_SAVE_CONTEXT, 0, 0}, + {"scissor_size", "ssz", FT_F_SCISSOR_SIZE, 2, 2}, + {"scissor_xy", "sxy", FT_F_SCISSOR_XY, 2, 2}, + {"stencil_func", "sf", FT_F_STENCIL_FUNC, 3, 3}, + {"stencil_mask", "sm", FT_F_STENCIL_MASK, 1, 1}, + {"stencil_op", "so", FT_F_STENCIL_OP, 2, 2}, + {"tag_mask", "tm", FT_F_TAG_MASK, 1, 1}, + {"tag", "t", FT_F_TAG, 1, 1}, + {"vertex_2f", "vf", FT_F_VERTEX_2F, 2, 2}, + {"vertex_2ii", "vi", FT_F_VERTEX_2II, 4, 4}, + {"vertex_format", "vfm", FT_F_VERTEX_FORMAT, 1, 1}, + {"vertex_translate_x", "vtx", FT_F_VERTEX_TRANSLATE_X, 1, 1}, + {"vertex_translate_y", "vty", FT_F_VERTEX_TRANSLATE_Y, 1, 1} +}; + +void ft_f_norm_name(const char *src, char *dst, size_t dst_size) +{ + size_t j = 0; + + if (!dst_size) return; + + while (src && *src && j + 1 < dst_size) + { + unsigned char c = (unsigned char)*src++; + if (c == '_' || c == '-' || c == ' ') + continue; + + dst[j++] = (char)tolower(c); + } + + dst[j] = 0; +} + +int ft_f_name_equals(const char *a, const char *b) +{ + char na[48]; + char nb[48]; + + ft_f_norm_name(a, na, sizeof(na)); + ft_f_norm_name(b, nb, sizeof(nb)); + return strcmp(na, nb) == 0; +} + +int ft_f_name_starts_with(const char *name, const char *prefix) +{ + char n[48]; + char p[48]; + + ft_f_norm_name(name, n, sizeof(n)); + ft_f_norm_name(prefix, p, sizeof(p)); + return p[0] && !strncmp(n, p, strlen(p)); +} + +int ft_f_alias_matches(const char *aliases, const char *name, int prefix) +{ + char item[48]; + size_t j = 0; + + if (!aliases) return 0; + + while (1) + { + char c = *aliases++; + if (c && c != ' ') + { + if (j + 1 < sizeof(item)) + item[j++] = c; + continue; + } + + if (j) + { + item[j] = 0; + if (prefix) + { + if (ft_f_name_starts_with(item, name)) + return 1; + } + else + { + if (ft_f_name_equals(item, name)) + return 1; + } + j = 0; + } + + if (!c) break; + } + + return 0; +} + +const FT_F_CMD_DEF *ft_f_find_cmd(const char *name, int *ambiguous) +{ + const FT_F_CMD_DEF *match = nullptr; + int matches = 0; + + *ambiguous = 0; + + for (size_t i = 0; i < sizeof(ft_f_cmds) / sizeof(ft_f_cmds[0]); ++i) + { + const FT_F_CMD_DEF *cmd = &ft_f_cmds[i]; + if (ft_f_name_equals(cmd->name, name) || ft_f_alias_matches(cmd->aliases, name, 0)) + { + match = cmd; + matches++; + } + } + + if (matches == 1) return match; + if (matches > 1) + { + *ambiguous = 1; + return nullptr; + } + + for (size_t i = 0; i < sizeof(ft_f_cmds) / sizeof(ft_f_cmds[0]); ++i) + { + const FT_F_CMD_DEF *cmd = &ft_f_cmds[i]; + if (ft_f_name_starts_with(cmd->name, name) || ft_f_alias_matches(cmd->aliases, name, 1)) + { + match = cmd; + matches++; + } + } + + if (matches == 1) return match; + if (matches > 1) *ambiguous = 1; + return nullptr; +} + +int ft_f_named_value(const char *name, u32 *out) +{ + for (size_t i = 0; i < sizeof(ft_f_values) / sizeof(ft_f_values[0]); ++i) + { + if (ft_f_name_equals(ft_f_values[i].name, name)) + { + *out = ft_f_values[i].value; + return 1; + } + } + + return 0; +} + +u32 ft_f_parse_arg(const char *s, const char *name, int *ok) +{ + char buf[48]; + size_t n; + char *endp = nullptr; + u32 named; + + *ok = 0; + + if (!s) + { + printf("Missing <%s>\r\n", name); + return 0; + } + + n = strlen(s); + if (n >= sizeof(buf)) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + memcpy(buf, s, n + 1); + + if (n && buf[n - 1] == ',') + buf[n - 1] = 0; + + if (ft_f_named_value(buf, &named)) + { + *ok = 1; + return named; + } + + if (buf[0] == '-') + { + long long v = strtoll(buf, &endp, 0); + if (!endp || *endp || v < -2147483647LL - 1LL || v > 2147483647LL) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + *ok = 1; + return (u32)(i32)v; + } + + unsigned long long v = strtoull(buf, &endp, 0); + if (!endp || *endp || v > 0xFFFFFFFFULL) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + *ok = 1; + return (u32)v; +} + +int ft_f_parse_repeat(const char *s, u32 *repeat_count) +{ + char *endp = nullptr; + unsigned long long v; + + if (!s || !*s) return 0; + if (!isdigit((unsigned char)s[0])) return 0; + + v = strtoull(s, &endp, 0); + if (!endp || *endp || !v || v > 0xFFFFULL) + { + printf("Bad repeat count: %s\r\n", s); + return -1; + } + + *repeat_count = (u32)v; + return 1; +} + +void ft_f_emit(const FT_F_CMD_DEF *cmd, const u32 *a) +{ + switch (cmd->id) + { + case FT_F_ALPHA_FUNC: ft_AlphaFunc((u8)a[0], (u8)a[1]); break; + case FT_F_BEGIN: ft_Begin((u8)a[0]); break; + case FT_F_BITMAPS_CMD: ft_Begin(FT_BITMAPS); break; + case FT_F_POINTS_CMD: ft_Begin(FT_POINTS); break; + case FT_F_LINES_CMD: ft_Begin(FT_LINES); break; + case FT_F_LINE_STRIP_CMD: ft_Begin(FT_LINE_STRIP); break; + case FT_F_EDGE_STRIP_R_CMD: ft_Begin(FT_EDGE_STRIP_R); break; + case FT_F_EDGE_STRIP_L_CMD: ft_Begin(FT_EDGE_STRIP_L); break; + case FT_F_EDGE_STRIP_A_CMD: ft_Begin(FT_EDGE_STRIP_A); break; + case FT_F_EDGE_STRIP_B_CMD: ft_Begin(FT_EDGE_STRIP_B); break; + case FT_F_RECTS_CMD: ft_Begin(FT_RECTS); break; + case FT_F_BITMAP_HANDLE: ft_BitmapHandle((u8)a[0]); break; + case FT_F_BITMAP_LAYOUT: ft_BitmapLayout((u8)a[0], (u16)a[1], (u16)a[2]); break; + case FT_F_BITMAP_SIZE: ft_BitmapSize((u8)a[0], (u8)a[1], (u8)a[2], (u16)a[3], (u16)a[4]); break; + case FT_F_BITMAP_SOURCE: ft_BitmapSource(a[0]); break; + case FT_F_BITMAP_TRANSFORM_A: ft_BitmapTransformA((i32)a[0]); break; + case FT_F_BITMAP_TRANSFORM_B: ft_BitmapTransformB((i32)a[0]); break; + case FT_F_BITMAP_TRANSFORM_C: ft_BitmapTransformC((i32)a[0]); break; + case FT_F_BITMAP_TRANSFORM_D: ft_BitmapTransformD((i32)a[0]); break; + case FT_F_BITMAP_TRANSFORM_E: ft_BitmapTransformE((i32)a[0]); break; + case FT_F_BITMAP_TRANSFORM_F: ft_BitmapTransformF((i32)a[0]); break; + case FT_F_BLEND_FUNC: ft_BlendFunc((u8)a[0], (u8)a[1]); break; + case FT_F_CALL: ft_Call((u16)a[0]); break; + case FT_F_CELL: ft_Cell((u8)a[0]); break; + case FT_F_CLEAR_COLOR_A: ft_ClearColorA((u8)a[0]); break; + case FT_F_CLEAR_COLOR_RGB: ft_ClearColorRGB((u8)a[0], (u8)a[1], (u8)a[2]); break; + case FT_F_CLEAR: ft_Clear((u8)a[0], (u8)a[1], (u8)a[2]); break; + case FT_F_CLEAR_ALL: ft_ClearAll(); break; + case FT_F_CLEAR_STENCIL: ft_ClearStencil((u8)a[0]); break; + case FT_F_CLEAR_TAG: ft_ClearTag((u8)a[0]); break; + case FT_F_COLOR_A: ft_ColorA((u8)a[0]); break; + case FT_F_COLOR_MASK: ft_ColorMask((u8)a[0], (u8)a[1], (u8)a[2], (u8)a[3]); break; + case FT_F_COLOR_RGB: ft_ColorRGB((u8)a[0], (u8)a[1], (u8)a[2]); break; + case FT_F_NOP: ft_Nop(); break; + case FT_F_DISPLAY: ft_Display(); break; + case FT_F_END: ft_End(); break; + case FT_F_JUMP: ft_Jump((u16)a[0]); break; + case FT_F_LINE_WIDTH: ft_LineWidth((u16)a[0]); break; + case FT_F_MACRO: ft_Macro((u8)a[0]); break; + case FT_F_PALETTE_SOURCE: ft_PaletteSource(a[0]); break; + case FT_F_POINT_SIZE: ft_PointSize((u16)a[0]); break; + case FT_F_RESTORE_CONTEXT: ft_RestoreContext(); break; + case FT_F_RETURN: ft_Return(); break; + case FT_F_SAVE_CONTEXT: ft_SaveContext(); break; + case FT_F_SCISSOR_SIZE: ft_ScissorSize((u16)a[0], (u16)a[1]); break; + case FT_F_SCISSOR_XY: ft_ScissorXY((u16)a[0], (u16)a[1]); break; + case FT_F_STENCIL_FUNC: ft_StencilFunc((u8)a[0], (u8)a[1], (u8)a[2]); break; + case FT_F_STENCIL_MASK: ft_StencilMask((u8)a[0]); break; + case FT_F_STENCIL_OP: ft_StencilOp((u8)a[0], (u8)a[1]); break; + case FT_F_TAG_MASK: ft_TagMask((u8)a[0]); break; + case FT_F_TAG: ft_Tag((u8)a[0]); break; + case FT_F_VERTEX_2F: ft_Vertex2f((i16)a[0], (i16)a[1]); break; + case FT_F_VERTEX_2II: ft_Vertex2ii((u16)a[0], (u16)a[1], (u8)a[2], (u8)a[3]); break; + case FT_F_VERTEX_FORMAT: ft_VertexFormat((u8)a[0]); break; + case FT_F_VERTEX_TRANSLATE_X: ft_VertexTranslateX((i32)a[0]); break; + case FT_F_VERTEX_TRANSLATE_Y: ft_VertexTranslateY((i32)a[0]); break; + } +} + +void ft_f_emit_rgb(const FT_F_CMD_DEF *cmd, const u32 *a, u8 arg_count) +{ + if (cmd->id == FT_F_CLEAR_COLOR_RGB) + { + if (arg_count == 1) + ft_ClearColorRGB32(a[0]); + else + ft_ClearColorRGB((u8)a[0], (u8)a[1], (u8)a[2]); + return; + } + + if (cmd->id == FT_F_COLOR_RGB) + { + if (arg_count == 1) + ft_ColorRGB32(a[0]); + else + ft_ColorRGB((u8)a[0], (u8)a[1], (u8)a[2]); + return; + } + + ft_f_emit(cmd, a); +} + +esp_err_t ft_f_apply() +{ + esp_err_t err; + esp_err_t err2; + u32 words = (u32)ft_f_dl_count + 1; + + ft_f_dl[ft_f_dl_count] = 0; + + err = ft_open_session(); + if (err != ESP_OK) + { + printf("FT open failed: %d\r\n", (int)err); + return err; + } + + err = ft_write_dl(ft_f_dl, words); + if (err == ESP_OK) + { + ft_wreg8(FT_REG_DLSWAP, FT_DLSWAP_FRAME); + err = ft_wait_swap(1000); + } + + err2 = ft_close_session(); + if (err == ESP_OK && err2 != ESP_OK) + err = err2; + + return err; +} + +void ft_f_reset() +{ + ft_f_dl_count = 0; + ft_f_dl_items = 0; + ft_f_dl_ready = 1; +} + +int ft_f_pop() +{ + esp_err_t err; + u16 words; + + if (!ft_f_dl_ready) + ft_f_reset(); + + if (!ft_f_dl_items) + { + printf("fd: no DL elements\r\n"); + return 1; + } + + words = ft_f_dl_words[ft_f_dl_items - 1]; + if (!words || words > ft_f_dl_count) + { + ft_f_reset(); + printf("fd: internal DL stack error, reset\r\n"); + return 1; + } + + ft_f_dl_count -= words; + ft_f_dl_items--; + + err = ft_f_apply(); + if (err != ESP_OK) + { + printf("fd failed: %s (0x%x)\r\n", esp_err_to_name(err), (unsigned int)err); + return 1; + } + + printf("fd: removed last, dl_words=%u\r\n", (unsigned int)(ft_f_dl_count + 1)); + return 0; +} + +const char *ft_f_cmd_args(const FT_F_CMD_DEF *cmd) +{ + switch (cmd->id) + { + case FT_F_ALPHA_FUNC: return " "; + case FT_F_BEGIN: return ""; + case FT_F_BITMAPS_CMD: return ""; + case FT_F_POINTS_CMD: return ""; + case FT_F_LINES_CMD: return ""; + case FT_F_LINE_STRIP_CMD: return ""; + case FT_F_EDGE_STRIP_R_CMD: return ""; + case FT_F_EDGE_STRIP_L_CMD: return ""; + case FT_F_EDGE_STRIP_A_CMD: return ""; + case FT_F_EDGE_STRIP_B_CMD: return ""; + case FT_F_RECTS_CMD: return ""; + case FT_F_BITMAP_HANDLE: return ""; + case FT_F_BITMAP_LAYOUT: return " "; + case FT_F_BITMAP_SIZE: return " "; + case FT_F_BITMAP_SOURCE: return ""; + case FT_F_BITMAP_TRANSFORM_A: return ""; + case FT_F_BITMAP_TRANSFORM_B: return ""; + case FT_F_BITMAP_TRANSFORM_C: return ""; + case FT_F_BITMAP_TRANSFORM_D: return ""; + case FT_F_BITMAP_TRANSFORM_E: return ""; + case FT_F_BITMAP_TRANSFORM_F: return ""; + case FT_F_BLEND_FUNC: return " "; + case FT_F_CALL: return ""; + case FT_F_CELL: return ""; + case FT_F_CLEAR_COLOR_A: return ""; + case FT_F_CLEAR_COLOR_RGB: return " | "; + case FT_F_CLEAR: return " "; + case FT_F_CLEAR_ALL: return ""; + case FT_F_CLEAR_STENCIL: return ""; + case FT_F_CLEAR_TAG: return ""; + case FT_F_COLOR_A: return ""; + case FT_F_COLOR_MASK: return " "; + case FT_F_COLOR_RGB: return " | "; + case FT_F_NOP: return ""; + case FT_F_DISPLAY: return ""; + case FT_F_END: return ""; + case FT_F_JUMP: return ""; + case FT_F_LINE_WIDTH: return ""; + case FT_F_MACRO: return ""; + case FT_F_PALETTE_SOURCE: return ""; + case FT_F_POINT_SIZE: return ""; + case FT_F_RESTORE_CONTEXT: return ""; + case FT_F_RETURN: return ""; + case FT_F_SAVE_CONTEXT: return ""; + case FT_F_SCISSOR_SIZE: return " "; + case FT_F_SCISSOR_XY: return " "; + case FT_F_STENCIL_FUNC: return " "; + case FT_F_STENCIL_MASK: return ""; + case FT_F_STENCIL_OP: return " "; + case FT_F_TAG_MASK: return ""; + case FT_F_TAG: return ""; + case FT_F_VERTEX_2F: return " "; + case FT_F_VERTEX_2II: return " "; + case FT_F_VERTEX_FORMAT: return ""; + case FT_F_VERTEX_TRANSLATE_X: return ""; + case FT_F_VERTEX_TRANSLATE_Y: return ""; + } + + return ""; +} + +int ft_f_cmd_help() +{ + printf("Usage:\r\n"); + printf(" fd show this help\r\n"); + printf(" fd ; reset display list\r\n"); + printf(" fd [args...]\r\n"); + printf(" fd ; ; ...\r\n"); + printf(" fd - remove last DL element\r\n"); + printf("Values:\r\n"); + printf(" primitives: bitmaps/b, points/p, lines/l, line_strip/ls, rects/r\r\n"); + printf(" formats: l1 l2 l4 l8 rgb565 argb1555 rgb332 paletted565/p565 paletted8/p8\r\n"); + printf("Commands:\r\n"); + + for (size_t i = 0; i < sizeof(ft_f_cmds) / sizeof(ft_f_cmds[0]); ++i) + { + const FT_F_CMD_DEF *cmd = &ft_f_cmds[i]; + printf(" %-20s %-10s %s\r\n", + cmd->name, + cmd->aliases ? cmd->aliases : "", + ft_f_cmd_args(cmd)); + } + + return 0; +} + +int ft_f_reset_cmd() +{ + esp_err_t err; + + ft_f_reset(); + err = ft_f_apply(); + if (err != ESP_OK) + { + printf("fd failed: %s (0x%x)\r\n", esp_err_to_name(err), (unsigned int)err); + return 1; + } + + printf("fd: reset, dl_words=%u\r\n", (unsigned int)(ft_f_dl_count + 1)); + return 0; +} + +int ft_f_exec(int argc, char **argv) +{ + const FT_F_CMD_DEF *cmd; + u32 args[8] = {}; + u32 tmp[4] = {}; + u32 repeat_count = 1; + u32 add_words; + u8 arg_count; + int ambiguous; + int cmd_arg = 1; + int repeat_parse; + esp_err_t err; + + if (argc == 1 || (argc == 2 && (!strcmp(argv[1], "?") || !strcmp(argv[1], "help")))) + return ft_f_cmd_help(); + + if (!strcmp(argv[1], "-")) + { + if (argc != 2) + { + printf("Usage: fd -\r\n"); + return 1; + } + + return ft_f_pop(); + } + + repeat_parse = ft_f_parse_repeat(argv[1], &repeat_count); + if (repeat_parse < 0) return 1; + if (repeat_parse > 0) + { + if (argc < 3) + { + printf("Usage: fd [] []\r\n"); + return 1; + } + + cmd_arg = 2; + } + + cmd = ft_f_find_cmd(argv[cmd_arg], &ambiguous); + if (!cmd) + { + if (ambiguous) + printf("Ambiguous DL element: %s\r\n", argv[cmd_arg]); + else + printf("Unknown DL element: %s\r\n", argv[cmd_arg]); + return 1; + } + + arg_count = (u8)(argc - cmd_arg - 1); + if (arg_count < cmd->min_args || arg_count > cmd->max_args || + ((cmd->id == FT_F_CLEAR_COLOR_RGB || cmd->id == FT_F_COLOR_RGB) && arg_count == 2)) + { + printf("Bad argument count for %s: %u, expected ", cmd->name, (unsigned int)arg_count); + if (cmd->min_args == cmd->max_args) + printf("%u\r\n", (unsigned int)cmd->min_args); + else + printf("%u..%u\r\n", (unsigned int)cmd->min_args, (unsigned int)cmd->max_args); + return 1; + } + + for (u8 i = 0; i < arg_count; ++i) + { + char name[16]; + int ok; + + snprintf(name, sizeof(name), "arg%u", (unsigned int)i); + args[i] = ft_f_parse_arg(argv[cmd_arg + 1 + i], name, &ok); + if (!ok) return 1; + } + + if (!ft_f_dl_ready) + ft_f_reset(); + + ft_ccmd_start(tmp); + ft_f_emit_rgb(cmd, args, arg_count); + + if (ft_ccmdp > sizeof(tmp) / sizeof(tmp[0])) + { + printf("Internal fd command overflow: %s\r\n", cmd->name); + return 1; + } + + add_words = (u32)ft_ccmdp * repeat_count; + if ((u32)ft_f_dl_count + add_words + 1 > FT_F_DL_MAX_DWORDS) + { + printf("DL is full: used=%u add=%u max=%u\r\n", + (unsigned int)ft_f_dl_count, + (unsigned int)add_words, + (unsigned int)FT_F_DL_MAX_DWORDS); + return 1; + } + + if ((u32)ft_f_dl_items + repeat_count > FT_F_DL_MAX_DWORDS) + { + printf("DL element stack is full: used=%u add=%u max=%u\r\n", + (unsigned int)ft_f_dl_items, + (unsigned int)repeat_count, + (unsigned int)FT_F_DL_MAX_DWORDS); + return 1; + } + + for (u32 i = 0; i < repeat_count; ++i) + { + memcpy(&ft_f_dl[ft_f_dl_count], tmp, (size_t)ft_ccmdp * sizeof(tmp[0])); + ft_f_dl_words[ft_f_dl_items++] = ft_ccmdp; + ft_f_dl_count += ft_ccmdp; + } + + err = ft_f_apply(); + if (err != ESP_OK) + { + printf("fd failed: %s (0x%x)\r\n", esp_err_to_name(err), (unsigned int)err); + return 1; + } + + if (repeat_count == 1) + printf("fd: added %s, dl_words=%u\r\n", cmd->name, (unsigned int)(ft_f_dl_count + 1)); + else + printf("fd: added %u x %s, dl_words=%u\r\n", + (unsigned int)repeat_count, + cmd->name, + (unsigned int)(ft_f_dl_count + 1)); + + return 0; +} + +int ft_f_has_separator(int argc, char **argv) +{ + for (int i = 0; i < argc; ++i) + { + if (argv[i] && strchr(argv[i], ';')) return 1; + } + + return 0; +} + +char *ft_f_skip_spaces(char *s) +{ + while (s && (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')) + s++; + + return s; +} + +int ft_f_split_words(char *s, char **argv, int max_argc) +{ + int argc = 0; + + s = ft_f_skip_spaces(s); + while (s && *s) + { + if (argc >= max_argc) + { + printf("Too many fd command arguments\r\n"); + return -1; + } + + argv[argc++] = s; + while (*s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n') + s++; + + if (!*s) break; + *s++ = 0; + s = ft_f_skip_spaces(s); + } + + return argc; +} + +int ft_f_exec_segment(char *segment) +{ + char *args[32]; + char *argv[33]; + int argc; + + argc = ft_f_split_words(segment, args, (int)(sizeof(args) / sizeof(args[0]))); + if (argc < 0) return 1; + if (!argc) return 0; + + if (ft_f_name_equals(args[0], "fd")) + { + if (argc == 1) return ft_f_reset_cmd(); + return ft_f_exec(argc, args); + } + + argv[0] = (char *)"fd"; + for (int i = 0; i < argc; ++i) + argv[i + 1] = args[i]; + + return ft_f_exec(argc + 1, argv); +} + +int ft_f_cmd_list(int argc, char **argv) +{ + char line[512]; + size_t pos = 0; + char *seg; + char *next; + int ret = 0; + + line[0] = 0; + for (int i = 0; i < argc; ++i) + { + size_t n; + + if (!argv[i]) continue; + + n = strlen(argv[i]); + if (pos + n + (pos ? 1 : 0) + 1 > sizeof(line)) + { + printf("fd command line is too long\r\n"); + return 1; + } + + if (pos) + line[pos++] = ' '; + memcpy(&line[pos], argv[i], n); + pos += n; + line[pos] = 0; + } + + seg = line; + while (seg) + { + next = strchr(seg, ';'); + if (next) + *next++ = 0; + + ret = ft_f_exec_segment(seg); + if (ret) return ret; + + seg = next; + } + + return 0; +} + +int ft_f_cmd(int argc, char **argv) +{ + if (ft_f_has_separator(argc, argv)) + return ft_f_cmd_list(argc, argv); + + return ft_f_exec(argc, argv); +} + + +#define FT_FC_RAM_G_SIZE (1024UL * 1024UL) +#define FT_FC_TS_COUNT 256 +#define FT_FC_SCRATCH_SIZE 256 +#define FT_FC_TS_ADDR (FT_RAM_G + FT_FC_RAM_G_SIZE - (FT_FC_TS_COUNT * 4UL)) +#define FT_FC_SCRATCH_ADDR (FT_FC_TS_ADDR - FT_FC_SCRATCH_SIZE) +#define FT_FC_CMD_MAX_BYTES (FT_CMD_FIFO_SIZE - FT_CMD_SIZE) +#define FT_FC_LINE_MAX 4096 +#define FT_FC_ARG_MAX 128 +#define FT_FC_RAW_ARG_MAX 64 +#define FT_FC_OUT_REC_MAX (FT_FC_TS_COUNT + (FT_FC_SCRATCH_SIZE / 4)) + +#define FT_FC_OUT(n) (1UL << (n)) + +typedef struct +{ + const char *name; + const char *aliases; + u32 value; +} +FT_FC_VALUE_DEF; + +typedef enum +{ + FT_FC_FMT_RAW = 0, + FT_FC_FMT_MEMWRITE, + FT_FC_FMT_TEXT, + FT_FC_FMT_BUTTON, + FT_FC_FMT_TOGGLE, + FT_FC_FMT_NUMBER, + FT_FC_FMT_CLOCK, + FT_FC_FMT_GAUGE, + FT_FC_FMT_SLIDER_PROGRESS, + FT_FC_FMT_SCROLLBAR, + FT_FC_FMT_DIAL, + FT_FC_FMT_GRADIENT, + FT_FC_FMT_TRACK, + FT_FC_FMT_SNAPSHOT2, + FT_FC_FMT_SKETCH, + FT_FC_FMT_CSKETCH, + FT_FC_FMT_SETBITMAP, + FT_FC_FMT_SPINNER +} +FT_FC_FMT; + +typedef struct +{ + const char *name; + const char *aliases; + u32 code; + u8 min_args; + u8 max_args; + u8 fmt; + u32 out_mask; +} +FT_FC_CMD_DEF; + +typedef enum +{ + FT_FC_DST_NONE = 0, + FT_FC_DST_SCRATCH, + FT_FC_DST_TS +} +FT_FC_DST; + +typedef struct +{ + u8 cmd[FT_CMD_FIFO_SIZE]; + char line[FT_FC_LINE_MAX]; + char *argv[FT_FC_ARG_MAX]; + u32 args[FT_FC_RAW_ARG_MAX]; + u8 ts[FT_FC_TS_COUNT * 4]; + u8 scratch[FT_FC_SCRATCH_SIZE]; + u32 out_dst_off[FT_FC_RAW_ARG_MAX]; + u32 out_offs[FT_FC_RAW_ARG_MAX]; + u8 out_dst_type[FT_FC_RAW_ARG_MAX]; + u8 out_save[FT_FC_RAW_ARG_MAX]; + u32 save_src_off[FT_FC_OUT_REC_MAX]; + u32 save_dst_off[FT_FC_OUT_REC_MAX]; + u8 save_dst_type[FT_FC_OUT_REC_MAX]; + u32 save_count; + u32 pos; + u32 ts_pos; + u32 sp; +} +FT_FC_WORKSPACE; + +EXT_RAM_BSS_ATTR FT_FC_WORKSPACE ft_fc_ws; + +const FT_FC_VALUE_DEF ft_fc_values[] = +{ + {"ram_g", "ramg rg", FT_RAM_G}, + {"ram_dl", "ramdl rd", FT_RAM_DL}, + {"ram_cmd", "ramcmd rc", FT_RAM_CMD}, + {"scratch", "scratchpad", FT_FC_SCRATCH_ADDR}, + {"timestamps", "timestamp tsbase", FT_FC_TS_ADDR}, + {"opt_center", "center", FT_OPT_CENTER}, + {"opt_centerx", "centerx", FT_OPT_CENTERX}, + {"opt_centery", "centery", FT_OPT_CENTERY}, + {"opt_flat", "flat", FT_OPT_FLAT}, + {"opt_mono", "mono", FT_OPT_MONO}, + {"opt_noback", "noback", FT_OPT_NOBACK}, + {"opt_nodl", "nodl", FT_OPT_NODL}, + {"opt_nohands", "nohands", FT_OPT_NOHANDS}, + {"opt_nohm", "nohm", FT_OPT_NOHM}, + {"opt_nopointer", "nopointer", FT_OPT_NOPOINTER}, + {"opt_nosecs", "nosecs", FT_OPT_NOSECS}, + {"opt_noticks", "noticks", FT_OPT_NOTICKS}, + {"opt_rightx", "rightx", FT_OPT_RIGHTX}, + {"opt_signed", "signed", FT_OPT_SIGNED}, + {"opt_notear", "notear", OPT_NOTEAR}, + {"opt_fullscreen", "fullscreen", OPT_FULLSCREEN}, + {"opt_mediafifo", "mediafifo", OPT_MEDIAFIFO}, + {"opt_sound", "sound", OPT_SOUND}, + {"reg_id", "id", FT_REG_ID}, + {"reg_frames", "frames", FT_REG_FRAMES}, + {"reg_clock", "clock", FT_REG_CLOCK}, + {"reg_frequency", "frequency freq", FT_REG_FREQUENCY}, + {"reg_cpureset", "cpureset", FT_REG_CPURESET}, + {"reg_cmd_read", "cmd_read cmdread", FT_REG_CMD_READ}, + {"reg_cmd_write", "cmd_write cmdwrite", FT_REG_CMD_WRITE}, + {"reg_cmd_dl", "cmd_dl cmddl", FT_REG_CMD_DL}, + {"reg_cmd_wp", "cmd_wp cmdwp", FT_REG_CMD_WRITE}, + {"reg_cmd_rp", "cmd_rp cmdrp", FT_REG_CMD_READ}, + {"reg_cmd_space", "cmd_space cmdspace", FT_REG_CMDB_SPACE}, + {"reg_cmdb_write", "cmdb_write cmdbwrite", FT_REG_CMDB_WRITE}, + {"reg_dlswap", "dlswap", FT_REG_DLSWAP}, + {"reg_hcycle", "hcycle", FT_REG_HCYCLE}, + {"reg_hoffset", "hoffset", FT_REG_HOFFSET}, + {"reg_hsize", "hsize", FT_REG_HSIZE}, + {"reg_hsync0", "hsync0", FT_REG_HSYNC0}, + {"reg_hsync1", "hsync1", FT_REG_HSYNC1}, + {"reg_vcycle", "vcycle", FT_REG_VCYCLE}, + {"reg_voffset", "voffset", FT_REG_VOFFSET}, + {"reg_vsize", "vsize", FT_REG_VSIZE}, + {"reg_vsync0", "vsync0", FT_REG_VSYNC0}, + {"reg_vsync1", "vsync1", FT_REG_VSYNC1}, + {"reg_pclk", "pclk", FT_REG_PCLK}, + {"reg_pclk_pol", "pclk_pol pclkpol", FT_REG_PCLK_POL}, + {"reg_swizzle", "swizzle", FT_REG_SWIZZLE}, + {"reg_cspread", "cspread", FT_REG_CSPREAD}, + {"reg_pwm_duty", "pwm_duty pwmduty", FT_REG_PWM_DUTY}, + {"reg_pwm_hz", "pwm_hz pwmhz", FT_REG_PWM_HZ}, + {"reg_gpio", "gpio", FT_REG_GPIO}, + {"reg_gpio_dir", "gpio_dir gpiodir", FT_REG_GPIO_DIR}, + {"reg_int_flags", "int_flags intflags", FT_REG_INT_FLAGS}, + {"reg_int_en", "int_en inten", FT_REG_INT_EN}, + {"reg_int_mask", "int_mask intmask", FT_REG_INT_MASK}, + {"reg_touch_mode", "touch_mode touchmode", FT_REG_TOUCH_MODE}, + {"reg_touch_adc_mode", "touch_adc_mode touchadcmode", FT_REG_TOUCH_ADC_MODE}, + {"reg_touch_charge", "touch_charge touchcharge", FT_REG_TOUCH_CHARGE}, + {"reg_touch_settle", "touch_settle touchsettle", FT_REG_TOUCH_SETTLE}, + {"reg_touch_oversample", "touch_oversample touchoversample", FT_REG_TOUCH_OVERSAMPLE}, + {"reg_touch_rzthresh", "touch_rzthresh touchrzthresh", FT_REG_TOUCH_RZTHRESH}, + {"reg_touch_raw_xy", "touch_raw_xy touchrawxy", FT_REG_TOUCH_RAW_XY}, + {"reg_touch_rz", "touch_rz touchrz", FT_REG_TOUCH_RZ}, + {"reg_touch_screen_xy", "touch_screen_xy touchscreenxy", FT_REG_TOUCH_SCREEN_XY}, + {"reg_touch_tag_xy", "touch_tag_xy touchtagxy", FT_REG_TOUCH_TAG_XY}, + {"reg_touch_tag", "touch_tag touchtag", FT_REG_TOUCH_TAG}, + {"reg_tracker", "tracker", FT_REG_TRACKER}, + {"reg_tracker_1", "tracker1 tracker_1", FT_REG_TRACKER_1}, + {"reg_tracker_2", "tracker2 tracker_2", FT_REG_TRACKER_2}, + {"reg_tracker_3", "tracker3 tracker_3", FT_REG_TRACKER_3}, + {"reg_tracker_4", "tracker4 tracker_4", FT_REG_TRACKER_4}, + {"reg_mediafifo_read", "mediafifo_read mediafiforead", FT_REG_MEDIAFIFO_READ}, + {"reg_mediafifo_write", "mediafifo_write mediafifowrite", FT_REG_MEDIAFIFO_WRITE}, + {"reg_flash_status", "flash_status flashstatus", FT_REG_FLASH_STATUS}, + {"reg_flash_size", "flash_size flashsize", FT_REG_FLASH_SIZE} +}; + +const FT_FC_CMD_DEF ft_fc_cmds[] = +{ + {"append", "ap", FT_CCMD_APPEND, 2, 2, FT_FC_FMT_RAW, 0}, + {"bgcolor", "bgc bc", FT_CCMD_BGCOLOR, 1, 1, FT_FC_FMT_RAW, 0}, + {"bitmap_transform", "bt", FT_CCMD_BITMAP_TRANSFORM, 13, 13, FT_FC_FMT_RAW, FT_FC_OUT(12)}, + {"button", "bu", FT_CCMD_BUTTON, 7, 7, FT_FC_FMT_BUTTON, 0}, + {"calibrate", "cal cb", FT_CCMD_CALIBRATE, 1, 1, FT_FC_FMT_RAW, FT_FC_OUT(0)}, + {"clock", "clk", FT_CCMD_CLOCK, 8, 8, FT_FC_FMT_CLOCK, 0}, + {"coldstart", "cold cs", FT_CCMD_COLDSTART, 0, 0, FT_FC_FMT_RAW, 0}, + {"crc", "crc", FT_CCMD_CRC, 3, 3, FT_FC_FMT_RAW, FT_FC_OUT(2)}, + {"csketch", "csk", FT_CCMD_CSKETCH, 7, 7, FT_FC_FMT_CSKETCH, 0}, + {"dial", "di", FT_CCMD_DIAL, 5, 5, FT_FC_FMT_DIAL, 0}, + {"dlstart", "dl", FT_CCMD_DLSTART, 0, 0, FT_FC_FMT_RAW, 0}, + {"execute", "ex", FT_CCMD_EXECUTE, 0, FT_FC_RAW_ARG_MAX, FT_FC_FMT_RAW, 0}, + {"fgcolor", "fgc", FT_CCMD_FGCOLOR, 1, 1, FT_FC_FMT_RAW, 0}, + {"flashattach", "fla", FT_CCMD_FLASHATTACH, 0, 0, FT_FC_FMT_RAW, 0}, + {"flashdetach", "fld", FT_CCMD_FLASHDETACH, 0, 0, FT_FC_FMT_RAW, 0}, + {"flasherase", "fle", FT_CCMD_FLASHERASE, 0, 0, FT_FC_FMT_RAW, 0}, + {"flashfast", "flf", FT_CCMD_FLASHFAST, 1, 1, FT_FC_FMT_RAW, FT_FC_OUT(0)}, + {"flashrx", "flr", FT_CCMD_FLASHRX, 2, 2, FT_FC_FMT_RAW, 0}, + {"flashsource", "fls", FT_CCMD_FLASHSOURCE, 1, 1, FT_FC_FMT_RAW, 0}, + {"flashspidesel", "fsd", FT_CCMD_FLASHSPIDESEL, 0, 0, FT_FC_FMT_RAW, 0}, + {"flashtx", "flt", FT_CCMD_FLASHTX, 1, 1, FT_FC_FMT_RAW, 0}, + {"flashupdate", "flu", FT_CCMD_FLASHUPDATE, 3, 3, FT_FC_FMT_RAW, 0}, + {"gauge", "ga", FT_CCMD_GAUGE, 8, 8, FT_FC_FMT_GAUGE, 0}, + {"getmatrix", "gm", FT_CCMD_GETMATRIX, 6, 6, FT_FC_FMT_RAW, FT_FC_OUT(0) | FT_FC_OUT(1) | FT_FC_OUT(2) | FT_FC_OUT(3) | FT_FC_OUT(4) | FT_FC_OUT(5)}, + {"getpoint", "gp", FT_CCMD_GETPOINT, 0, FT_FC_RAW_ARG_MAX, FT_FC_FMT_RAW, 0}, + {"getprops", "gpr", FT_CCMD_GETPROPS, 3, 3, FT_FC_FMT_RAW, FT_FC_OUT(1) | FT_FC_OUT(2)}, + {"getptr", "gpt", FT_CCMD_GETPTR, 1, 1, FT_FC_FMT_RAW, FT_FC_OUT(0)}, + {"gradcolor", "gc", FT_CCMD_GRADCOLOR, 1, 1, FT_FC_FMT_RAW, 0}, + {"gradient", "gr", FT_CCMD_GRADIENT, 6, 6, FT_FC_FMT_GRADIENT, 0}, + {"hammeraux", "ha", FT_CCMD_HAMMERAUX, 0, FT_FC_RAW_ARG_MAX, FT_FC_FMT_RAW, 0}, + {"idct_deleted", "idct", FT_CCMD_IDCT_DELETED, 0, FT_FC_RAW_ARG_MAX, FT_FC_FMT_RAW, 0}, + {"inflate", "inf", FT_CCMD_INFLATE, 1, FT_FC_RAW_ARG_MAX, FT_FC_FMT_RAW, 0}, + {"interrupt", "intr in", FT_CCMD_INTERRUPT, 1, 1, FT_FC_FMT_RAW, 0}, + {"int_ramshared", "irs", FT_CCMD_INT_RAMSHARED, 1, 1, FT_FC_FMT_RAW, 0}, + {"int_swloadimage", "isl", FT_CCMD_INT_SWLOADIMAGE, 2, 2, FT_FC_FMT_RAW, 0}, + {"keys", "ke", FT_CCMD_KEYS, 7, 7, FT_FC_FMT_BUTTON, 0}, + {"loadidentity", "li", FT_CCMD_LOADIDENTITY, 0, 0, FT_FC_FMT_RAW, 0}, + {"loadimage", "limg", FT_CCMD_LOADIMAGE, 2, FT_FC_RAW_ARG_MAX, FT_FC_FMT_RAW, 0}, + {"logo", "lo", FT_CCMD_LOGO, 0, 0, FT_FC_FMT_RAW, 0}, + {"march", "ma", FT_CCMD_MARCH, 0, FT_FC_RAW_ARG_MAX, FT_FC_FMT_RAW, 0}, + {"mediafifo", "mf", FT_CCMD_MEDIAFIFO, 2, 2, FT_FC_FMT_RAW, 0}, + {"memcpy", "mc", FT_CCMD_MEMCPY, 3, 3, FT_FC_FMT_RAW, 0}, + {"memcrc", "mcrc", FT_CCMD_MEMCRC, 3, 3, FT_FC_FMT_RAW, FT_FC_OUT(2)}, + {"memset", "ms", FT_CCMD_MEMSET, 3, 3, FT_FC_FMT_RAW, 0}, + {"memwrite", "mw", FT_CCMD_MEMWRITE, 2, FT_FC_RAW_ARG_MAX, FT_FC_FMT_MEMWRITE, 0}, + {"memzero", "mz", FT_CCMD_MEMZERO, 2, 2, FT_FC_FMT_RAW, 0}, + {"number", "num nb", FT_CCMD_NUMBER, 5, 5, FT_FC_FMT_NUMBER, 0}, + {"playvideo", "pv", FT_CCMD_PLAYVIDEO, 1, FT_FC_RAW_ARG_MAX, FT_FC_FMT_RAW, 0}, + {"progress", "pr", FT_CCMD_PROGRESS, 7, 7, FT_FC_FMT_SLIDER_PROGRESS, 0}, + {"regread", "rr", FT_CCMD_REGREAD, 2, 2, FT_FC_FMT_RAW, FT_FC_OUT(1)}, + {"romfont", "rf", FT_CCMD_ROMFONT, 2, 2, FT_FC_FMT_RAW, 0}, + {"rotate", "rot", FT_CCMD_ROTATE, 1, 1, FT_FC_FMT_RAW, 0}, + {"scale", "sca", FT_CCMD_SCALE, 2, 2, FT_FC_FMT_RAW, 0}, + {"screensaver", "ss", FT_CCMD_SCREENSAVER, 0, 0, FT_FC_FMT_RAW, 0}, + {"scrollbar", "sb", FT_CCMD_SCROLLBAR, 8, 8, FT_FC_FMT_SCROLLBAR, 0}, + {"setbase", "sbase", FT_CCMD_SETBASE, 1, 1, FT_FC_FMT_RAW, 0}, + {"setbitmap", "sbit", FT_CCMD_SETBITMAP, 4, 4, FT_FC_FMT_SETBITMAP, 0}, + {"setfont", "sfnt", FT_CCMD_SETFONT, 2, 2, FT_FC_FMT_RAW, 0}, + {"setfont2", "sf2", FT_CCMD_SETFONT2, 3, 3, FT_FC_FMT_RAW, 0}, + {"setmatrix", "smat", FT_CCMD_SETMATRIX, 0, 0, FT_FC_FMT_RAW, 0}, + {"setrotate", "sr", FT_CCMD_SETROTATE, 1, 1, FT_FC_FMT_RAW, 0}, + {"setscratch", "sscr", FT_CCMD_SETSCRATCH, 1, 1, FT_FC_FMT_RAW, 0}, + {"sketch", "sk", FT_CCMD_SKETCH, 6, 6, FT_FC_FMT_SKETCH, 0}, + {"slider", "sl", FT_CCMD_SLIDER, 7, 7, FT_FC_FMT_SLIDER_PROGRESS, 0}, + {"snapshot", "snap", FT_CCMD_SNAPSHOT, 1, 1, FT_FC_FMT_RAW, 0}, + {"snapshot2", "snap2", FT_CCMD_SNAPSHOT2, 6, 6, FT_FC_FMT_SNAPSHOT2, 0}, + {"spinner", "spn", FT_CCMD_SPINNER, 4, 4, FT_FC_FMT_SPINNER, 0}, + {"stop", "st", FT_CCMD_STOP, 0, 0, FT_FC_FMT_RAW, 0}, + {"swap", "sw", FT_CCMD_SWAP, 0, 0, FT_FC_FMT_RAW, 0}, + {"sync", "sy", FT_CCMD_SYNC, 0, 0, FT_FC_FMT_RAW, 0}, + {"text", "tx", FT_CCMD_TEXT, 5, 5, FT_FC_FMT_TEXT, 0}, + {"toggle", "tg", FT_CCMD_TOGGLE, 7, 7, FT_FC_FMT_TOGGLE, 0}, + {"touch_transform", "tt", FT_CCMD_TOUCH_TRANSFORM, 13, 13, FT_FC_FMT_RAW, FT_FC_OUT(12)}, + {"track", "trk", FT_CCMD_TRACK, 5, 5, FT_FC_FMT_TRACK, 0}, + {"translate", "tr", FT_CCMD_TRANSLATE, 2, 2, FT_FC_FMT_RAW, 0}, + {"videoframe", "vf", FT_CCMD_VIDEOFRAME, 2, 2, FT_FC_FMT_RAW, 0}, + {"videostart", "vs", FT_CCMD_VIDEOSTART, 0, 0, FT_FC_FMT_RAW, 0} +}; + +int ft_fc_named_value(const char *name, u32 *out) +{ + for (size_t i = 0; i < sizeof(ft_fc_values) / sizeof(ft_fc_values[0]); ++i) + { + if (ft_f_name_equals(ft_fc_values[i].name, name) || ft_f_alias_matches(ft_fc_values[i].aliases, name, 0)) + { + *out = ft_fc_values[i].value; + return 1; + } + } + + return ft_f_named_value(name, out); +} + +const FT_FC_CMD_DEF *ft_fc_find_cmd(const char *name, int *ambiguous) +{ + const FT_FC_CMD_DEF *match = nullptr; + int matches = 0; + + *ambiguous = 0; + + for (size_t i = 0; i < sizeof(ft_fc_cmds) / sizeof(ft_fc_cmds[0]); ++i) + { + const FT_FC_CMD_DEF *cmd = &ft_fc_cmds[i]; + if (ft_f_name_equals(cmd->name, name) || ft_f_alias_matches(cmd->aliases, name, 0)) + { + match = cmd; + matches++; + } + } + + if (matches == 1) return match; + if (matches > 1) + { + *ambiguous = 1; + return nullptr; + } + + for (size_t i = 0; i < sizeof(ft_fc_cmds) / sizeof(ft_fc_cmds[0]); ++i) + { + const FT_FC_CMD_DEF *cmd = &ft_fc_cmds[i]; + if (ft_f_name_starts_with(cmd->name, name) || ft_f_alias_matches(cmd->aliases, name, 1)) + { + match = cmd; + matches++; + } + } + + if (matches == 1) return match; + if (matches > 1) *ambiguous = 1; + return nullptr; +} + +int ft_fc_parse_base_expr(const char *s, const char *name, u32 base, u32 *out) +{ + size_t i = 0; + char *endp = nullptr; + unsigned long long off; + + if (!s || !name) return 0; + + while (name[i]) + { + if (tolower((unsigned char)s[i]) != tolower((unsigned char)name[i])) + return 0; + i++; + } + + if (!s[i]) + { + *out = base; + return 1; + } + + if (s[i] != '+') return 0; + + off = strtoull(s + i + 1, &endp, 0); + if (!endp || *endp || off > 0xFFFFFFFFULL) + return 0; + + *out = base + (u32)off; + return 1; +} + +int ft_fc_parse_out_arg(const char *s, u32 *value, u8 *dst_type, u32 *dst_off) +{ + u32 off; + + *dst_type = FT_FC_DST_NONE; + *dst_off = 0; + + if (ft_f_name_equals(s, "sp")) + { + if (ft_fc_ws.sp + 4 > FT_FC_SCRATCH_SIZE) + { + printf("fc scratchpad output overflow\r\n"); + return 0; + } + + *value = 0; + *dst_type = FT_FC_DST_SCRATCH; + *dst_off = ft_fc_ws.sp; + ft_fc_ws.sp += 4; + return 1; + } + + if (ft_fc_parse_base_expr(s, "scratch", 0, &off) || + ft_fc_parse_base_expr(s, "scratchpad", 0, &off)) + { + if (off + 4 > FT_FC_SCRATCH_SIZE || off > FT_FC_SCRATCH_SIZE) + { + printf("fc scratchpad output offset out of range: %lu\r\n", (unsigned long)off); + return 0; + } + + *value = 0; + *dst_type = FT_FC_DST_SCRATCH; + *dst_off = off; + return 1; + } + + if (ft_fc_parse_base_expr(s, "ts", 0, &off) || + ft_fc_parse_base_expr(s, "timestamps", 0, &off)) + { + if ((off & 3) || off + 4 > FT_FC_TS_COUNT * 4UL || off > FT_FC_TS_COUNT * 4UL) + { + printf("fc timestamp output offset out of range: %lu\r\n", (unsigned long)off); + return 0; + } + + *value = 0; + *dst_type = FT_FC_DST_TS; + *dst_off = off; + return 1; + } + + return 0; +} + +u32 ft_fc_parse_arg(const char *s, const char *name, int out_arg, int *ok, u8 *dst_type, u32 *dst_off, int *save) +{ + char *endp = nullptr; + u32 named; + size_t n; + + *ok = 0; + if (save) *save = 0; + if (dst_type) *dst_type = FT_FC_DST_NONE; + if (dst_off) *dst_off = 0; + + if (!s) + { + printf("Missing <%s>\r\n", name); + return 0; + } + + n = strlen(s); + if (n && s[n - 1] == ',') + ((char *)s)[n - 1] = 0; + + if (out_arg && dst_type && dst_off && save && ft_fc_parse_out_arg(s, &named, dst_type, dst_off)) + { + *ok = 1; + *save = 1; + return named; + } + + if (ft_fc_parse_base_expr(s, "sp", FT_FC_SCRATCH_ADDR + ft_fc_ws.sp, &named) || + ft_fc_parse_base_expr(s, "scratch", FT_FC_SCRATCH_ADDR, &named) || + ft_fc_parse_base_expr(s, "scratchpad", FT_FC_SCRATCH_ADDR, &named) || + ft_fc_parse_base_expr(s, "ts", FT_FC_TS_ADDR, &named) || + ft_fc_parse_base_expr(s, "timestamps", FT_FC_TS_ADDR, &named)) + { + *ok = 1; + return named; + } + + if (ft_fc_named_value(s, &named)) + { + *ok = 1; + return named; + } + + if (s[0] == '-') + { + long long v = strtoll(s, &endp, 0); + if (!endp || *endp || v < -2147483647LL - 1LL || v > 2147483647LL) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + *ok = 1; + return (u32)(i32)v; + } + + unsigned long long v = strtoull(s, &endp, 0); + if (!endp || *endp || v > 0xFFFFFFFFULL) + { + printf("Bad <%s>: %s\r\n", name, s); + return 0; + } + + *ok = 1; + return (u32)v; +} + + +int ft_fc_emit_u32(u32 v) +{ + if (ft_fc_ws.pos + 4 > FT_FC_CMD_MAX_BYTES) + { + printf("fc command buffer overflow: used=%lu max=%lu\r\n", + (unsigned long)ft_fc_ws.pos, + (unsigned long)FT_FC_CMD_MAX_BYTES); + return 0; + } + + wr32le(&ft_fc_ws.cmd[ft_fc_ws.pos], v); + ft_fc_ws.pos += 4; + return 1; +} + +int ft_fc_emit_str(const char *s) +{ + size_t len; + size_t padded; + + if (!s) s = ""; + + len = strlen(s) + 1; + padded = (len + 3) & ~(size_t)3; + + if (ft_fc_ws.pos + padded > FT_FC_CMD_MAX_BYTES) + { + printf("fc command buffer overflow: used=%lu add=%lu max=%lu\r\n", + (unsigned long)ft_fc_ws.pos, + (unsigned long)padded, + (unsigned long)FT_FC_CMD_MAX_BYTES); + return 0; + } + + memcpy(&ft_fc_ws.cmd[ft_fc_ws.pos], s, len); + memset(&ft_fc_ws.cmd[ft_fc_ws.pos + len], 0, padded - len); + ft_fc_ws.pos += (u32)padded; + return 1; +} + +u32 ft_fc_pack_16(u32 hi, u32 lo) +{ + return ((hi & 0xffffUL) << 16) | (lo & 0xffffUL); +} + +int ft_fc_add_output_save(u32 src_off, u8 dst_type, u32 dst_off) +{ + if (ft_fc_ws.save_count >= FT_FC_OUT_REC_MAX) + { + printf("fc output record overflow\r\n"); + return 0; + } + + if (src_off + 4 > ft_fc_ws.pos) + { + printf("fc bad output offset: %lu\r\n", (unsigned long)src_off); + return 0; + } + + ft_fc_ws.save_src_off[ft_fc_ws.save_count] = src_off; + ft_fc_ws.save_dst_type[ft_fc_ws.save_count] = dst_type; + ft_fc_ws.save_dst_off[ft_fc_ws.save_count] = dst_off; + ft_fc_ws.save_count++; + return 1; +} + +int ft_fc_emit_raw(const FT_FC_CMD_DEF *cmd, const u32 *a, int argc) +{ + if (!ft_fc_emit_u32(cmd->code)) return 0; + + for (int i = 0; i < argc; ++i) + { + ft_fc_ws.out_offs[i] = ft_fc_ws.pos; + if (!ft_fc_emit_u32(a[i])) return 0; + } + + for (int i = 0; i < argc; ++i) + { + if (ft_fc_ws.out_save[i]) + { + if (!ft_fc_add_output_save(ft_fc_ws.out_offs[i], ft_fc_ws.out_dst_type[i], ft_fc_ws.out_dst_off[i])) + return 0; + } + } + + return 1; +} + + +int ft_fc_emit_memwrite(const FT_FC_CMD_DEF *cmd, const u32 *a, int argc) +{ + u32 num; + + if (argc < 2) + { + printf("Bad argument count for %s: %d, expected 2..%u\r\n", + cmd->name, argc, (unsigned int)cmd->max_args); + return 0; + } + + num = (u32)(argc - 1) * 4UL; + + if (!ft_fc_emit_u32(cmd->code)) return 0; + if (!ft_fc_emit_u32(a[0])) return 0; + if (!ft_fc_emit_u32(num)) return 0; + + for (int i = 1; i < argc; ++i) + { + if (!ft_fc_emit_u32(a[i])) return 0; + } + + return 1; +} + +int ft_fc_emit_cmd(const FT_FC_CMD_DEF *cmd, const u32 *a, int argc, const char *str) +{ + switch ((FT_FC_FMT)cmd->fmt) + { + case FT_FC_FMT_RAW: + return ft_fc_emit_raw(cmd, a, argc); + + case FT_FC_FMT_MEMWRITE: + return ft_fc_emit_memwrite(cmd, a, argc); + + case FT_FC_FMT_TEXT: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_str(str); + + case FT_FC_FMT_BUTTON: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(ft_fc_pack_16(a[5], a[4])) && + ft_fc_emit_str(str); + + case FT_FC_FMT_TOGGLE: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(ft_fc_pack_16(a[5], a[4])) && + ft_fc_emit_str(str); + + case FT_FC_FMT_NUMBER: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(a[4]); + + case FT_FC_FMT_CLOCK: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(ft_fc_pack_16(a[5], a[4])) && + ft_fc_emit_u32(ft_fc_pack_16(a[7], a[6])); + + case FT_FC_FMT_GAUGE: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(ft_fc_pack_16(a[5], a[4])) && + ft_fc_emit_u32(ft_fc_pack_16(a[7], a[6])); + + case FT_FC_FMT_SLIDER_PROGRESS: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(ft_fc_pack_16(a[5], a[4])) && + ft_fc_emit_u32(a[6]); + + case FT_FC_FMT_SCROLLBAR: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(ft_fc_pack_16(a[5], a[4])) && + ft_fc_emit_u32(ft_fc_pack_16(a[7], a[6])); + + case FT_FC_FMT_DIAL: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(a[4]); + + case FT_FC_FMT_GRADIENT: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(a[2]) && + ft_fc_emit_u32(ft_fc_pack_16(a[4], a[3])) && + ft_fc_emit_u32(a[5]); + + case FT_FC_FMT_TRACK: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(a[4]); + + case FT_FC_FMT_SNAPSHOT2: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(a[0]) && + ft_fc_emit_u32(a[1]) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(ft_fc_pack_16(a[5], a[4])); + + case FT_FC_FMT_SKETCH: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(a[4]) && + ft_fc_emit_u32(a[5]); + + case FT_FC_FMT_CSKETCH: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])) && + ft_fc_emit_u32(a[4]) && + ft_fc_emit_u32(ft_fc_pack_16(a[6], a[5])); + + case FT_FC_FMT_SETBITMAP: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(a[0]) && + ft_fc_emit_u32(ft_fc_pack_16(a[2], a[1])) && + ft_fc_emit_u32(a[3]); + + case FT_FC_FMT_SPINNER: + return ft_fc_emit_u32(cmd->code) && + ft_fc_emit_u32(ft_fc_pack_16(a[1], a[0])) && + ft_fc_emit_u32(ft_fc_pack_16(a[3], a[2])); + } + + return 0; +} + +int ft_fc_emit_timestamp() +{ + u32 out_off; + + if (ft_fc_ws.ts_pos >= FT_FC_TS_COUNT) + { + printf("fc timestamp stack overflow\r\n"); + return 0; + } + + if (!ft_fc_emit_u32(FT_CCMD_REGREAD)) return 0; + if (!ft_fc_emit_u32(FT_REG_CLOCK)) return 0; + out_off = ft_fc_ws.pos; + if (!ft_fc_emit_u32(0)) return 0; + + if (!ft_fc_add_output_save(out_off, FT_FC_DST_TS, ft_fc_ws.ts_pos * 4UL)) + return 0; + + ft_fc_ws.ts_pos++; + return 1; +} + + + +char *ft_fc_unescape_token(char *s, char quote) +{ + char *d = s; + + while (*s) + { + if (*s == quote) + { + *d = 0; + return s + 1; + } + + if (*s == '\\' && s[1]) + { + s++; + switch (*s) + { + case 'n': *d++ = '\n'; break; + case 'r': *d++ = '\r'; break; + case 't': *d++ = '\t'; break; + default: *d++ = *s; break; + } + s++; + continue; + } + + *d++ = *s++; + } + + *d = 0; + return nullptr; +} + +int ft_fc_split_words(char *s, char **argv, int max_argc) +{ + int argc = 0; + + s = ft_f_skip_spaces(s); + while (s && *s) + { + if (argc >= max_argc) + { + printf("Too many fc command arguments\r\n"); + return -1; + } + + if (*s == '"' || *s == '\'') + { + char quote = *s++; + argv[argc++] = s; + s = ft_fc_unescape_token(s, quote); + if (!s) + { + printf("Unterminated string in fc command\r\n"); + return -1; + } + + s = ft_f_skip_spaces(s); + continue; + } + + argv[argc++] = s; + while (*s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n') + s++; + + if (!*s) break; + *s++ = 0; + s = ft_f_skip_spaces(s); + } + + return argc; +} + +char *ft_fc_next_segment(char **cursor) +{ + char *seg = *cursor; + char *s = seg; + char quote = 0; + + if (!seg) return nullptr; + + while (*s) + { + if (quote) + { + if (*s == '\\' && s[1]) + { + s += 2; + continue; + } + + if (*s == quote) + quote = 0; + + s++; + continue; + } + + if (*s == '"' || *s == '\'') + { + quote = *s++; + continue; + } + + if (*s == ';') + { + *s++ = 0; + *cursor = s; + return seg; + } + + s++; + } + + *cursor = nullptr; + return seg; +} + +int ft_fc_exec_segment(char *segment) +{ + const FT_FC_CMD_DEF *cmd; + const char *str = nullptr; + int argc; + int cmd_arg = 0; + int arg_count; + int ambiguous; + + argc = ft_fc_split_words(segment, ft_fc_ws.argv, FT_FC_ARG_MAX); + if (argc < 0) return 1; + if (!argc) return 0; + + if (ft_f_name_equals(ft_fc_ws.argv[0], "fc")) + { + if (argc == 1) return 0; + cmd_arg = 1; + } + + if (ft_f_name_equals(ft_fc_ws.argv[cmd_arg], "ts")) + { + if (argc != cmd_arg + 1) + { + printf("Usage: ts\r\n"); + return 1; + } + + return ft_fc_emit_timestamp() ? 0 : 1; + } + + cmd = ft_fc_find_cmd(ft_fc_ws.argv[cmd_arg], &ambiguous); + if (!cmd) + { + if (ambiguous) + printf("Ambiguous co-processor command: %s\r\n", ft_fc_ws.argv[cmd_arg]); + else + printf("Unknown co-processor command: %s\r\n", ft_fc_ws.argv[cmd_arg]); + return 1; + } + + arg_count = argc - cmd_arg - 1; + if (arg_count < cmd->min_args || arg_count > cmd->max_args) + { + printf("Bad argument count for %s: %d, expected ", cmd->name, arg_count); + if (cmd->min_args == cmd->max_args) + printf("%u\r\n", (unsigned int)cmd->min_args); + else + printf("%u..%u\r\n", (unsigned int)cmd->min_args, (unsigned int)cmd->max_args); + return 1; + } + + if (cmd->fmt == FT_FC_FMT_TEXT || cmd->fmt == FT_FC_FMT_BUTTON || cmd->fmt == FT_FC_FMT_TOGGLE) + { + str = ft_fc_ws.argv[argc - 1]; + arg_count--; + } + + if (arg_count > FT_FC_RAW_ARG_MAX) + { + printf("Too many fc command arguments\r\n"); + return 1; + } + + memset(ft_fc_ws.out_save, 0, sizeof(ft_fc_ws.out_save)); + memset(ft_fc_ws.out_dst_type, 0, sizeof(ft_fc_ws.out_dst_type)); + memset(ft_fc_ws.out_dst_off, 0, sizeof(ft_fc_ws.out_dst_off)); + + for (int i = 0; i < arg_count; ++i) + { + int ok; + int save; + u8 dst_type; + u32 dst_off; + int out_arg = (cmd->out_mask & FT_FC_OUT(i)) != 0; + ft_fc_ws.args[i] = ft_fc_parse_arg(ft_fc_ws.argv[cmd_arg + 1 + i], "arg", out_arg, &ok, &dst_type, &dst_off, &save); + if (!ok) return 1; + ft_fc_ws.out_save[i] = (u8)save; + ft_fc_ws.out_dst_type[i] = dst_type; + ft_fc_ws.out_dst_off[i] = dst_off; + } + + if (!ft_fc_emit_cmd(cmd, ft_fc_ws.args, arg_count, str)) + return 1; + + return 0; +} + +int ft_fc_build(int argc, char **argv) +{ + size_t pos = 0; + char *seg; + char *cursor; + + ft_fc_ws.pos = 0; + ft_fc_ws.ts_pos = 0; + ft_fc_ws.save_count = 0; + ft_fc_ws.sp = 0; + ft_fc_ws.line[0] = 0; + memset(ft_fc_ws.ts, 0, sizeof(ft_fc_ws.ts)); + memset(ft_fc_ws.scratch, 0, sizeof(ft_fc_ws.scratch)); + + for (int i = 0; i < argc; ++i) + { + size_t n; + + if (!argv[i]) continue; + + n = strlen(argv[i]); + if (pos + n + (pos ? 1 : 0) + 1 > sizeof(ft_fc_ws.line)) + { + printf("fc command line is too long\r\n"); + return 1; + } + + if (pos) + ft_fc_ws.line[pos++] = ' '; + memcpy(&ft_fc_ws.line[pos], argv[i], n); + pos += n; + ft_fc_ws.line[pos] = 0; + } + + cursor = ft_fc_ws.line; + while ((seg = ft_fc_next_segment(&cursor)) != nullptr) + { + if (ft_fc_exec_segment(seg)) + return 1; + } + + return 0; +} + +esp_err_t ft_fc_wait_idle(uint32_t timeout_ms) +{ + int64_t t0 = esp_timer_get_time(); + + while (1) + { + u16 rp = ft_rreg16(FT_REG_CMD_READ) & 0x0FFF; + u16 wp = ft_rreg16(FT_REG_CMD_WRITE) & 0x0FFF; + + if (rp == 0x0FFF || wp == 0x0FFF) + return ESP_FAIL; + + if (rp == wp) + return ESP_OK; + + if (((esp_timer_get_time() - t0) / 1000) >= (int64_t)timeout_ms) + return ESP_ERR_TIMEOUT; + + vTaskDelay(pdMS_TO_TICKS(1)); + } +} + +esp_err_t ft_fc_write_cmd_stream(u32 start, u32 size) +{ + u32 first; + esp_err_t err; + + if (!size) return ESP_OK; + + if (start + size <= FT_CMD_FIFO_SIZE) + return ft_write(ft_fc_ws.cmd, FT_RAM_CMD + start, size); + + first = FT_CMD_FIFO_SIZE - start; + err = ft_write(ft_fc_ws.cmd, FT_RAM_CMD + start, first); + if (err != ESP_OK) return err; + + return ft_write(ft_fc_ws.cmd + first, FT_RAM_CMD, size - first); +} + +esp_err_t ft_fc_read_cmd_stream(u32 start, u32 size) +{ + u32 first; + esp_err_t err; + + if (!size) return ESP_OK; + + if (start + size <= FT_CMD_FIFO_SIZE) + return ft_read(ft_fc_ws.cmd, FT_RAM_CMD + start, size); + + first = FT_CMD_FIFO_SIZE - start; + err = ft_read(ft_fc_ws.cmd, FT_RAM_CMD + start, first); + if (err != ESP_OK) return err; + + return ft_read(ft_fc_ws.cmd + first, FT_RAM_CMD, size - first); +} + +void ft_fc_store_output(u8 dst_type, u32 dst_off, u32 value) +{ + if (dst_type == FT_FC_DST_SCRATCH) + { + wr32le(&ft_fc_ws.scratch[dst_off], value); + return; + } + + if (dst_type == FT_FC_DST_TS) + wr32le(&ft_fc_ws.ts[dst_off], value); +} + +int ft_fc_extract_outputs() +{ + for (u32 i = 0; i < ft_fc_ws.save_count; ++i) + { + u32 src_off = ft_fc_ws.save_src_off[i]; + u32 value; + + if (src_off + 4 > ft_fc_ws.pos) + { + printf("fc bad output readback offset: %lu\r\n", (unsigned long)src_off); + return 0; + } + + value = ft_rd32le(&ft_fc_ws.cmd[src_off]); + ft_fc_store_output(ft_fc_ws.save_dst_type[i], ft_fc_ws.save_dst_off[i], value); + } + + return 1; +} + +esp_err_t ft_fc_reset_fifo() +{ + esp_err_t err; + + err = ft_cp_reset(); + if (err != ESP_OK) return err; + + return ft_fc_wait_idle(1000); +} + +void ft_fc_dump_stream(u32 start, u32 next) +{ + printf("\r\nfc command stream before exec (%lu bytes, start=0x%03lX next=0x%03lX):\r\n", + (unsigned long)ft_fc_ws.pos, + (unsigned long)start, + (unsigned long)next); + hexdump(ft_fc_ws.cmd, ft_fc_ws.pos, FT_RAM_CMD + start); +} + +void ft_fc_print_timestamps(u32 frequency) +{ + u32 base = 0; + u32 prev = 0; + int have_base = 0; + u32 printed = 0; + + printf("\r\nfc timestamps:\r\n"); + + if (!frequency) + frequency = 60000000UL; + + for (u32 i = 0; i < ft_fc_ws.save_count; ++i) + { + u32 off; + u32 v; + u32 total_ticks; + u32 delta_ticks; + uint64_t total_us; + uint64_t delta_us; + + if (ft_fc_ws.save_dst_type[i] != FT_FC_DST_TS) + continue; + + off = ft_fc_ws.save_dst_off[i]; + v = ft_rd32le(&ft_fc_ws.ts[off]); + + if (!have_base) + { + base = v; + prev = v; + have_base = 1; + } + + total_ticks = v - base; + delta_ticks = v - prev; + total_us = ((uint64_t)total_ticks * 1000000ULL) / (uint64_t)frequency; + delta_us = ((uint64_t)delta_ticks * 1000000ULL) / (uint64_t)frequency; + + printf(" %03lu: total %lu ticks, %llu us; delta %lu ticks, %llu us\r\n", + (unsigned long)printed, + (unsigned long)total_ticks, + (unsigned long long)total_us, + (unsigned long)delta_ticks, + (unsigned long long)delta_us); + + prev = v; + printed++; + } + + if (!printed) + printf(" none\r\n"); +} + + +const char *ft_fc_cmd_args(const FT_FC_CMD_DEF *cmd) +{ + switch (cmd->code) + { + case FT_CCMD_APPEND: return " "; + case FT_CCMD_BGCOLOR: return ""; + case FT_CCMD_BITMAP_TRANSFORM: return " "; + case FT_CCMD_BUTTON: return " "; + case FT_CCMD_CALIBRATE: return ""; + case FT_CCMD_CLOCK: return " "; + case FT_CCMD_COLDSTART: return ""; + case FT_CCMD_CRC: return " "; + case FT_CCMD_CSKETCH: return " "; + case FT_CCMD_DIAL: return " "; + case FT_CCMD_DLSTART: return ""; + case FT_CCMD_EXECUTE: return "[u32...]"; + case FT_CCMD_FGCOLOR: return ""; + case FT_CCMD_FLASHATTACH: return ""; + case FT_CCMD_FLASHDETACH: return ""; + case FT_CCMD_FLASHERASE: return ""; + case FT_CCMD_FLASHFAST: return ""; + case FT_CCMD_FLASHRX: return " "; + case FT_CCMD_FLASHSOURCE: return ""; + case FT_CCMD_FLASHSPIDESEL: return ""; + case FT_CCMD_FLASHTX: return ""; + case FT_CCMD_FLASHUPDATE: return " "; + case FT_CCMD_GAUGE: return " "; + case FT_CCMD_GETMATRIX: return " "; + case FT_CCMD_GETPOINT: return "[u32...]"; + case FT_CCMD_GETPROPS: return " "; + case FT_CCMD_GETPTR: return ""; + case FT_CCMD_GRADCOLOR: return ""; + case FT_CCMD_GRADIENT: return " "; + case FT_CCMD_HAMMERAUX: return "[u32...]"; + case FT_CCMD_IDCT_DELETED: return "[u32...]"; + case FT_CCMD_INFLATE: return " [data...]"; + case FT_CCMD_INTERRUPT: return ""; + case FT_CCMD_INT_RAMSHARED: return ""; + case FT_CCMD_INT_SWLOADIMAGE: return " "; + case FT_CCMD_KEYS: return " "; + case FT_CCMD_LOADIDENTITY: return ""; + case FT_CCMD_LOADIMAGE: return " [image-data...]"; + case FT_CCMD_LOGO: return ""; + case FT_CCMD_MARCH: return "[u32...]"; + case FT_CCMD_MEDIAFIFO: return " "; + case FT_CCMD_MEMCPY: return " "; + case FT_CCMD_MEMCRC: return " "; + case FT_CCMD_MEMSET: return " "; + case FT_CCMD_MEMWRITE: return " "; + case FT_CCMD_MEMZERO: return " "; + case FT_CCMD_NUMBER: return " "; + case FT_CCMD_PLAYVIDEO: return " [video-data...]"; + case FT_CCMD_PROGRESS: return " "; + case FT_CCMD_REGREAD: return " "; + case FT_CCMD_ROMFONT: return " "; + case FT_CCMD_ROTATE: return ""; + case FT_CCMD_SCALE: return " "; + case FT_CCMD_SCREENSAVER: return ""; + case FT_CCMD_SCROLLBAR: return " "; + case FT_CCMD_SETBASE: return ""; + case FT_CCMD_SETBITMAP: return " "; + case FT_CCMD_SETFONT: return " "; + case FT_CCMD_SETFONT2: return " "; + case FT_CCMD_SETMATRIX: return ""; + case FT_CCMD_SETROTATE: return ""; + case FT_CCMD_SETSCRATCH: return ""; + case FT_CCMD_SKETCH: return " "; + case FT_CCMD_SLIDER: return " "; + case FT_CCMD_SNAPSHOT: return ""; + case FT_CCMD_SNAPSHOT2: return " "; + case FT_CCMD_SPINNER: return "