chore: checkpoint 第一版
ci / verify (push) Canceled after 0s

This commit is contained in:
Codex Local
2026-09-06 17:04:11 +08:00
parent a8cdec98d1
commit 0c2151ace9
659 changed files with 185855 additions and 554 deletions
@@ -0,0 +1,13 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
# include($ENV{IDF_PATH}/tools/cmake/project.cmake)
#include($ENV{ADF_PATH}/CMakeLists.txt)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(VolcRTCDemo)
# add_compile_definitions(LWIP_DEBUG=1)
+211
View File
@@ -0,0 +1,211 @@
<h1 align="center"><img src="https://iam.volccdn.com/obj/volcengine-public/pic/volcengine-icon.png"></h1>
<h1 align="center">ConversationalAI Embedded Kit 2.0 </h1>
## EchoEar 平台版固件
本目录是在火山官方 Embedded Kit 2.0 基础上适配的 ESP32-S3 EchoEar 固件。它使用低负载 WebSocket 方案,并将设备身份、动态注册和会话配置统一接入自有 SaaS。
安全边界:
- 固件和设备端都不包含火山 `Product Secret`;
- SaaS 使用平台设备身份为 EchoEar 动态申请火山 `Device Secret`;
- EchoEar 只保存自己的平台设备凭据和火山单设备凭据;
- 每次对话前由 SaaS 下发 Bot、人设、记忆上下文和会话配置;
- 字幕和最终轮次回传 SaaS,供会话记录与长期记忆处理。
当前测试硬件:ESP32-S3 EchoEar,16 MB Flash、16 MB PSRAM,硬件标识由 STA MAC 生成(当前板为 `echoear-b43a451634a8`)。
每次申请对话前,先通过 `/device/v2/bootstrap` 上报实际固件版本并检查 `firmware_compatible`,再获取配置和创建会话。固件版本为 `1.0.0-echoear-platform.1`;本工程基于 Embedded Kit 2.0,硬件智能体 SDK 版本独立上报为 `2.0.0`。会话能力中的 `sdk_version` 不能用固件版本代替。会话尚未创建时保持唤醒采集,不重复拆建音频管线。SPI 屏幕仅在 `on_color_trans_done` 后释放 GFX 帧缓冲,避免异步传输期间提前复用缓冲区。运行状态用眼睛动画表示,避免 80 MHz 下中文逐像素渲染长期占用 CPU:快速眨眼表示聆听,转圈表示思考,正常眼睛表示待机或回答。
本板构建使用 16 MB Flash,Flash 与八线 PSRAM 均为 80 MHz。通用默认配置、ESP32-S3 默认配置和当前 `sdkconfig` 必须一致;不要恢复上游的 32 MB Flash 或实验性 120 MHz PSRAM 参数。
唤醒词为“嗨,乐鑫”,启用 `CONFIG_SR_WN_WN9_HILEXIN`,使用 `DET_MODE_95` 高灵敏度检测,并将 AFE 线性增益设为 2.0。生成的 `build/srmodels/srmodels.bin` 必须包含 `wn9_hilexin` 模型(约291 KB),并烧录到 `model` 分区 `0x510000`;不能使用未选择任何模型时生成的4字节空文件。
EchoEar V1.2 的 ES7210 使用 TDM:I2S 按两路32位接收,AFE 按四路16位解释,布局为 `RMNM`(ch1/ch3 麦克风、ch0 回声参考、ch2 忽略)。不可改成两路16位 `MR`。诊断日志 `MIC_LEVEL` 仅记录各路幅度统计,不保存录音。PCM输出每帧60 ms、16 kHz、单声道16位,读取缓冲区为1920字节,避免截断半帧。唤醒事件在会话服务就绪后直接发布,不依赖已移除的 `CONFIG_LANGUAGE_WAKEUP_MODE`。
低负载 WebSocket 任务使用 12 KiB 栈;4 KiB 会在收到 `session.created` 后发生栈溢出并重启。握手期间暂停上传麦克风帧,待引擎进入 STARTED 后再发送。低负载接口返回的 PCM 按 24 kHz 单声道16位解码,再由播放管线转换到板载 16 kHz I2S。`session.created` 的 `job_id` 用作平台启动确认,确保后续字幕和结束事件在 ACTIVE 会话上提交。
联网、平台 HTTPS 激活和音频初始化在独立的 24 KiB 启动任务中执行,避免默认 4 KiB `main` 栈溢出导致循环重启;任务退出时释放栈,并记录启动阶段最小栈余量。平台激活成功后才启动音频采集。激活失败时保留设备配置、显示绑定或配置提示,并仅记录平台错误码,不输出响应正文或凭据。
STA 连接使用全信道扫描并按信号强度选择同名 AP,实时语音期间关闭 Wi-Fi 省电,避免多 AP 环境中误连弱信号节点造成 WebSocket 写入失败。
### Windows 编译与烧录
使用 ESP-IDF v5.5.1:
```powershell
. 'E:\Codex\toolchains\esp-idf-v5.5.1\export.ps1'
idf.py build
idf.py -p COM6 flash
idf.py -p COM6 monitor
```
首次烧录前建议完整备份 Flash。当前板原厂备份位于 `backups/b43a451634a8/factory-2026-09-03-16mb.bin`,恢复命令:
```powershell
esptool.py --chip esp32s3 --port COM6 write_flash 0x0 backups/b43a451634a8/factory-2026-09-03-16mb.bin
```
### 首次激活
首次启动、缺少平台设备凭据、保存的 Wi-Fi 连接失败或超时,以及手动请求重新配网时,都会进入配置热点,无需清空 NVS:
1. 连接 `VolcConvAI-XXXXXX`,热点密码与热点名相同;
2. 打开 `http://192.168.4.1`;
3. 填写 2.4 GHz Wi-Fi、平台 Device ID 和平台 Device Secret;
4. 重启后,设备通过 SaaS 完成火山动态注册并获取单设备运行凭据。
正常运行时短触圆屏任意位置可直接开始对话,作为唤醒词的可靠备用入口。屏幕底部区域持续按住3秒后设备重启并开启配置热点。该操作保留原来的 Wi-Fi 和设备身份,只记录重新配网请求;成功提交配网页后退出配网模式。触摸任务在联网和平台激活之前创建,因此激活失败时也可以请求重新配网。
如果尚未配置平台设备身份,固件不会尝试用 Product Secret 直接访问火山。
重新配网回归检查(需要烧录后实机验证):
- 已保存可用 Wi-Fi、但缺少平台凭据:启动后直接出现热点和配网地址。
- Wi-Fi 密码错误或 DHCP 超时:连接等待结束后进入热点,不能重启循环。
- 正常运行时:短触屏幕启动对话;按住屏幕底部区域3秒进入配置热点。
- 配网页提交错误 Wi-Fi 后可重试;只有取得 IP 地址后才保存配置并重启。
- 配网页成功提交后正常启动,手动配网请求清除,原平台身份不会因进入配网而被删除。
本地 `idf.py build` 仅验证编译、链接和分区大小,不代替热点可见性、触摸坐标及长按时长的实机验证。
配网页提交使用 JSON 与后台连接任务,`POST /submit` 受理后立即返回 202,页面通过 `GET /setup-status` 查询连接、保存成功或失败状态。连接失败可以重试;保存成功后等待15秒重启,再由启动流程执行平台激活。Wi-Fi 扫描改为手动触发,连接期间不扫描。更新固件后请刷新配网页,避免继续使用已经打开的旧表单。
配网页交互回归:`node --test tests/setup-portal.test.cjs`(模拟设备响应,覆盖失败重试、响应丢失、断联、成功提示和输入校验)。
## 快速开始
具体操作,请参考 [官网文档](https://www.volcengine.com/docs/6348/1806625)。
## 运行设备端(乐鑫)
以下操作以 macOS 操作系统为例。
### 环境与硬件要求
- 乐鑫 ESP32-S3-Korvo-2
- USB 数据线:两条 A 转 Micro-B 数据线,一条作为电源线,一条作为串口线。
- PC 设备:编译和烧录。支持 Windows、Linux 或者 macOS 操作系统。(本文操作以 macOS 为例)
### 配置乐鑫环境
详见[开发环境配置文档](https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32s3/get-started/index.html)。
1. 安装 CMake 和 Ninja 编译工具。
```bash
brew install cmake ninja dfu-util
```
2. 将乐鑫 ADF 框架克隆到本地,并同步各子仓(submodule)代码。
> **注意**:Demo 中使用的 ADF 版本为 `eca11f20e56f9b5321b714da4305e123672d92a9`,对应 IDF 版本为 `v5.4`,请确保 ADF 版本与 IDF 版本匹配。
>
```bash
# 1. clone 乐鑫 ADF 框架
git clone https://github.com/espressif/esp-adf.git
# 2. 进入esp-adf目录
cd esp-adf
# 3. 切换到乐鑫 ADF 指定版本
git reset --hard eca11f20e56f9b5321b714da4305e123672d92a9
# 4. 同步各子仓代码
git submodule update --init --recursive
```
3. 安装乐鑫 esp32s3 开发环境相关依赖。
```bash
./install.sh esp32s3
```
成功安装所有依赖后,命令行会出现如下提示:
```bash
All done! You can now run:
. ./export.sh
```
> 如在上述任何步骤中遇到以下错误:
> `<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:xxx)`
> 可前往**访达->应用程序->Python** 文件夹,点击 `Install Certificates.command` 安装证书。更多信息,请参考 [安装 ESP-IDF 工具时出现的下载错误](https://github.com/espressif/esp-idf/issues/4775)。
>
4. 设置环境变量。
> **每次打开命令行窗口均需要运行该命令进行设置。**
>
```bash
. ./export.sh
```
### 下载并配置工程
1. 将实时对话式 AI 硬件示例工程克隆到 乐鑫 ADF examples 目录下。
1. 进入 esp-adf/examples 目录。
```bash
cd $ADF_PATH/examples
```
2. 克隆实时对话式 AI 硬件示例工程。
```bash
git clone https://github.com/volcengine/ConversationalAI-Embedded-Kit-2.0.git
```
2. 修复乐鑫按键问题
1. 进入 esp-adf 目录。
```bash
cd $ADF_PATH
```
2. 修复乐鑫按键问题。
```bash
git apply $ADF_PATH/examples/ConversationalAI-Embedded-Kit-2.0/low_load_first/espressif/0002-fix-esp-button.patch
```
### 编译固件
进入 `esp-adf/examples/ConversationalAI-Embedded-Kit-2.0/low_load_first/espressif` 目录下编译固件。
1. 进入 espressif 目录。
```bash
cd $ADF_PATH/examples/ConversationalAI-Embedded-Kit-2.0/low_load_first/espressif
```
2. 设置编译目标平台。
```bash
idf.py set-target esp32s3
```
3. 设置 实例ID、产品ID、产品秘钥、设备ID等参数。
```bash
idf.py menuconfig
```
进入 `Example Configuration` 菜单,在 `volcano instance id` 中填入你的实例ID,在 `volcano product key` 中填入你的产品Key,在 `volcano product secret` 中填入你的产品秘钥,在 `device name` 中填入你的设备ID, 在 `bot id` 中填入你的智能体ID,并保存。
4. 编译固件。
```bash
idf.py build
```
### 烧录并运行示例 Demo
1. 打开乐鑫开发板电源开关。
2. 烧录固件。
```bash
idf.py flash
```
3. 运行示例 Demo 并查看串口日志输出。
```bash
idf.py monitor
```
4. Wi-Fi 配网。
1. 手机找到名如 VolcConvAI-XXXXXX” 的 Wi-Fi 热点,密码同Wi-Fi名,连接上 Wi-Fi。
2. 打开浏览器,在地址栏输入 `http://192.168.4.1`,进入 Wi-Fi 配网页面。
3. 输入 Wi-Fi 名称和密码,点击提交。
> **注意**:如果需更换 Wi-Fi,请重启设备。如果设备重启后无法连接到之前保存的 Wi-Fi(例如超出了范围或旧网络已关闭),请等待 30s 进入配网模式,再重新执行上面 Wi-Fi 配网的 3 个步骤。
>
Binary file not shown.
@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.16)
message(STATUS "................. ${CMAKE_SYSTEM_NAME}")
if("${CMAKE_SYSTEM_NAME}" MATCHES "(Rtos|rtos|RTOS)+")
set(PLATFORM_RTOS TRUE)
add_compile_definitions(PLATFORM_RTOS)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "(Linux|linux|LINUX)+")
set(PLATFORM_LINUX TRUE)
add_compile_definitions(PLATFORM_LINUX)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "(android|Android|ANDROID)+")
set(PLATFORM_ANDROID TRUE)
add_compile_definitions(PLATFORM_ANDROID)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "(Darwin|darwin|MACOSX|macosx|MACOS|macos)+")
set(PLATFORM_MACOS TRUE)
add_compile_definitions(PLATFORM_MACOS)
endif()
include(${CMAKE_CURRENT_LIST_DIR}/cmake/common.cmake)
if(ESP_PLATFORM)
message(STATUS "ESP_PLATFORM is defined, including esp.cmake")
include(${CMAKE_CURRENT_LIST_DIR}/cmake/espressif.cmake)
return()
elseif(PLATFORM_MACOS)
message(STATUS "PLATFORM_MACOS is defined, including macos.cmake")
include(${CMAKE_CURRENT_LIST_DIR}/cmake/macos.cmake)
return()
endif()
@@ -0,0 +1,734 @@
# `application` 代码梳理
> 说明:本文档由 AI 在阅读当前目录代码后生成,目标是帮助读者快速理解代码结构、模块职责与主要运行流程,作为代码导读使用。
## 1. 目录定位
`application` 不是单一的业务文件夹,而是一套面向设备侧 AI 对话场景的“应用层组件”:
- `framework/` 提供事件驱动框架,解决不同业务模块之间的通信问题。
- `platform/` 提供硬件抽象层 HAL,屏蔽板级和外设细节。
- `service/` 提供 AI 对话业务拆分后的多个服务模块。
- `cmake/` 负责把 framework、platform、service 组装成一个 ESP-IDF 组件。
结合各子目录 `README_zh.md` 的设计说明,可以把这套代码理解为:
- `volc_conv_ai` 是底层云连接 SDK。
- `application` 则是建立在该 SDK 之上的业务应用框架。
也就是说,`application` 关注的是“设备如何组织业务逻辑、如何和硬件协作、如何把 AI 对话跑起来”,而不是连接协议本身。
## 2. 总体分层
整个目录可以概括成 3 层:
### 2.1 Framework 层
职责是让不同业务模块通过事件 `pub/sub` 通信,不直接相互调用。
核心文件:
- `framework/inc/aios.h`
- `framework/inc/aios_def.h`
- `framework/src/aios.c`
这是整个应用层的“调度内核”。
### 2.2 Platform 层
职责是为 AI 对话场景提供硬件抽象:
- 音频采集
- 音频播放
- 屏幕显示
- 按键
- 文件系统
- 全局硬件上下文
核心文件:
- `platform/inc/volc_hal.h`
- `platform/inc/volc_hal_*.h`
- `platform/src/espressif/*.c`
从当前实现看,`platform/src/espressif` 是主实现平台,明显以 ESP32/ESP-IDF 为目标。
### 2.3 Service 层
职责是把 AI 对话业务拆成几个相互解耦的服务:
- `conv_service`
- 负责 AI 对话的建立、运行、退出。
- `function_call_service`
- 负责处理智能体触发的 function call。
- `local_logic_service`
- 负责本地预设逻辑,不依赖大模型理解。
- `service/src/volc_manager_service.c`
- 负责接收高层业务入口事件,并拉起对应 service。
这与 `service/README_zh.md` 的描述是一致的。
## 3. 这个目录不是完整 App Main
单看 `application` 目录,本身**没有完整的 `main/app_main`**。
它更像是一个“可复用的应用组件库”。真正的组装顺序出现在仓库里的示例,例如:
- `examples/high_quality_solution/espressif/main/conv_ai_embedded_kit.c`
该示例展示了应用启动的标准顺序:
1. `volc_hal_init()`
2. `volc_hal_display_create()`
3. 初始化网络、时间同步等系统能力
4. `aios_init(VOLC_SERVICE_EVENT_MAX)`
5. 初始化各 service:
- `volc_service_manager_init()`
- `volc_conv_service_manager_init()`
- `function_call_service_init()`
- `local_logic_service_init()`
6. `aios_run()`
7. 在 wakeup 回调中发布 `VOLC_SERVICE_AI_CONVERSATION` 事件
因此,`application` 目录的代码更应该被理解成“主程序可直接引用的一套模块化应用骨架”。
## 4. Framework:AIOS 事件框架
### 4.1 AIOS 是什么
`framework` 的 README_zh 说明得很直白:它是为了让不同业务模块通过 `sub/pub event` 进行通信。
`aios.c` 的实现表明,这实际上是一个:
- 单线程事件循环
- 状态机驱动
- 带优先级的 session 调度器
- 带定时器能力的轻量运行时
### 4.2 核心概念
#### 1. `aios_session_t`
表示一个业务状态机实例,包含:
- 优先级
- 是否启用
- 当前状态函数
应用中的每个 service 基本都对应一个 session。
#### 2. `aios_event_t`
表示一个事件,包含:
- 事件 ID
- 当前尚未消费它的订阅者位图
- 事件数据
- 数据释放回调
#### 3. 状态函数
每个 session 都由状态函数驱动,签名是:
```c
aios_ret_t (*aios_state_handler)(struct aios_session *const me, aios_event_t const * const e);
```
返回值可以表示:
- 已处理
- 未处理
- 状态迁移
### 4.3 调度方式
`aios_run()` 会不断调用 `aios_once()`。
`aios_once()` 的主逻辑是:
1. 处理到期定时器,定时器会转化为普通事件。
2. 如果当前没有事件,则进入可中断睡眠。
3. 从高优先级到低优先级寻找“当前有订阅事件待处理”的 session。
4. 找出这个 session 最早应该消费的事件。
5. 调用 session 的当前状态函数处理事件。
6. 如果该事件没有剩余订阅者,则释放它。
这套机制的重点是:
- 事件是共享的,但每个订阅者只消费一次。
- 调度按 session 优先级进行。
- 不同 service 之间完全依赖事件通信。
### 4.4 为什么适合这个项目
这套框架特别适合当前项目,因为这里的业务是典型的“多模块协作”:
- 唤醒触发 AI 对话
- AI 对话过程中收到字幕
- 字幕再触发本地逻辑
- function call 消息再触发本地动作
如果全部互相直接调用,耦合会很高;用 AIOS 后,模块只需要关心自己订阅和发布什么事件。
## 5. Service 层:业务模块划分
`service/README_zh.md` 已给出分工,源码进一步明确了具体职责。
### 5.1 公共事件定义
`service/inc/volc_service_common.h` 是业务总线的关键头文件,定义了:
- 事件 ID
- session 优先级
主要事件包括:
- `VOLC_SERVICE_AI_CONVERSATION`
- 请求进入 AI 对话
- `VOLC_SERVICE_AI_CONVERSATION_START`
- 真正启动 AI 对话线程
- `VOLC_SERVICE_AI_CONVERSATION_QUIT`
- 退出 AI 对话
- `VOLC_SERVICE_AI_CONVERSATION_OVER`
- AI 对话线程结束后的通知
- `VOLC_FUNCTION_CALL_EXEC`
- 执行 function call
- `VOLC_FUNCTION_CALL_TRIGGER`
- function call 被智能体触发
- `VOLC_LOCAL_LOGIC_PLAY_WELCOME`
- 播放欢迎音
- `VOLC_LOCAL_LOGIC_PROCESS_SUBTITLE`
- 本地处理字幕
优先级定义为:
- AI 对话服务优先级最低编号 `0`
- 然后是 function call
- 然后是 local logic
- app manager 优先级最高编号 `3`
在 `aios.c` 中,高优先级 session 会先被选中执行。
## 6. `volc_manager_service`:业务入口管理
文件:
- `service/src/volc_manager_service.c`
这是最上层的“应用业务入口控制器”。
### 6.1 它做了什么
它订阅两个顶层事件:
- `VOLC_SERVICE_NETWORK_CONFIG`
- `VOLC_SERVICE_AI_CONVERSATION`
当前代码里真正有效的是:
- 收到 `VOLC_SERVICE_AI_CONVERSATION`
- 再发布 `VOLC_SERVICE_AI_CONVERSATION_START`
因此它的本质是:
- 作为“业务启动总入口”
- 把更粗粒度的用户/系统动作转换成具体 service 执行动作
### 6.2 作用
这一层让“谁要求启动 AI 对话”和“AI 对话服务怎么起线程”分离开了。
## 7. `conv_service`:核心 AI 对话服务
这是整个目录最关键的业务模块。
相关文件:
- `service/conv_service/src/volc_conv_service.c`
- `service/conv_service/src/volc_conv.c`
两者分工明显:
- `volc_conv_service.c`
- service 管理器,负责事件响应与线程管理
- `volc_conv.c`
- AI 对话线程的真正业务实现
### 7.1 `volc_conv_service_manager.c` 的职责
`volc_conv_service_manager_init()` 会注册一个 session,并订阅:
- `VOLC_SERVICE_AI_CONVERSATION_START`
- `VOLC_SERVICE_AI_CONVERSATION_INTERRUPT`
- `VOLC_SERVICE_AI_CONVERSATION_QUIT`
- `VOLC_SERVICE_AI_CONVERSATION_OVER`
收到不同事件后的行为:
- `START`
- 创建 `conv_ai_service_task` 线程
- `QUIT`
- 调用 `conv_ai_service_task_stop()`
- `OVER`
- 清空线程句柄
也就是说,这一层负责“线程生命周期管理”,而不是 AI 对话本身。
### 7.2 `volc_conv.c` 的职责
这个文件是 AI 对话业务主实现。
它做了 5 件关键事情:
#### 1. 构造 `volc_conv_ai` 配置
通过 `CONV_AI_CONFIG_FORMAT` 拼出连接云端 SDK 所需的 JSON,包含:
- IoT 配置
- RTC 配置
- 编解码参数
- RTC 参数扩展
然后在 `conv_ai_service_init()` 里调用:
- `volc_create()`
这说明 `application` 这一层直接把底层 SDK 当成对话引擎使用。
#### 2. 建立采集与播放
`conv_ai_service_task()` 启动时会:
- 创建或复用音频采集对象
- 切换采集模式到 `VOLC_AUDIO_MODE_CAPTURE`
- 创建或复用音频播放器
- 启动播放器
其中:
- 采集回调 `__audio_capture_cb()`
- 采集到音频后立即调用 `volc_send_audio_data()`
- 音频回调 `__on_volc_audio_data()`
- 收到智能体返回的音频后用 `volc_hal_player_play_data()` 播放
这就形成了一个完整的音频闭环:
- 麦克风采集 -> 发送到云端
- 云端返回语音 -> 喇叭播放
#### 3. 处理会话状态并驱动 UI
`__on_volc_conversation_status()` 会根据 SDK 回调状态更新显示层:
- `LISTENING`
- 状态栏显示“智能体聆听中”
- `THINKING`
- 主画面切到思考表情
- 状态栏显示“智能体思考中”
- `ANSWERING`
- 主画面切到开心表情
- 状态栏显示“智能体说话中”
- `INTERRUPTED`
- 状态栏显示“智能体被打断”
- `ANSWER_FINISH`
- 状态栏显示“智能体说话完成”
这表明 UI 与对话状态是强绑定的。
#### 4. 处理消息数据
`__on_volc_message_data()` 会解析从底层 SDK 收到的二进制消息头:
- `subv`
- 字幕消息
- `tool`
- function call 执行消息
- `info`
- function call 触发提示消息
随后:
- 字幕消息交给 `__on_subtitle_message_received()`
- `tool` 发布 `VOLC_FUNCTION_CALL_EXEC`
- `info` 发布 `VOLC_FUNCTION_CALL_TRIGGER`
所以 `conv_service` 其实是“AI 中枢”,它把底层 SDK 输出的不同类别消息重新分发给其他 service。
#### 5. 管理对话生命周期
线程主体会:
1. 启动采集与播放
2. 调用 `volc_start()`
3. 进入循环等待,按秒累加 `wait_time`
4. 超时或被要求退出时:
- `volc_stop()`
- 发布 `VOLC_SERVICE_AI_CONVERSATION_OVER`
- 停止采集、停止播放、销毁播放对象
- 重启唤醒模式采集
- 恢复待机 UI
这里的设计非常关键:
- AI 对话期间使用 `CAPTURE` 模式持续采音
- AI 对话结束后恢复 `WAKEUP` 模式等待下一次唤醒
这体现了“待机态/对话态”双模式切换。
## 8. `function_call_service`:函数调用桥接层
文件:
- `service/function_call_service/src/volc_function_call_service.c`
- `service/function_call_service/src/volc_local_function_list.c`
### 8.1 作用
这个 service 专门处理智能体下发的 function call。
当前代码里只实现了一个本地函数:
- `adjust_audio_val`
### 8.2 两类消息
#### 1. 触发提示消息 `VOLC_FUNCTION_CALL_TRIGGER`
收到后,会判断是否是 `adjust_audio_val`,如果是就先调用:
- `volc_send_text_to_agent(..., "别着急,我来给你调整音量", VOLC_AGENT_TYPE_TTS, 2)`
这相当于先让智能体“说一句回应”,再执行工具。
#### 2. 执行消息 `VOLC_FUNCTION_CALL_EXEC`
收到真正的 `tool_calls` JSON 后:
- 解析函数名
- 解析参数
- 如果是 `adjust_audio_val`
- 调用本地音量调整逻辑
- 再构造带 `func` 头的结果消息
- 调用 `volc_send_message()` 把执行结果回传给智能体
### 8.3 本地函数实现
`volc_local_function_list.c` 中实现了:
- 调大音量
- 调小音量
它通过 HAL 获取当前播放器句柄,再调用:
- `volc_hal_get_audio_player_volume()`
- `volc_hal_set_audio_player_volume()`
所以 function call 服务的本质是:
- 把模型侧工具调用,映射为设备本地硬件动作
## 9. `local_logic_service`:本地规则逻辑
文件:
- `service/local_logic_service/src/local_logic_service.c`
### 9.1 它与 function call 的区别
README_zh 已经说明了区别:
- `function_call_service`
- 处理智能体明确发起的工具调用
- `local_logic_service`
- 处理设备本地预设逻辑,不依赖智能体工具协议
### 9.2 当前实现的两个能力
#### 1. 播放欢迎音
收到 `VOLC_LOCAL_LOGIC_PLAY_WELCOME` 事件时:
- 从 `/sdcard/wel.pcm` 读取 PCM 数据
- 逐块送入播放器播放
#### 2. 解析字幕并触发退出逻辑
收到 `VOLC_LOCAL_LOGIC_PROCESS_SUBTITLE` 事件时:
- 检查字幕中是否包含“退下吧”或“拜拜”
- 如果命中,则发送一条 `TTS` 给智能体:“好的拜拜”
- 当后续字幕中真的出现“好的拜拜”时,再发布:
- `VOLC_SERVICE_AI_CONVERSATION_QUIT`
这个逻辑很有代表性,它说明:
- 本地逻辑可以直接基于字幕内容快速决策
- 不必走 function call,也不必重新交给云端理解
## 10. Platform:硬件抽象层
`platform/README_zh.md` 说明了整体设计原则:
- 接口正交,尽量屏蔽硬件细节
- 但为了 AI 对话场景易用性,允许一定“场景定制化”
核心思想是:
- 不追求绝对通用
- 优先服务“AI 对话设备”这个具体场景
### 10.1 `volc_hal.h`:全局 HAL 上下文
`platform/inc/volc_hal.h` 定义了全局结构 `volc_hal_context_t`,里面集中保存:
- 按键句柄
- 音频/视频采集句柄
- 显示句柄
- 音频/视频播放器句柄
- 设备名
`volc_hal_init()` 只做必要初始化,不要求把所有外设一次性拉起。
### 10.2 `volc_hal.c`:ESP 平台 HAL 根初始化
当前 `espressif/volc_hal.c` 会完成:
- 分配全局 HAL context
- 调用 `basic_board_init()` 完成板级外设探测与初始化
- 初始化文件系统
- 根据 MAC 生成设备名
其中 `basic_board.c` 又做了:
- 查询板型
- 绑定播放设备、录音设备、LCD 设备
- 配置采样率、位宽、通道数、mic layout
- 打开 codec 设备
所以 `volc_hal_init()` 实际上是整个硬件层的入口。
## 11. 平台子模块
### 11.1 音频采集 `volc_hal_capture`
头文件:
- `platform/inc/volc_hal_capture.h`
实现:
- `platform/src/espressif/volc_hal_capture.c`
这个模块的重要特点有两个:
#### 1. 回调式采集
不是业务主动 `read()`,而是内部线程采集后异步回调一帧帧音频数据。
这与 README_zh 的设计说明完全一致。
#### 2. 支持两种音频模式
- `VOLC_AUDIO_MODE_WAKEUP`
- `VOLC_AUDIO_MODE_CAPTURE`
当前实现里:
- `WAKEUP`
- 打开带唤醒能力的 AFE/Recorder
- `CAPTURE`
- 打开正常语音采集
但底层仍然复用同一套采集模块,只是内部 pipeline 模式不同。
这也是 README_zh 中“唤醒和采集属于同一音频采集范畴”的具体落地。
### 11.2 音频播放 `volc_hal_player`
头文件:
- `platform/inc/volc_hal_player.h`
实现:
- `platform/src/espressif/volc_hal_player.c`
当前重点支持音频播放:
- 创建时初始化 feeder
- `start()` 启动喂音流程
- `play_data()` 将数据送入播放链路
- 支持音量获取和设置
业务层基本不需要关心具体解码器或采样参数,因为这些在编译期和平台层已经固化。
### 11.3 显示 `volc_hal_display`
头文件:
- `platform/inc/volc_hal_display.h`
实现有两套:
- `platform/src/espressif/volc_hal_display.c`
- `platform/src/espressif/volc_hal_display_lvgl.c`
README_zh 提到,显示层不是让业务任意创建区域,而是预先划分屏幕区域。接口中也确实体现了这一点。
预定义区域包括:
- `VOLC_DISPLAY_OBJ_STATUS`
- `VOLC_DISPLAY_OBJ_MAIN`
- `VOLC_DISPLAY_OBJ_SUBTITLE`
当前主实现 `volc_hal_display.c` 更偏向:
- 通过 `gfx/mmap_assets` 渲染 EAF 动画表情
- 叠加状态文字
- 根据状态切换不同动画
这使 UI 能直接表现智能体当前情绪和状态。
### 11.4 按键 `volc_hal_button`
头文件:
- `platform/inc/volc_hal_button.h`
实现:
- `platform/src/espressif/volc_hal_button.c`
这个模块本质是对底层 `iot_button` 的适配:
- 统一按钮事件枚举
- 注册回调
- 在回调中把底层事件转成 HAL 事件
### 11.5 文件 `volc_hal_file`
头文件:
- `platform/inc/volc_hal_file.h`
实现:
- `platform/src/espressif/volc_hal_file.c`
这层很薄,基本是 ANSI C 文件接口的简单包装:
- `open/read/write/seek/close`
当前主要被 `local_logic_service` 用来播放欢迎音频。
## 12. `application` 与 `volc_conv_ai` 的关系
这个目录与上层云端对话 SDK 的连接点,主要就在 `service/conv_service/src/volc_conv.c`。
对接方式是:
1. 用 `volc_create()` 创建对话引擎
2. 用 `volc_start()` 启动 RTC 模式对话
3. 采集到的音频通过 `volc_send_audio_data()` 上送
4. 收到的音频通过 `volc_hal_player_play_data()` 播放
5. 收到的消息按 `subv/tool/info` 分类再转给其他 service
6. 本地业务通过:
- `volc_send_message()`
- `volc_send_text_to_agent()`
继续和智能体交互
所以可以把 `application` 看成:
- 向下对接 `volc_conv_ai`
- 向上对接硬件和本地业务
是一个“设备侧 AI 对话编排层”。
## 13. 关键运行链路
从实际运行角度,主链路可以总结为:
### 13.1 待机态
1. HAL 初始化
2. 创建显示层
3. 启动 AIOS
4. 初始化各个 service
5. 启动 wakeup 模式音频采集
6. 屏幕提示“请说 hi 乐鑫,启动ai对话”
### 13.2 唤醒后进入对话
1. 唤醒回调发布 `VOLC_SERVICE_AI_CONVERSATION`
2. `volc_manager_service` 转发为 `VOLC_SERVICE_AI_CONVERSATION_START`
3. `conv_service_manager` 创建 `conv_ai_service_task`
4. 采集模块切换到 `CAPTURE` 模式
5. 启动播放器
6. 调用 `volc_start()` 建立云端对话
### 13.3 对话中
1. 本地采集音频并上传
2. 智能体返回音频并播放
3. 状态回调刷新 UI
4. 字幕消息更新显示
5. 字幕触发本地逻辑
6. 工具调用消息触发 function call 服务
### 13.4 对话结束
1. 超时、退出指令或其他条件触发结束
2. `volc_stop()`
3. 停止采集/播放
4. 恢复 wakeup 模式采集
5. UI 回到待机提示
## 14. 目录级总结
### 14.1 `framework/`
是一个轻量事件驱动状态机框架,负责 service 之间的解耦通信。
### 14.2 `platform/`
是面向 AI 对话设备场景定制的 HAL,不追求绝对通用,但强调对业务简单易用。
### 14.3 `service/`
是具体业务编排层:
- `volc_manager_service`
- 业务入口与事件分发
- `conv_service`
- AI 对话主流程
- `function_call_service`
- 工具调用桥接
- `local_logic_service`
- 本地规则逻辑
### 14.4 `cmake/`
负责把上述模块连成一个 ESP-IDF component,并依赖底层 `volc_conv_ai` 组件。
## 15. 一句话总结
`application` 目录本质上是一套“设备侧 AI 对话应用框架”:
- `framework` 解决模块通信
- `platform` 解决硬件适配
- `service` 解决业务编排
- `conv_service` 作为核心中枢把 `volc_conv_ai`、音频设备、显示设备、本地逻辑和 function call 串起来
如果后续继续深入阅读,推荐顺序如下:
1. `service/inc/volc_service_common.h`
2. `framework/src/aios.c`
3. `service/src/volc_manager_service.c`
4. `service/conv_service/src/volc_conv_service.c`
5. `service/conv_service/src/volc_conv.c`
6. `service/function_call_service/src/volc_function_call_service.c`
7. `service/local_logic_service/src/local_logic_service.c`
8. `platform/src/espressif/volc_hal.c`
9. `platform/src/espressif/volc_hal_capture.c`
10. `platform/src/espressif/volc_hal_player.c`
11. `platform/src/espressif/volc_hal_display.c`
@@ -0,0 +1,25 @@
set(VOLC_FRAMEWORK_SRCS "${CMAKE_CURRENT_LIST_DIR}/../framework/src/aios.c"
CACHE INTERNAL "ConversationalAI-Embedded-Kit-2.0 framework src file")
set(VOLC_FRAMEWORK_INCS "${CMAKE_CURRENT_LIST_DIR}/../framework/inc"
CACHE INTERNAL "ConversationalAI-Embedded-Kit-2.0 framework include dir")
set(VOLC_PLATFORM_INCS "${CMAKE_CURRENT_LIST_DIR}/../platform/inc"
CACHE INTERNAL "ConversationalAI-Embedded-Kit-2.0 platform include dir")
set(VOLC_SERVICE_INCS "${CMAKE_CURRENT_LIST_DIR}/../service/inc"
"${CMAKE_CURRENT_LIST_DIR}/../service/conv_service/inc"
"${CMAKE_CURRENT_LIST_DIR}/../service/function_call_service/inc"
"${CMAKE_CURRENT_LIST_DIR}/../service/local_logic_service/inc"
CACHE INTERNAL "ConversationalAI-Embedded-Kit-2.0 service include dir")
set(VOLC_SERVICE_SRCS "${CMAKE_CURRENT_LIST_DIR}/../service/src/volc_manager_service.c"
"${CMAKE_CURRENT_LIST_DIR}/../service/conv_service/src/volc_conv_service.c"
"${CMAKE_CURRENT_LIST_DIR}/../service/conv_service/src/volc_conv.c"
"${CMAKE_CURRENT_LIST_DIR}/../service/function_call_service/src/volc_function_call_service.c"
"${CMAKE_CURRENT_LIST_DIR}/../service/function_call_service/src/volc_local_function_list.c"
"${CMAKE_CURRENT_LIST_DIR}/../service/local_logic_service/src/local_logic_service.c"
CACHE INTERNAL "ConversationalAI-Embedded-Kit-2.0 service src file")
set(VOLC_UTIL_INCS "${CMAKE_CURRENT_LIST_DIR}/../utils"
CACHE INTERNAL "ConversationalAI-Embedded-Kit-2.0 util include dir")
@@ -0,0 +1,55 @@
# Copyright (2025) Beijing Volcano Engine Technology Ltd.
# SPDX-License-Identifier: Apache-2.0
# ConversationalAI SDK ESP-IDF component configuration
# Converted from standard CMake to ESP-IDF component format
# Source files
set(VOLC_ESP_SRCS "${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/volc_hal.c"
"${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/volc_hal_button.c"
"${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/volc_hal_capture.c"
"${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/volc_hal_display.c"
"${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/volc_hal_file.c"
"${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/volc_hal_led.c"
"${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/volc_hal_player.c"
"${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/basic_board.c"
)
set(VOLC_ESP_DISPLAY_SRCS "${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/lvgl_source/echoear_font.c"
"${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/lvgl_source/img_app_aiPhone.c"
)
set(VOLC_APP_SRCS ${VOLC_FRAMEWORK_SRCS}
${VOLC_SERVICE_SRCS}
${VOLC_ESP_SRCS}
${VOLC_ESP_DISPLAY_SRCS}
)
set(VOLC_LVGL_SOURCE_INCS "${CMAKE_CURRENT_LIST_DIR}/../platform/src/espressif/lvgl_source/")
set(VOLC_ASSETS_SOURCE_INCS "${CMAKE_CURRENT_LIST_DIR}/../../../main/")
set(VOLC_APP_INCS ${VOLC_FRAMEWORK_INCS}
${VOLC_PLATFORM_INCS}
${VOLC_SERVICE_INCS}
${VOLC_UTIL_INCS}
${VOLC_LVGL_SOURCE_INCS}
${VOLC_ASSETS_SOURCE_INCS}
)
idf_component_register(
SRCS ${VOLC_APP_SRCS}
INCLUDE_DIRS ${VOLC_APP_INCS}
REQUIRES volc_conv_ai
PRIV_REQUIRES lvgl button av_processor esp_board_manager hw_init esp_mmap_assets esp_emote_gfx esp_vocat_base_control
)
# Compiler flags
target_compile_options(${COMPONENT_LIB} PRIVATE
-w
-Os
-ffunction-sections
-fdata-sections
)
# Export the library for use by other components
set(VOLC_CONV_APP_LIBRARIES ${COMPONENT_LIB} PARENT_SCOPE)
set(VOLC_CONV_APP_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../framework/inc PARENT_SCOPE)
@@ -0,0 +1,6 @@
# Copyright (2025) Beijing Volcano Engine Technology Ltd.
# SPDX-License-Identifier: Apache License 2.0
set(FRAMEWORK_SRCS ${CMAKE_CURRENT_LIST_DIR}/src/aios.c)
set(FRAMEWORK_INC ${CMAKE_CURRENT_LIST_DIR}/inc)
@@ -0,0 +1,5 @@
# framework
## brief introduction
This directory is designed to facilitate communication between different business modules (functional modules). The main communication method is subscribing to (sub) and publishing (pub) events, and the externally provided interface files are located in the `inc` directory.
@@ -0,0 +1,5 @@
# framework
## 目录简介
本目录是为了方便不用业务模块(功能模块)相互间进行通信使用的,主要的方式是sub和pub event事件,对外提供的接口文件在inc。
@@ -0,0 +1,125 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef AIOS_H_
#define AIOS_H_
/* include ------------------------------------------------------------------ */
#include "aios_config.h"
#include "volc_list.h"
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif
/* default configuration ---------------------------------------------------- */
#ifndef AIOS_MAX_ACTORS
#define AIOS_MAX_ACTORS 8 // 默认最多8个Actor
#endif
#ifndef AIOS_USE_ASSERT
#define AIOS_USE_ASSERT 1 // 默认打开断言
#endif
#include "aios_def.h"
/* data struct -------------------------------------------------------------- */
// 状态返回值的定义
typedef enum aios_ret {
AIOS_Ret_Null = 0, // 无效值
AIOS_Ret_Handled, // 已处理,不产生跳转
AIOS_Ret_NotHandled, // 未处理,不产生跳转
AIOS_Ret_Tran, // 跳转
} aios_ret_t;
// 事件类
struct aios_event;
typedef void (*aios_event_free_handler)(const void *data);
typedef struct aios_event {
volc_list_head_t node;
uint32_t sub; // 订阅者
aios_event_id_t id; // 事件主题
void *data; // 事件数据
aios_event_free_handler free_handler; // 事件数据释放函数
} aios_event_t;
// 数据结构 - 行为树相关 --------------------------------------------------------
// 状态函数句柄的定义
struct aios_session;
typedef aios_ret_t (* aios_state_handler)(struct aios_session *const me, aios_event_t const * const e);
// 状态机类
typedef struct aios_session {
uint32_t priority : 5; // 优先级,0-31,数值越大优先级越高
uint32_t enabled : 1; // 是否使能
uint32_t reserve : 1; // 保留位
volatile aios_state_handler state;
} aios_session_t;
// api -------------------------------------------------------------------------
// 对框架进行初始化,在各状态机初始化之前调用。
void aios_init(int event_size);
// 启动框架,放在main函数的末尾。
void aios_run(void);
// 停止框架的运行(不常用)
// 停止框架后,框架会在执行完当前状态机的当前事件后,清空各状态机事件队列,清空事件池,
// 不再执行任何功能,直至框架被再次启动。
void aios_stop(void);
// 关于状态机 -----------------------------------------------
// 状态机初始化函数
void aios_session_init( aios_session_t * const me,
uint8_t priority,
void const * const parameter);
void aios_session_start(aios_session_t * const me, aios_state_handler state_init);
aios_ret_t aios_tran(aios_session_t * const me, aios_state_handler state);
#define AIOS_TRAN(target) aios_tran((aios_session_t * )me, (aios_state_handler)target)
#define AIOS_STATE_CAST(state) ((aios_state_handler)(state))
// 关于事件 -------------------------------------------------
// 事件订阅
void aios_event_sub(aios_session_t * const me, aios_event_id_t id);
// 事件取消订阅
void aios_event_unsub(aios_session_t * const me, aios_event_id_t id);
// 事件订阅宏定义
#define AIOS_EVENT_SUB(_evt) aios_event_sub(&(me->super), _evt)
// 事件取消订阅宏定义
#define AIOS_EVENT_UNSUB(_evt) aios_event_unsub(&(me->super), _evt)
// 发布事件(携带数据)
int aios_event_pub(aios_event_id_t id, void *data, aios_event_free_handler free_handler);
// 发布周期性或延时事件
void* aios_event_time_pub(aios_event_id_t id, uint32_t timeout_ms, uint32_t period_ms);
// 取消延时事件或者周期事件的发布
void aios_event_time_cancel(void** timer);
/* port --------------------------------------------------------------------- */
// void* aios_malloc(uint32_t size);
// void aios_free(void* ptr);
// void* aios_mutex_create(void);
// void aios_mutex_lock(void* mutex);
// void aios_mutex_unlock(void* mutex);
// void aios_mutex_destroy(void** mutex);
void aios_port_assert(uint32_t error_id);
/* hook --------------------------------------------------------------------- */
// 结束AIOS Nano的运行的时候,所调用的回调函数。
void aios_hook_stop(void);
// 启动AIOS Nano的时候,所调用的回调函数
void aios_hook_start(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,15 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef AIOS_CONFIG_H__
#define AIOS_CONFIG_H__
/* AIOS General Configuration --------------------------------------- */
#define AIOS_MCU_TYPE 32
#define AIOS_MAX_ACTORS 4
#define AIOS_TEST_PLATFORM 64
#define AIOS_USE_MAGIC 0
/* Assert Configuration ----------------------------------------------------- */
#define AIOS_USE_ASSERT 1
#endif
@@ -0,0 +1,21 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef AIOS_DEF_H__
#define AIOS_DEF_H__
#include "aios_config.h"
#define AIOS_MAX_SLEEP_MS (1000 * 10)
typedef enum aios_event_id {
// 系统事件
Event_Null = 0,
Event_Enter,
Event_Exit,
// 用户事件
Event_User,
} aios_event_id_t;
#endif
@@ -0,0 +1,255 @@
/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef UV_SRC_HEAP_H_
#define UV_SRC_HEAP_H_
#include <stddef.h> /* NULL */
#if defined(__GNUC__)
# define HEAP_EXPORT(declaration) __attribute__((unused)) static declaration
#else
# define HEAP_EXPORT(declaration) static declaration
#endif
struct heap_node {
struct heap_node* left;
struct heap_node* right;
struct heap_node* parent;
};
/* A binary min heap. The usual properties hold: the root is the lowest
* element in the set, the height of the tree is at most log2(nodes) and
* it's always a complete binary tree.
*
* The heap function try hard to detect corrupted tree nodes at the cost
* of a minor reduction in performance. Compile with -DNDEBUG to disable.
*/
struct heap {
struct heap_node* min;
unsigned int nelts;
};
/* Return non-zero if a < b. */
typedef int (*heap_compare_fn)(const struct heap_node* a,
const struct heap_node* b);
/* Public functions. */
HEAP_EXPORT(void heap_init(struct heap* heap));
HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap));
HEAP_EXPORT(void heap_insert(struct heap* heap,
struct heap_node* newnode,
heap_compare_fn less_than));
HEAP_EXPORT(void heap_remove(struct heap* heap,
struct heap_node* node,
heap_compare_fn less_than));
HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than));
/* Implementation follows. */
HEAP_EXPORT(void heap_init(struct heap* heap)) {
heap->min = NULL;
heap->nelts = 0;
}
HEAP_EXPORT(void heap_node_init(struct heap_node* hnode)) {
hnode->left = 0;
hnode->parent = 0;
hnode->right = 0;
}
HEAP_EXPORT(int heap_node_is_empty(struct heap_node* hnode)) {
return (hnode->left == 0 && hnode->parent == 0 && hnode->right == 0);
}
HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)) {
return heap->min;
}
/* Swap parent with child. Child moves closer to the root, parent moves away. */
static void heap_node_swap(struct heap* heap,
struct heap_node* parent,
struct heap_node* child) {
struct heap_node* sibling;
struct heap_node t;
t = *parent;
*parent = *child;
*child = t;
parent->parent = child;
if (child->left == child) {
child->left = parent;
sibling = child->right;
} else {
child->right = parent;
sibling = child->left;
}
if (sibling != NULL)
sibling->parent = child;
if (parent->left != NULL)
parent->left->parent = parent;
if (parent->right != NULL)
parent->right->parent = parent;
if (child->parent == NULL)
heap->min = child;
else if (child->parent->left == parent)
child->parent->left = child;
else
child->parent->right = child;
}
HEAP_EXPORT(void heap_insert(struct heap* heap,
struct heap_node* newnode,
heap_compare_fn less_than)) {
struct heap_node** parent;
struct heap_node** child;
unsigned int path;
unsigned int n;
unsigned int k;
newnode->left = NULL;
newnode->right = NULL;
newnode->parent = NULL;
/* Calculate the path from the root to the insertion point. This is a min
* heap so we always insert at the left-most free node of the bottom row.
*/
path = 0;
for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2)
path = (path << 1) | (n & 1);
/* Now traverse the heap using the path we calculated in the previous step. */
parent = child = &heap->min;
while (k > 0) {
parent = child;
if (path & 1)
child = &(*child)->right;
else
child = &(*child)->left;
path >>= 1;
k -= 1;
}
/* Insert the new node. */
newnode->parent = *parent;
*child = newnode;
heap->nelts += 1;
/* Walk up the tree and check at each node if the heap property holds.
* It's a min heap so parent < child must be true.
*/
while (newnode->parent != NULL && less_than(newnode, newnode->parent))
heap_node_swap(heap, newnode->parent, newnode);
}
HEAP_EXPORT(void heap_remove(struct heap* heap,
struct heap_node* node,
heap_compare_fn less_than)) {
struct heap_node* smallest;
struct heap_node** max;
struct heap_node* child;
unsigned int path;
unsigned int k;
unsigned int n;
if (heap->nelts == 0)
return;
/* Calculate the path from the min (the root) to the max, the left-most node
* of the bottom row.
*/
path = 0;
for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2)
path = (path << 1) | (n & 1);
/* Now traverse the heap using the path we calculated in the previous step. */
max = &heap->min;
while (k > 0) {
if (path & 1)
max = &(*max)->right;
else
max = &(*max)->left;
path >>= 1;
k -= 1;
}
heap->nelts -= 1;
/* Unlink the max node. */
child = *max;
*max = NULL;
if (child == node) {
/* We're removing either the max or the last node in the tree. */
if (child == heap->min) {
heap->min = NULL;
}
return;
}
/* Replace the to be deleted node with the max node. */
child->left = node->left;
child->right = node->right;
child->parent = node->parent;
if (child->left != NULL) {
child->left->parent = child;
}
if (child->right != NULL) {
child->right->parent = child;
}
if (node->parent == NULL) {
heap->min = child;
} else if (node->parent->left == node) {
node->parent->left = child;
} else {
node->parent->right = child;
}
/* Walk down the subtree and check at each node if the heap property holds.
* It's a min heap so parent < child must be true. If the parent is bigger,
* swap it with the smallest child.
*/
for (;;) {
smallest = child;
if (child->left != NULL && less_than(child->left, smallest))
smallest = child->left;
if (child->right != NULL && less_than(child->right, smallest))
smallest = child->right;
if (smallest == child)
break;
heap_node_swap(heap, child, smallest);
}
/* Walk up the subtree and check that each parent is less than the node
* this is required, because `max` node is not guaranteed to be the
* actual maximum in tree
*/
while (child->parent != NULL && less_than(child, child->parent))
heap_node_swap(heap, child->parent, child);
}
HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)) {
heap_remove(heap, heap->min, less_than);
}
#undef HEAP_EXPORT
#endif /* UV_SRC_HEAP_H_ */
@@ -0,0 +1,79 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __CONV_AI_SRC_UTIL_VOLC_LIST_H__
#define __CONV_AI_SRC_UTIL_VOLC_LIST_H__
// #include <stdio.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct volc_list_head_t
{
struct volc_list_head_t *next, *prev;
} volc_list_head_t;
#define __LIST_ADD(entry, before, after) \
{ \
volc_list_head_t *new_ = (entry), *prev = (before), *next = (after); \
(next)->prev = (new_); \
(new_)->next = (next); \
(new_)->prev = (prev); \
(prev)->next = (new_); \
}
#define volc_list_init(entry) \
do \
{ \
(entry)->next = (entry); \
(entry)->prev = (entry); \
} while (0)
#define volc_list_add(entry, base) \
do \
{ \
__LIST_ADD((entry), (base), (base)->next); \
} while (0)
#define volc_list_add_after(entry, base) \
do \
{ \
__LIST_ADD((entry), (base), (base)->next); \
} while (0)
#define volc_list_add_before(entry, base) \
do \
{ \
__LIST_ADD((entry), (base)->prev, (base)); \
} while (0)
#define volc_list_add_head(entry, head) volc_list_add_after(entry, head)
#define volc_list_add_tail(entry, head) volc_list_add_before(entry, head)
#define volc_list_del(entry) \
do \
{ \
(entry)->prev->next = (entry)->next; \
(entry)->next->prev = (entry)->prev; \
(entry)->next = (entry)->prev = (entry); \
} while (0)
#define volc_list_empty(head) ((head)->next == (head))
#define volc_list_get_head(head) (volc_list_empty(head) ? (volc_list_head_t *)NULL : (head)->next)
#define volc_list_get_tail(head) (volc_list_empty(head) ? (volc_list_head_t *)NULL : (head)->prev)
#define volc_list_is_head(entry, head) ((entry)->prev == head)
#define volc_list_is_tail(entry, head) ((entry)->next == head)
#define volc_list_entry(ptr, type, member) ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
#define volc_list_for_each(h, head) for (h = (head)->next; h != (head); h = h->next)
#define volc_list_for_each_safe(h, n, head) for (h = (head)->next, n = h->next; h != (head); h = n, n = h->next)
#define volc_list_for_each_entry(p, head, type, member) \
for (p = volc_list_entry((head)->next, type, member); &p->member != (head); \
p = volc_list_entry(p->member.next, type, member))
#define volc_list_for_each_entry_safe(p, t, head, type, member) \
for (p = volc_list_entry((head)->next, type, member), t = volc_list_entry(p->member.next, type, member); \
&p->member != (head); p = t, t = volc_list_entry(t->member.next, type, member))
#define volc_list_get_head_entry(head, type, member) \
(volc_list_empty(head) ? (type *)NULL : volc_list_entry(((head)->next), type, member))
#define volc_list_get_tail_entry(head, type, member) \
(volc_list_empty(head) ? (type *)NULL : volc_list_entry(((head)->prev), type, member))
#ifdef __cplusplus
}
#endif
#endif /* #define __CONV_AI_SRC_UTIL_VOLC_LIST_H__ */
@@ -0,0 +1,646 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
// include ---------------------------------------------------------------------
#include "../inc/aios.h"
#include <string.h>
#include <stdbool.h>
#include "heap-inl.h"
//socket
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
// time
#include <sys/time.h>
#include "volc_osal.h"
#ifdef __cplusplus
extern "C" {
#endif
/* assert ------------------------------------------------------------------- */
#if (AIOS_USE_ASSERT != 0)
#define AIOS_ASSERT(test_) do { if (!(test_)) { \
aios_hook_stop(); \
aios_port_assert(__LINE__); \
} } while (0)
#else
#define AIOS_ASSERT(test_) ((void)0)
#endif
// aios define ------------------------------------------------------------------
// **aios** ---------------------------------------------------------------------
enum {
EosRun_OK = 0,
EosRun_NotEnabled,
EosRun_NoEvent,
EosRun_NoActor,
EosRun_NoActorSub,
// Timer
EosTimer_Empty,
EosTimer_NotTimeout,
EosTimer_ChangeToEmpty,
EosRunErr_NotInitEnd = -1,
EosRunErr_ActorNotSub = -2,
EosRunErr_MallocFail = -3,
EosRunErr_SubTableNull = -4,
EosRunErr_InvalidEventData = -5,
EosRunErr_HeapMemoryNotEnough = -6,
EosRunErr_TimerRepeated = -7,
};
typedef struct timer_item {
struct heap_node node;
aios_event_id_t id;
int64_t timeout_ms;
uint32_t period_ms;
} aios_timer_t;
typedef struct aios_tag {
uint32_t *sub_table; // event sub table
uint32_t session_exist;
uint32_t session_enabled;
aios_session_t * sessions[AIOS_MAX_ACTORS];
uint32_t sub_general;
void* event_mutex;
volc_list_head_t event_list;
uint32_t time;
void* timer_mutex;
struct heap timer_heap;
int fd[2];
uint8_t enabled : 1;
uint8_t running : 1;
uint8_t init_end : 1;
uint8_t reserved : 5;
} aios_t;
static aios_t aios;
// data ------------------------------------------------------------------------
static const aios_event_t aios_event_table[Event_User] = {
{{ 0 }, 0, Event_Null, 0, NULL},
{{ 0 }, 0, Event_Enter, 0, NULL},
{{ 0 }, 0, Event_Exit, 0, NULL},
};
// macro -----------------------------------------------------------------------
#define HSM_TRIG_(state_, topic_) \
((*(state_))(me, &aios_event_table[topic_]))
// static function -------------------------------------------------------------
static void aios_session_dispath(aios_session_t * const me, aios_event_t const * const e);
#ifndef VOLC_OFFSET
#define VOLC_OFFSET(type, member) ((size_t) &((type *)0)->member)
#endif
#ifndef VOLC_CONTAINER_OF
#define VOLC_CONTAINER_OF(ptr, type, member) \
((type *)((char *)(ptr) - VOLC_OFFSET(type, member)))
#endif
static int __heap_node_less(const struct heap_node* a, const struct heap_node* b) {
aios_timer_t* item_a = VOLC_CONTAINER_OF(a, aios_timer_t, node);
aios_timer_t* item_b = VOLC_CONTAINER_OF(b, aios_timer_t, node);
if (item_a->timeout_ms < item_b->timeout_ms) {
return 1;
}
if (item_a->timeout_ms > item_b->timeout_ms) {
return 0;
}
return item_a->id > item_b->id;
}
static int __set_block_mode(int sockfd, int block) {
int flags = fcntl(sockfd, F_GETFL);
if (flags < 0) {
return -1;
}
if (block) {
if ((flags & O_NONBLOCK) != 0) {
flags ^= O_NONBLOCK;
}
} else {
flags |= O_NONBLOCK;
}
if (fcntl(sockfd, F_SETFL, flags) < 0) {
return -1;
}
return 0;
}
static int __pipe(int fds[2]) {
int ret = 0;
fds[0] = -1;
fds[1] = -1;
int err = 0,opt = 0,write_fd = -1,read_fd = -1;
read_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (read_fd < 0) {
ret = -1;
goto err_out_label;
}
struct sockaddr_in servaddr;
uint32_t addr_len = sizeof(servaddr);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
servaddr.sin_port = 0;
if (bind(read_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
ret = -1;
goto err_out_label;
}
// get port bind by system
if (getsockname(read_fd, (struct sockaddr*)&servaddr, &addr_len) < 0) {
ret = -1;
goto err_out_label;
}
if(servaddr.sin_addr.s_addr == htonl(INADDR_ANY))
servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
write_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
int conn_ret = connect(write_fd, (struct sockaddr*)&servaddr, addr_len);
__set_block_mode(write_fd, 0);
__set_block_mode(read_fd, 0);
fds[0] = read_fd;
fds[1] = write_fd;
err_out_label:
if(ret < 0) {
if (read_fd > 0) {
close(read_fd);
}
if (write_fd > 0) {
close(write_fd);
}
}
return ret;
}
static int __interruptable_init(void) {
if (__pipe(aios.fd) < 0) {
return -1;
}
return 0;
}
static int __interruptable_deinit(void) {
close(aios.fd[0]);
close(aios.fd[1]);
return 0;
}
static int __interruptable_sleep(int64_t sleep_ms) {
int ret = 0;
char buf[64] = { 0 };
fd_set readfds = { 0 };
struct timeval tv = { 0 };
if (sleep_ms < 0) {
sleep_ms = AIOS_MAX_SLEEP_MS;
}
tv.tv_sec = sleep_ms / 1000;
tv.tv_usec = (sleep_ms % 1000) * 1000;
FD_ZERO(&readfds);
FD_SET(aios.fd[0], &readfds);
ret = select(aios.fd[0] + 1, &readfds, NULL, NULL, &tv);
if (ret < 0) {
return -1;
}
if (FD_ISSET(aios.fd[0], &readfds)) {
if ((ret = read(aios.fd[0], buf, sizeof(buf))) < 0) {
return -1;
}
}
return 0;
}
static int __interruptable_break(void) {
char c[1] = { 0x5A};
return (write(aios.fd[1], c, sizeof(c)) ? 0 : -1);
}
static int64_t aios_get_time(void)
{
struct timeval time_crt;
gettimeofday(&time_crt, (void *)0);
int64_t time_crt_ms = time_crt.tv_sec * 1000 + time_crt.tv_usec / 1000;
return time_crt_ms;
}
void aios_init(int event_size)
{
aios.enabled = true;
aios.running = false;
aios.session_exist = 0;
aios.session_enabled = 0;
aios.sub_table = NULL;
heap_init(&aios.timer_heap);
if (__interruptable_init() < 0) {
printf("aios_init: __interruptable_init fail\n");
return;
}
aios.sub_general = 0;
volc_list_init(&aios.event_list);
aios.event_mutex = volc_osal_mutex_create();
if (NULL == aios.event_mutex) {
printf("aios_init: event_mutex create fail\n");
return;
}
// printf("event: %p\n", aios.event_mutex);
aios.init_end = 1;
aios.time = 0;
aios.timer_mutex = volc_osal_mutex_create();
if (NULL == aios.timer_mutex) {
printf("aios_init: timer_mutex create fail\n");
return;
}
// printf("timer: %p\n", aios.timer_mutex);
aios.sub_table = (uint32_t *)volc_osal_malloc(sizeof(uint32_t) * event_size);
if (NULL == aios.sub_table) {
printf("aios_init: sub_table create fail\n");
return;
}
}
void aios_deinit(void)
{
volc_osal_mutex_destroy(&aios.event_mutex);
volc_osal_mutex_destroy(&aios.timer_mutex);
__interruptable_deinit();
}
void aios_sub_init(uint32_t *flag_sub, aios_event_id_t topic_max)
{
aios.sub_table = flag_sub;
for (int i = 0; i < topic_max; i ++) {
aios.sub_table[i] = 0;
}
}
int64_t aios_evttimer(void)
{
int64_t system_time = aios_get_time();
volc_osal_mutex_lock(aios.timer_mutex);
if (aios.timer_heap.nelts == 0) {
volc_osal_mutex_unlock(aios.timer_mutex);
return -1;
}
aios_timer_t* item = VOLC_CONTAINER_OF(heap_min(&aios.timer_heap), aios_timer_t, node);
if (item->timeout_ms > system_time) {
volc_osal_mutex_unlock(aios.timer_mutex);
return item->timeout_ms - system_time;
}
while (item->timeout_ms <= system_time) {
heap_remove(&aios.timer_heap, &item->node, __heap_node_less);
aios_event_pub(item->id, NULL, NULL);
if (item->period_ms == 0) {
continue;
}
item->timeout_ms += item->period_ms;
heap_insert(&aios.timer_heap, &item->node, __heap_node_less);
item = VOLC_CONTAINER_OF(heap_min(&aios.timer_heap), aios_timer_t, node);
}
volc_osal_mutex_unlock(aios.timer_mutex);
return 0;
}
void *aios_event_get_block(uint8_t priority);
void aios_event_gc(void *data);
int aios_once(void)
{
int64_t timeout_ms = -1;
if (aios.init_end == 0) {
return (int)EosRunErr_NotInitEnd;
}
if (aios.sub_table == NULL) {
return (int)EosRunErr_SubTableNull;
}
if (aios.enabled == false) {
return (int)EosRun_NotEnabled;
}
// 检查是否有状态机的注册
if (aios.session_exist == 0 || aios.session_enabled == 0) {
return (int)EosRun_NoActor;
}
timeout_ms = aios_evttimer();
if (volc_list_empty(&aios.event_list)) {
__interruptable_sleep(timeout_ms);
return (int)EosRun_NoEvent;
}
// 寻找到优先级最高,且有事件需要处理的Actor
aios_session_t *session = NULL;
uint8_t priority = AIOS_MAX_ACTORS;
for (int i = (int)(AIOS_MAX_ACTORS - 1); i >= 0; i --) {
if ((aios.session_exist & (1 << i)) == 0)
continue;
if ((aios.sub_general & (1 << i)) == 0)
continue;
session = aios.sessions[i];
priority = i;
break;
}
// 如果没有找到,返回
if (priority == AIOS_MAX_ACTORS) {
__interruptable_sleep(AIOS_MAX_SLEEP_MS);
return (int)EosRun_NoActorSub;
}
// 寻找当前Actor的最老的事件
volc_osal_mutex_lock(aios.event_mutex);
aios_event_t * e = aios_event_get_block(priority);
AIOS_ASSERT(e != NULL);
volc_osal_mutex_unlock(aios.event_mutex);
// 对事件进行执行
if ((aios.sub_table[e->id] & (1 << session->priority)) != 0)
{
// 执行状态的转换
aios_session_dispath(session, e);
}
else {
__interruptable_sleep(AIOS_MAX_SLEEP_MS);
return (int)EosRunErr_ActorNotSub;
}
// 销毁过期事件与其携带的参数
volc_osal_mutex_lock(aios.event_mutex);
aios_event_gc(e);
volc_osal_mutex_unlock(aios.event_mutex);
volc_osal_mutex_lock(aios.timer_mutex);
if (aios.timer_heap.nelts == 0) {
volc_osal_mutex_unlock(aios.timer_mutex);
// __interruptable_sleep(AIOS_MAX_SLEEP_MS);
} else {
aios_timer_t* item = VOLC_CONTAINER_OF(heap_min(&aios.timer_heap), aios_timer_t, node);
volc_osal_mutex_unlock(aios.timer_mutex);
int sleep_ms = item->timeout_ms - aios_get_time();
__interruptable_sleep(sleep_ms);
}
return (int)EosRun_OK;
}
void aios_run(void)
{
aios_hook_start();
AIOS_ASSERT(aios.enabled == true);
AIOS_ASSERT(aios.sub_table != 0);
aios.running = true;
while (aios.enabled) {
int ret = aios_once();
AIOS_ASSERT(ret >= 0);
if (ret == EosRun_NotEnabled) {
break;
}
}
}
void aios_hook_start(void)
{
}
void aios_hook_stop(void)
{
}
void aios_port_assert(uint32_t error_id)
{
printf("------------------------------------\n");
printf("ASSERT >>> Module: EventOS Nano, ErrorId: %d.\n", (int)error_id);
printf("------------------------------------\n");
while (1) {
usleep(100000);
}
}
void aios_stop(void)
{
aios.enabled = false;
// TODO: release resource
aios_hook_stop();
}
// state machine ---------------------------------------------------------------
void aios_session_init( aios_session_t * const me,
uint8_t priority,
void const * const parameter)
{
// 框架需要先启动起来
AIOS_ASSERT(aios.enabled == true);
AIOS_ASSERT(aios.running == false);
AIOS_ASSERT(aios.sub_table != NULL);
// 参数检查
AIOS_ASSERT(me != (aios_session_t *)0);
AIOS_ASSERT(priority < AIOS_MAX_ACTORS);
// 防止二次启动
if (me->enabled == true)
return;
// 检查优先级的重复注册
AIOS_ASSERT((aios.session_exist & (1 << priority)) == 0);
// 注册到框架里
aios.session_exist |= (1 << priority);
aios.sessions[priority] = me;
// 状态机
me->priority = priority;
me->state = NULL;
}
void aios_session_start(aios_session_t * const me, aios_state_handler state_init)
{
aios_state_handler t;
me->state = state_init;
me->enabled = true;
aios.session_enabled |= (1 << me->priority);
// 进入初始状态,执行TRAN动作。这也意味着,进入初始状态,必须无条件执行Tran动作。
t = me->state;
aios_ret_t ret = t(me, &aios_event_table[Event_Null]);
AIOS_ASSERT(ret == AIOS_Ret_Tran);
ret = me->state(me, &aios_event_table[Event_Enter]);
AIOS_ASSERT(ret != AIOS_Ret_Tran);
}
// event -----------------------------------------------------------------------
int aios_event_pub(aios_event_id_t id, void *data, aios_event_free_handler free_handler)
{
if (aios.init_end == 0) {
return EosRunErr_NotInitEnd;
}
if (aios.sub_table == NULL) {
return EosRunErr_SubTableNull;
}
// 保证框架已经运行
if (aios.enabled == 0) {
return EosRun_NotEnabled;
}
if (aios.session_exist == 0) {
return EosRun_NoActor;
}
// 没有状态机使能,返回
if (aios.session_enabled == 0) {
return EosRun_NotEnabled;
}
// 没有状态机订阅,返回
if (aios.sub_table[id] == 0) {
return EosRun_NoActorSub;
}
// 申请事件空间
aios_event_t *e = (aios_event_t *)volc_osal_malloc(sizeof(aios_event_t));
if (e == NULL) {
return EosRunErr_MallocFail;
}
e->id = id;
e->sub = aios.sub_table[e->id];
aios.sub_general |= e->sub;
e->data = data;
e->free_handler = free_handler;
volc_osal_mutex_lock(aios.event_mutex);
volc_list_add_tail(&e->node, &aios.event_list);
volc_osal_mutex_unlock(aios.event_mutex);
__interruptable_break();
return EosRun_OK;
}
void aios_event_sub(aios_session_t * const me, aios_event_id_t id)
{
aios.sub_table[id] |= (1 << me->priority);
}
void aios_event_unsub(aios_session_t * const me, aios_event_id_t id)
{
aios.sub_table[id] &= ~(1 << me->priority);
}
void* aios_event_time_pub(aios_event_id_t id, uint32_t time_ms, uint32_t period_ms)
{
aios_timer_t* item = (aios_timer_t *)volc_osal_malloc(sizeof(aios_timer_t));
AIOS_ASSERT(item != NULL);
memset(item, 0, sizeof(aios_timer_t));
item->id = id;
item->timeout_ms = aios_get_time() + time_ms;
item->period_ms = period_ms;
volc_osal_mutex_lock(aios.timer_mutex);
heap_insert(&aios.timer_heap, &item->node, __heap_node_less);
volc_osal_mutex_unlock(aios.timer_mutex);
return (void *)item;
}
void aios_event_time_cancel(void** timer)
{
if (timer == NULL || NULL == *timer) {
return;
}
aios_timer_t* item = (aios_timer_t *)*timer;
volc_osal_mutex_lock(aios.timer_mutex);
heap_remove(&aios.timer_heap, &item->node, __heap_node_less);
volc_osal_mutex_unlock(aios.timer_mutex);
volc_osal_free(item);
*timer = NULL;
}
// state tran ------------------------------------------------------------------
aios_ret_t aios_tran(aios_session_t * const me, aios_state_handler state)
{
me->state = state;
return AIOS_Ret_Tran;
}
// static function -------------------------------------------------------------
static void aios_session_dispath(aios_session_t * const me, aios_event_t const * const e)
{
aios_ret_t r;
AIOS_ASSERT(e != (aios_event_t *)0);
aios_state_handler s = me->state;
aios_state_handler t;
r = s(me, e);
if (r == AIOS_Ret_Tran) {
t = me->state;
r = s(me, &aios_event_table[Event_Exit]);
AIOS_ASSERT(r == AIOS_Ret_Handled || r == AIOS_Ret_NotHandled);
r = t(me, &aios_event_table[Event_Enter]);
AIOS_ASSERT(r == AIOS_Ret_Handled || r == AIOS_Ret_NotHandled);
me->state = t;
}
else {
me->state = s;
}
}
/* heap library ------------------------------------------------------------- */
void aios_event_gc(void *data)
{
aios_event_t * e = (aios_event_t *)data;
if (e->sub == 0) {
volc_list_del(&e->node);
if (e->free_handler != NULL) {
e->free_handler(e->data);
}
volc_osal_free(e);
}
aios.sub_general = 0;
volc_list_for_each_entry(e, &aios.event_list, aios_event_t, node) {
aios.sub_general |= e->sub;
}
}
void *aios_event_get_block(uint8_t priority)
{
aios_event_t * e = NULL;
volc_list_for_each_entry(e, &aios.event_list, aios_event_t, node) {
if ((e->sub & (1 << priority)) == 0) {
continue;
}
e->sub &=~ (1 << priority);
break;
}
return (void *)e;
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,49 @@
# Platform
## brief introduction
This directory serves as the software abstraction layer for the Hardware Conversational AI Agent Development Kit, built around the business characteristic of AI conversation. Its purpose is to shield hardware details, enabling users to focus on software development and business implementation.
Among this directory:
- inc: Contains header files
- src: Contains specific implementations for different hardware platforms
## principles
As a Hardware Abstraction Layer (HAL), we typically expect capabilities to be atomized, interfaces to be orthogonal, and high flexibility to be maintained. However, excessive pursuit of atomization and flexibility often reduces interface usability and impairs business development efficiency. These two aspects are often mutually exclusive. // Nevertheless, this development platform focuses on AI conversation scenarios; therefore, given the relatively fixed business scenarios, we can make trade-offs with greater engineering practical value. // Our core design principles are as follows:
1. Orthogonal interfaces to reduce coupling and shield hardware details.
2. Interface design takes certain business characteristics into account:
some implementations and configuration parameters are implicitly implemented according to business requirements,and not all software configurable items are retained.This prevents upper-layer business development from being bogged down in endless detailed configuration and parameter tuning. For example: we enable the Acoustic Echo Cancellation (AEC) module by default for audio capture,instead of requiring upper-layer business to configure aec_enabled in the config file;thus, many interface designs at this layer do not make complete sense.For detailed explanations and trade-offs, refer to the implementation details.Interface design takes certain business characteristics into account: ails.
## implementation
### volc_hal
volc_hal_init() Do the necessary actions after the hardware is powered on, it is not necessary to initialize all the hardware modules, but it is necessary to set the device name.
volc_get_global_hal_context() ithis function could help you get the hal context everywhere. Do not Modify the return value
### volc_hal_player
We do not specify specific media configurations (e.g., encoding format, sampling rate, or resolution).This is because we expect all the aforementioned parameters to be uniquely determined and immutable across all scenarios.Therefore, these values must be fixed at compile time; if your device supports multiple parameters,macros should be used to select the desired ones at compile time.This design adheres to Principle 2.
for volc_hal_player_play_data(),We have not specified whether this function is sync or async. However, it is strongly recommended to implement this function as non-blocking with a certain internal buffer, ensuring that the caller of the function does not need to overly consider the function's call frequency. For example, the function can be called every 1 second to play 1.2 seconds of audio or video data.
### volc_hal_capture
We do not specify specific media configurations (e.g., encoding format, sampling rate, or resolution).This is because we expect all the aforementioned parameters to be uniquely determined and immutable across all scenarios.Therefore, these values must be fixed at compile time; if your device supports multiple parameters,macros should be used to select the desired ones at compile time.This design adheres to Principle 2.
To ensure a uniform rate for media capture data, we adopt the callback function approach: frame-by-frame audio and video data is delivered asynchronously via callbacks, instead of providing an active capture interface. Therefore, during the function implementation, a capture thread needs to be created to asynchronously callback the data out.
We consider both voice wake-up and voice data capture to fall under the category of audio capture, differing only in mode (internal pipeline). For this reason, we do not redesign a separate module for voice wake-up; instead, we add an additional mode specifically for voice wake-up.
Finally, note that acoustic echo cancellation (AEC) must be implemented for audio capture.
### volc_hal_display
Typically, a set of screen display interfaces allows upper-layer callers to independently create and destroy regions for display purposes.However, to minimize the development effort of upper-layer business logic,we do not allow the business side to create and manage different screen regions on their own.Instead, different screen regions are divided and created during the execution of volc_hal_display_create().The business layer can only obtain different render layer objects,pass data to them, and perform rendering operations. For example, we divide the screen into a status bar(VOLC_DISPLAY_OBJ_STATUS), main screen(VOLC_DISPLAY_OBJ_MAIN), and subtitle display bar(VOLC_DISPLAY_OBJ_SUBTITLE).You may define your own divisions, as all these codes are open-source and modifiable.
### volc_hal_file
File systems may have different implementations on different devices,but we generally adhere to the ANSI C style.For devices without a file system, these interfaces may be left unimplemented as this is not mandatory.
@@ -0,0 +1,45 @@
# Platform
## 目录简介
本目录是硬件对话智能体开发套件基于ai对话这一业务特性,进行的软件抽象层,目的是屏蔽硬件细节,使用户专注软件开发与业务实现。其中inc是header,src是不同硬件平台的具体实现。
## 设计原则
作为硬件抽象层往往期待,能力原子化,接口正交,且保持高度的灵活性。但是过分追求原子化和灵活性,往往会降低接口易用性,降低业务开发的效率。这两者往往不可兼得。不过本开发平台专注于ai对话场景,因此在业务场景相对固定的情况下,还是能做成一些更有工程实践价值的trade off的。我们设计的基本原则如下:
1 接口正交,减少耦合且屏蔽硬件细节
2 接口设计考虑一定的业务特点,某些实现和配置参数会按照业务要求隐式实现,不会保留所有的软件可配置项,避免上层业务开发陷入无穷无尽的细节配置和调参上。这里举一个例子: 我们默认音频采集都会打开回声消除(aec)模块,而不是让上层业务去config里配置 aec_enabled;因此,这一层不少的接口设计并不百分百的make sense,详细的说明和取舍见实现细节。
## 部分实现思路
### volc_hal
volc_hal_init() 只实现硬件上电后必要的初始化动作,例如设置gpid,联网等;音视频采播等模块可以在其他子模块中init
volc_get_global_hal_context() 方便拿到全局唯一的硬件context,但不要修改该返回值
### volc_hal_player
请注意该模块的接口设计上,我们没有给定一些具体的媒体配置,例如编码格式,采样率或者分辨率;这是因为我们期待上述的所有参数在全场景都是唯一确定且不能改变的。所以这些值需要在编译时就确定好,如果你的设备支持多种参数,那么也应该在编译时用宏做以选择。这一设计遵循原则2;
对于volc_hal_player_play_data()接口,我们并未规定该函数是同步的还是异步的,但是还是强烈建议你讲该函数实现为非阻塞的,且内部有一定缓存,确保函数的调用者不用过分考虑函数的调用频次;例如,可以1s中调用该函数play 1.2s的audio或video数据
### volc_hal_capture
请注意该模块的接口设计上,我们没有给定一些具体的媒体配置,例如编码格式,采样率或者分辨率;这是因为我们期待上述的所有参数在全场景都是唯一确定且不能改变的。所以这些值需要在编译时就确定好,如果你的设备支持多种参数,那么也应该在编译时用宏做以选择。这一设计遵循原则2;
为了确保媒体采集数据的速率均匀,我们采取回调函数的方式,异步的回调出一帧一帧的音视频数据,而非主动给一个capture接口。所以需要在函数实现的过程中,创建一个采集线程,异步的将数据回调出来。
请注意,我们认为语音唤醒和语音数据采集都属于音频采集的范畴,只是模式(内部pipeline)不同,所以我们并未重新设计一套语音唤醒的模块,而是多设计了一个语音唤醒的mode
最后,需要注意,音频的采集需要做aec和ns等模块,这一设计遵循原则2;
### volc_hal_display
通常情况下一套屏幕显示的接口,会允许上层调用者自行创建和销毁一块用于显示的区域;但是根据原则2,为了最简化上层业务的开发,我们不允许业务侧去自行创建和管理屏幕的不同区域;而是在volc\_hal\_display\_create就将不同的屏幕区域划分且创建好。然后业务层只能拿到不同的渲染层obj,传递数据并进行渲染。例如,我们将屏幕分为状态栏、主屏幕和字幕显示栏。你也可以有自己的划分,因为这些代码都是开源可修改的
### volc_hal_file
不同的设备上文件系统可能有不同的实现,但是我们总体上遵循ANSI C style。对于没有文件系统的设备,这些接口可以不做实现,这并不是必须的
@@ -0,0 +1,92 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __VOLC_HAL_H__
#define __VOLC_HAL_H__
#include "volc_hal_button.h"
#include "volc_hal_capture.h"
#include "volc_hal_display.h"
#include "volc_hal_player.h"
#ifdef __cplusplus
extern "C" {
#endif
#define VOLC_DEVICE_NAME_LENGTH 32
typedef enum {
VOLC_HAL_CAPTURE_AUDIO = 0, // audio capture
VOLC_HAL_CAPTURE_VIDEO, // video capture
VOLC_HAL_CAPTURE_MAX, // Maximum capture count
} volc_hal_capture_e;
typedef enum {
VOLC_HAL_PLAYER_AUDIO = 0, // audio player
VOLC_HAL_PLAYER_VIDEO, // video player
VOLC_HAL_PLAYER_MAX, // Maximum player count
} volc_hal_player_e;
/**
* @brief All hardware resources handle and context
* @details generally,this structure should be singleton
* you can get the Instance by volc_get_global_hal_context()
* And, you just set the value when the hardware submodule be inited
* the function volc_hal_init() just do some necessary initialization actions
* such as, malloc the volc_hal_context_t mem and set the device_name
*/
typedef struct {
/**
* @brief the button handle pointer
* @details It should be set value when the volc_hal_button_create() is called
*/
volc_hal_button_t button_handle;
/**
* @brief the capture pointer array, include audio_capture and video_capture
* @details It should be set value when the volc_hal_capture_create() is called
*/
volc_hal_capture_t capture_handle[VOLC_HAL_CAPTURE_MAX];
/**
* @brief the display pointer
* @details It should be set value when the volc_hal_display_create() is called
*/
volc_hal_display_t display_handle;
/**
* @brief the player pointer array, include audio_player and video_player
* @details It should be set value when the volc_hal_player_create() is called
*/
volc_hal_player_t player_handle[VOLC_HAL_PLAYER_MAX];
/**
* @brief the device name, in most cases, it is a mac address
* @details It should be set a value when the volc_hal_init() is called
*/
char device_name[VOLC_DEVICE_NAME_LENGTH];
} volc_hal_context_t;
/**
* @brief Initialize the HAL module
* @details Do the necessary actions after the hardware is powered on
* it is not necessary to initialize all the hardware modules
* but it is necessary to set the device name
*
* @return int 0 if success, otherwise error code
*/
int volc_hal_init(void);
/**
* @brief return global hal context
* @details you can get the singleton Instance volc_hal_context_t by volc_get_global_hal_context()
* this function could help you get the hal context everywhere
* please be carefully, Do not Modify the return value
*/
volc_hal_context_t* volc_get_global_hal_context();
/**
* @brief Deinitialize the HAL module
*/
void volc_hal_fini(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,59 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __VOLC_HAL_BUTTON_H__
#define __VOLC_HAL_BUTTON_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef void* volc_hal_button_t;
typedef enum {
VOLC_BUTTON_PRESS_DOWN = 0, // Button press down event
VOLC_BUTTON_PRESS_UP, // Button press up event
VOLC_BUTTON_PRESS_REPEAT, // Button press repeat event
VOLC_BUTTON_PRESS_REPEAT_DONE, // Button press repeat done event
VOLC_BUTTON_SINGLE_CLICK, // Button single click event
VOLC_BUTTON_DOUBLE_CLICK, // Button double click event
VOLC_BUTTON_MULTIPLE_CLICK, // Button multiple click event
VOLC_BUTTON_LONG_PRESS_START, // Button long press start event
VOLC_BUTTON_LONG_PRESS_HOLD, // Button long press hold event
VOLC_BUTTON_LONG_PRESS_UP, // Button long press up event
VOLC_BUTTON_PRESS_END, // Button press end event
VOLC_BUTTON_EVENT_MAX, // Maximum number of button events
} volc_hal_button_event_e;
typedef void (*volc_hal_button_event_cb_t)(volc_hal_button_t button, volc_hal_button_event_e event, void* user_data);
typedef struct volc_hal_button_config {
int gpio_num; // GPIO number of the button
int active_level; // Active level of the button (0 or 1)
int long_press_ms; // Long press threshold in milliseconds
int short_press_ms; // Short press threshold in milliseconds
int enable_power_save; // Whether to enable power save mode (0 or 1)
void* user_data; // User data pointer
volc_hal_button_event_cb_t event_cb; // Button event callback function
} volc_hal_button_config_t;
/**
* @brief Create a button instance
*
* @param config Button configuration
* @return volc_hal_button_t Button instance pointer
*/
volc_hal_button_t volc_hal_button_create(volc_hal_button_config_t* config);
/**
* @brief Destroy a button instance
*
* @param button Button instance pointer
*/
void volc_hal_button_destroy(volc_hal_button_t button);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,98 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __VOLC_HAL_CAPTURE_H__
#define __VOLC_HAL_CAPTURE_H__
#include "volc_hal_type.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* @brief Capture instance pointer
*/
typedef void* volc_hal_capture_t;
typedef struct {
volc_audio_data_type_e data_type; // Audio data type
void* user_data; // User data pointer
} volc_hal_frame_info_t;
typedef enum {
VOLC_AUDIO_MODE_WAKEUP = 0,
VOLC_AUDIO_MODE_CAPTURE,
} volc_hal_audio_capture_mode_e;
typedef void (*volc_hal_capture_data_cb_t)(volc_hal_capture_t capture, const void* data, int len, volc_hal_frame_info_t* frame_info);
typedef void (*volc_hal_audio_wakeup_cb_t)(void *event, void *user_data);
typedef struct volc_hal_capture_config {
volc_media_type_e media_type; // Media type
volc_hal_capture_data_cb_t data_cb; // Data callback function
volc_hal_audio_wakeup_cb_t audio_wakeup_cb; // audio wakeup cb
void* user_data; // User data pointer
} volc_hal_capture_config_t;
/**
* @brief Create a capture instance
* @details To ensure a uniform rate for media capture data, we adopt the callback function approach:
* frame-by-frame audio and video data is delivered asynchronously via callbacks,
* instead of providing an active capture interface.
* Therefore, during the function implementation, a capture thread needs to be created
* to asynchronously callback the data out.
* @note We do not specify specific media configurations (e.g., encoding format, sampling rate, or resolution).
* This is because we expect all the aforementioned parameters to be uniquely determined and immutable across all scenarios.
* Therefore, these values must be fixed at compile time; if your device supports multiple parameters,
* macros should be used to select the desired ones at compile time.
* We consider both voice wake-up and voice data capture to fall under the category of audio capture,
* differing only in mode (internal pipeline).
* For this reason, we do not redesign a separate module for voice wake-up;
* instead, we add an additional mode specifically for voice wake-up.
* Finally, note that acoustic echo cancellation (AEC) must be implemented for audio capture.
*
* @param config Capture configuration pointer
* @return volc_hal_capture_t Capture instance pointer
*/
volc_hal_capture_t volc_hal_capture_create(volc_hal_capture_config_t* config);
/**
* @brief Destroy a capture instance
*
* @param capture Capture instance pointer
*/
void volc_hal_capture_destroy(volc_hal_capture_t capture);
/**
* @brief Start a capture instance
*
* @param capture Capture instance pointer
* @return int 0 if success, otherwise error code
*/
int volc_hal_capture_start(volc_hal_capture_t capture,volc_hal_audio_capture_mode_e mode);
/**
* @brief Stop a capture instance
* @details you should start your capture thread within this function.
*
* @param capture Capture instance pointer
* @return int 0 if success, otherwise error code
*/
int volc_hal_capture_stop(volc_hal_capture_t capture);
/**
* @brief Update audio capture configuration
* @note this function could help you update the capture config
* Please check if it is thread-safe or not;
*
* @param capture Capture instance pointer
* @param config Capture configuration pointer
* @return int 0 if success, otherwise error code
*/
int volc_hal_capture_update_config(volc_hal_capture_t capture, volc_hal_capture_config_t* config);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,85 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __VOLC_HAL_DISPLAY_H__
#define __VOLC_HAL_DISPLAY_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Display instance pointer
*/
typedef void* volc_hal_display_t;
/** This enumeration exists to map to distinct regions of the screen.
* Note: Typically, a set of screen display interfaces allows upper-layer callers
* to independently create and destroy regions for display purposes.
* However, to minimize the development effort of upper-layer business logic,
* we do not allow the business side to create and manage different screen regions on their own.
* Instead, different screen regions are divided and created during the execution of volc_hal_display_create().
* The business layer can only obtain different render layer objects,
* pass data to them, and perform rendering operations.
* For example, we divide the screen into a status bar(VOLC_DISPLAY_OBJ_STATUS),
* main screen(VOLC_DISPLAY_OBJ_MAIN), and subtitle display bar(VOLC_DISPLAY_OBJ_SUBTITLE).
* You may define your own divisions, as all these codes are open-source and modifiable.
*/
typedef enum {
VOLC_DISPLAY_OBJ_STATUS = 0, // Status display object
VOLC_DISPLAY_OBJ_MAIN,
VOLC_DISPLAY_OBJ_SUBTITLE, // Subtitle display object
// VOLC_DISPLAY_OBJ_EMOJI, // Emoji display object
VOLC_DISPLAY_OBJ_MAX, // Maximum display object count
} volc_hal_display_obj_e;
typedef enum {
VOLC_DISPLAY_TEXT = 0, // Text display type
VOLC_DISPLAY_IMAGE, // Image display type
VOLC_DISPLAY_EMOJI // Emoji display type
} volc_hal_display_type_e;
typedef struct volc_hal_display_config {
int width; // Width of the display
int height; // Height of the display
} volc_hal_display_config_t;
/**
* @brief Create a Display instance
*
* @param config Display configuration
* @return volc_hal_display_t Display instance pointer
*/
volc_hal_display_t volc_hal_display_create(volc_hal_display_config_t* config);
/**
* @brief set brightness
*
* @param display Display instance pointer
* @param brightness the brightness value [0,100]
* @return volc_hal_display_t Display instance pointer
*/
int volc_hal_display_set_brightness(volc_hal_display_t display, int brightness);
/**
* @brief Destroy a Display instance
*
* @param display Display instance pointer
*/
void volc_hal_display_destroy(volc_hal_display_t display);
/**
* @brief Set the display emotion
*
* @param display Display instance pointer
* @param type Display type (VOLC_DISPLAY_TEXT, VOLC_DISPLAY_IMAGE, or VOLC_DISPLAY_EMOJI)
* @param content Content to be displayed (string for text, image pointer for image, emoji string for emoji)
* @return int 0 if success, otherwise error code
*/
int volc_hal_display_set_content(volc_hal_display_t display, volc_hal_display_obj_e obj, volc_hal_display_type_e type, const void* content);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,83 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __VOLC_HAL_FILE_H__
#define __VOLC_HAL_FILE_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* File systems may have different implementations on different devices,
* but we generally adhere to the ANSI C style.
* For devices without a file system, these interfaces may be left unimplemented
* as this is not mandatory.
*/
/**
* @brief file instance pointer
*/
typedef void* volc_hal_file_t;
/**
* @brief init the file system
* @return int 0 if success, otherwise error code
*/
int volc_hal_file_system_init();
/**
* @brief open a file instance
* @param file_name the file name
* @param mode openmode, just follow ANSI C style(fopen)
* @return volc_hal_file_t file instance pointer
*/
volc_hal_file_t volc_hal_file_open(char* file_name, char* mode);
/**
* @brief read the data from the file
* @param file the file instance pointer
* @param data the data pointer
* @param size the data size
* @return return the real read data size
*/
uint64_t volc_hal_file_read(volc_hal_file_t file, void *data, uint64_t size);
/**
* @brief write the data from the file
* @param file the file instance pointer
* @param data the data pointer
* @param size the data size
* @return return the real writed data size
*/
uint64_t volc_hal_file_write(volc_hal_file_t file, void *data, uint64_t size);
/**
* @brief get the file size
* @param file the file instance pointer
* @return return the file size
*/
uint64_t volc_hal_file_get_size(volc_hal_file_t file);
/**
* @brief get the file size
* @param file the file instance pointer
* @param offset the file offset (start is 0)
* @return int 0 if success, otherwise error code
*/
int volc_hal_file_seek(volc_hal_file_t file,uint64_t offset);
/**
* @brief close a file instance
* @param mode openmode, just follow ANSI C style(fopen)
* @return volc_hal_file_t file instance pointer
*/
int volc_hal_file_close(volc_hal_file_t file);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,56 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __VOLC_HAL_LED_H__
#define __VOLC_HAL_LED_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief LED instance pointer
*/
typedef void* volc_led_t;
/**
* @brief LED state enumeration
*/
typedef enum {
VOLC_LED_OFF = 0, // LED off state
VOLC_LED_ON, // LED on state
} volc_led_state_e;
typedef struct volc_led_config {
int gpio_num; // GPIO number of the LED
int active_level; // Active level of the LED (0 or 1)
} volc_led_config_t;
/**
* @brief Create a LED instance
*
* @param config LED configuration
* @return volc_led_t LED instance pointer
*/
volc_led_t volc_led_create(volc_led_config_t* config);
/**
* @brief Destroy a LED instance
*
* @param led LED instance pointer
*/
void volc_led_destroy(volc_led_t led);
/**
* @brief Set the LED state
*
* @param led LED instance pointer
* @param state LED state (VOLC_LED_OFF, VOLC_LED_ON, or VOLC_LED_BLINK)
*/
void volc_led_set_state(volc_led_t led, volc_led_state_e state);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,98 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __VOLC_HAL_PLAYER_H__
#define __VOLC_HAL_PLAYER_H__
#include "volc_hal_type.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Player instance pointer
*/
typedef void* volc_hal_player_t;
typedef struct volc_hal_player_config {
volc_media_type_e media_type; // Media type
} volc_hal_player_config_t;
/**
* @brief Create a player instance
* @details this function shoudle set the player_handle value in the volc_hal_context_t structure.
* @note We do not specify specific media configurations (e.g., encoding format, sampling rate, or resolution).
* This is because we expect all the aforementioned parameters to be uniquely determined and immutable across all scenarios.
* Therefore, these values must be fixed at compile time; if your device supports multiple parameters,
* macros should be used to select the desired ones at compile time.
*
* @param config Player configuration
* @return volc_hal_player_t Player instance pointer
*/
volc_hal_player_t volc_hal_player_create(volc_hal_player_config_t* config);
/**
* @brief set audio player volume
*
* @param player Player instance pointer (audio)
* @param volume the volume [0,100]
* @return int 0 if success
*/
int volc_hal_set_audio_player_volume(volc_hal_player_t player, int volume);
/**
* @brief get audio player volume
*
* @param player Player instance pointer (audio)
* @return the volume
*/
int volc_hal_get_audio_player_volume(volc_hal_player_t player);
/**
* @brief Destroy a player instance
* @details this function shoudle set the player_handle to NULL in the volc_hal_context_t structure.
*
* @param player Player instance pointer
*/
void volc_hal_player_destroy(volc_hal_player_t player);
/**
* @brief Start a player instance
*
* @param player Player instance pointer
* @return int 0 if success, otherwise error code
*/
int volc_hal_player_start(volc_hal_player_t player);
/**
* @brief Stop a player instance
*
* @param player Player instance pointer
* @return int 0 if success, otherwise error code
*/
int volc_hal_player_stop(volc_hal_player_t player);
/**
* @brief Play data with a player instance
* @note We have not specified whether this function is sync or async.
* However, it is strongly recommended to implement this function as non-blocking
* with a certain internal buffer, ensuring that the caller of the function
* does not need to overly consider the function's call frequency.
* For example, the function can be called every 1 second to play 1.2 seconds of audio or video data.
*
* @param player Player instance pointer
* @param data Data to play
* @param len Data length
* @return int 0 if success, otherwise error code
*/
int volc_hal_player_play_data(volc_hal_player_t player, const void* data, int len);
void volc_hal_player_discard_pending(volc_hal_player_t player);
/* Allow a fully received short response to start without filling the prebuffer. */
void volc_hal_player_finish_segment(volc_hal_player_t player);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,26 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef __VOLC_HAL_TYPE_H__
#define __VOLC_HAL_TYPE_H__
#include "volc_conv_ai.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Media type enumeration
*/
typedef enum volc_media_type {
VOLC_MEDIA_TYPE_AUDIO = 0, // Audio media type
VOLC_MEDIA_TYPE_VIDEO, // Video media type
VOLC_MEDIA_TYPE_MAX, // Maximum media type count
} volc_media_type_e;
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,225 @@
/**
* ESPRESSIF MIT License
*
* Copyright (c) 2025 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
*
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "esp_log.h"
#include "esp_err.h"
#include "esp_board_manager.h"
#include "dev_audio_codec.h"
#include "dev_display_lcd_spi.h"
#include "basic_board.h"
static const char *TAG = "BASIC_BOARD";
typedef struct {
const char *name;
const char *mic_layout;
uint32_t sample_rate;
uint8_t sample_bits;
uint8_t channels;
} board_config_t;
static const board_config_t supported_boards[] = {
{"echoear_core_board_v1_2", "RMNM", 16000, 32, 2},
{"esp32_s3_korvo2_v3", "RMNM", 16000, 32, 2},
{"esp_vocat_board_v1_2", "RMNM", 16000, 32, 2},
{"esp_box_3", "RMNM", 16000, 32, 2},
{"ESP32_S3_Korvo_2L", "MR", 16000, 16, 2},
};
static const size_t supported_boards_count = sizeof(supported_boards) / sizeof(supported_boards[0]);
#define DEFAULT_PLAY_VOLUME 30
#define DEFAULT_REC_GAIN 32.0
#define DEFAULT_REC_CHANNEL_GAIN 32.0
#define REC_CHANNEL_MASK BIT(2)
static inline bool is_board_name(const char *board_name, const char *target_name)
{
ESP_LOGI(TAG, "board_name: %s, target_name: %s", board_name, target_name);
return strcmp(board_name, target_name) == 0;
}
static dev_audio_codec_handles_t *play_dev_handles2 = NULL;
static dev_audio_codec_handles_t *rec_dev_handles2 = NULL;
static esp_err_t setup_board_devices(basic_board_periph_t *periph)
{
esp_err_t ret = ESP_OK;
dev_audio_codec_handles_t *play_dev_handles = NULL;
dev_audio_codec_handles_t *rec_dev_handles = NULL;
void *lcd_handle = NULL;
esp_board_manager_init();
// esp_board_manager_print();
ret = esp_board_device_init_all();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize board devices: %s", esp_err_to_name(ret));
return ret;
}
esp_board_device_show("fs_sdcard");
ret = esp_board_manager_get_device_handle("audio_dac", (void **)&play_dev_handles);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get audio_dac handle: %s", esp_err_to_name(ret));
return ret;
}
ret = esp_board_manager_get_device_handle("audio_adc", (void **)&rec_dev_handles);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get audio_adc handle: %s", esp_err_to_name(ret));
return ret;
}
periph->play_dev = play_dev_handles->codec_dev;
periph->rec_dev = rec_dev_handles->codec_dev;
play_dev_handles2 = play_dev_handles;
rec_dev_handles2 = rec_dev_handles;
ret = esp_board_manager_get_device_handle("display_lcd", &lcd_handle);
if (ret == ESP_OK && lcd_handle) {
dev_display_lcd_spi_handles_t *lcd_handles = (dev_display_lcd_spi_handles_t *)lcd_handle;
periph->lcd_pannel = lcd_handles->panel_handle;
ESP_LOGI(TAG, "LCD panel handle: %p", periph->lcd_pannel);
} else {
ESP_LOGW(TAG, "Failed to get LCD device handle: %s", esp_err_to_name(ret));
}
if (periph->play_dev) {
ret = esp_codec_dev_set_out_vol(periph->play_dev, DEFAULT_PLAY_VOLUME);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set playback volume: %s", esp_err_to_name(ret));
return ret;
}
ESP_LOGI(TAG, "Playback device configured with volume: %d", DEFAULT_PLAY_VOLUME);
}
if (periph->rec_dev) {
ret = esp_codec_dev_set_in_gain(periph->rec_dev, DEFAULT_REC_GAIN);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set recording gain: %s", esp_err_to_name(ret));
return ret;
}
// ret = esp_codec_dev_set_in_channel_gain(periph->rec_dev, REC_CHANNEL_MASK, DEFAULT_REC_CHANNEL_GAIN);
// if (ret != ESP_OK) {
// ESP_LOGE(TAG, "Failed to set recording channel gain: %s", esp_err_to_name(ret));
// // return ret;
// }
ESP_LOGI(TAG, "Recording device configured with gain: %.1f", DEFAULT_REC_GAIN);
}
return ESP_OK;
}
static esp_err_t configure_board_settings(basic_board_periph_t *periph)
{
const board_config_t *config = NULL;
for (size_t i = 0; i < supported_boards_count; i++) {
ESP_LOGI(TAG, "g_esp_board_info.name: %s, supported_boards[i].name: %s", g_esp_board_info.name, supported_boards[i].name);
if (is_board_name(g_esp_board_info.name, supported_boards[i].name)) {
config = &supported_boards[i];
break;
}
}
if (config == NULL) {
ESP_LOGE(TAG, "Unsupported board: %s", g_esp_board_info.name);
ESP_LOGE(TAG, "Supported boards:");
for (size_t i = 0; i < supported_boards_count; i++) {
ESP_LOGE(TAG, " - %s", supported_boards[i].name);
}
return ESP_ERR_NOT_SUPPORTED;
}
strcpy(periph->mic_layout, config->mic_layout);
periph->sample_rate = config->sample_rate;
periph->sample_bits = config->sample_bits;
periph->channels = config->channels;
ESP_LOGI(TAG, "Board: %s", g_esp_board_info.name);
ESP_LOGI(TAG, "Mic layout: %s", periph->mic_layout);
ESP_LOGI(TAG, "Sample rate: %d Hz", periph->sample_rate);
ESP_LOGI(TAG, "Sample bits: %d", periph->sample_bits);
ESP_LOGI(TAG, "Channels: %d", periph->channels);
return ESP_OK;
}
esp_err_t basic_board_init(basic_board_periph_t *periph)
{
esp_err_t ret = ESP_OK;
if (periph == NULL) {
ESP_LOGE(TAG, "Invalid parameter: periph is NULL");
return ESP_ERR_INVALID_ARG;
}
memset(periph, 0, sizeof(basic_board_periph_t));
ret = setup_board_devices(periph);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to setup board devices");
return ret;
}
ret = configure_board_settings(periph);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to configure board settings");
return ret;
}
ESP_LOGI(TAG, "Basic board initialization completed successfully");
esp_codec_dev_sample_info_t fs = {
.sample_rate = periph->sample_rate,
.channel = periph->channels,
.bits_per_sample = periph->sample_bits,
};
ESP_LOGI(TAG, "sample_rate: %d, channel: %d, bits: %d", fs.sample_rate, fs.channel, fs.bits_per_sample);
if (periph->play_dev) {
ret = esp_codec_dev_open(periph->play_dev, &fs);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to open audio dac <%p>", periph->play_dev);
return ret;
}
}
if (periph->rec_dev) {
ret = esp_codec_dev_open(periph->rec_dev, &fs);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to open audio_adc <%p>", periph->rec_dev);
return ret;
}
}
return ESP_OK;
}
@@ -0,0 +1,44 @@
/**
* ESPRESSIF MIT License
*
* Copyright (c) 2025 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
*
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
void *play_dev;
void *rec_dev;
void *lcd_pannel;
int sample_rate;
char sample_bits;
char channels;
char mic_layout[8];
} basic_board_periph_t;
int basic_board_init(basic_board_periph_t *periph);
#ifdef __cplusplus
}
#endif /* __cplusplus */
@@ -0,0 +1,146 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMAGE_OUTPUT_112X112
#define LV_ATTRIBUTE_IMAGE_OUTPUT_112X112
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMAGE_OUTPUT_112X112 uint8_t output_112x112_map[] = {
0xfd, 0xfd, 0xf8, 0xff, 0xfd, 0xfd, 0xf7, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf6, 0xff, 0xfc, 0xf9, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xf8, 0xf5, 0xff, 0xfd, 0xf8, 0xf4, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xf8, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xf8, 0xf4, 0xff, 0xfc, 0xf8, 0xf4, 0xff, 0xfc, 0xf8, 0xf4, 0xff, 0xfd, 0xf8, 0xf5, 0xff, 0xfd, 0xf8, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfd, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfd, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xf9, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xf9, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xf9, 0xf5, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xfe, 0xfe, 0xf9, 0xff,
0xfd, 0xfd, 0xf7, 0xff, 0xfd, 0xfd, 0xf7, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfb, 0xf7, 0xf3, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfb, 0xf8, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf3, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xfe, 0xfe, 0xf8, 0xff,
0xfd, 0xfd, 0xf7, 0xff, 0xfd, 0xfd, 0xf7, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xf9, 0xfa, 0xf5, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfa, 0xf8, 0xf5, 0xff, 0xf9, 0xf7, 0xf4, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfe, 0xfb, 0xf6, 0xff,
0xfd, 0xfd, 0xf7, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfa, 0xfb, 0xf6, 0xff, 0xf8, 0xf9, 0xf5, 0xff, 0xf6, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf9, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfe, 0xfb, 0xf6, 0xff,
0xfd, 0xfd, 0xf6, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xf9, 0xfa, 0xf6, 0xff, 0xf8, 0xf9, 0xf5, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf4, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf1, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfe, 0xfc, 0xf8, 0xff,
0xfc, 0xfc, 0xf7, 0xff, 0xfb, 0xfc, 0xf6, 0xff, 0xf9, 0xfa, 0xf5, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf4, 0xf1, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf6, 0xf5, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfe, 0xfd, 0xf8, 0xff,
0xfc, 0xfc, 0xf6, 0xff, 0xfb, 0xfc, 0xf6, 0xff, 0xf9, 0xfa, 0xf5, 0xff, 0xf7, 0xf9, 0xf5, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf5, 0xf4, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfe, 0xfc, 0xf7, 0xff,
0xfc, 0xfc, 0xf6, 0xff, 0xfb, 0xfc, 0xf6, 0xff, 0xf9, 0xfa, 0xf6, 0xff, 0xf8, 0xf9, 0xf5, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf8, 0xf9, 0xf3, 0xff, 0xf8, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf7, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfc, 0xfd, 0xf7, 0xff, 0xfb, 0xfc, 0xf6, 0xff, 0xf9, 0xfb, 0xf5, 0xff, 0xf8, 0xfa, 0xf5, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfe, 0xfc, 0xf7, 0xff,
0xfc, 0xfc, 0xf6, 0xff, 0xfb, 0xfc, 0xf6, 0xff, 0xfa, 0xfb, 0xf6, 0xff, 0xf8, 0xfa, 0xf5, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf6, 0xf8, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfe, 0xfc, 0xf7, 0xff,
0xfc, 0xfc, 0xf6, 0xff, 0xfb, 0xfc, 0xf6, 0xff, 0xf9, 0xfb, 0xf6, 0xff, 0xf8, 0xfa, 0xf5, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf3, 0xff, 0xf6, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf8, 0xf3, 0xff, 0xf6, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfe, 0xfb, 0xf7, 0xff,
0xfc, 0xfc, 0xf6, 0xff, 0xfb, 0xfc, 0xf6, 0xff, 0xf9, 0xfa, 0xf6, 0xff, 0xf8, 0xf9, 0xf5, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf7, 0xf3, 0xff, 0xf5, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfe, 0xfb, 0xf7, 0xff,
0xfc, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf6, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfd, 0xfb, 0xf7, 0xff,
0xfc, 0xfb, 0xf6, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfe, 0xfb, 0xf7, 0xff,
0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf9, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf0, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xf9, 0xfa, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf9, 0xf7, 0xf1, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf4, 0xf6, 0xf4, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfd, 0xfb, 0xf6, 0xff,
0xfd, 0xfb, 0xf5, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfa, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf5, 0xf4, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfd, 0xfb, 0xf6, 0xff,
0xfd, 0xfb, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfb, 0xfa, 0xf7, 0xff, 0xfa, 0xfb, 0xf8, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfb, 0xfa, 0xf7, 0xff, 0xfa, 0xfa, 0xf7, 0xff, 0xfa, 0xfb, 0xf8, 0xff, 0xfa, 0xfb, 0xf8, 0xff, 0xfa, 0xfb, 0xf8, 0xff, 0xfa, 0xfb, 0xf8, 0xff, 0xfa, 0xfb, 0xf8, 0xff, 0xfa, 0xfb, 0xf8, 0xff, 0xfa, 0xfb, 0xf8, 0xff, 0xfb, 0xfb, 0xf8, 0xff, 0xfb, 0xfb, 0xf8, 0xff, 0xfc, 0xfb, 0xf9, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfb, 0xfb, 0xf8, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfc, 0xfa, 0xf8, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfb, 0xfa, 0xf7, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfb, 0xfa, 0xf8, 0xff, 0xfa, 0xfa, 0xf8, 0xff, 0xfa, 0xfa, 0xf8, 0xff, 0xfa, 0xfa, 0xf8, 0xff, 0xfa, 0xfa, 0xf7, 0xff, 0xfb, 0xf9, 0xf6, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf5, 0xff, 0xf6, 0xf6, 0xf5, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf5, 0xf6, 0xf5, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfd, 0xfb, 0xf6, 0xff,
0xfe, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xfa, 0xff, 0xfd, 0xfe, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfc, 0xfa, 0xf2, 0xff, 0xfb, 0xf8, 0xe6, 0xff, 0xfb, 0xf6, 0xe2, 0xff, 0xfb, 0xf6, 0xe3, 0xff, 0xfb, 0xf6, 0xe2, 0xff, 0xfb, 0xf5, 0xe3, 0xff, 0xfb, 0xf5, 0xe3, 0xff, 0xfb, 0xf6, 0xe3, 0xff, 0xfb, 0xf6, 0xe3, 0xff, 0xfc, 0xf7, 0xe3, 0xff, 0xfc, 0xf7, 0xe3, 0xff, 0xfc, 0xf7, 0xe4, 0xff, 0xfc, 0xf7, 0xe3, 0xff, 0xfc, 0xf7, 0xe4, 0xff, 0xfb, 0xf6, 0xe3, 0xff, 0xfc, 0xf6, 0xe3, 0xff, 0xfc, 0xf7, 0xe3, 0xff, 0xfc, 0xf7, 0xe3, 0xff, 0xfb, 0xf7, 0xe4, 0xff, 0xfc, 0xf7, 0xe4, 0xff, 0xfc, 0xf7, 0xe3, 0xff, 0xfc, 0xf6, 0xe3, 0xff, 0xfc, 0xf7, 0xe3, 0xff, 0xfb, 0xf7, 0xe2, 0xff, 0xfb, 0xf6, 0xe3, 0xff, 0xfb, 0xf6, 0xe3, 0xff, 0xfb, 0xf6, 0xe3, 0xff, 0xfc, 0xf6, 0xe2, 0xff, 0xfb, 0xf7, 0xe2, 0xff, 0xfb, 0xf6, 0xe2, 0xff, 0xfb, 0xf6, 0xe1, 0xff, 0xfa, 0xf5, 0xe0, 0xff, 0xfa, 0xf6, 0xe2, 0xff, 0xfb, 0xf9, 0xed, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfb, 0xfd, 0xff, 0xff, 0xfa, 0xfc, 0xfc, 0xff, 0xf9, 0xfa, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf6, 0xf5, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf6, 0xf5, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfd, 0xfc, 0xf6, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf4, 0xf4, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfb, 0xfb, 0xf9, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xfc, 0xf5, 0xda, 0xff, 0xfc, 0xe4, 0x8e, 0xff, 0xfc, 0xd4, 0x4f, 0xff, 0xfc, 0xca, 0x2c, 0xff, 0xfc, 0xc5, 0x19, 0xff, 0xfc, 0xc5, 0x14, 0xff, 0xfc, 0xc5, 0x15, 0xff, 0xfc, 0xc6, 0x15, 0xff, 0xfc, 0xc6, 0x16, 0xff, 0xfc, 0xc6, 0x16, 0xff, 0xfc, 0xc5, 0x16, 0xff, 0xfc, 0xc5, 0x16, 0xff, 0xfc, 0xc5, 0x16, 0xff, 0xfc, 0xc5, 0x16, 0xff, 0xfc, 0xc6, 0x15, 0xff, 0xfc, 0xc7, 0x15, 0xff, 0xfc, 0xc7, 0x16, 0xff, 0xfc, 0xc6, 0x17, 0xff, 0xfc, 0xc6, 0x17, 0xff, 0xfc, 0xc6, 0x17, 0xff, 0xfb, 0xc7, 0x17, 0xff, 0xfc, 0xc6, 0x18, 0xff, 0xfc, 0xc6, 0x18, 0xff, 0xfc, 0xc8, 0x17, 0xff, 0xfc, 0xc7, 0x17, 0xff, 0xfc, 0xc4, 0x16, 0xff, 0xfb, 0xc3, 0x15, 0xff, 0xfc, 0xc3, 0x15, 0xff, 0xfc, 0xc6, 0x16, 0xff, 0xfd, 0xc6, 0x17, 0xff, 0xfc, 0xc5, 0x15, 0xff, 0xfc, 0xc5, 0x15, 0xff, 0xfc, 0xc5, 0x15, 0xff, 0xfc, 0xc4, 0x14, 0xff, 0xfb, 0xc3, 0x13, 0xff, 0xfb, 0xc3, 0x16, 0xff, 0xfb, 0xc8, 0x24, 0xff, 0xfc, 0xd0, 0x3e, 0xff, 0xfb, 0xdc, 0x74, 0xff, 0xfb, 0xed, 0xbd, 0xff, 0xfa, 0xfb, 0xf6, 0xff, 0xfa, 0xfc, 0xfe, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xfa, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf6, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xfc, 0xf6, 0xe1, 0xff, 0xfb, 0xda, 0x6d, 0xff, 0xfc, 0xc3, 0x0f, 0xff, 0xfd, 0xba, 0x00, 0xff, 0xfd, 0xbb, 0x00, 0xff, 0xfd, 0xbc, 0x00, 0xff, 0xfd, 0xbd, 0x00, 0xff, 0xfd, 0xbe, 0x00, 0xff, 0xfd, 0xbd, 0x00, 0xff, 0xfd, 0xbd, 0x00, 0xff, 0xfd, 0xbe, 0x00, 0xff, 0xfd, 0xbf, 0x00, 0xff, 0xfe, 0xbf, 0x00, 0xff, 0xfe, 0xc0, 0x00, 0xff, 0xfd, 0xbf, 0x00, 0xff, 0xfe, 0xbf, 0x00, 0xff, 0xfd, 0xc1, 0x00, 0xff, 0xfd, 0xc1, 0x00, 0xff, 0xfd, 0xc0, 0x00, 0xff, 0xfe, 0xbf, 0x00, 0xff, 0xfd, 0xbf, 0x00, 0xff, 0xfd, 0xbf, 0x00, 0xff, 0xfd, 0xc0, 0x01, 0xff, 0xfd, 0xbf, 0x01, 0xff, 0xfd, 0xbf, 0x00, 0xff, 0xfd, 0xbf, 0x00, 0xff, 0xfd, 0xbe, 0x00, 0xff, 0xfe, 0xbe, 0x00, 0xff, 0xfe, 0xbe, 0x00, 0xff, 0xfe, 0xbe, 0x00, 0xff, 0xfd, 0xbf, 0x00, 0xff, 0xfe, 0xbf, 0x00, 0xff, 0xfd, 0xbd, 0x00, 0xff, 0xfd, 0xbe, 0x00, 0xff, 0xfe, 0xbe, 0x00, 0xff, 0xfe, 0xbf, 0x00, 0xff, 0xfd, 0xbd, 0x00, 0xff, 0xfc, 0xbb, 0x00, 0xff, 0xfd, 0xbb, 0x00, 0xff, 0xfd, 0xbc, 0x00, 0xff, 0xfd, 0xbb, 0x00, 0xff, 0xfc, 0xbb, 0x00, 0xff, 0xfb, 0xcc, 0x3b, 0xff, 0xfb, 0xec, 0xb4, 0xff, 0xfc, 0xfd, 0xfe, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xfc, 0xeb, 0xb6, 0xff, 0xfc, 0xc4, 0x1f, 0xff, 0xfd, 0xba, 0x00, 0xff, 0xfd, 0xbc, 0x00, 0xff, 0xfd, 0xbd, 0x02, 0xff, 0xfd, 0xbd, 0x03, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbe, 0x02, 0xff, 0xfd, 0xbe, 0x03, 0xff, 0xfd, 0xbf, 0x02, 0xff, 0xfd, 0xbe, 0x03, 0xff, 0xfd, 0xbe, 0x03, 0xff, 0xfd, 0xbf, 0x04, 0xff, 0xfd, 0xbf, 0x05, 0xff, 0xfe, 0xbf, 0x05, 0xff, 0xfe, 0xbe, 0x06, 0xff, 0xfe, 0xbf, 0x05, 0xff, 0xfd, 0xc0, 0x05, 0xff, 0xfd, 0xc1, 0x06, 0xff, 0xfd, 0xbf, 0x07, 0xff, 0xfe, 0xbe, 0x06, 0xff, 0xfe, 0xbf, 0x05, 0xff, 0xfd, 0xbe, 0x05, 0xff, 0xfe, 0xbe, 0x04, 0xff, 0xfe, 0xbf, 0x03, 0xff, 0xfd, 0xbe, 0x03, 0xff, 0xfd, 0xbe, 0x04, 0xff, 0xfe, 0xbe, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbe, 0x05, 0xff, 0xfd, 0xbf, 0x04, 0xff, 0xfd, 0xbe, 0x04, 0xff, 0xfd, 0xbe, 0x04, 0xff, 0xfc, 0xbd, 0x03, 0xff, 0xfd, 0xbd, 0x02, 0xff, 0xfd, 0xbd, 0x02, 0xff, 0xfd, 0xbb, 0x00, 0xff, 0xfd, 0xbb, 0x00, 0xff, 0xfd, 0xbe, 0x00, 0xff, 0xfb, 0xdb, 0x6d, 0xff, 0xfd, 0xfb, 0xf4, 0xff, 0xfd, 0xfc, 0xfa, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xfd, 0xff, 0xff, 0xfc, 0xe6, 0xa2, 0xff, 0xfc, 0xbd, 0x05, 0xff, 0xfd, 0xba, 0x00, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbe, 0x05, 0xff, 0xfd, 0xbe, 0x06, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbe, 0x06, 0xff, 0xfd, 0xc0, 0x07, 0xff, 0xfd, 0xbf, 0x08, 0xff, 0xfd, 0xbe, 0x08, 0xff, 0xfd, 0xbe, 0x07, 0xff, 0xfd, 0xbe, 0x07, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbc, 0x04, 0xff, 0xfd, 0xbc, 0x04, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbe, 0x06, 0xff, 0xfd, 0xbe, 0x05, 0xff, 0xfe, 0xbe, 0x05, 0xff, 0xfd, 0xbe, 0x05, 0xff, 0xfd, 0xbd, 0x04, 0xff, 0xfd, 0xbc, 0x04, 0xff, 0xfd, 0xbc, 0x04, 0xff, 0xfd, 0xbc, 0x03, 0xff, 0xfd, 0xbd, 0x03, 0xff, 0xfd, 0xbd, 0x00, 0xff, 0xfc, 0xb9, 0x00, 0xff, 0xfb, 0xd1, 0x4f, 0xff, 0xfd, 0xfb, 0xf3, 0xff, 0xfc, 0xfb, 0xf8, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf6, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf3, 0xff, 0xfd, 0xfc, 0xfe, 0xff, 0xfc, 0xed, 0xba, 0xff, 0xfc, 0xc0, 0x06, 0xff, 0xfd, 0xbc, 0x00, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfd, 0xbb, 0x07, 0xff, 0xfd, 0xbb, 0x05, 0xff, 0xfd, 0xbc, 0x04, 0xff, 0xfd, 0xbc, 0x05, 0xff, 0xfd, 0xbd, 0x05, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfe, 0xbc, 0x09, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfe, 0xbd, 0x08, 0xff, 0xfd, 0xbd, 0x09, 0xff, 0xfd, 0xbe, 0x09, 0xff, 0xfd, 0xbf, 0x0a, 0xff, 0xfe, 0xbf, 0x0b, 0xff, 0xfd, 0xbf, 0x0a, 0xff, 0xfd, 0xbe, 0x0a, 0xff, 0xfd, 0xbd, 0x0a, 0xff, 0xfe, 0xbd, 0x09, 0xff, 0xfe, 0xbd, 0x08, 0xff, 0xfd, 0xbd, 0x07, 0xff, 0xfd, 0xbd, 0x07, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbb, 0x05, 0xff, 0xfe, 0xbd, 0x07, 0xff, 0xfd, 0xbe, 0x07, 0xff, 0xfd, 0xbe, 0x08, 0xff, 0xfd, 0xbf, 0x06, 0xff, 0xfd, 0xbe, 0x06, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbc, 0x05, 0xff, 0xfd, 0xbc, 0x05, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbc, 0x05, 0xff, 0xfd, 0xbb, 0x03, 0xff, 0xfd, 0xb8, 0x00, 0xff, 0xfc, 0xd7, 0x63, 0xff, 0xfd, 0xfd, 0xfc, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xfa, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfd, 0xfb, 0xf6, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf7, 0xff, 0xfd, 0xf8, 0xe8, 0xff, 0xfc, 0xc7, 0x28, 0xff, 0xfd, 0xbc, 0x00, 0xff, 0xfd, 0xbe, 0x06, 0xff, 0xfd, 0xbc, 0x05, 0xff, 0xfd, 0xbb, 0x05, 0xff, 0xfd, 0xbb, 0x04, 0xff, 0xfd, 0xbb, 0x05, 0xff, 0xfd, 0xbb, 0x07, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfd, 0xbc, 0x07, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfe, 0xbb, 0x08, 0xff, 0xfd, 0xba, 0x07, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfe, 0xbc, 0x0a, 0xff, 0xfe, 0xbc, 0x0a, 0xff, 0xfd, 0xbd, 0x0a, 0xff, 0xfd, 0xbd, 0x0a, 0xff, 0xfd, 0xbd, 0x0b, 0xff, 0xfd, 0xbd, 0x0b, 0xff, 0xfd, 0xbe, 0x0b, 0xff, 0xfd, 0xbd, 0x0b, 0xff, 0xfd, 0xbd, 0x0b, 0xff, 0xfd, 0xbc, 0x0a, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfd, 0xbc, 0x0c, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfd, 0xbc, 0x0a, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xbc, 0x07, 0xff, 0xfd, 0xbc, 0x07, 0xff, 0xfd, 0xbd, 0x09, 0xff, 0xfd, 0xbd, 0x09, 0xff, 0xfd, 0xbd, 0x09, 0xff, 0xfd, 0xbd, 0x07, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfd, 0xbc, 0x07, 0xff, 0xfd, 0xbc, 0x05, 0xff, 0xfd, 0xbd, 0x06, 0xff, 0xfd, 0xbc, 0x06, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfd, 0xbb, 0x06, 0xff, 0xfd, 0xba, 0x02, 0xff, 0xfc, 0xb7, 0x00, 0xff, 0xfb, 0xe6, 0xa3, 0xff, 0xfc, 0xfd, 0xff, 0xff, 0xfb, 0xf9, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfe, 0xfb, 0xf6, 0xff,
0xfd, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xfc, 0xde, 0x85, 0xff, 0xfd, 0xb9, 0x00, 0xff, 0xfd, 0xbd, 0x07, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xba, 0x06, 0xff, 0xfd, 0xba, 0x05, 0xff, 0xfd, 0xba, 0x07, 0xff, 0xfd, 0xba, 0x09, 0xff, 0xfd, 0xba, 0x08, 0xff, 0xfd, 0xba, 0x09, 0xff, 0xfd, 0xbb, 0x09, 0xff, 0xfd, 0xbc, 0x0a, 0xff, 0xfe, 0xbc, 0x0a, 0xff, 0xfe, 0xbb, 0x0a, 0xff, 0xfd, 0xbb, 0x09, 0xff, 0xfd, 0xbb, 0x09, 0xff, 0xfd, 0xba, 0x09, 0xff, 0xfe, 0xba, 0x08, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xbb, 0x0a, 0xff, 0xfe, 0xbc, 0x0c, 0xff, 0xfd, 0xbc, 0x0c, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfd, 0xbd, 0x0a, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfd, 0xbc, 0x0a, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfd, 0xbc, 0x0c, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfd, 0xbc, 0x0c, 0xff, 0xfd, 0xbb, 0x0d, 0xff, 0xfd, 0xbb, 0x0d, 0xff, 0xfe, 0xbb, 0x0d, 0xff, 0xfd, 0xbb, 0x0b, 0xff, 0xfe, 0xbb, 0x0a, 0xff, 0xfd, 0xbc, 0x0a, 0xff, 0xfd, 0xbd, 0x0b, 0xff, 0xfd, 0xbd, 0x0c, 0xff, 0xfd, 0xbc, 0x0c, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfe, 0xbc, 0x0a, 0xff, 0xfd, 0xbb, 0x09, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xbc, 0x07, 0xff, 0xfd, 0xbc, 0x08, 0xff, 0xfe, 0xbc, 0x09, 0xff, 0xfd, 0xbb, 0x08, 0xff, 0xfd, 0xba, 0x05, 0xff, 0xfd, 0xb6, 0x00, 0xff, 0xfc, 0xc3, 0x29, 0xff, 0xfd, 0xfa, 0xef, 0xff, 0xfd, 0xfb, 0xf7, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfe, 0xfb, 0xf6, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xf9, 0xfa, 0xf5, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfc, 0xf9, 0xf6, 0xff, 0xfd, 0xf7, 0xec, 0xff, 0xfc, 0xc4, 0x27, 0xff, 0xfd, 0xbb, 0x00, 0xff, 0xfe, 0xbc, 0x0a, 0xff, 0xfd, 0xba, 0x09, 0xff, 0xfd, 0xba, 0x09, 0xff, 0xfd, 0xb9, 0x08, 0xff, 0xfd, 0xb9, 0x08, 0xff, 0xfd, 0xb9, 0x0a, 0xff, 0xfe, 0xb9, 0x0a, 0xff, 0xfd, 0xb9, 0x0a, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb9, 0x0a, 0xff, 0xfd, 0xba, 0x0c, 0xff, 0xfd, 0xba, 0x0b, 0xff, 0xfd, 0xba, 0x0b, 0xff, 0xfd, 0xba, 0x0b, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb9, 0x09, 0xff, 0xfd, 0xb9, 0x09, 0xff, 0xfe, 0xba, 0x0b, 0xff, 0xfe, 0xbb, 0x0d, 0xff, 0xfd, 0xbb, 0x0d, 0xff, 0xfd, 0xbc, 0x0d, 0xff, 0xfd, 0xbd, 0x0d, 0xff, 0xfd, 0xbc, 0x0d, 0xff, 0xfd, 0xbb, 0x0d, 0xff, 0xfd, 0xbb, 0x0c, 0xff, 0xfe, 0xba, 0x0c, 0xff, 0xfe, 0xba, 0x0c, 0xff, 0xfd, 0xba, 0x0b, 0xff, 0xfe, 0xbb, 0x0c, 0xff, 0xfe, 0xbb, 0x0c, 0xff, 0xfe, 0xbc, 0x0c, 0xff, 0xfd, 0xbc, 0x0d, 0xff, 0xfd, 0xbc, 0x0d, 0xff, 0xfd, 0xbc, 0x0c, 0xff, 0xfd, 0xbd, 0x0d, 0xff, 0xfd, 0xbc, 0x0e, 0xff, 0xfd, 0xbc, 0x0e, 0xff, 0xfd, 0xbc, 0x0e, 0xff, 0xfd, 0xbb, 0x0e, 0xff, 0xfd, 0xbb, 0x0d, 0xff, 0xfd, 0xbb, 0x0d, 0xff, 0xfe, 0xbb, 0x0c, 0xff, 0xfe, 0xbb, 0x0b, 0xff, 0xfe, 0xbc, 0x0a, 0xff, 0xfe, 0xbd, 0x0a, 0xff, 0xfd, 0xbd, 0x0a, 0xff, 0xfd, 0xbb, 0x07, 0xff, 0xfd, 0xba, 0x04, 0xff, 0xfc, 0xb4, 0x00, 0xff, 0xfc, 0xe6, 0xab, 0xff, 0xfd, 0xfe, 0xff, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xff, 0xfe, 0xf9, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xfe, 0xfe, 0xf8, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfe, 0xfb, 0xf6, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfd, 0xfa, 0xfb, 0xff, 0xfc, 0xe9, 0xb9, 0xff, 0xfc, 0xb8, 0x00, 0xff, 0xfd, 0xba, 0x06, 0xff, 0xfd, 0xbb, 0x0b, 0xff, 0xfd, 0xba, 0x0b, 0xff, 0xfd, 0xb9, 0x0a, 0xff, 0xfd, 0xb8, 0x09, 0xff, 0xfd, 0xb8, 0x09, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb7, 0x0c, 0xff, 0xfd, 0xb6, 0x0c, 0xff, 0xfd, 0xb6, 0x0c, 0xff, 0xfd, 0xb7, 0x0c, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb8, 0x09, 0xff, 0xfd, 0xb7, 0x0a, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xba, 0x0c, 0xff, 0xfd, 0xba, 0x0d, 0xff, 0xfd, 0xba, 0x0e, 0xff, 0xfd, 0xba, 0x0e, 0xff, 0xfe, 0xba, 0x0d, 0xff, 0xfd, 0xb9, 0x0d, 0xff, 0xfd, 0xb8, 0x0c, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb6, 0x0a, 0xff, 0xfd, 0xb7, 0x0a, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xba, 0x0c, 0xff, 0xfe, 0xbb, 0x0c, 0xff, 0xfd, 0xbb, 0x0c, 0xff, 0xfe, 0xbb, 0x0c, 0xff, 0xfd, 0xbb, 0x0c, 0xff, 0xfd, 0xbb, 0x0d, 0xff, 0xfd, 0xbb, 0x0d, 0xff, 0xfd, 0xbb, 0x0e, 0xff, 0xfd, 0xbb, 0x0e, 0xff, 0xfe, 0xba, 0x0e, 0xff, 0xfd, 0xb9, 0x0d, 0xff, 0xfd, 0xb9, 0x0d, 0xff, 0xfd, 0xbb, 0x0c, 0xff, 0xfe, 0xbb, 0x0c, 0xff, 0xfe, 0xbb, 0x0c, 0xff, 0xfe, 0xbb, 0x0b, 0xff, 0xfd, 0xbc, 0x0b, 0xff, 0xfd, 0xbb, 0x0b, 0xff, 0xfd, 0xb9, 0x07, 0xff, 0xfd, 0xb2, 0x00, 0xff, 0xfc, 0xce, 0x5e, 0xff, 0xfd, 0xfe, 0xff, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xef, 0xec, 0xff, 0xda, 0xce, 0xcb, 0xff, 0xc1, 0xaa, 0xa5, 0xff, 0xae, 0x8d, 0x88, 0xff, 0x9d, 0x74, 0x6e, 0xff, 0x90, 0x63, 0x5d, 0xff, 0x8a, 0x59, 0x53, 0xff, 0x87, 0x55, 0x50, 0xff, 0x89, 0x57, 0x52, 0xff, 0x91, 0x63, 0x5e, 0xff, 0xa0, 0x79, 0x74, 0xff, 0xb2, 0x95, 0x91, 0xff, 0xca, 0xb7, 0xb3, 0xff, 0xe5, 0xdb, 0xd8, 0xff, 0xfb, 0xfb, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf9, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfe, 0xfb, 0xf6, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xfb, 0xf6, 0xf1, 0xff, 0xfd, 0xfa, 0xfc, 0xff, 0xfc, 0xda, 0x88, 0xff, 0xfd, 0xb5, 0x00, 0xff, 0xfd, 0xb9, 0x08, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfe, 0xba, 0x0b, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb8, 0x0a, 0xff, 0xfd, 0xb8, 0x0a, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb5, 0x0c, 0xff, 0xfd, 0xb5, 0x0c, 0xff, 0xfd, 0xb5, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb3, 0x0d, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb6, 0x0c, 0xff, 0xfc, 0xb6, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb6, 0x0a, 0xff, 0xfd, 0xb7, 0x0c, 0xff, 0xfd, 0xb7, 0x0e, 0xff, 0xfd, 0xb6, 0x0e, 0xff, 0xfd, 0xb6, 0x0e, 0xff, 0xfd, 0xb6, 0x0d, 0xff, 0xfd, 0xb6, 0x0c, 0xff, 0xfd, 0xb6, 0x0b, 0xff, 0xfd, 0xb5, 0x0a, 0xff, 0xfd, 0xb5, 0x09, 0xff, 0xfd, 0xb5, 0x09, 0xff, 0xfd, 0xb6, 0x0a, 0xff, 0xfd, 0xb7, 0x0a, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb9, 0x0c, 0xff, 0xfe, 0xba, 0x0d, 0xff, 0xfd, 0xb9, 0x0d, 0xff, 0xfd, 0xb7, 0x0d, 0xff, 0xfd, 0xb7, 0x0c, 0xff, 0xfd, 0xb7, 0x0c, 0xff, 0xfd, 0xb8, 0x0c, 0xff, 0xfd, 0xb8, 0x0c, 0xff, 0xfd, 0xb9, 0x0c, 0xff, 0xfd, 0xb9, 0x0b, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb8, 0x09, 0xff, 0xfd, 0xb4, 0x00, 0xff, 0xfc, 0xc1, 0x31, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xf8, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xff, 0xfe, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xdf, 0xd4, 0xd0, 0xff, 0xad, 0x8f, 0x8b, 0xff, 0x7e, 0x4d, 0x48, 0xff, 0x62, 0x22, 0x1c, 0xff, 0x52, 0x0b, 0x02, 0xff, 0x4b, 0x00, 0x00, 0xff, 0x48, 0x00, 0x00, 0xff, 0x49, 0x00, 0x00, 0xff, 0x4b, 0x01, 0x00, 0xff, 0x4e, 0x03, 0x00, 0xff, 0x4e, 0x03, 0x00, 0xff, 0x4c, 0x02, 0x00, 0xff, 0x4b, 0x00, 0x00, 0xff, 0x49, 0x00, 0x00, 0xff, 0x49, 0x00, 0x00, 0xff, 0x4c, 0x02, 0x00, 0xff, 0x59, 0x11, 0x0a, 0xff, 0x70, 0x33, 0x2e, 0xff, 0x9a, 0x6f, 0x6d, 0xff, 0xd2, 0xbe, 0xbb, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xf8, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfe, 0xfd, 0xf6, 0xff,
0xfd, 0xfb, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf9, 0xf6, 0xf0, 0xff, 0xfc, 0xf5, 0xef, 0xff, 0xfd, 0xf9, 0xf8, 0xff, 0xfc, 0xd0, 0x68, 0xff, 0xfd, 0xb3, 0x00, 0xff, 0xfd, 0xb7, 0x0a, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfc, 0xb7, 0x0b, 0xff, 0xfd, 0xb5, 0x0b, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb2, 0x0d, 0xff, 0xfd, 0xb1, 0x0e, 0xff, 0xfd, 0xb1, 0x0c, 0xff, 0xfd, 0xb2, 0x0c, 0xff, 0xfd, 0xb3, 0x0d, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb4, 0x0b, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0b, 0xff, 0xfd, 0xb4, 0x0a, 0xff, 0xfd, 0xb5, 0x0b, 0xff, 0xfd, 0xb5, 0x0c, 0xff, 0xfd, 0xb4, 0x0d, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0a, 0xff, 0xfd, 0xb4, 0x08, 0xff, 0xfd, 0xb3, 0x09, 0xff, 0xfd, 0xb3, 0x0b, 0xff, 0xfd, 0xb4, 0x0a, 0xff, 0xfd, 0xb6, 0x0b, 0xff, 0xfd, 0xb6, 0x0c, 0xff, 0xfd, 0xb7, 0x0c, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb8, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb7, 0x0c, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb6, 0x0b, 0xff, 0xfd, 0xb6, 0x0c, 0xff, 0xfd, 0xb5, 0x0d, 0xff, 0xfd, 0xb5, 0x0c, 0xff, 0xfd, 0xb5, 0x0c, 0xff, 0xfd, 0xb6, 0x0c, 0xff, 0xfc, 0xb7, 0x0b, 0xff, 0xfd, 0xb7, 0x0b, 0xff, 0xfd, 0xb6, 0x0a, 0xff, 0xfd, 0xb4, 0x03, 0xff, 0xfc, 0xbb, 0x1c, 0xff, 0xfd, 0xf6, 0xe7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf8, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xc1, 0xa8, 0xa2, 0xff, 0x7f, 0x49, 0x41, 0xff, 0x54, 0x0f, 0x05, 0xff, 0x49, 0x00, 0x00, 0xff, 0x4b, 0x02, 0x00, 0xff, 0x52, 0x07, 0x00, 0xff, 0x54, 0x0c, 0x00, 0xff, 0x55, 0x0d, 0x02, 0xff, 0x54, 0x0d, 0x03, 0xff, 0x54, 0x0d, 0x03, 0xff, 0x54, 0x0e, 0x02, 0xff, 0x55, 0x0f, 0x03, 0xff, 0x55, 0x0f, 0x04, 0xff, 0x54, 0x0e, 0x03, 0xff, 0x54, 0x0d, 0x03, 0xff, 0x55, 0x0c, 0x01, 0xff, 0x55, 0x0c, 0x01, 0xff, 0x56, 0x0b, 0x01, 0xff, 0x55, 0x09, 0x00, 0xff, 0x51, 0x03, 0x00, 0xff, 0x4c, 0x00, 0x00, 0xff, 0x4e, 0x04, 0x00, 0xff, 0x6e, 0x32, 0x2b, 0xff, 0xb5, 0x96, 0x91, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfe, 0xfd, 0xf7, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf0, 0xff, 0xfc, 0xf5, 0xed, 0xff, 0xfe, 0xf7, 0xf5, 0xff, 0xfc, 0xcc, 0x5d, 0xff, 0xfd, 0xb3, 0x00, 0xff, 0xfd, 0xb5, 0x09, 0xff, 0xfd, 0xb5, 0x0b, 0xff, 0xfd, 0xb6, 0x0b, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb2, 0x0c, 0xff, 0xfd, 0xb1, 0x0d, 0xff, 0xfd, 0xb0, 0x0d, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xb0, 0x0c, 0xff, 0xfd, 0xb1, 0x0d, 0xff, 0xfd, 0xb1, 0x0d, 0xff, 0xfd, 0xb1, 0x0c, 0xff, 0xfd, 0xb1, 0x0c, 0xff, 0xfd, 0xb1, 0x0c, 0xff, 0xfd, 0xb1, 0x0b, 0xff, 0xfd, 0xb2, 0x0b, 0xff, 0xfd, 0xb3, 0x0b, 0xff, 0xfd, 0xb2, 0x0d, 0xff, 0xfd, 0xb2, 0x0d, 0xff, 0xfd, 0xb2, 0x0c, 0xff, 0xfd, 0xb2, 0x0d, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb2, 0x0b, 0xff, 0xfd, 0xb1, 0x0b, 0xff, 0xfd, 0xb0, 0x0d, 0xff, 0xfd, 0xb1, 0x0d, 0xff, 0xfd, 0xb3, 0x0d, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0b, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb4, 0x0b, 0xff, 0xfd, 0xb4, 0x0b, 0xff, 0xfd, 0xb3, 0x0b, 0xff, 0xfd, 0xb4, 0x0d, 0xff, 0xfd, 0xb3, 0x0d, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb3, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb4, 0x0c, 0xff, 0xfd, 0xb2, 0x05, 0xff, 0xfc, 0xb8, 0x19, 0xff, 0xfc, 0xf6, 0xe3, 0xff, 0xfd, 0xfb, 0xf7, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfd, 0xfb, 0xf5, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xca, 0xb4, 0xaf, 0xff, 0x72, 0x36, 0x2e, 0xff, 0x4c, 0x00, 0x00, 0xff, 0x4f, 0x02, 0x00, 0xff, 0x55, 0x0b, 0x00, 0xff, 0x55, 0x0e, 0x02, 0xff, 0x55, 0x0f, 0x03, 0xff, 0x57, 0x0f, 0x03, 0xff, 0x56, 0x10, 0x04, 0xff, 0x57, 0x10, 0x05, 0xff, 0x58, 0x10, 0x05, 0xff, 0x58, 0x10, 0x05, 0xff, 0x58, 0x10, 0x04, 0xff, 0x58, 0x10, 0x04, 0xff, 0x57, 0x10, 0x04, 0xff, 0x57, 0x0f, 0x04, 0xff, 0x57, 0x0e, 0x04, 0xff, 0x57, 0x0e, 0x02, 0xff, 0x57, 0x0d, 0x03, 0xff, 0x57, 0x0d, 0x04, 0xff, 0x57, 0x0d, 0x03, 0xff, 0x57, 0x0c, 0x02, 0xff, 0x57, 0x0b, 0x01, 0xff, 0x55, 0x0a, 0x00, 0xff, 0x4e, 0x02, 0x00, 0xff, 0x48, 0x00, 0x00, 0xff, 0x69, 0x2d, 0x27, 0xff, 0xc8, 0xb0, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf9, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfe, 0xfd, 0xf7, 0xff,
0xfc, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xfa, 0xf5, 0xef, 0xff, 0xfc, 0xf4, 0xec, 0xff, 0xfd, 0xf5, 0xf4, 0xff, 0xfc, 0xcb, 0x5d, 0xff, 0xfd, 0xb0, 0x00, 0xff, 0xfd, 0xb2, 0x0b, 0xff, 0xfe, 0xb2, 0x0b, 0xff, 0xfd, 0xb3, 0x0b, 0xff, 0xfd, 0xb1, 0x0c, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xaf, 0x0c, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xae, 0x0d, 0xff, 0xfd, 0xae, 0x0d, 0xff, 0xfd, 0xad, 0x0d, 0xff, 0xfd, 0xae, 0x0d, 0xff, 0xfd, 0xae, 0x0d, 0xff, 0xfe, 0xaf, 0x0c, 0xff, 0xfd, 0xae, 0x0c, 0xff, 0xfe, 0xaf, 0x0c, 0xff, 0xfd, 0xaf, 0x0b, 0xff, 0xfe, 0xaf, 0x0a, 0xff, 0xfe, 0xaf, 0x0a, 0xff, 0xfd, 0xaf, 0x0a, 0xff, 0xfd, 0xaf, 0x0a, 0xff, 0xfd, 0xb0, 0x0b, 0xff, 0xfd, 0xaf, 0x0c, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xb0, 0x0e, 0xff, 0xfd, 0xb0, 0x0e, 0xff, 0xfd, 0xb1, 0x0e, 0xff, 0xfd, 0xb0, 0x0d, 0xff, 0xfc, 0xaf, 0x0d, 0xff, 0xfd, 0xaf, 0x0d, 0xff, 0xfd, 0xae, 0x0e, 0xff, 0xfd, 0xae, 0x0e, 0xff, 0xfd, 0xb0, 0x0e, 0xff, 0xfd, 0xb0, 0x0d, 0xff, 0xfd, 0xaf, 0x0c, 0xff, 0xfd, 0xb0, 0x0c, 0xff, 0xfd, 0xb0, 0x0b, 0xff, 0xfe, 0xb0, 0x0b, 0xff, 0xfd, 0xb0, 0x0a, 0xff, 0xfd, 0xb0, 0x0c, 0xff, 0xfd, 0xb0, 0x0d, 0xff, 0xfd, 0xb1, 0x0e, 0xff, 0xfd, 0xb2, 0x0d, 0xff, 0xfd, 0xb2, 0x0c, 0xff, 0xfd, 0xb1, 0x0e, 0xff, 0xfd, 0xb0, 0x0e, 0xff, 0xfd, 0xb0, 0x0e, 0xff, 0xfd, 0xb0, 0x0e, 0xff, 0xfd, 0xb1, 0x0e, 0xff, 0xfd, 0xaf, 0x06, 0xff, 0xfc, 0xb6, 0x19, 0xff, 0xfd, 0xf5, 0xe4, 0xff, 0xfc, 0xfa, 0xf7, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf1, 0xeb, 0xff, 0x91, 0x65, 0x5d, 0xff, 0x4d, 0x03, 0x00, 0xff, 0x4e, 0x03, 0x00, 0xff, 0x55, 0x0c, 0x01, 0xff, 0x56, 0x0e, 0x02, 0xff, 0x56, 0x0f, 0x03, 0xff, 0x57, 0x10, 0x05, 0xff, 0x58, 0x11, 0x05, 0xff, 0x58, 0x11, 0x06, 0xff, 0x58, 0x11, 0x07, 0xff, 0x58, 0x11, 0x07, 0xff, 0x59, 0x11, 0x07, 0xff, 0x59, 0x11, 0x07, 0xff, 0x59, 0x10, 0x06, 0xff, 0x58, 0x10, 0x05, 0xff, 0x58, 0x0f, 0x04, 0xff, 0x57, 0x0e, 0x01, 0xff, 0x54, 0x0d, 0x00, 0xff, 0x51, 0x0b, 0x00, 0xff, 0x4f, 0x0a, 0x00, 0xff, 0x4e, 0x09, 0x00, 0xff, 0x4d, 0x08, 0x00, 0xff, 0x4d, 0x08, 0x00, 0xff, 0x4e, 0x08, 0x00, 0xff, 0x52, 0x0a, 0x00, 0xff, 0x54, 0x09, 0x00, 0xff, 0x53, 0x09, 0x00, 0xff, 0x4c, 0x01, 0x00, 0xff, 0x4c, 0x03, 0x00, 0xff, 0x9a, 0x6f, 0x68, 0xff, 0xfb, 0xf7, 0xf3, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xfd, 0xfd, 0xf8, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf5, 0xef, 0xff, 0xfa, 0xf4, 0xed, 0xff, 0xfb, 0xf2, 0xeb, 0xff, 0xfc, 0xf4, 0xf2, 0xff, 0xfc, 0xc7, 0x5d, 0xff, 0xfd, 0xaa, 0x00, 0xff, 0xfd, 0xae, 0x0c, 0xff, 0xfc, 0xaf, 0x0d, 0xff, 0xfc, 0xaf, 0x0d, 0xff, 0xfd, 0xae, 0x0d, 0xff, 0xfd, 0xad, 0x0c, 0xff, 0xfd, 0xad, 0x0c, 0xff, 0xfd, 0xad, 0x0c, 0xff, 0xfd, 0xab, 0x0b, 0xff, 0xfd, 0xac, 0x0c, 0xff, 0xfd, 0xad, 0x0d, 0xff, 0xfd, 0xad, 0x0d, 0xff, 0xfd, 0xad, 0x0d, 0xff, 0xfd, 0xad, 0x0c, 0xff, 0xfd, 0xae, 0x0c, 0xff, 0xfd, 0xae, 0x0c, 0xff, 0xfd, 0xad, 0x0c, 0xff, 0xfd, 0xad, 0x0c, 0xff, 0xfd, 0xab, 0x06, 0xff, 0xfd, 0xa9, 0x00, 0xff, 0xfd, 0xaa, 0x00, 0xff, 0xfd, 0xa9, 0x00, 0xff, 0xfd, 0xa9, 0x00, 0xff, 0xfd, 0xa9, 0x00, 0xff, 0xfd, 0xac, 0x08, 0xff, 0xfd, 0xae, 0x0d, 0xff, 0xfc, 0xaf, 0x0e, 0xff, 0xfd, 0xaf, 0x0f, 0xff, 0xfd, 0xaf, 0x0f, 0xff, 0xfd, 0xaf, 0x0e, 0xff, 0xfc, 0xae, 0x0e, 0xff, 0xfd, 0xae, 0x0e, 0xff, 0xfd, 0xae, 0x0e, 0xff, 0xfd, 0xae, 0x0e, 0xff, 0xfc, 0xae, 0x0e, 0xff, 0xfd, 0xae, 0x0e, 0xff, 0xfd, 0xae, 0x09, 0xff, 0xfd, 0xab, 0x00, 0xff, 0xfd, 0xab, 0x00, 0xff, 0xfe, 0xaa, 0x00, 0xff, 0xfd, 0xa9, 0x00, 0xff, 0xfd, 0xac, 0x04, 0xff, 0xfd, 0xb0, 0x0e, 0xff, 0xfd, 0xb1, 0x0f, 0xff, 0xfc, 0xb2, 0x0f, 0xff, 0xfd, 0xb2, 0x0f, 0xff, 0xfd, 0xb0, 0x0f, 0xff, 0xfd, 0xaf, 0x0e, 0xff, 0xfc, 0xae, 0x0e, 0xff, 0xfd, 0xaf, 0x0e, 0xff, 0xfd, 0xaf, 0x0f, 0xff, 0xfd, 0xae, 0x08, 0xff, 0xfc, 0xb5, 0x1a, 0xff, 0xfd, 0xf5, 0xe4, 0xff, 0xfd, 0xfb, 0xf7, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0xdb, 0xd6, 0xff, 0x6f, 0x36, 0x2e, 0xff, 0x46, 0x00, 0x00, 0xff, 0x51, 0x09, 0x00, 0xff, 0x55, 0x0d, 0x03, 0xff, 0x57, 0x0e, 0x03, 0xff, 0x58, 0x10, 0x05, 0xff, 0x58, 0x11, 0x06, 0xff, 0x58, 0x11, 0x07, 0xff, 0x58, 0x12, 0x07, 0xff, 0x58, 0x12, 0x07, 0xff, 0x59, 0x12, 0x08, 0xff, 0x59, 0x12, 0x08, 0xff, 0x5a, 0x11, 0x08, 0xff, 0x5a, 0x10, 0x07, 0xff, 0x58, 0x0f, 0x04, 0xff, 0x52, 0x0c, 0x00, 0xff, 0x4e, 0x09, 0x00, 0xff, 0x5e, 0x0d, 0x06, 0xff, 0x78, 0x15, 0x1c, 0xff, 0x91, 0x1e, 0x32, 0xff, 0xa0, 0x24, 0x3e, 0xff, 0xa5, 0x27, 0x41, 0xff, 0xa3, 0x25, 0x3d, 0xff, 0x96, 0x20, 0x31, 0xff, 0x79, 0x16, 0x1d, 0xff, 0x5c, 0x0c, 0x07, 0xff, 0x4d, 0x06, 0x00, 0xff, 0x4d, 0x07, 0x00, 0xff, 0x51, 0x09, 0x01, 0xff, 0x4f, 0x07, 0x00, 0xff, 0x44, 0x00, 0x00, 0xff, 0x7b, 0x46, 0x41, 0xff, 0xf2, 0xed, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf9, 0xf4, 0xed, 0xff, 0xfa, 0xf2, 0xeb, 0xff, 0xfb, 0xf1, 0xea, 0xff, 0xfc, 0xf2, 0xf1, 0xff, 0xfb, 0xc4, 0x5d, 0xff, 0xfd, 0xa8, 0x00, 0xff, 0xfd, 0xad, 0x0d, 0xff, 0xfd, 0xae, 0x0e, 0xff, 0xfd, 0xad, 0x0d, 0xff, 0xfd, 0xad, 0x0d, 0xff, 0xfd, 0xac, 0x0d, 0xff, 0xfd, 0xac, 0x0d, 0xff, 0xfd, 0xaa, 0x0d, 0xff, 0xfd, 0xa9, 0x0c, 0xff, 0xfd, 0xa9, 0x0c, 0xff, 0xfd, 0xaa, 0x0e, 0xff, 0xfd, 0xac, 0x0e, 0xff, 0xfd, 0xad, 0x0f, 0xff, 0xfd, 0xad, 0x0e, 0xff, 0xfd, 0xad, 0x0e, 0xff, 0xfd, 0xad, 0x0f, 0xff, 0xfd, 0xac, 0x0e, 0xff, 0xfd, 0xaa, 0x07, 0xff, 0xfb, 0xb6, 0x27, 0xff, 0xfb, 0xca, 0x60, 0xff, 0xfc, 0xc9, 0x5e, 0xff, 0xfc, 0xc9, 0x5e, 0xff, 0xfc, 0xcb, 0x63, 0xff, 0xfc, 0xca, 0x60, 0xff, 0xfc, 0xb1, 0x1b, 0xff, 0xfd, 0xab, 0x09, 0xff, 0xfd, 0xad, 0x0f, 0xff, 0xfd, 0xae, 0x10, 0xff, 0xfd, 0xaf, 0x10, 0xff, 0xfd, 0xae, 0x10, 0xff, 0xfc, 0xae, 0x0f, 0xff, 0xfc, 0xae, 0x0f, 0xff, 0xfc, 0xae, 0x0e, 0xff, 0xfd, 0xae, 0x0e, 0xff, 0xfd, 0xad, 0x0e, 0xff, 0xfd, 0xac, 0x0a, 0xff, 0xfc, 0xb5, 0x1d, 0xff, 0xfc, 0xce, 0x65, 0xff, 0xfc, 0xcd, 0x66, 0xff, 0xfc, 0xcc, 0x66, 0xff, 0xfc, 0xcd, 0x6a, 0xff, 0xfc, 0xc5, 0x4e, 0xff, 0xfd, 0xb0, 0x0e, 0xff, 0xfd, 0xb0, 0x0f, 0xff, 0xfd, 0xb0, 0x11, 0xff, 0xfd, 0xb0, 0x0f, 0xff, 0xfd, 0xaf, 0x0f, 0xff, 0xfc, 0xae, 0x0f, 0xff, 0xfc, 0xae, 0x0f, 0xff, 0xfc, 0xae, 0x0f, 0xff, 0xfd, 0xae, 0x0f, 0xff, 0xfd, 0xac, 0x09, 0xff, 0xfc, 0xb3, 0x1a, 0xff, 0xfd, 0xf4, 0xe3, 0xff, 0xfc, 0xfa, 0xf7, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xda, 0xd5, 0xff, 0x61, 0x24, 0x1c, 0xff, 0x48, 0x00, 0x00, 0xff, 0x52, 0x0c, 0x02, 0xff, 0x54, 0x0e, 0x04, 0xff, 0x57, 0x0f, 0x05, 0xff, 0x58, 0x10, 0x05, 0xff, 0x59, 0x11, 0x07, 0xff, 0x59, 0x12, 0x07, 0xff, 0x59, 0x12, 0x07, 0xff, 0x5a, 0x12, 0x07, 0xff, 0x59, 0x13, 0x06, 0xff, 0x5a, 0x12, 0x06, 0xff, 0x5a, 0x11, 0x07, 0xff, 0x5a, 0x10, 0x05, 0xff, 0x56, 0x0e, 0x02, 0xff, 0x52, 0x0a, 0x00, 0xff, 0x76, 0x16, 0x1b, 0xff, 0xb6, 0x2c, 0x4e, 0xff, 0xd5, 0x35, 0x6a, 0xff, 0xcc, 0x33, 0x68, 0xff, 0xb9, 0x2b, 0x56, 0xff, 0xa8, 0x25, 0x44, 0xff, 0x9e, 0x23, 0x3b, 0xff, 0xa1, 0x24, 0x3c, 0xff, 0xb2, 0x2a, 0x47, 0xff, 0xc8, 0x36, 0x56, 0xff, 0xd4, 0x3b, 0x5a, 0xff, 0xc0, 0x32, 0x49, 0xff, 0x80, 0x18, 0x1d, 0xff, 0x4d, 0x07, 0x00, 0xff, 0x49, 0x05, 0x00, 0xff, 0x4f, 0x07, 0x00, 0xff, 0x44, 0x00, 0x00, 0xff, 0x73, 0x3b, 0x36, 0xff, 0xf5, 0xf2, 0xef, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf4, 0xed, 0xff, 0xfb, 0xf2, 0xea, 0xff, 0xfb, 0xf0, 0xe8, 0xff, 0xfc, 0xf1, 0xef, 0xff, 0xfc, 0xc2, 0x5d, 0xff, 0xfd, 0xa7, 0x03, 0xff, 0xfd, 0xac, 0x0f, 0xff, 0xfd, 0xad, 0x0f, 0xff, 0xfd, 0xac, 0x0e, 0xff, 0xfd, 0xac, 0x0f, 0xff, 0xfd, 0xaa, 0x0e, 0xff, 0xfd, 0xaa, 0x0e, 0xff, 0xfd, 0xa9, 0x0e, 0xff, 0xfd, 0xa8, 0x0f, 0xff, 0xfd, 0xa7, 0x0e, 0xff, 0xfd, 0xa8, 0x0f, 0xff, 0xfd, 0xa9, 0x10, 0xff, 0xfd, 0xab, 0x10, 0xff, 0xfe, 0xad, 0x12, 0xff, 0xfd, 0xad, 0x13, 0xff, 0xfd, 0xab, 0x11, 0xff, 0xfd, 0xa9, 0x0f, 0xff, 0xfd, 0xaa, 0x0d, 0xff, 0xfb, 0xea, 0xc2, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xfe, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xdc, 0x9a, 0xff, 0xfd, 0xa7, 0x01, 0xff, 0xfd, 0xab, 0x0d, 0xff, 0xfd, 0xad, 0x11, 0xff, 0xfc, 0xad, 0x12, 0xff, 0xfd, 0xad, 0x11, 0xff, 0xfd, 0xad, 0x11, 0xff, 0xfd, 0xae, 0x10, 0xff, 0xfc, 0xae, 0x10, 0xff, 0xfd, 0xae, 0x10, 0xff, 0xfd, 0xad, 0x10, 0xff, 0xfd, 0xa8, 0x02, 0xff, 0xfc, 0xce, 0x6d, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xf9, 0xec, 0xff, 0xfc, 0xb5, 0x22, 0xff, 0xfd, 0xad, 0x0b, 0xff, 0xfd, 0xaf, 0x10, 0xff, 0xfc, 0xae, 0x10, 0xff, 0xfd, 0xae, 0x10, 0xff, 0xfd, 0xad, 0x11, 0xff, 0xfd, 0xad, 0x11, 0xff, 0xfd, 0xad, 0x10, 0xff, 0xfd, 0xad, 0x0f, 0xff, 0xfd, 0xaa, 0x09, 0xff, 0xfc, 0xb0, 0x1b, 0xff, 0xfd, 0xf4, 0xe2, 0xff, 0xfb, 0xfa, 0xf7, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xf2, 0xed, 0xe8, 0xff, 0x6b, 0x31, 0x2a, 0xff, 0x48, 0x00, 0x00, 0xff, 0x52, 0x0c, 0x02, 0xff, 0x54, 0x0e, 0x04, 0xff, 0x55, 0x10, 0x06, 0xff, 0x58, 0x11, 0x07, 0xff, 0x59, 0x12, 0x07, 0xff, 0x5a, 0x13, 0x08, 0xff, 0x5a, 0x13, 0x08, 0xff, 0x5a, 0x13, 0x08, 0xff, 0x5b, 0x13, 0x08, 0xff, 0x5b, 0x12, 0x07, 0xff, 0x5b, 0x11, 0x05, 0xff, 0x5a, 0x10, 0x04, 0xff, 0x54, 0x0c, 0x00, 0xff, 0x6b, 0x11, 0x0e, 0xff, 0xc0, 0x2e, 0x52, 0xff, 0xd2, 0x36, 0x64, 0xff, 0x98, 0x21, 0x38, 0xff, 0x62, 0x0d, 0x10, 0xff, 0x4d, 0x05, 0x00, 0xff, 0x49, 0x03, 0x00, 0xff, 0x49, 0x01, 0x00, 0xff, 0x49, 0x01, 0x00, 0xff, 0x47, 0x00, 0x00, 0xff, 0x48, 0x01, 0x00, 0xff, 0x4f, 0x03, 0x00, 0xff, 0x62, 0x0c, 0x09, 0xff, 0x8c, 0x1e, 0x26, 0xff, 0xc9, 0x34, 0x4a, 0xff, 0xcb, 0x32, 0x4a, 0xff, 0x78, 0x14, 0x17, 0xff, 0x49, 0x05, 0x00, 0xff, 0x50, 0x07, 0x00, 0xff, 0x47, 0x00, 0x00, 0xff, 0x83, 0x4f, 0x4a, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xfa, 0xf4, 0xed, 0xff, 0xfb, 0xf2, 0xea, 0xff, 0xfb, 0xef, 0xe7, 0xff, 0xfd, 0xef, 0xec, 0xff, 0xfc, 0xc1, 0x5d, 0xff, 0xfd, 0xa6, 0x06, 0xff, 0xfd, 0xaa, 0x11, 0xff, 0xfd, 0xab, 0x12, 0xff, 0xfd, 0xab, 0x11, 0xff, 0xfc, 0xaa, 0x11, 0xff, 0xfd, 0xa8, 0x10, 0xff, 0xfd, 0xa8, 0x10, 0xff, 0xfd, 0xa7, 0x10, 0xff, 0xfc, 0xa5, 0x0f, 0xff, 0xfc, 0xa5, 0x0f, 0xff, 0xfd, 0xa5, 0x10, 0xff, 0xfd, 0xa7, 0x11, 0xff, 0xfd, 0xa8, 0x12, 0xff, 0xfd, 0xab, 0x13, 0xff, 0xfd, 0xab, 0x15, 0xff, 0xfd, 0xa9, 0x14, 0xff, 0xfd, 0xa5, 0x0a, 0xff, 0xfb, 0xbd, 0x46, 0xff, 0xfb, 0xfd, 0xfa, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfc, 0xfc, 0xfb, 0xff, 0xfd, 0xf6, 0xe7, 0xff, 0xfc, 0xb1, 0x23, 0xff, 0xfd, 0xa8, 0x09, 0xff, 0xfd, 0xaa, 0x11, 0xff, 0xfd, 0xaa, 0x13, 0xff, 0xfd, 0xab, 0x13, 0xff, 0xfc, 0xac, 0x13, 0xff, 0xfd, 0xac, 0x14, 0xff, 0xfd, 0xad, 0x14, 0xff, 0xfd, 0xad, 0x14, 0xff, 0xfd, 0xab, 0x12, 0xff, 0xfd, 0xa6, 0x03, 0xff, 0xfc, 0xd0, 0x75, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfd, 0xfe, 0xfc, 0xff, 0xfd, 0xf9, 0xea, 0xff, 0xfc, 0xb5, 0x26, 0xff, 0xfd, 0xac, 0x0c, 0xff, 0xfc, 0xad, 0x11, 0xff, 0xfd, 0xac, 0x12, 0xff, 0xfd, 0xac, 0x12, 0xff, 0xfe, 0xab, 0x12, 0xff, 0xfd, 0xac, 0x11, 0xff, 0xfd, 0xad, 0x12, 0xff, 0xfd, 0xad, 0x11, 0xff, 0xfd, 0xaa, 0x0a, 0xff, 0xfc, 0xb1, 0x1b, 0xff, 0xfd, 0xf4, 0xe2, 0xff, 0xfb, 0xfa, 0xf7, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x5d, 0x56, 0xff, 0x47, 0x00, 0x00, 0xff, 0x53, 0x0d, 0x03, 0xff, 0x54, 0x0e, 0x04, 0xff, 0x56, 0x10, 0x06, 0xff, 0x57, 0x12, 0x07, 0xff, 0x59, 0x13, 0x08, 0xff, 0x5a, 0x13, 0x09, 0xff, 0x5b, 0x14, 0x09, 0xff, 0x5a, 0x15, 0x08, 0xff, 0x5a, 0x14, 0x09, 0xff, 0x5b, 0x14, 0x08, 0xff, 0x5c, 0x13, 0x06, 0xff, 0x5c, 0x10, 0x04, 0xff, 0x51, 0x0b, 0x00, 0xff, 0x81, 0x18, 0x1f, 0xff, 0xde, 0x38, 0x64, 0xff, 0x9d, 0x23, 0x3c, 0xff, 0x52, 0x06, 0x02, 0xff, 0x48, 0x03, 0x00, 0xff, 0x49, 0x01, 0x00, 0xff, 0x48, 0x00, 0x00, 0xff, 0x4f, 0x02, 0x00, 0xff, 0x5d, 0x11, 0x00, 0xff, 0x66, 0x1d, 0x01, 0xff, 0x69, 0x20, 0x01, 0xff, 0x64, 0x18, 0x01, 0xff, 0x5a, 0x09, 0x00, 0xff, 0x4e, 0x00, 0x00, 0xff, 0x46, 0x00, 0x00, 0xff, 0x4d, 0x04, 0x00, 0xff, 0x82, 0x18, 0x1d, 0xff, 0xd6, 0x35, 0x4c, 0xff, 0xae, 0x24, 0x31, 0xff, 0x55, 0x06, 0x00, 0xff, 0x51, 0x05, 0x00, 0xff, 0x4b, 0x00, 0x00, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xfa, 0xf4, 0xef, 0xff, 0xfb, 0xf3, 0xec, 0xff, 0xfb, 0xf1, 0xe9, 0xff, 0xfc, 0xee, 0xe6, 0xff, 0xfd, 0xee, 0xeb, 0xff, 0xfb, 0xbf, 0x5f, 0xff, 0xfd, 0xa4, 0x08, 0xff, 0xfd, 0xa7, 0x12, 0xff, 0xfd, 0xa8, 0x13, 0xff, 0xfd, 0xa8, 0x13, 0xff, 0xfd, 0xa7, 0x12, 0xff, 0xfc, 0xa6, 0x12, 0xff, 0xfd, 0xa5, 0x12, 0xff, 0xfd, 0xa4, 0x12, 0xff, 0xfd, 0xa4, 0x12, 0xff, 0xfc, 0xa4, 0x12, 0xff, 0xfc, 0xa4, 0x12, 0xff, 0xfd, 0xa5, 0x13, 0xff, 0xfd, 0xa6, 0x13, 0xff, 0xfd, 0xa8, 0x15, 0xff, 0xfd, 0xa8, 0x15, 0xff, 0xfd, 0xa7, 0x15, 0xff, 0xfc, 0xa2, 0x08, 0xff, 0xfb, 0xdd, 0xa2, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xfa, 0xf5, 0xff, 0xf9, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xcb, 0x76, 0xff, 0xfd, 0xa3, 0x04, 0xff, 0xfd, 0xa7, 0x11, 0xff, 0xfd, 0xa7, 0x13, 0xff, 0xfd, 0xa8, 0x15, 0xff, 0xfd, 0xa9, 0x16, 0xff, 0xfd, 0xaa, 0x16, 0xff, 0xfd, 0xab, 0x15, 0xff, 0xfd, 0xab, 0x15, 0xff, 0xfd, 0xaa, 0x14, 0xff, 0xfd, 0xa4, 0x04, 0xff, 0xfc, 0xce, 0x74, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfd, 0xfb, 0xff, 0xfd, 0xf9, 0xe9, 0xff, 0xfc, 0xb4, 0x25, 0xff, 0xfd, 0xab, 0x0b, 0xff, 0xfd, 0xad, 0x13, 0xff, 0xfd, 0xac, 0x15, 0xff, 0xfd, 0xab, 0x14, 0xff, 0xfe, 0xab, 0x13, 0xff, 0xfd, 0xac, 0x14, 0xff, 0xfd, 0xad, 0x14, 0xff, 0xfd, 0xac, 0x14, 0xff, 0xfd, 0xaa, 0x0e, 0xff, 0xfc, 0xb0, 0x1d, 0xff, 0xfd, 0xf3, 0xe1, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfd, 0xf9, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, 0xaf, 0xaa, 0xff, 0x4a, 0x03, 0x00, 0xff, 0x50, 0x0b, 0x01, 0xff, 0x54, 0x0e, 0x05, 0xff, 0x55, 0x10, 0x06, 0xff, 0x57, 0x11, 0x07, 0xff, 0x58, 0x12, 0x08, 0xff, 0x5a, 0x13, 0x08, 0xff, 0x5b, 0x14, 0x09, 0xff, 0x5c, 0x15, 0x09, 0xff, 0x5c, 0x16, 0x09, 0xff, 0x5c, 0x15, 0x09, 0xff, 0x5c, 0x13, 0x07, 0xff, 0x5b, 0x12, 0x05, 0xff, 0x54, 0x0e, 0x00, 0xff, 0x88, 0x1c, 0x26, 0xff, 0xdf, 0x3b, 0x6a, 0xff, 0x74, 0x14, 0x1c, 0xff, 0x46, 0x04, 0x00, 0xff, 0x4c, 0x03, 0x00, 0xff, 0x4c, 0x00, 0x00, 0xff, 0x72, 0x24, 0x01, 0xff, 0xad, 0x64, 0x02, 0xff, 0xcf, 0x91, 0x02, 0xff, 0xd5, 0x9e, 0x03, 0xff, 0xd2, 0x9c, 0x02, 0xff, 0xd1, 0x9a, 0x02, 0xff, 0xd5, 0x9b, 0x03, 0xff, 0xd6, 0x97, 0x03, 0xff, 0xc2, 0x7e, 0x03, 0xff, 0x8f, 0x45, 0x02, 0xff, 0x5a, 0x0b, 0x01, 0xff, 0x45, 0x00, 0x00, 0xff, 0x54, 0x05, 0x03, 0xff, 0xbe, 0x2c, 0x3f, 0xff, 0xc3, 0x2c, 0x3f, 0xff, 0x55, 0x05, 0x00, 0xff, 0x4f, 0x04, 0x00, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf6, 0xf0, 0xff, 0xfa, 0xf4, 0xed, 0xff, 0xfb, 0xf3, 0xec, 0xff, 0xfb, 0xf0, 0xe8, 0xff, 0xfb, 0xed, 0xe5, 0xff, 0xfd, 0xed, 0xea, 0xff, 0xfc, 0xbe, 0x5f, 0xff, 0xfd, 0xa2, 0x09, 0xff, 0xfc, 0xa5, 0x13, 0xff, 0xfd, 0xa6, 0x15, 0xff, 0xfd, 0xa6, 0x16, 0xff, 0xfd, 0xa6, 0x16, 0xff, 0xfd, 0xa5, 0x17, 0xff, 0xfd, 0xa4, 0x17, 0xff, 0xfd, 0xa4, 0x16, 0xff, 0xfd, 0xa3, 0x15, 0xff, 0xfd, 0xa3, 0x15, 0xff, 0xfd, 0xa3, 0x16, 0xff, 0xfd, 0xa4, 0x16, 0xff, 0xfd, 0xa5, 0x17, 0xff, 0xfd, 0xa6, 0x18, 0xff, 0xfd, 0xa6, 0x18, 0xff, 0xfd, 0xa3, 0x11, 0xff, 0xfc, 0xae, 0x2a, 0xff, 0xfb, 0xf7, 0xea, 0xff, 0xfc, 0xfc, 0xfa, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xfb, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfc, 0xfe, 0xfd, 0xff, 0xfd, 0xeb, 0xcc, 0xff, 0xfc, 0xa4, 0x13, 0xff, 0xfd, 0xa5, 0x10, 0xff, 0xfd, 0xa5, 0x14, 0xff, 0xfd, 0xa5, 0x16, 0xff, 0xfd, 0xa6, 0x18, 0xff, 0xfd, 0xa7, 0x17, 0xff, 0xfd, 0xa8, 0x17, 0xff, 0xfd, 0xa8, 0x19, 0xff, 0xfd, 0xa8, 0x17, 0xff, 0xfd, 0xa2, 0x06, 0xff, 0xfc, 0xcd, 0x74, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfd, 0xf9, 0xeb, 0xff, 0xfc, 0xb4, 0x27, 0xff, 0xfd, 0xa9, 0x0c, 0xff, 0xfd, 0xab, 0x15, 0xff, 0xfc, 0xab, 0x16, 0xff, 0xfd, 0xaa, 0x16, 0xff, 0xfd, 0xaa, 0x15, 0xff, 0xfc, 0xab, 0x16, 0xff, 0xfd, 0xab, 0x17, 0xff, 0xfd, 0xab, 0x17, 0xff, 0xfd, 0xa8, 0x10, 0xff, 0xfc, 0xaf, 0x1e, 0xff, 0xfd, 0xf3, 0xe2, 0xff, 0xfc, 0xfa, 0xf7, 0xff, 0xfa, 0xf8, 0xf1, 0xff, 0xf8, 0xf8, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfa, 0xf7, 0xf3, 0xff, 0x6d, 0x35, 0x2d, 0xff, 0x4d, 0x04, 0x00, 0xff, 0x53, 0x0e, 0x04, 0xff, 0x54, 0x10, 0x06, 0xff, 0x57, 0x11, 0x07, 0xff, 0x57, 0x12, 0x08, 0xff, 0x58, 0x12, 0x09, 0xff, 0x5a, 0x13, 0x09, 0xff, 0x5d, 0x15, 0x09, 0xff, 0x5d, 0x15, 0x09, 0xff, 0x5c, 0x15, 0x09, 0xff, 0x5c, 0x14, 0x08, 0xff, 0x5d, 0x13, 0x06, 0xff, 0x58, 0x0f, 0x02, 0xff, 0x73, 0x14, 0x12, 0xff, 0xe1, 0x3c, 0x66, 0xff, 0x72, 0x14, 0x19, 0xff, 0x48, 0x04, 0x00, 0xff, 0x4a, 0x00, 0x00, 0xff, 0x70, 0x20, 0x01, 0xff, 0xc6, 0x7a, 0x02, 0xff, 0xd7, 0x99, 0x03, 0xff, 0xa4, 0x6a, 0x02, 0xff, 0x77, 0x33, 0x01, 0xff, 0x60, 0x17, 0x01, 0xff, 0x58, 0x0d, 0x01, 0xff, 0x55, 0x0b, 0x01, 0xff, 0x59, 0x10, 0x01, 0xff, 0x6a, 0x23, 0x01, 0xff, 0x92, 0x4f, 0x03, 0xff, 0xc8, 0x8b, 0x03, 0xff, 0xda, 0x9b, 0x03, 0xff, 0x96, 0x4d, 0x02, 0xff, 0x4c, 0x00, 0x00, 0xff, 0x45, 0x00, 0x00, 0xff, 0xb7, 0x28, 0x3d, 0xff, 0xba, 0x26, 0x3c, 0xff, 0x4a, 0x02, 0x00, 0xff,
0xfd, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfb, 0xf7, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xfa, 0xf4, 0xed, 0xff, 0xfb, 0xf3, 0xec, 0xff, 0xfc, 0xf1, 0xe9, 0xff, 0xfc, 0xed, 0xe6, 0xff, 0xfd, 0xed, 0xe9, 0xff, 0xfc, 0xbd, 0x60, 0xff, 0xfd, 0xa1, 0x0c, 0xff, 0xfd, 0xa4, 0x16, 0xff, 0xfd, 0xa5, 0x19, 0xff, 0xfd, 0xa4, 0x1a, 0xff, 0xfd, 0xa4, 0x1a, 0xff, 0xfd, 0xa4, 0x19, 0xff, 0xfc, 0xa3, 0x18, 0xff, 0xfd, 0xa3, 0x17, 0xff, 0xfd, 0xa3, 0x18, 0xff, 0xfd, 0xa3, 0x18, 0xff, 0xfd, 0xa3, 0x19, 0xff, 0xfd, 0xa2, 0x19, 0xff, 0xfc, 0xa3, 0x19, 0xff, 0xfd, 0xa4, 0x1a, 0xff, 0xfd, 0xa4, 0x19, 0xff, 0xfd, 0x9d, 0x08, 0xff, 0xfb, 0xcc, 0x7b, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfe, 0xfc, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xba, 0x51, 0xff, 0xfd, 0xa0, 0x0a, 0xff, 0xfd, 0xa4, 0x15, 0xff, 0xfd, 0xa3, 0x16, 0xff, 0xfd, 0xa3, 0x17, 0xff, 0xfd, 0xa4, 0x18, 0xff, 0xfd, 0xa5, 0x18, 0xff, 0xfd, 0xa5, 0x19, 0xff, 0xfd, 0xa5, 0x18, 0xff, 0xfd, 0x9f, 0x08, 0xff, 0xfc, 0xcb, 0x77, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xf9, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfe, 0xfc, 0xff, 0xfd, 0xf9, 0xeb, 0xff, 0xfc, 0xb2, 0x28, 0xff, 0xfd, 0xa7, 0x0f, 0xff, 0xfd, 0xa9, 0x18, 0xff, 0xfd, 0xa8, 0x1a, 0xff, 0xfd, 0xa8, 0x19, 0xff, 0xfd, 0xa8, 0x19, 0xff, 0xfd, 0xa8, 0x1b, 0xff, 0xfc, 0xa8, 0x1b, 0xff, 0xfd, 0xa9, 0x1b, 0xff, 0xfd, 0xa7, 0x13, 0xff, 0xfc, 0xaf, 0x20, 0xff, 0xfc, 0xf3, 0xe2, 0xff, 0xfc, 0xfa, 0xf7, 0xff, 0xfa, 0xf8, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc5, 0xae, 0xa8, 0xff, 0x49, 0x02, 0x00, 0xff, 0x53, 0x0d, 0x02, 0xff, 0x54, 0x0f, 0x05, 0xff, 0x56, 0x11, 0x06, 0xff, 0x57, 0x12, 0x08, 0xff, 0x58, 0x12, 0x09, 0xff, 0x5a, 0x12, 0x09, 0xff, 0x5b, 0x13, 0x0a, 0xff, 0x5c, 0x14, 0x0a, 0xff, 0x5b, 0x15, 0x09, 0xff, 0x5a, 0x14, 0x09, 0xff, 0x5b, 0x13, 0x08, 0xff, 0x5c, 0x11, 0x05, 0xff, 0x5a, 0x0e, 0x03, 0xff, 0xcc, 0x32, 0x4b, 0xff, 0x91, 0x1f, 0x28, 0xff, 0x47, 0x03, 0x00, 0xff, 0x4b, 0x00, 0x00, 0xff, 0x97, 0x46, 0x02, 0xff, 0xe5, 0x97, 0x03, 0xff, 0x9a, 0x55, 0x02, 0xff, 0x53, 0x0f, 0x01, 0xff, 0x49, 0x00, 0x01, 0xff, 0x50, 0x05, 0x01, 0xff, 0x54, 0x08, 0x01, 0xff, 0x56, 0x0a, 0x02, 0xff, 0x56, 0x0a, 0x02, 0xff, 0x53, 0x08, 0x01, 0xff, 0x51, 0x05, 0x00, 0xff, 0x4d, 0x01, 0x00, 0xff, 0x4e, 0x02, 0x01, 0xff, 0x77, 0x2c, 0x02, 0xff, 0xd0, 0x8b, 0x02, 0xff, 0xc6, 0x7e, 0x03, 0xff, 0x56, 0x0c, 0x00, 0xff, 0x46, 0x00, 0x00, 0xff, 0xc8, 0x2a, 0x46, 0xff, 0x9a, 0x1a, 0x2c, 0xff,
0xfd, 0xfa, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfb, 0xf6, 0xf0, 0xff, 0xfc, 0xf5, 0xee, 0xff, 0xfc, 0xf3, 0xec, 0xff, 0xfc, 0xf1, 0xe9, 0xff, 0xfd, 0xed, 0xe6, 0xff, 0xfd, 0xec, 0xe9, 0xff, 0xfc, 0xbc, 0x61, 0xff, 0xfd, 0x9e, 0x0f, 0xff, 0xfd, 0xa2, 0x1b, 0xff, 0xfd, 0xa3, 0x1d, 0xff, 0xfd, 0xa3, 0x1e, 0xff, 0xfd, 0xa2, 0x1f, 0xff, 0xfd, 0xa2, 0x1d, 0xff, 0xfd, 0xa1, 0x1a, 0xff, 0xfd, 0xa1, 0x19, 0xff, 0xfd, 0xa1, 0x1a, 0xff, 0xfd, 0xa1, 0x1b, 0xff, 0xfc, 0xa1, 0x1b, 0xff, 0xfd, 0xa1, 0x1c, 0xff, 0xfd, 0xa1, 0x1b, 0xff, 0xfd, 0xa1, 0x1c, 0xff, 0xfd, 0x9f, 0x17, 0xff, 0xfc, 0xa1, 0x17, 0xff, 0xfc, 0xed, 0xd1, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfd, 0xfc, 0xf8, 0xff, 0xfc, 0xf8, 0xf0, 0xff, 0xfa, 0xe8, 0xc9, 0xff, 0xfc, 0xfd, 0xfb, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xdd, 0xa8, 0xff, 0xfc, 0x9e, 0x0a, 0xff, 0xfd, 0xa2, 0x15, 0xff, 0xfd, 0xa2, 0x15, 0xff, 0xfd, 0xa2, 0x17, 0xff, 0xfd, 0xa3, 0x18, 0xff, 0xfd, 0xa4, 0x19, 0xff, 0xfd, 0xa4, 0x19, 0xff, 0xfd, 0xa4, 0x18, 0xff, 0xfd, 0x9d, 0x09, 0xff, 0xfc, 0xca, 0x79, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfc, 0xfe, 0xfe, 0xff, 0xfd, 0xf9, 0xeb, 0xff, 0xfc, 0xb0, 0x2b, 0xff, 0xfd, 0xa5, 0x11, 0xff, 0xfd, 0xa6, 0x1a, 0xff, 0xfd, 0xa5, 0x1b, 0xff, 0xfd, 0xa5, 0x1a, 0xff, 0xfd, 0xa6, 0x1a, 0xff, 0xfd, 0xa6, 0x1b, 0xff, 0xfd, 0xa7, 0x1b, 0xff, 0xfd, 0xa8, 0x1b, 0xff, 0xfd, 0xa5, 0x14, 0xff, 0xfc, 0xae, 0x23, 0xff, 0xfc, 0xf3, 0xe2, 0xff, 0xfc, 0xf9, 0xf6, 0xff, 0xfb, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfd, 0xf9, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x55, 0x4f, 0xff, 0x4a, 0x01, 0x00, 0xff, 0x54, 0x0e, 0x04, 0xff, 0x55, 0x10, 0x05, 0xff, 0x57, 0x11, 0x07, 0xff, 0x57, 0x12, 0x08, 0xff, 0x58, 0x12, 0x08, 0xff, 0x59, 0x13, 0x09, 0xff, 0x5a, 0x14, 0x0a, 0xff, 0x5a, 0x14, 0x0a, 0xff, 0x5a, 0x14, 0x09, 0xff, 0x5a, 0x13, 0x0a, 0xff, 0x5c, 0x13, 0x08, 0xff, 0x57, 0x0f, 0x03, 0xff, 0x7a, 0x1b, 0x15, 0xff, 0xd3, 0x3e, 0x45, 0xff, 0x49, 0x03, 0x00, 0xff, 0x48, 0x00, 0x00, 0xff, 0xa6, 0x55, 0x03, 0xff, 0xdc, 0x8c, 0x03, 0xff, 0x6c, 0x22, 0x02, 0xff, 0x4b, 0x03, 0x01, 0xff, 0x54, 0x0b, 0x01, 0xff, 0x58, 0x0d, 0x01, 0xff, 0x58, 0x0d, 0x01, 0xff, 0x59, 0x0d, 0x01, 0xff, 0x59, 0x0d, 0x02, 0xff, 0x58, 0x0c, 0x02, 0xff, 0x56, 0x0b, 0x01, 0xff, 0x56, 0x0b, 0x01, 0xff, 0x59, 0x0b, 0x01, 0xff, 0x5a, 0x0b, 0x00, 0xff, 0x53, 0x05, 0x00, 0xff, 0x53, 0x05, 0x01, 0xff, 0xa8, 0x5d, 0x02, 0xff, 0xd6, 0x88, 0x03, 0xff, 0x54, 0x0c, 0x00, 0xff, 0x56, 0x03, 0x06, 0xff, 0xde, 0x32, 0x55, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfa, 0xf6, 0xf1, 0xff, 0xfb, 0xf5, 0xee, 0xff, 0xfb, 0xf3, 0xec, 0xff, 0xfc, 0xf0, 0xe9, 0xff, 0xfd, 0xed, 0xe6, 0xff, 0xfd, 0xed, 0xe9, 0xff, 0xfc, 0xba, 0x62, 0xff, 0xfd, 0x9b, 0x10, 0xff, 0xfd, 0xa0, 0x1d, 0xff, 0xfd, 0xa1, 0x20, 0xff, 0xfd, 0xa1, 0x20, 0xff, 0xfd, 0xa0, 0x20, 0xff, 0xfd, 0x9f, 0x1f, 0xff, 0xfd, 0x9f, 0x1e, 0xff, 0xfd, 0x9f, 0x1d, 0xff, 0xfd, 0xa0, 0x1e, 0xff, 0xfd, 0xa0, 0x1e, 0xff, 0xfd, 0xa1, 0x1f, 0xff, 0xfd, 0xa1, 0x1e, 0xff, 0xfd, 0xa1, 0x1d, 0xff, 0xfd, 0x9f, 0x1d, 0xff, 0xfd, 0x9a, 0x12, 0xff, 0xfc, 0xba, 0x57, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe4, 0xc2, 0xff, 0xf9, 0xa6, 0x3a, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfb, 0xfd, 0xfa, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfb, 0xfd, 0xfb, 0xff, 0xfc, 0xf8, 0xed, 0xff, 0xfc, 0xa9, 0x32, 0xff, 0xfd, 0x9e, 0x0e, 0xff, 0xfd, 0xa0, 0x14, 0xff, 0xfd, 0x9f, 0x17, 0xff, 0xfd, 0xa1, 0x18, 0xff, 0xfc, 0xa1, 0x19, 0xff, 0xfc, 0xa2, 0x18, 0xff, 0xfd, 0xa1, 0x18, 0xff, 0xfd, 0x9a, 0x0b, 0xff, 0xfc, 0xc8, 0x7b, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfe, 0xfd, 0xff, 0xfd, 0xf8, 0xec, 0xff, 0xfc, 0xaf, 0x2f, 0xff, 0xfd, 0xa3, 0x13, 0xff, 0xfd, 0xa3, 0x1b, 0xff, 0xfd, 0xa3, 0x1b, 0xff, 0xfd, 0xa3, 0x19, 0xff, 0xfd, 0xa4, 0x1a, 0xff, 0xfd, 0xa4, 0x1d, 0xff, 0xfd, 0xa5, 0x1c, 0xff, 0xfd, 0xa6, 0x1a, 0xff, 0xfd, 0xa3, 0x15, 0xff, 0xfc, 0xaa, 0x23, 0xff, 0xfc, 0xf2, 0xe0, 0xff, 0xfc, 0xf9, 0xf6, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xff, 0xfd, 0xf9, 0xff, 0xec, 0xe5, 0xe1, 0xff, 0x5a, 0x1a, 0x12, 0xff, 0x50, 0x09, 0x00, 0xff, 0x54, 0x0f, 0x04, 0xff, 0x56, 0x10, 0x06, 0xff, 0x57, 0x11, 0x07, 0xff, 0x57, 0x11, 0x08, 0xff, 0x57, 0x12, 0x08, 0xff, 0x58, 0x13, 0x09, 0xff, 0x59, 0x14, 0x09, 0xff, 0x59, 0x14, 0x09, 0xff, 0x5a, 0x13, 0x0a, 0xff, 0x5a, 0x13, 0x09, 0xff, 0x5b, 0x13, 0x08, 0xff, 0x58, 0x10, 0x05, 0xff, 0x6a, 0x17, 0x0d, 0xff, 0xdd, 0x4d, 0x2f, 0xff, 0x71, 0x17, 0x0a, 0xff, 0x91, 0x41, 0x02, 0xff, 0xdf, 0x88, 0x05, 0xff, 0x62, 0x16, 0x03, 0xff, 0x50, 0x08, 0x02, 0xff, 0x57, 0x0e, 0x03, 0xff, 0x57, 0x0f, 0x03, 0xff, 0x58, 0x0e, 0x02, 0xff, 0x58, 0x0e, 0x02, 0xff, 0x58, 0x0e, 0x02, 0xff, 0x57, 0x0d, 0x01, 0xff, 0x53, 0x0a, 0x00, 0xff, 0x4f, 0x07, 0x00, 0xff, 0x4d, 0x06, 0x00, 0xff, 0x51, 0x07, 0x00, 0xff, 0x56, 0x09, 0x00, 0xff, 0x5a, 0x0b, 0x00, 0xff, 0x58, 0x0a, 0x00, 0xff, 0x4e, 0x00, 0x01, 0xff, 0xa7, 0x55, 0x02, 0xff, 0xcc, 0x7b, 0x03, 0xff, 0x47, 0x02, 0x00, 0xff, 0x73, 0x11, 0x16, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xfa, 0xf4, 0xef, 0xff, 0xfa, 0xf2, 0xed, 0xff, 0xfc, 0xef, 0xe9, 0xff, 0xfd, 0xed, 0xe5, 0xff, 0xfd, 0xee, 0xe9, 0xff, 0xfc, 0xba, 0x64, 0xff, 0xfd, 0x9a, 0x11, 0xff, 0xfd, 0x9e, 0x1e, 0xff, 0xfd, 0x9e, 0x21, 0xff, 0xfd, 0x9e, 0x22, 0xff, 0xfd, 0x9d, 0x21, 0xff, 0xfd, 0x9c, 0x21, 0xff, 0xfd, 0x9c, 0x20, 0xff, 0xfd, 0x9e, 0x1f, 0xff, 0xfd, 0x9e, 0x1f, 0xff, 0xfd, 0x9e, 0x20, 0xff, 0xfd, 0x9f, 0x21, 0xff, 0xfd, 0x9f, 0x20, 0xff, 0xfd, 0x9f, 0x20, 0xff, 0xfd, 0x9d, 0x20, 0xff, 0xfc, 0x99, 0x15, 0xff, 0xfb, 0xdd, 0xaf, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xf9, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xc5, 0x80, 0xff, 0xfc, 0x8b, 0x03, 0xff, 0xfc, 0xe5, 0xc5, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfb, 0xfc, 0xf7, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xc9, 0x82, 0xff, 0xfd, 0x97, 0x09, 0xff, 0xfd, 0x9c, 0x16, 0xff, 0xfd, 0x9d, 0x18, 0xff, 0xfd, 0x9f, 0x1b, 0xff, 0xfc, 0x9f, 0x1c, 0xff, 0xfd, 0x9f, 0x1b, 0xff, 0xfd, 0x9e, 0x1a, 0xff, 0xfd, 0x97, 0x0d, 0xff, 0xfc, 0xc7, 0x7b, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfb, 0xfe, 0xfd, 0xff, 0xfd, 0xf8, 0xee, 0xff, 0xfc, 0xac, 0x31, 0xff, 0xfd, 0xa0, 0x14, 0xff, 0xfd, 0xa1, 0x1c, 0xff, 0xfd, 0xa1, 0x1c, 0xff, 0xfd, 0xa1, 0x19, 0xff, 0xfd, 0xa2, 0x1b, 0xff, 0xfd, 0xa2, 0x1d, 0xff, 0xfd, 0xa2, 0x1d, 0xff, 0xfd, 0xa2, 0x1b, 0xff, 0xfd, 0xa0, 0x16, 0xff, 0xfc, 0xa8, 0x25, 0xff, 0xfd, 0xf1, 0xe0, 0xff, 0xfc, 0xf9, 0xf6, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0xb4, 0xb0, 0xff, 0x4b, 0x03, 0x00, 0xff, 0x54, 0x0d, 0x02, 0xff, 0x55, 0x0f, 0x05, 0xff, 0x56, 0x11, 0x06, 0xff, 0x57, 0x11, 0x07, 0xff, 0x57, 0x12, 0x08, 0xff, 0x58, 0x12, 0x08, 0xff, 0x59, 0x14, 0x08, 0xff, 0x59, 0x14, 0x08, 0xff, 0x5a, 0x14, 0x09, 0xff, 0x5b, 0x14, 0x09, 0xff, 0x5a, 0x14, 0x09, 0xff, 0x5b, 0x14, 0x09, 0xff, 0x5b, 0x13, 0x07, 0xff, 0x54, 0x0d, 0x03, 0xff, 0x83, 0x24, 0x0f, 0xff, 0xe1, 0x63, 0x18, 0xff, 0xda, 0x75, 0x07, 0xff, 0x6f, 0x20, 0x04, 0xff, 0x53, 0x0a, 0x03, 0xff, 0x5a, 0x10, 0x04, 0xff, 0x59, 0x10, 0x04, 0xff, 0x5a, 0x10, 0x04, 0xff, 0x5a, 0x0f, 0x03, 0xff, 0x59, 0x0e, 0x02, 0xff, 0x52, 0x0a, 0x00, 0xff, 0x55, 0x0a, 0x00, 0xff, 0x6f, 0x17, 0x07, 0xff, 0x8a, 0x25, 0x0e, 0xff, 0x94, 0x29, 0x10, 0xff, 0x86, 0x21, 0x0e, 0xff, 0x67, 0x10, 0x06, 0xff, 0x50, 0x06, 0x00, 0xff, 0x52, 0x08, 0x00, 0xff, 0x57, 0x09, 0x01, 0xff, 0x51, 0x02, 0x01, 0xff, 0xc7, 0x70, 0x03, 0xff, 0xa3, 0x50, 0x03, 0xff, 0x3b, 0x00, 0x00, 0xff,
0xfd, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf7, 0xf3, 0xff, 0xf9, 0xf5, 0xf1, 0xff, 0xf9, 0xf4, 0xef, 0xff, 0xf9, 0xf2, 0xed, 0xff, 0xfc, 0xef, 0xe9, 0xff, 0xfd, 0xec, 0xe5, 0xff, 0xfd, 0xed, 0xe9, 0xff, 0xfc, 0xba, 0x67, 0xff, 0xfd, 0x99, 0x15, 0xff, 0xfd, 0x9b, 0x20, 0xff, 0xfd, 0x9b, 0x21, 0xff, 0xfd, 0x9b, 0x22, 0xff, 0xfd, 0x9a, 0x22, 0xff, 0xfd, 0x9a, 0x22, 0xff, 0xfd, 0x9a, 0x21, 0xff, 0xfd, 0x9a, 0x21, 0xff, 0xfd, 0x9b, 0x21, 0xff, 0xfd, 0x9c, 0x22, 0xff, 0xfd, 0x9d, 0x22, 0xff, 0xfc, 0x9d, 0x22, 0xff, 0xfd, 0x9d, 0x22, 0xff, 0xfd, 0x99, 0x1b, 0xff, 0xfc, 0xa8, 0x3d, 0xff, 0xfc, 0xf9, 0xf0, 0xff, 0xfc, 0xfd, 0xfb, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfd, 0xfe, 0xfb, 0xff, 0xfd, 0xfa, 0xf3, 0xff, 0xfa, 0xa3, 0x3b, 0xff, 0xfd, 0x8b, 0x04, 0xff, 0xfc, 0xc2, 0x7a, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0xfd, 0xed, 0xd5, 0xff, 0xfc, 0x9c, 0x1d, 0xff, 0xfd, 0x9a, 0x16, 0xff, 0xfd, 0x9c, 0x1a, 0xff, 0xfd, 0x9d, 0x1d, 0xff, 0xfd, 0x9e, 0x1e, 0xff, 0xfd, 0x9d, 0x1e, 0xff, 0xfd, 0x9c, 0x1d, 0xff, 0xfd, 0x96, 0x0f, 0xff, 0xfc, 0xc6, 0x7d, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfe, 0xfd, 0xff, 0xfd, 0xf8, 0xef, 0xff, 0xfc, 0xaa, 0x33, 0xff, 0xfd, 0x9d, 0x18, 0xff, 0xfd, 0xa0, 0x1e, 0xff, 0xfd, 0xa0, 0x1e, 0xff, 0xfc, 0xa0, 0x1e, 0xff, 0xfd, 0xa1, 0x1d, 0xff, 0xfd, 0xa1, 0x1c, 0xff, 0xfd, 0xa1, 0x1c, 0xff, 0xfd, 0xa0, 0x1c, 0xff, 0xfd, 0x9d, 0x18, 0xff, 0xfc, 0xa7, 0x29, 0xff, 0xfc, 0xf1, 0xe0, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf7, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xfa, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0x85, 0x81, 0xff, 0x49, 0x00, 0x00, 0xff, 0x55, 0x0d, 0x03, 0xff, 0x56, 0x0f, 0x05, 0xff, 0x58, 0x11, 0x07, 0xff, 0x56, 0x12, 0x07, 0xff, 0x57, 0x12, 0x07, 0xff, 0x59, 0x13, 0x07, 0xff, 0x59, 0x14, 0x08, 0xff, 0x5a, 0x15, 0x08, 0xff, 0x5c, 0x14, 0x09, 0xff, 0x5d, 0x15, 0x09, 0xff, 0x5d, 0x15, 0x09, 0xff, 0x5d, 0x14, 0x08, 0xff, 0x5d, 0x13, 0x07, 0xff, 0x5d, 0x11, 0x05, 0xff, 0x57, 0x0c, 0x03, 0xff, 0x6b, 0x19, 0x07, 0xff, 0x65, 0x16, 0x06, 0xff, 0x56, 0x0c, 0x04, 0xff, 0x5b, 0x11, 0x05, 0xff, 0x5b, 0x11, 0x05, 0xff, 0x5c, 0x10, 0x04, 0xff, 0x5c, 0x10, 0x04, 0xff, 0x5a, 0x0f, 0x03, 0xff, 0x53, 0x0a, 0x01, 0xff, 0x82, 0x20, 0x0a, 0xff, 0xd8, 0x4a, 0x1b, 0xff, 0xfb, 0x5f, 0x24, 0xff, 0xf4, 0x5f, 0x26, 0xff, 0xed, 0x5c, 0x28, 0xff, 0xf6, 0x5a, 0x2c, 0xff, 0xf6, 0x53, 0x2c, 0xff, 0xc5, 0x39, 0x20, 0xff, 0x71, 0x14, 0x0a, 0xff, 0x50, 0x07, 0x00, 0xff, 0x53, 0x06, 0x00, 0xff, 0x6c, 0x17, 0x01, 0xff, 0xde, 0x81, 0x04, 0xff, 0x57, 0x0f, 0x02, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf8, 0xf3, 0xef, 0xff, 0xfa, 0xf2, 0xec, 0xff, 0xfb, 0xef, 0xe9, 0xff, 0xfd, 0xed, 0xe5, 0xff, 0xfd, 0xed, 0xea, 0xff, 0xfc, 0xb6, 0x69, 0xff, 0xfd, 0x95, 0x18, 0xff, 0xfd, 0x98, 0x22, 0xff, 0xfd, 0x97, 0x23, 0xff, 0xfd, 0x97, 0x24, 0xff, 0xfd, 0x96, 0x25, 0xff, 0xfd, 0x96, 0x24, 0xff, 0xfd, 0x97, 0x24, 0xff, 0xfd, 0x97, 0x24, 0xff, 0xfd, 0x97, 0x23, 0xff, 0xfd, 0x99, 0x24, 0xff, 0xfd, 0x9b, 0x24, 0xff, 0xfd, 0x9b, 0x24, 0xff, 0xfd, 0x9a, 0x23, 0xff, 0xfd, 0x92, 0x16, 0xff, 0xfc, 0xcc, 0x8e, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe0, 0xbe, 0xff, 0xfb, 0x8f, 0x17, 0xff, 0xfd, 0x90, 0x14, 0xff, 0xfc, 0x9e, 0x33, 0xff, 0xfd, 0xf8, 0xf0, 0xff, 0xfc, 0xfe, 0xfe, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfc, 0xfd, 0xf9, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfc, 0xb7, 0x5e, 0xff, 0xfd, 0x95, 0x10, 0xff, 0xfd, 0x9a, 0x1b, 0xff, 0xfd, 0x9b, 0x1d, 0xff, 0xfd, 0x9b, 0x1f, 0xff, 0xfd, 0x9b, 0x20, 0xff, 0xfd, 0x9b, 0x1f, 0xff, 0xfd, 0x95, 0x12, 0xff, 0xfc, 0xc6, 0x7f, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfe, 0xfc, 0xff, 0xfd, 0xf8, 0xed, 0xff, 0xfc, 0xa8, 0x34, 0xff, 0xfd, 0x9c, 0x1b, 0xff, 0xfd, 0x9e, 0x20, 0xff, 0xfd, 0x9e, 0x1f, 0xff, 0xfd, 0x9f, 0x21, 0xff, 0xfd, 0x9f, 0x20, 0xff, 0xfd, 0x9f, 0x20, 0xff, 0xfd, 0x9f, 0x1f, 0xff, 0xfd, 0x9f, 0x1f, 0xff, 0xfd, 0x9c, 0x1a, 0xff, 0xfc, 0xa5, 0x2d, 0xff, 0xfd, 0xf2, 0xe1, 0xff, 0xfd, 0xf9, 0xf5, 0xff, 0xfb, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0x61, 0x5b, 0xff, 0x4b, 0x00, 0x00, 0xff, 0x55, 0x0d, 0x02, 0xff, 0x56, 0x10, 0x05, 0xff, 0x57, 0x12, 0x07, 0xff, 0x58, 0x13, 0x07, 0xff, 0x59, 0x15, 0x07, 0xff, 0x5b, 0x15, 0x06, 0xff, 0x5d, 0x16, 0x07, 0xff, 0x5f, 0x17, 0x07, 0xff, 0x60, 0x17, 0x08, 0xff, 0x61, 0x17, 0x08, 0xff, 0x60, 0x16, 0x08, 0xff, 0x60, 0x16, 0x08, 0xff, 0x60, 0x14, 0x08, 0xff, 0x5f, 0x12, 0x07, 0xff, 0x5d, 0x11, 0x06, 0xff, 0x5a, 0x0f, 0x04, 0xff, 0x59, 0x0f, 0x05, 0xff, 0x5a, 0x11, 0x05, 0xff, 0x5a, 0x11, 0x05, 0xff, 0x5d, 0x12, 0x05, 0xff, 0x5d, 0x11, 0x05, 0xff, 0x5b, 0x0f, 0x03, 0xff, 0x58, 0x0c, 0x02, 0xff, 0xac, 0x37, 0x14, 0xff, 0xff, 0x63, 0x25, 0xff, 0xd5, 0x49, 0x1a, 0xff, 0x86, 0x20, 0x08, 0xff, 0x62, 0x0d, 0x01, 0xff, 0x5c, 0x09, 0x01, 0xff, 0x61, 0x0b, 0x01, 0xff, 0x85, 0x1c, 0x0c, 0xff, 0xd9, 0x3e, 0x29, 0xff, 0xfc, 0x47, 0x3a, 0xff, 0x93, 0x1d, 0x18, 0xff, 0x50, 0x06, 0x00, 0xff, 0x54, 0x05, 0x00, 0xff, 0x78, 0x25, 0x02, 0xff, 0x5d, 0x0d, 0x01, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf8, 0xf3, 0xee, 0xff, 0xfa, 0xf1, 0xec, 0xff, 0xfb, 0xef, 0xe9, 0xff, 0xfd, 0xed, 0xe6, 0xff, 0xfd, 0xed, 0xea, 0xff, 0xfc, 0xb5, 0x6a, 0xff, 0xfd, 0x93, 0x1b, 0xff, 0xfd, 0x96, 0x24, 0xff, 0xfd, 0x95, 0x25, 0xff, 0xfe, 0x95, 0x27, 0xff, 0xfd, 0x95, 0x28, 0xff, 0xfd, 0x94, 0x28, 0xff, 0xfd, 0x94, 0x28, 0xff, 0xfe, 0x94, 0x28, 0xff, 0xfd, 0x95, 0x28, 0xff, 0xfd, 0x96, 0x28, 0xff, 0xfd, 0x97, 0x28, 0xff, 0xfd, 0x97, 0x27, 0xff, 0xfd, 0x95, 0x22, 0xff, 0xfc, 0x9a, 0x2c, 0xff, 0xfd, 0xf1, 0xdd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfc, 0xfd, 0xf9, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xba, 0x74, 0xff, 0xfd, 0x8c, 0x15, 0xff, 0xfd, 0x92, 0x1f, 0xff, 0xfc, 0x8d, 0x14, 0xff, 0xfb, 0xdb, 0xb4, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xdd, 0xb7, 0xff, 0xfc, 0x92, 0x15, 0xff, 0xfd, 0x96, 0x1d, 0xff, 0xfd, 0x97, 0x1f, 0xff, 0xfd, 0x97, 0x21, 0xff, 0xfd, 0x98, 0x22, 0xff, 0xfd, 0x99, 0x22, 0xff, 0xfd, 0x92, 0x16, 0xff, 0xfc, 0xc5, 0x82, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xf9, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfb, 0xfe, 0xfb, 0xff, 0xfd, 0xf7, 0xeb, 0xff, 0xfc, 0xa6, 0x34, 0xff, 0xfd, 0x9a, 0x1a, 0xff, 0xfd, 0x9c, 0x21, 0xff, 0xfd, 0x9c, 0x23, 0xff, 0xfd, 0x9c, 0x23, 0xff, 0xfd, 0x9d, 0x24, 0xff, 0xfd, 0x9c, 0x24, 0xff, 0xfd, 0x9c, 0x22, 0xff, 0xfc, 0x9c, 0x22, 0xff, 0xfd, 0x9a, 0x1c, 0xff, 0xfc, 0xa4, 0x30, 0xff, 0xfd, 0xf2, 0xe2, 0xff, 0xfc, 0xf8, 0xf4, 0xff, 0xfb, 0xf7, 0xf1, 0xff, 0xfa, 0xf7, 0xf3, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xff, 0xff, 0xfd, 0xff, 0x81, 0x4c, 0x46, 0xff, 0x4e, 0x01, 0x00, 0xff, 0x56, 0x0d, 0x01, 0xff, 0x58, 0x10, 0x04, 0xff, 0x5a, 0x14, 0x07, 0xff, 0x5d, 0x16, 0x07, 0xff, 0x5e, 0x17, 0x07, 0xff, 0x60, 0x19, 0x06, 0xff, 0x62, 0x1a, 0x07, 0xff, 0x64, 0x1a, 0x07, 0xff, 0x65, 0x1b, 0x08, 0xff, 0x65, 0x1a, 0x08, 0xff, 0x63, 0x19, 0x08, 0xff, 0x64, 0x18, 0x08, 0xff, 0x63, 0x17, 0x08, 0xff, 0x60, 0x15, 0x08, 0xff, 0x5e, 0x13, 0x06, 0xff, 0x5c, 0x12, 0x06, 0xff, 0x5b, 0x11, 0x06, 0xff, 0x5a, 0x11, 0x05, 0xff, 0x5a, 0x11, 0x05, 0xff, 0x5c, 0x11, 0x05, 0xff, 0x5e, 0x0f, 0x04, 0xff, 0x55, 0x0b, 0x02, 0xff, 0xa8, 0x36, 0x15, 0xff, 0xff, 0x67, 0x28, 0xff, 0xa7, 0x31, 0x13, 0xff, 0x5f, 0x0a, 0x00, 0xff, 0x8f, 0x1f, 0x10, 0xff, 0xc7, 0x38, 0x2b, 0xff, 0xd5, 0x39, 0x3b, 0xff, 0xc6, 0x2b, 0x3e, 0xff, 0x8c, 0x17, 0x23, 0xff, 0x51, 0x03, 0x00, 0xff, 0x9e, 0x21, 0x1c, 0xff, 0xff, 0x43, 0x4a, 0xff, 0x8c, 0x18, 0x19, 0xff, 0x52, 0x06, 0x00, 0xff, 0x56, 0x05, 0x00, 0xff, 0x5e, 0x09, 0x01, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf7, 0xf1, 0xff, 0xf9, 0xf5, 0xef, 0xff, 0xf8, 0xf3, 0xee, 0xff, 0xfb, 0xf1, 0xeb, 0xff, 0xfc, 0xef, 0xe9, 0xff, 0xfd, 0xec, 0xe6, 0xff, 0xfd, 0xed, 0xea, 0xff, 0xfc, 0xb3, 0x6c, 0xff, 0xfd, 0x91, 0x1e, 0xff, 0xfd, 0x94, 0x27, 0xff, 0xfd, 0x93, 0x28, 0xff, 0xfd, 0x92, 0x28, 0xff, 0xfd, 0x91, 0x29, 0xff, 0xfd, 0x91, 0x2a, 0xff, 0xfd, 0x91, 0x2a, 0xff, 0xfd, 0x91, 0x2b, 0xff, 0xfd, 0x92, 0x2c, 0xff, 0xfd, 0x93, 0x2b, 0xff, 0xfd, 0x94, 0x2a, 0xff, 0xfd, 0x95, 0x2a, 0xff, 0xfd, 0x8f, 0x1d, 0xff, 0xfb, 0xb8, 0x6d, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xf7, 0xeb, 0xff, 0xfb, 0x98, 0x36, 0xff, 0xfd, 0x8e, 0x1f, 0xff, 0xfd, 0x91, 0x24, 0xff, 0xfd, 0x8b, 0x17, 0xff, 0xfb, 0xb3, 0x66, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfd, 0xfa, 0xf2, 0xff, 0xfb, 0xa1, 0x40, 0xff, 0xfd, 0x90, 0x19, 0xff, 0xfd, 0x94, 0x22, 0xff, 0xfd, 0x95, 0x23, 0xff, 0xfd, 0x95, 0x24, 0xff, 0xfd, 0x96, 0x25, 0xff, 0xfd, 0x8f, 0x17, 0xff, 0xfc, 0xc4, 0x81, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xf8, 0xff, 0xfb, 0xfc, 0xf7, 0xff, 0xfb, 0xfd, 0xfa, 0xff, 0xfd, 0xf7, 0xeb, 0xff, 0xfd, 0xa3, 0x35, 0xff, 0xfd, 0x96, 0x1b, 0xff, 0xfd, 0x98, 0x22, 0xff, 0xfd, 0x98, 0x24, 0xff, 0xfd, 0x99, 0x25, 0xff, 0xfd, 0x99, 0x24, 0xff, 0xfd, 0x9a, 0x24, 0xff, 0xfd, 0x9a, 0x25, 0xff, 0xfd, 0x9a, 0x24, 0xff, 0xfd, 0x98, 0x1e, 0xff, 0xfc, 0xa3, 0x32, 0xff, 0xfd, 0xf2, 0xe2, 0xff, 0xfd, 0xf9, 0xf4, 0xff, 0xfb, 0xf8, 0xf2, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfd, 0xfb, 0xf5, 0xff, 0xff, 0xff, 0xfc, 0xff, 0x7b, 0x43, 0x3e, 0xff, 0x4e, 0x01, 0x00, 0xff, 0x56, 0x0d, 0x01, 0xff, 0x59, 0x11, 0x04, 0xff, 0x5d, 0x16, 0x06, 0xff, 0x61, 0x19, 0x07, 0xff, 0x65, 0x1b, 0x07, 0xff, 0x67, 0x1d, 0x07, 0xff, 0x6a, 0x1f, 0x07, 0xff, 0x6d, 0x20, 0x06, 0xff, 0x6e, 0x21, 0x07, 0xff, 0x6c, 0x20, 0x07, 0xff, 0x6a, 0x1f, 0x08, 0xff, 0x67, 0x1c, 0x08, 0xff, 0x65, 0x1a, 0x08, 0xff, 0x63, 0x17, 0x07, 0xff, 0x60, 0x15, 0x07, 0xff, 0x5d, 0x13, 0x07, 0xff, 0x5a, 0x11, 0x07, 0xff, 0x5a, 0x11, 0x06, 0xff, 0x5a, 0x11, 0x06, 0xff, 0x5b, 0x10, 0x04, 0xff, 0x58, 0x0b, 0x02, 0xff, 0x7d, 0x1f, 0x0b, 0xff, 0xff, 0x68, 0x29, 0xff, 0xb3, 0x37, 0x17, 0xff, 0x65, 0x0a, 0x04, 0xff, 0xc7, 0x39, 0x1d, 0xff, 0xff, 0x4f, 0x39, 0xff, 0xed, 0x40, 0x3c, 0xff, 0xd8, 0x33, 0x38, 0xff, 0xd7, 0x30, 0x3f, 0xff, 0xf3, 0x3b, 0x5e, 0xff, 0xcd, 0x2e, 0x4d, 0xff, 0x58, 0x02, 0x01, 0xff, 0xad, 0x22, 0x2a, 0xff, 0xef, 0x3b, 0x5a, 0xff, 0x66, 0x0c, 0x08, 0xff, 0x5a, 0x08, 0x00, 0xff, 0x5f, 0x0a, 0x01, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf8, 0xf5, 0xef, 0xff, 0xf9, 0xf4, 0xee, 0xff, 0xfb, 0xf2, 0xec, 0xff, 0xfc, 0xef, 0xea, 0xff, 0xfd, 0xec, 0xe6, 0xff, 0xfd, 0xec, 0xe9, 0xff, 0xfc, 0xaf, 0x6d, 0xff, 0xfd, 0x8c, 0x22, 0xff, 0xfe, 0x91, 0x2a, 0xff, 0xfe, 0x90, 0x2a, 0xff, 0xfd, 0x8f, 0x2b, 0xff, 0xfe, 0x8f, 0x2c, 0xff, 0xfd, 0x8e, 0x2c, 0xff, 0xfd, 0x8e, 0x2c, 0xff, 0xfd, 0x8f, 0x2e, 0xff, 0xfd, 0x90, 0x2e, 0xff, 0xfd, 0x91, 0x2e, 0xff, 0xfd, 0x91, 0x2c, 0xff, 0xfd, 0x91, 0x29, 0xff, 0xfc, 0x8e, 0x21, 0xff, 0xfb, 0xe0, 0xbf, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfb, 0xfc, 0xf9, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfb, 0xd7, 0xb4, 0xff, 0xfc, 0x86, 0x1d, 0xff, 0xfd, 0x8d, 0x26, 0xff, 0xfd, 0x8f, 0x27, 0xff, 0xfd, 0x8c, 0x22, 0xff, 0xfc, 0x90, 0x2e, 0xff, 0xfc, 0xef, 0xe1, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xc7, 0x8f, 0xff, 0xfc, 0x8a, 0x17, 0xff, 0xfd, 0x91, 0x25, 0xff, 0xfd, 0x92, 0x26, 0xff, 0xfe, 0x93, 0x27, 0xff, 0xfd, 0x93, 0x27, 0xff, 0xfd, 0x8c, 0x18, 0xff, 0xfc, 0xc1, 0x80, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfd, 0xf6, 0xeb, 0xff, 0xfd, 0x9e, 0x37, 0xff, 0xfd, 0x92, 0x1d, 0xff, 0xfd, 0x95, 0x25, 0xff, 0xfd, 0x96, 0x27, 0xff, 0xfd, 0x96, 0x27, 0xff, 0xfd, 0x97, 0x27, 0xff, 0xfd, 0x97, 0x26, 0xff, 0xfd, 0x98, 0x27, 0xff, 0xfd, 0x99, 0x27, 0xff, 0xfd, 0x96, 0x21, 0xff, 0xfc, 0x9f, 0x33, 0xff, 0xfd, 0xf1, 0xe2, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfb, 0xf8, 0xf2, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xfb, 0xff, 0x78, 0x3e, 0x39, 0xff, 0x4e, 0x01, 0x00, 0xff, 0x56, 0x0e, 0x01, 0xff, 0x5a, 0x13, 0x04, 0xff, 0x60, 0x18, 0x07, 0xff, 0x66, 0x1d, 0x08, 0xff, 0x6d, 0x22, 0x06, 0xff, 0x73, 0x25, 0x05, 0xff, 0x78, 0x28, 0x05, 0xff, 0x7b, 0x2a, 0x05, 0xff, 0x7c, 0x2a, 0x05, 0xff, 0x7a, 0x28, 0x05, 0xff, 0x75, 0x25, 0x06, 0xff, 0x6d, 0x21, 0x07, 0xff, 0x69, 0x1c, 0x08, 0xff, 0x65, 0x19, 0x08, 0xff, 0x61, 0x16, 0x08, 0xff, 0x5d, 0x14, 0x08, 0xff, 0x5b, 0x12, 0x08, 0xff, 0x5a, 0x12, 0x07, 0xff, 0x59, 0x10, 0x07, 0xff, 0x5a, 0x0f, 0x06, 0xff, 0x56, 0x0a, 0x03, 0xff, 0xca, 0x4a, 0x1b, 0xff, 0xec, 0x5a, 0x22, 0xff, 0x72, 0x0f, 0x09, 0xff, 0xbc, 0x37, 0x1d, 0xff, 0xff, 0x53, 0x38, 0xff, 0xf1, 0x3a, 0x40, 0xff, 0xe8, 0x33, 0x40, 0xff, 0xea, 0x32, 0x40, 0xff, 0xe0, 0x2e, 0x39, 0xff, 0xc4, 0x26, 0x2f, 0xff, 0xeb, 0x38, 0x5c, 0xff, 0xc5, 0x2b, 0x4c, 0xff, 0x52, 0x01, 0x00, 0xff, 0xea, 0x3a, 0x63, 0xff, 0xa5, 0x20, 0x34, 0xff, 0x55, 0x06, 0x00, 0xff, 0x5d, 0x09, 0x01, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf8, 0xf3, 0xee, 0xff, 0xfa, 0xf1, 0xed, 0xff, 0xfc, 0xef, 0xea, 0xff, 0xfd, 0xec, 0xe6, 0xff, 0xfd, 0xec, 0xe9, 0xff, 0xfc, 0xac, 0x6d, 0xff, 0xfd, 0x89, 0x25, 0xff, 0xfd, 0x8e, 0x2f, 0xff, 0xfd, 0x8d, 0x2e, 0xff, 0xfd, 0x8c, 0x2d, 0xff, 0xfd, 0x8c, 0x2f, 0xff, 0xfd, 0x8b, 0x2f, 0xff, 0xfd, 0x8b, 0x2e, 0xff, 0xfd, 0x8b, 0x2f, 0xff, 0xfd, 0x8c, 0x2f, 0xff, 0xfd, 0x8d, 0x2f, 0xff, 0xfe, 0x8f, 0x2e, 0xff, 0xfe, 0x8b, 0x26, 0xff, 0xfb, 0xa3, 0x4f, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfa, 0xa5, 0x5e, 0xff, 0xfd, 0x7f, 0x15, 0xff, 0xfd, 0x85, 0x20, 0xff, 0xfd, 0x86, 0x20, 0xff, 0xfd, 0x84, 0x20, 0xff, 0xfd, 0x7a, 0x11, 0xff, 0xfa, 0xc5, 0x99, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfd, 0xfe, 0xfc, 0xff, 0xfd, 0xec, 0xdc, 0xff, 0xfc, 0x91, 0x2c, 0xff, 0xfd, 0x8c, 0x23, 0xff, 0xfd, 0x8e, 0x27, 0xff, 0xfd, 0x8f, 0x29, 0xff, 0xfd, 0x8f, 0x2a, 0xff, 0xfd, 0x88, 0x1b, 0xff, 0xfc, 0xc0, 0x82, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfc, 0xf5, 0xec, 0xff, 0xfc, 0x99, 0x39, 0xff, 0xfd, 0x8f, 0x20, 0xff, 0xfd, 0x93, 0x27, 0xff, 0xfd, 0x93, 0x29, 0xff, 0xfd, 0x93, 0x2a, 0xff, 0xfd, 0x94, 0x2a, 0xff, 0xfc, 0x94, 0x2a, 0xff, 0xfd, 0x95, 0x2a, 0xff, 0xfd, 0x96, 0x2a, 0xff, 0xfd, 0x94, 0x25, 0xff, 0xfc, 0x9c, 0x37, 0xff, 0xfd, 0xf1, 0xe3, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf8, 0xf2, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf4, 0xff, 0xfe, 0xfd, 0xf8, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0x77, 0x3c, 0x37, 0xff, 0x50, 0x03, 0x00, 0xff, 0x5a, 0x10, 0x01, 0xff, 0x5e, 0x15, 0x04, 0xff, 0x64, 0x1b, 0x06, 0xff, 0x6d, 0x22, 0x07, 0xff, 0x77, 0x29, 0x05, 0xff, 0x80, 0x2e, 0x04, 0xff, 0x86, 0x32, 0x05, 0xff, 0x89, 0x32, 0x05, 0xff, 0x89, 0x31, 0x05, 0xff, 0x86, 0x30, 0x04, 0xff, 0x7f, 0x2c, 0x05, 0xff, 0x75, 0x26, 0x07, 0xff, 0x6c, 0x20, 0x07, 0xff, 0x67, 0x1b, 0x08, 0xff, 0x62, 0x18, 0x08, 0xff, 0x5e, 0x15, 0x08, 0xff, 0x5b, 0x13, 0x08, 0xff, 0x5a, 0x12, 0x08, 0xff, 0x5b, 0x11, 0x07, 0xff, 0x57, 0x0e, 0x05, 0xff, 0x69, 0x15, 0x08, 0xff, 0xf7, 0x67, 0x26, 0xff, 0xb9, 0x39, 0x18, 0xff, 0x8e, 0x1c, 0x14, 0xff, 0xfa, 0x5e, 0x38, 0xff, 0xfd, 0x47, 0x46, 0xff, 0xf5, 0x35, 0x4c, 0xff, 0xf7, 0x39, 0x4d, 0xff, 0xfb, 0x3a, 0x4e, 0xff, 0xfe, 0x39, 0x4f, 0xff, 0xf3, 0x33, 0x47, 0xff, 0xc8, 0x23, 0x38, 0xff, 0xf1, 0x39, 0x6b, 0xff, 0x6d, 0x0b, 0x16, 0xff, 0x9e, 0x1f, 0x3a, 0xff, 0xda, 0x34, 0x62, 0xff, 0x59, 0x07, 0x00, 0xff, 0x5a, 0x09, 0x00, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf3, 0xee, 0xff, 0xfa, 0xf1, 0xec, 0xff, 0xfc, 0xef, 0xea, 0xff, 0xfd, 0xec, 0xe7, 0xff, 0xfd, 0xed, 0xea, 0xff, 0xfc, 0xab, 0x6f, 0xff, 0xfd, 0x85, 0x27, 0xff, 0xfd, 0x89, 0x32, 0xff, 0xfd, 0x89, 0x31, 0xff, 0xfd, 0x89, 0x31, 0xff, 0xfd, 0x89, 0x32, 0xff, 0xfd, 0x89, 0x32, 0xff, 0xfd, 0x89, 0x32, 0xff, 0xfd, 0x89, 0x31, 0xff, 0xfd, 0x89, 0x31, 0xff, 0xfd, 0x8a, 0x30, 0xff, 0xfd, 0x8b, 0x30, 0xff, 0xfd, 0x86, 0x23, 0xff, 0xfb, 0xcd, 0xa0, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfb, 0xfd, 0xfa, 0xff, 0xfb, 0xf6, 0xee, 0xff, 0xfa, 0xb3, 0x7a, 0xff, 0xfc, 0xae, 0x6f, 0xff, 0xfc, 0xb0, 0x74, 0xff, 0xfc, 0xb0, 0x74, 0xff, 0xfb, 0xaf, 0x73, 0xff, 0xfb, 0xaa, 0x6c, 0xff, 0xf9, 0xc5, 0x9d, 0xff, 0xfb, 0xfd, 0xfb, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfb, 0xad, 0x6b, 0xff, 0xfd, 0x84, 0x1e, 0xff, 0xfd, 0x8b, 0x2a, 0xff, 0xfd, 0x8d, 0x2b, 0xff, 0xfd, 0x8d, 0x2c, 0xff, 0xfd, 0x86, 0x1f, 0xff, 0xfc, 0xbf, 0x85, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfd, 0xf5, 0xec, 0xff, 0xfc, 0x95, 0x3a, 0xff, 0xfd, 0x8b, 0x20, 0xff, 0xfd, 0x8f, 0x29, 0xff, 0xfd, 0x90, 0x2c, 0xff, 0xfd, 0x91, 0x2f, 0xff, 0xfd, 0x92, 0x2f, 0xff, 0xfd, 0x93, 0x2f, 0xff, 0xfd, 0x93, 0x2f, 0xff, 0xfd, 0x93, 0x2f, 0xff, 0xfd, 0x91, 0x29, 0xff, 0xfc, 0x9a, 0x3a, 0xff, 0xfd, 0xf0, 0xe4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfe, 0xfd, 0xf8, 0xff, 0xfe, 0xfe, 0xf9, 0xff, 0x74, 0x39, 0x33, 0xff, 0x52, 0x03, 0x00, 0xff, 0x5b, 0x11, 0x01, 0xff, 0x62, 0x18, 0x04, 0xff, 0x69, 0x1f, 0x05, 0xff, 0x74, 0x28, 0x05, 0xff, 0x82, 0x30, 0x03, 0xff, 0x8d, 0x33, 0x03, 0xff, 0x9c, 0x41, 0x04, 0xff, 0xae, 0x57, 0x02, 0xff, 0xb1, 0x5f, 0x02, 0xff, 0x97, 0x3f, 0x03, 0xff, 0x87, 0x32, 0x04, 0xff, 0x7c, 0x2b, 0x06, 0xff, 0x6f, 0x23, 0x08, 0xff, 0x67, 0x1d, 0x08, 0xff, 0x62, 0x18, 0x07, 0xff, 0x5e, 0x15, 0x08, 0xff, 0x5c, 0x13, 0x08, 0xff, 0x5a, 0x12, 0x08, 0xff, 0x5a, 0x11, 0x07, 0xff, 0x55, 0x0c, 0x04, 0xff, 0x7f, 0x22, 0x0d, 0xff, 0xff, 0x73, 0x2c, 0xff, 0xa7, 0x28, 0x1a, 0xff, 0xb6, 0x33, 0x23, 0xff, 0xff, 0x6a, 0x41, 0xff, 0xfc, 0x3f, 0x53, 0xff, 0xfa, 0x38, 0x55, 0xff, 0xfc, 0x3b, 0x55, 0xff, 0xfd, 0x3c, 0x55, 0xff, 0xfd, 0x3c, 0x54, 0xff, 0xff, 0x3b, 0x55, 0xff, 0xe0, 0x2a, 0x45, 0xff, 0xe3, 0x2f, 0x5e, 0xff, 0xa5, 0x21, 0x43, 0xff, 0x6c, 0x0e, 0x1a, 0xff, 0xec, 0x40, 0x7c, 0xff, 0x64, 0x0a, 0x08, 0xff, 0x57, 0x07, 0x00, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf3, 0xee, 0xff, 0xfb, 0xf1, 0xed, 0xff, 0xfd, 0xf0, 0xea, 0xff, 0xfe, 0xec, 0xe6, 0xff, 0xfd, 0xec, 0xe9, 0xff, 0xfc, 0xa9, 0x71, 0xff, 0xfd, 0x81, 0x2a, 0xff, 0xfd, 0x86, 0x33, 0xff, 0xfd, 0x86, 0x33, 0xff, 0xfd, 0x87, 0x34, 0xff, 0xfd, 0x88, 0x35, 0xff, 0xfd, 0x89, 0x34, 0xff, 0xfd, 0x88, 0x34, 0xff, 0xfd, 0x88, 0x34, 0xff, 0xfd, 0x88, 0x33, 0xff, 0xfd, 0x87, 0x32, 0xff, 0xfd, 0x84, 0x2e, 0xff, 0xfc, 0x8d, 0x38, 0xff, 0xfc, 0xf1, 0xe3, 0xff, 0xfc, 0xfe, 0xfb, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xf9, 0xfd, 0xfd, 0xff, 0xf9, 0xfa, 0xf6, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xd9, 0xbd, 0xff, 0xfd, 0x82, 0x25, 0xff, 0xfd, 0x88, 0x2b, 0xff, 0xfd, 0x8a, 0x2e, 0xff, 0xfd, 0x8a, 0x30, 0xff, 0xfc, 0x84, 0x24, 0xff, 0xfc, 0xbe, 0x87, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfe, 0xfb, 0xff, 0xfd, 0xf5, 0xed, 0xff, 0xfc, 0x93, 0x3c, 0xff, 0xfd, 0x87, 0x23, 0xff, 0xfd, 0x8c, 0x2d, 0xff, 0xfd, 0x8d, 0x30, 0xff, 0xfd, 0x8f, 0x32, 0xff, 0xfd, 0x8f, 0x32, 0xff, 0xfd, 0x90, 0x32, 0xff, 0xfd, 0x91, 0x32, 0xff, 0xfd, 0x91, 0x32, 0xff, 0xfd, 0x8f, 0x2c, 0xff, 0xfc, 0x98, 0x3b, 0xff, 0xfc, 0xf0, 0xe4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x80, 0x4b, 0x45, 0xff, 0x50, 0x01, 0x00, 0xff, 0x5e, 0x12, 0x01, 0xff, 0x64, 0x18, 0x03, 0xff, 0x6d, 0x20, 0x04, 0xff, 0x7a, 0x2b, 0x04, 0xff, 0x8d, 0x36, 0x02, 0xff, 0xc8, 0x83, 0x02, 0xff, 0xf0, 0xc4, 0x01, 0xff, 0xfa, 0xdb, 0x01, 0xff, 0xff, 0xe6, 0x01, 0xff, 0xdb, 0xa8, 0x02, 0xff, 0x8f, 0x39, 0x05, 0xff, 0x80, 0x2e, 0x05, 0xff, 0x72, 0x25, 0x07, 0xff, 0x68, 0x1d, 0x08, 0xff, 0x62, 0x18, 0x07, 0xff, 0x5e, 0x16, 0x07, 0xff, 0x5c, 0x13, 0x07, 0xff, 0x5b, 0x12, 0x08, 0xff, 0x5a, 0x11, 0x08, 0xff, 0x54, 0x0a, 0x04, 0xff, 0x8c, 0x2a, 0x10, 0xff, 0xff, 0x75, 0x2e, 0xff, 0xa8, 0x25, 0x20, 0xff, 0xc6, 0x40, 0x2b, 0xff, 0xff, 0x74, 0x45, 0xff, 0xfd, 0x3d, 0x5f, 0xff, 0xfd, 0x3b, 0x5f, 0xff, 0xfd, 0x3d, 0x5e, 0xff, 0xfd, 0x3d, 0x5e, 0xff, 0xfd, 0x3d, 0x5e, 0xff, 0xff, 0x3c, 0x5d, 0xff, 0xee, 0x30, 0x51, 0xff, 0xdf, 0x2c, 0x5d, 0xff, 0xbb, 0x2d, 0x5d, 0xff, 0x61, 0x09, 0x12, 0xff, 0xeb, 0x44, 0x81, 0xff, 0x66, 0x0c, 0x0d, 0xff, 0x53, 0x06, 0x00, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf5, 0xef, 0xff, 0xf9, 0xf3, 0xee, 0xff, 0xfa, 0xf1, 0xec, 0xff, 0xfd, 0xef, 0xe8, 0xff, 0xfe, 0xeb, 0xe5, 0xff, 0xfd, 0xec, 0xe9, 0xff, 0xfc, 0xa6, 0x74, 0xff, 0xfc, 0x7d, 0x2c, 0xff, 0xfd, 0x82, 0x35, 0xff, 0xfd, 0x83, 0x37, 0xff, 0xfd, 0x84, 0x38, 0xff, 0xfd, 0x85, 0x39, 0xff, 0xfd, 0x86, 0x3a, 0xff, 0xfd, 0x86, 0x3a, 0xff, 0xfd, 0x85, 0x38, 0xff, 0xfc, 0x85, 0x36, 0xff, 0xfd, 0x83, 0x35, 0xff, 0xfd, 0x7c, 0x27, 0xff, 0xfb, 0xaf, 0x78, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfb, 0xfd, 0xf9, 0xff, 0xfb, 0xfd, 0xf9, 0xff, 0xfb, 0xfc, 0xf9, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfa, 0xfa, 0xf7, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfd, 0xf9, 0xf4, 0xff, 0xfb, 0x96, 0x4f, 0xff, 0xfd, 0x81, 0x28, 0xff, 0xfd, 0x86, 0x31, 0xff, 0xfd, 0x87, 0x33, 0xff, 0xfd, 0x81, 0x27, 0xff, 0xfc, 0xbc, 0x89, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfe, 0xfc, 0xff, 0xfd, 0xf5, 0xed, 0xff, 0xfd, 0x91, 0x3f, 0xff, 0xfd, 0x85, 0x27, 0xff, 0xfd, 0x89, 0x30, 0xff, 0xfd, 0x8b, 0x34, 0xff, 0xfd, 0x8c, 0x35, 0xff, 0xfd, 0x8d, 0x35, 0xff, 0xfd, 0x8d, 0x35, 0xff, 0xfd, 0x8e, 0x35, 0xff, 0xfd, 0x8e, 0x33, 0xff, 0xfd, 0x8c, 0x2d, 0xff, 0xfc, 0x95, 0x3d, 0xff, 0xfc, 0xef, 0xe4, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0xbd, 0xb8, 0xff, 0x56, 0x0d, 0x02, 0xff, 0x5d, 0x10, 0x00, 0xff, 0x65, 0x18, 0x03, 0xff, 0x6e, 0x21, 0x04, 0xff, 0x7a, 0x28, 0x03, 0xff, 0xab, 0x5e, 0x02, 0xff, 0xff, 0xe3, 0x01, 0xff, 0xff, 0xe3, 0x00, 0xff, 0xfe, 0xe1, 0x00, 0xff, 0xff, 0xe6, 0x00, 0xff, 0xf4, 0xd1, 0x01, 0xff, 0x97, 0x43, 0x04, 0xff, 0x80, 0x2d, 0x06, 0xff, 0x73, 0x25, 0x07, 0xff, 0x68, 0x1d, 0x07, 0xff, 0x62, 0x19, 0x08, 0xff, 0x5e, 0x16, 0x07, 0xff, 0x5e, 0x14, 0x07, 0xff, 0x5c, 0x12, 0x08, 0xff, 0x5a, 0x11, 0x08, 0xff, 0x54, 0x0b, 0x04, 0xff, 0x84, 0x26, 0x0e, 0xff, 0xff, 0x76, 0x2d, 0xff, 0xaf, 0x29, 0x25, 0xff, 0xc2, 0x39, 0x2f, 0xff, 0xff, 0x84, 0x46, 0xff, 0xfd, 0x42, 0x6a, 0xff, 0xfd, 0x3e, 0x6b, 0xff, 0xfd, 0x3e, 0x69, 0xff, 0xfd, 0x3e, 0x69, 0xff, 0xfd, 0x3e, 0x69, 0xff, 0xff, 0x3c, 0x68, 0xff, 0xef, 0x2f, 0x55, 0xff, 0xea, 0x32, 0x6b, 0xff, 0xac, 0x29, 0x56, 0xff, 0x66, 0x0d, 0x19, 0xff, 0xe6, 0x41, 0x81, 0xff, 0x5d, 0x09, 0x07, 0xff, 0x52, 0x03, 0x00, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf4, 0xef, 0xff, 0xf9, 0xf3, 0xee, 0xff, 0xf9, 0xf0, 0xeb, 0xff, 0xfb, 0xed, 0xe6, 0xff, 0xfd, 0xeb, 0xe4, 0xff, 0xfd, 0xeb, 0xe8, 0xff, 0xfc, 0xa5, 0x76, 0xff, 0xfd, 0x78, 0x2f, 0xff, 0xfd, 0x7e, 0x38, 0xff, 0xfd, 0x80, 0x3a, 0xff, 0xfc, 0x81, 0x3c, 0xff, 0xfd, 0x82, 0x3d, 0xff, 0xfd, 0x82, 0x3e, 0xff, 0xfd, 0x82, 0x3e, 0xff, 0xfc, 0x82, 0x3c, 0xff, 0xfd, 0x82, 0x3a, 0xff, 0xfd, 0x7e, 0x36, 0xff, 0xfc, 0x7c, 0x30, 0xff, 0xfc, 0xdf, 0xc9, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfb, 0xfe, 0xfb, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xc5, 0x9f, 0xff, 0xfd, 0x7b, 0x26, 0xff, 0xfd, 0x83, 0x33, 0xff, 0xfc, 0x84, 0x34, 0xff, 0xfd, 0x7d, 0x29, 0xff, 0xfc, 0xb9, 0x8b, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfc, 0xfe, 0xfb, 0xff, 0xfd, 0xf5, 0xed, 0xff, 0xfd, 0x8f, 0x43, 0xff, 0xfd, 0x82, 0x2b, 0xff, 0xfd, 0x87, 0x33, 0xff, 0xfd, 0x88, 0x35, 0xff, 0xfd, 0x89, 0x37, 0xff, 0xfd, 0x8a, 0x38, 0xff, 0xfd, 0x8a, 0x39, 0xff, 0xfd, 0x8b, 0x38, 0xff, 0xfd, 0x8a, 0x37, 0xff, 0xfe, 0x88, 0x32, 0xff, 0xfc, 0x93, 0x40, 0xff, 0xfc, 0xef, 0xe4, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfe, 0xfc, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x94, 0x67, 0x5f, 0xff, 0x57, 0x07, 0x00, 0xff, 0x64, 0x17, 0x02, 0xff, 0x6f, 0x20, 0x02, 0xff, 0x7a, 0x27, 0x03, 0xff, 0xa2, 0x51, 0x02, 0xff, 0xfa, 0xd3, 0x01, 0xff, 0xff, 0xe2, 0x00, 0xff, 0xfe, 0xdb, 0x01, 0xff, 0xf8, 0xd1, 0x01, 0xff, 0xc6, 0x86, 0x03, 0xff, 0x8c, 0x35, 0x05, 0xff, 0x7f, 0x2c, 0x06, 0xff, 0x72, 0x23, 0x07, 0xff, 0x68, 0x1d, 0x08, 0xff, 0x63, 0x18, 0x07, 0xff, 0x60, 0x15, 0x08, 0xff, 0x5f, 0x14, 0x06, 0xff, 0x5c, 0x12, 0x07, 0xff, 0x59, 0x11, 0x07, 0xff, 0x56, 0x0c, 0x03, 0xff, 0x70, 0x17, 0x07, 0xff, 0xfa, 0x72, 0x29, 0xff, 0xc2, 0x38, 0x29, 0xff, 0xac, 0x1c, 0x2e, 0xff, 0xfb, 0x89, 0x46, 0xff, 0xfe, 0x5d, 0x69, 0xff, 0xfd, 0x3d, 0x76, 0xff, 0xfd, 0x41, 0x75, 0xff, 0xfd, 0x40, 0x74, 0xff, 0xfd, 0x40, 0x73, 0xff, 0xfe, 0x3d, 0x6f, 0xff, 0xeb, 0x29, 0x58, 0xff, 0xf5, 0x3b, 0x89, 0xff, 0x73, 0x12, 0x29, 0xff, 0x8e, 0x21, 0x3d, 0xff, 0xd2, 0x3d, 0x76, 0xff, 0x4a, 0x00, 0x00, 0xff, 0x6e, 0x1f, 0x03, 0xff,
0xfd, 0xf9, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf4, 0xee, 0xff, 0xfa, 0xf1, 0xea, 0xff, 0xfb, 0xec, 0xe6, 0xff, 0xfd, 0xea, 0xe4, 0xff, 0xfd, 0xeb, 0xe7, 0xff, 0xfc, 0xa2, 0x79, 0xff, 0xfd, 0x75, 0x33, 0xff, 0xfd, 0x7b, 0x3b, 0xff, 0xfd, 0x7b, 0x3c, 0xff, 0xfd, 0x7d, 0x3e, 0xff, 0xfd, 0x7f, 0x41, 0xff, 0xfd, 0x7f, 0x41, 0xff, 0xfd, 0x7f, 0x41, 0xff, 0xfd, 0x7f, 0x40, 0xff, 0xfd, 0x7d, 0x3e, 0xff, 0xfd, 0x76, 0x33, 0xff, 0xfb, 0x97, 0x60, 0xff, 0xfc, 0xfe, 0xfa, 0xff, 0xfc, 0xfe, 0xfa, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfb, 0xfd, 0xfa, 0xff, 0xfb, 0xf0, 0xe7, 0xff, 0xfc, 0xe8, 0xdc, 0xff, 0xfc, 0xe8, 0xdd, 0xff, 0xfc, 0xe8, 0xde, 0xff, 0xfc, 0xe8, 0xdf, 0xff, 0xfc, 0xe9, 0xe0, 0xff, 0xfc, 0xe9, 0xdf, 0xff, 0xfc, 0xe9, 0xdf, 0xff, 0xfc, 0xea, 0xdf, 0xff, 0xfc, 0xe9, 0xdd, 0xff, 0xfc, 0xf7, 0xf1, 0xff, 0xfc, 0xfe, 0xfb, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfe, 0xfb, 0xff, 0xfc, 0xf0, 0xe4, 0xff, 0xfc, 0x86, 0x40, 0xff, 0xfd, 0x7e, 0x32, 0xff, 0xfd, 0x80, 0x36, 0xff, 0xfd, 0x79, 0x2b, 0xff, 0xfc, 0xb8, 0x8e, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xf9, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfe, 0xfb, 0xff, 0xfd, 0xf4, 0xed, 0xff, 0xfc, 0x8b, 0x46, 0xff, 0xfd, 0x7d, 0x2f, 0xff, 0xfd, 0x82, 0x36, 0xff, 0xfd, 0x84, 0x38, 0xff, 0xfd, 0x84, 0x39, 0xff, 0xfd, 0x85, 0x3b, 0xff, 0xfd, 0x86, 0x3c, 0xff, 0xfd, 0x86, 0x3d, 0xff, 0xfd, 0x86, 0x3c, 0xff, 0xfd, 0x84, 0x36, 0xff, 0xfc, 0x8f, 0x44, 0xff, 0xfc, 0xf0, 0xe4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xb4, 0xae, 0xff, 0x57, 0x08, 0x00, 0xff, 0x62, 0x16, 0x02, 0xff, 0x6e, 0x1f, 0x03, 0xff, 0x79, 0x29, 0x04, 0xff, 0x87, 0x30, 0x04, 0xff, 0xac, 0x5a, 0x03, 0xff, 0xc2, 0x78, 0x03, 0xff, 0xb6, 0x64, 0x03, 0xff, 0xa5, 0x4e, 0x03, 0xff, 0x90, 0x39, 0x04, 0xff, 0x85, 0x31, 0x05, 0xff, 0x7a, 0x28, 0x06, 0xff, 0x6e, 0x20, 0x07, 0xff, 0x66, 0x1a, 0x08, 0xff, 0x62, 0x17, 0x08, 0xff, 0x61, 0x15, 0x07, 0xff, 0x5f, 0x13, 0x06, 0xff, 0x5d, 0x11, 0x05, 0xff, 0x5a, 0x10, 0x04, 0xff, 0x59, 0x0d, 0x02, 0xff, 0x57, 0x08, 0x00, 0xff, 0xd6, 0x5b, 0x20, 0xff, 0xea, 0x5d, 0x2a, 0xff, 0x9a, 0x0b, 0x27, 0xff, 0xd8, 0x4f, 0x41, 0xff, 0xff, 0x88, 0x64, 0xff, 0xfd, 0x4e, 0x79, 0xff, 0xfd, 0x43, 0x7c, 0xff, 0xfd, 0x43, 0x7b, 0xff, 0xfc, 0x40, 0x76, 0xff, 0xf4, 0x34, 0x6c, 0xff, 0xfb, 0x38, 0x86, 0xff, 0xe8, 0x46, 0x71, 0xff, 0x54, 0x0b, 0x00, 0xff, 0xd8, 0x45, 0x84, 0xff, 0xa1, 0x29, 0x4c, 0xff, 0x42, 0x00, 0x00, 0xff, 0x9c, 0x52, 0x03, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xfb, 0xf4, 0xee, 0xff, 0xfb, 0xf2, 0xeb, 0xff, 0xfa, 0xed, 0xe7, 0xff, 0xfc, 0xea, 0xe4, 0xff, 0xfd, 0xeb, 0xe7, 0xff, 0xfb, 0x9f, 0x7a, 0xff, 0xfd, 0x72, 0x37, 0xff, 0xfd, 0x78, 0x3f, 0xff, 0xfd, 0x78, 0x40, 0xff, 0xfd, 0x7a, 0x42, 0xff, 0xfd, 0x7c, 0x44, 0xff, 0xfd, 0x7b, 0x44, 0xff, 0xfd, 0x7b, 0x44, 0xff, 0xfd, 0x7a, 0x43, 0xff, 0xfd, 0x78, 0x41, 0xff, 0xfc, 0x6f, 0x33, 0xff, 0xfc, 0xc6, 0xab, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfd, 0xfc, 0xf8, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xf9, 0x8e, 0x65, 0xff, 0xfc, 0x72, 0x40, 0xff, 0xfc, 0x75, 0x44, 0xff, 0xfc, 0x75, 0x44, 0xff, 0xfc, 0x75, 0x43, 0xff, 0xfc, 0x75, 0x43, 0xff, 0xfc, 0x75, 0x42, 0xff, 0xfc, 0x76, 0x41, 0xff, 0xfc, 0x77, 0x40, 0xff, 0xfc, 0x6f, 0x35, 0xff, 0xfa, 0xaf, 0x8d, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xaa, 0x7f, 0xff, 0xfd, 0x76, 0x2f, 0xff, 0xfd, 0x7d, 0x3a, 0xff, 0xfd, 0x76, 0x2f, 0xff, 0xfc, 0xb6, 0x90, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf9, 0xff, 0xfb, 0xfc, 0xf8, 0xff, 0xfb, 0xfe, 0xfc, 0xff, 0xfd, 0xf4, 0xed, 0xff, 0xfc, 0x89, 0x48, 0xff, 0xfd, 0x7a, 0x32, 0xff, 0xfd, 0x7e, 0x3a, 0xff, 0xfd, 0x80, 0x3c, 0xff, 0xfd, 0x81, 0x3d, 0xff, 0xfd, 0x81, 0x3d, 0xff, 0xfd, 0x82, 0x3f, 0xff, 0xfd, 0x83, 0x40, 0xff, 0xfd, 0x83, 0x3f, 0xff, 0xfd, 0x80, 0x3a, 0xff, 0xfc, 0x8a, 0x47, 0xff, 0xfd, 0xee, 0xe4, 0xff, 0xfb, 0xf8, 0xf5, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xac, 0xa7, 0xff, 0x52, 0x06, 0x00, 0xff, 0x61, 0x14, 0x02, 0xff, 0x6b, 0x1d, 0x05, 0xff, 0x74, 0x25, 0x06, 0xff, 0x7e, 0x2c, 0x05, 0xff, 0x89, 0x30, 0x04, 0xff, 0x8f, 0x33, 0x04, 0xff, 0x91, 0x36, 0x04, 0xff, 0x8e, 0x36, 0x04, 0xff, 0x86, 0x32, 0x05, 0xff, 0x7d, 0x2a, 0x05, 0xff, 0x74, 0x22, 0x06, 0xff, 0x6a, 0x1c, 0x07, 0xff, 0x65, 0x18, 0x07, 0xff, 0x62, 0x15, 0x07, 0xff, 0x5f, 0x13, 0x06, 0xff, 0x5e, 0x11, 0x06, 0xff, 0x5c, 0x0f, 0x05, 0xff, 0x5b, 0x0e, 0x03, 0xff, 0x59, 0x0d, 0x02, 0xff, 0x4c, 0x04, 0x00, 0xff, 0x87, 0x28, 0x0e, 0xff, 0xff, 0x77, 0x2b, 0xff, 0xbd, 0x2f, 0x27, 0xff, 0x9e, 0x0a, 0x28, 0xff, 0xe3, 0x53, 0x52, 0xff, 0xff, 0x75, 0x7c, 0xff, 0xff, 0x5a, 0x90, 0xff, 0xff, 0x4a, 0x8e, 0xff, 0xfe, 0x43, 0x8d, 0xff, 0xff, 0x46, 0x9b, 0xff, 0xdd, 0x36, 0x85, 0xff, 0xcf, 0x7e, 0x0e, 0xff, 0xdf, 0x78, 0x41, 0xff, 0xe6, 0x46, 0x98, 0xff, 0x5f, 0x0a, 0x0b, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xcf, 0x8f, 0x03, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf8, 0xf5, 0xef, 0xff, 0xf9, 0xf3, 0xee, 0xff, 0xfb, 0xf1, 0xeb, 0xff, 0xfb, 0xed, 0xe8, 0xff, 0xfd, 0xea, 0xe5, 0xff, 0xfd, 0xeb, 0xe8, 0xff, 0xfb, 0x9e, 0x7e, 0xff, 0xfd, 0x71, 0x3b, 0xff, 0xfd, 0x76, 0x42, 0xff, 0xfd, 0x76, 0x43, 0xff, 0xfd, 0x77, 0x46, 0xff, 0xfd, 0x79, 0x47, 0xff, 0xfc, 0x79, 0x48, 0xff, 0xfd, 0x78, 0x48, 0xff, 0xfd, 0x76, 0x46, 0xff, 0xfd, 0x72, 0x40, 0xff, 0xfc, 0x7e, 0x4d, 0xff, 0xfd, 0xf0, 0xe7, 0xff, 0xfd, 0xff, 0xfb, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfb, 0xd9, 0xcb, 0xff, 0xfc, 0x6c, 0x3e, 0xff, 0xfd, 0x6f, 0x40, 0xff, 0xfd, 0x6f, 0x41, 0xff, 0xfd, 0x6f, 0x42, 0xff, 0xfd, 0x70, 0x42, 0xff, 0xfd, 0x70, 0x42, 0xff, 0xfd, 0x71, 0x41, 0xff, 0xfd, 0x72, 0x40, 0xff, 0xfd, 0x72, 0x3f, 0xff, 0xfd, 0x6d, 0x38, 0xff, 0xfc, 0x7e, 0x4e, 0xff, 0xfd, 0xf5, 0xef, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xfd, 0xfc, 0xf7, 0xff, 0xfd, 0xfc, 0xf7, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xdb, 0xca, 0xff, 0xfc, 0x76, 0x38, 0xff, 0xfd, 0x7a, 0x3b, 0xff, 0xfd, 0x73, 0x32, 0xff, 0xfc, 0xb4, 0x8f, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfc, 0xfd, 0xf9, 0xff, 0xfd, 0xfe, 0xfc, 0xff, 0xfd, 0xf4, 0xed, 0xff, 0xfc, 0x85, 0x4b, 0xff, 0xfd, 0x78, 0x35, 0xff, 0xfd, 0x7b, 0x3d, 0xff, 0xfd, 0x7c, 0x3e, 0xff, 0xfd, 0x7e, 0x40, 0xff, 0xfd, 0x7e, 0x41, 0xff, 0xfc, 0x7f, 0x42, 0xff, 0xfc, 0x7f, 0x43, 0xff, 0xfd, 0x80, 0x43, 0xff, 0xfd, 0x7d, 0x3e, 0xff, 0xfc, 0x88, 0x4b, 0xff, 0xfc, 0xee, 0xe4, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0x98, 0x6f, 0x69, 0xff, 0x4e, 0x02, 0x00, 0xff, 0x5e, 0x13, 0x03, 0xff, 0x66, 0x19, 0x05, 0xff, 0x6e, 0x1f, 0x06, 0xff, 0x75, 0x25, 0x07, 0xff, 0x7d, 0x2b, 0x07, 0xff, 0x81, 0x2e, 0x07, 0xff, 0x83, 0x2f, 0x07, 0xff, 0x80, 0x2d, 0x07, 0xff, 0x7b, 0x2a, 0x06, 0xff, 0x74, 0x24, 0x05, 0xff, 0x6c, 0x1e, 0x07, 0xff, 0x66, 0x1a, 0x07, 0xff, 0x64, 0x17, 0x06, 0xff, 0x61, 0x14, 0x06, 0xff, 0x5f, 0x12, 0x06, 0xff, 0x5c, 0x10, 0x05, 0xff, 0x59, 0x0e, 0x03, 0xff, 0x59, 0x0c, 0x03, 0xff, 0x52, 0x07, 0x00, 0xff, 0x66, 0x13, 0x03, 0xff, 0x53, 0x07, 0x01, 0xff, 0xbf, 0x48, 0x1b, 0xff, 0xff, 0x6b, 0x30, 0xff, 0xb3, 0x23, 0x28, 0xff, 0x9d, 0x06, 0x23, 0xff, 0xc4, 0x26, 0x45, 0xff, 0xdf, 0x41, 0x74, 0xff, 0xe8, 0x49, 0x88, 0xff, 0xda, 0x3e, 0x7e, 0xff, 0xa6, 0x20, 0x49, 0xff, 0x5b, 0x01, 0x07, 0xff, 0x8b, 0x22, 0x2e, 0xff, 0xff, 0x5b, 0x9e, 0xff, 0x88, 0x1d, 0x36, 0xff, 0x45, 0x00, 0x00, 0xff, 0x79, 0x2a, 0x02, 0xff, 0xe2, 0x9e, 0x04, 0xff,
0xfd, 0xfb, 0xf5, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfa, 0xf8, 0xf2, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf3, 0xee, 0xff, 0xfb, 0xf1, 0xec, 0xff, 0xfc, 0xee, 0xe9, 0xff, 0xfd, 0xeb, 0xe6, 0xff, 0xfd, 0xeb, 0xe9, 0xff, 0xfc, 0x9c, 0x81, 0xff, 0xfd, 0x6d, 0x3f, 0xff, 0xfd, 0x72, 0x46, 0xff, 0xfd, 0x73, 0x48, 0xff, 0xfd, 0x74, 0x4b, 0xff, 0xfd, 0x76, 0x4c, 0xff, 0xfd, 0x76, 0x4c, 0xff, 0xfd, 0x75, 0x4b, 0xff, 0xfd, 0x74, 0x49, 0xff, 0xfd, 0x6a, 0x3c, 0xff, 0xfb, 0xab, 0x8c, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xf7, 0xff, 0xfe, 0xfd, 0xf8, 0xff, 0xfd, 0xfd, 0xfa, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xa5, 0x8c, 0xff, 0xfd, 0x66, 0x3b, 0xff, 0xfd, 0x70, 0x45, 0xff, 0xfd, 0x70, 0x45, 0xff, 0xfd, 0x70, 0x47, 0xff, 0xfd, 0x70, 0x48, 0xff, 0xfd, 0x71, 0x48, 0xff, 0xfd, 0x71, 0x48, 0xff, 0xfd, 0x72, 0x47, 0xff, 0xfd, 0x72, 0x45, 0xff, 0xfd, 0x70, 0x44, 0xff, 0xfc, 0x68, 0x39, 0xff, 0xfc, 0xcd, 0xba, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfd, 0xfe, 0xfa, 0xff, 0xfd, 0xfb, 0xf7, 0xff, 0xfc, 0x90, 0x65, 0xff, 0xfd, 0x73, 0x3a, 0xff, 0xfd, 0x70, 0x35, 0xff, 0xfc, 0xb3, 0x92, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xfa, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfd, 0xff, 0xfb, 0xff, 0xfd, 0xf5, 0xee, 0xff, 0xfc, 0x82, 0x4e, 0xff, 0xfd, 0x73, 0x39, 0xff, 0xfd, 0x77, 0x3f, 0xff, 0xfd, 0x79, 0x42, 0xff, 0xfd, 0x7a, 0x43, 0xff, 0xfd, 0x7b, 0x45, 0xff, 0xfd, 0x7c, 0x45, 0xff, 0xfd, 0x7d, 0x45, 0xff, 0xfc, 0x7c, 0x46, 0xff, 0xfd, 0x7a, 0x41, 0xff, 0xfc, 0x86, 0x50, 0xff, 0xfd, 0xef, 0xe6, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf1, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfe, 0xfb, 0xf7, 0xff, 0xfa, 0xf7, 0xf3, 0xff, 0x6d, 0x31, 0x2a, 0xff, 0x51, 0x07, 0x00, 0xff, 0x5b, 0x12, 0x03, 0xff, 0x60, 0x16, 0x05, 0xff, 0x67, 0x1b, 0x07, 0xff, 0x6d, 0x1f, 0x08, 0xff, 0x71, 0x23, 0x08, 0xff, 0x74, 0x25, 0x08, 0xff, 0x76, 0x26, 0x07, 0xff, 0x74, 0x25, 0x07, 0xff, 0x71, 0x22, 0x07, 0xff, 0x6b, 0x1e, 0x07, 0xff, 0x66, 0x1a, 0x07, 0xff, 0x64, 0x17, 0x07, 0xff, 0x61, 0x15, 0x06, 0xff, 0x5f, 0x12, 0x05, 0xff, 0x5e, 0x0f, 0x04, 0xff, 0x5a, 0x0d, 0x03, 0xff, 0x54, 0x09, 0x02, 0xff, 0x4e, 0x05, 0x01, 0xff, 0x93, 0x2b, 0x0c, 0xff, 0xca, 0x4a, 0x13, 0xff, 0x5b, 0x0d, 0x02, 0xff, 0x54, 0x08, 0x01, 0xff, 0xca, 0x4c, 0x25, 0xff, 0xff, 0x67, 0x3f, 0xff, 0xce, 0x36, 0x38, 0xff, 0xa0, 0x0f, 0x21, 0xff, 0x8b, 0x03, 0x11, 0xff, 0x81, 0x01, 0x0c, 0xff, 0x72, 0x00, 0x05, 0xff, 0x72, 0x07, 0x12, 0xff, 0xb4, 0x2d, 0x56, 0xff, 0xf7, 0x4d, 0x96, 0xff, 0x98, 0x23, 0x43, 0xff, 0x49, 0x01, 0x00, 0xff, 0x4d, 0x00, 0x00, 0xff, 0xcf, 0x87, 0x03, 0xff, 0xa6, 0x56, 0x07, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xfa, 0xf3, 0xef, 0xff, 0xfb, 0xf1, 0xed, 0xff, 0xfc, 0xef, 0xea, 0xff, 0xfd, 0xec, 0xe7, 0xff, 0xfd, 0xec, 0xe9, 0xff, 0xfc, 0x9a, 0x83, 0xff, 0xfd, 0x69, 0x43, 0xff, 0xfd, 0x70, 0x4a, 0xff, 0xfd, 0x72, 0x4c, 0xff, 0xfd, 0x72, 0x4f, 0xff, 0xfd, 0x72, 0x50, 0xff, 0xfd, 0x73, 0x4f, 0xff, 0xfd, 0x72, 0x4d, 0xff, 0xfd, 0x6f, 0x4a, 0xff, 0xfc, 0x71, 0x4b, 0xff, 0xfc, 0xe7, 0xda, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xf5, 0xf1, 0xff, 0xfb, 0x77, 0x57, 0xff, 0xfd, 0x69, 0x44, 0xff, 0xfd, 0x6d, 0x48, 0xff, 0xfd, 0x6d, 0x48, 0xff, 0xfd, 0x6d, 0x49, 0xff, 0xfd, 0x6e, 0x4a, 0xff, 0xfd, 0x6e, 0x4b, 0xff, 0xfd, 0x6f, 0x4b, 0xff, 0xfd, 0x6f, 0x4b, 0xff, 0xfd, 0x6f, 0x49, 0xff, 0xfd, 0x6e, 0x49, 0xff, 0xfd, 0x66, 0x3e, 0xff, 0xfb, 0x96, 0x78, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xcb, 0xb7, 0xff, 0xfc, 0x6f, 0x3c, 0xff, 0xfd, 0x6c, 0x38, 0xff, 0xfc, 0xb4, 0x98, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfb, 0x80, 0x51, 0xff, 0xfd, 0x70, 0x3c, 0xff, 0xfd, 0x75, 0x43, 0xff, 0xfd, 0x76, 0x45, 0xff, 0xfd, 0x77, 0x47, 0xff, 0xfd, 0x79, 0x48, 0xff, 0xfd, 0x7a, 0x49, 0xff, 0xfd, 0x7b, 0x49, 0xff, 0xfd, 0x7b, 0x49, 0xff, 0xfd, 0x77, 0x44, 0xff, 0xfd, 0x84, 0x53, 0xff, 0xfc, 0xef, 0xe7, 0xff, 0xfc, 0xf8, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xd7, 0xc7, 0xc3, 0xff, 0x52, 0x09, 0x00, 0xff, 0x56, 0x0c, 0x00, 0xff, 0x59, 0x11, 0x03, 0xff, 0x5d, 0x15, 0x06, 0xff, 0x61, 0x18, 0x08, 0xff, 0x66, 0x1a, 0x08, 0xff, 0x69, 0x1c, 0x08, 0xff, 0x6a, 0x1d, 0x08, 0xff, 0x69, 0x1d, 0x08, 0xff, 0x69, 0x1d, 0x08, 0xff, 0x67, 0x1b, 0x08, 0xff, 0x65, 0x19, 0x07, 0xff, 0x63, 0x17, 0x07, 0xff, 0x60, 0x15, 0x06, 0xff, 0x5e, 0x12, 0x05, 0xff, 0x5c, 0x0f, 0x04, 0xff, 0x59, 0x0d, 0x03, 0xff, 0x4f, 0x06, 0x01, 0xff, 0x59, 0x0d, 0x02, 0xff, 0xb8, 0x48, 0x0e, 0xff, 0xbe, 0x48, 0x14, 0xff, 0x60, 0x10, 0x03, 0xff, 0x53, 0x08, 0x00, 0xff, 0x52, 0x08, 0x00, 0xff, 0x55, 0x08, 0x02, 0xff, 0xa2, 0x31, 0x21, 0xff, 0xf1, 0x58, 0x4e, 0xff, 0xfd, 0x56, 0x66, 0xff, 0xea, 0x44, 0x68, 0xff, 0xde, 0x3d, 0x6a, 0xff, 0xe5, 0x42, 0x7a, 0xff, 0xf6, 0x4c, 0x91, 0xff, 0xe0, 0x44, 0x7f, 0xff, 0x7f, 0x17, 0x29, 0xff, 0x48, 0x01, 0x00, 0xff, 0x45, 0x00, 0x00, 0xff, 0x9e, 0x52, 0x01, 0xff, 0xdb, 0x95, 0x06, 0xff, 0x6b, 0x10, 0x04, 0xff,
0xfe, 0xfb, 0xf6, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfa, 0xf6, 0xf2, 0xff, 0xf9, 0xf4, 0xef, 0xff, 0xfa, 0xf3, 0xee, 0xff, 0xfb, 0xf1, 0xed, 0xff, 0xfc, 0xef, 0xea, 0xff, 0xfd, 0xec, 0xe7, 0xff, 0xfd, 0xec, 0xe8, 0xff, 0xfc, 0x98, 0x85, 0xff, 0xfd, 0x65, 0x46, 0xff, 0xfd, 0x6c, 0x4e, 0xff, 0xfe, 0x6f, 0x50, 0xff, 0xfd, 0x70, 0x52, 0xff, 0xfd, 0x6f, 0x52, 0xff, 0xfd, 0x6e, 0x51, 0xff, 0xfd, 0x6e, 0x4f, 0xff, 0xfd, 0x6a, 0x4c, 0xff, 0xfc, 0x72, 0x55, 0xff, 0xfc, 0xcb, 0xbe, 0xff, 0xfc, 0xd9, 0xcf, 0xff, 0xfc, 0xd7, 0xcd, 0xff, 0xfc, 0xd8, 0xcf, 0xff, 0xfc, 0xdd, 0xd5, 0xff, 0xfb, 0xa7, 0x97, 0xff, 0xfd, 0x63, 0x46, 0xff, 0xfd, 0x6a, 0x4c, 0xff, 0xfd, 0x6a, 0x4b, 0xff, 0xfd, 0x69, 0x4b, 0xff, 0xfd, 0x6a, 0x4c, 0xff, 0xfd, 0x6b, 0x4e, 0xff, 0xfd, 0x6b, 0x50, 0xff, 0xfd, 0x6c, 0x50, 0xff, 0xfd, 0x6b, 0x4f, 0xff, 0xfd, 0x6c, 0x4f, 0xff, 0xfd, 0x6c, 0x4e, 0xff, 0xfd, 0x69, 0x4a, 0xff, 0xfc, 0x6c, 0x4b, 0xff, 0xfb, 0xc5, 0xb6, 0xff, 0xfb, 0xd9, 0xcf, 0xff, 0xfc, 0xd6, 0xcb, 0xff, 0xfc, 0xd6, 0xcb, 0xff, 0xfc, 0xdd, 0xd2, 0xff, 0xfc, 0xb9, 0xa5, 0xff, 0xfc, 0x6d, 0x43, 0xff, 0xfd, 0x6b, 0x40, 0xff, 0xfc, 0x8b, 0x6b, 0xff, 0xfc, 0xd9, 0xcb, 0xff, 0xfc, 0xd9, 0xcb, 0xff, 0xfc, 0xd8, 0xcb, 0xff, 0xfc, 0xdd, 0xd1, 0xff, 0xfc, 0xc2, 0xb0, 0xff, 0xfc, 0x72, 0x49, 0xff, 0xfd, 0x70, 0x44, 0xff, 0xfd, 0x72, 0x47, 0xff, 0xfd, 0x74, 0x49, 0xff, 0xfd, 0x74, 0x4b, 0xff, 0xfd, 0x75, 0x4c, 0xff, 0xfd, 0x76, 0x4d, 0xff, 0xfd, 0x78, 0x4e, 0xff, 0xfd, 0x78, 0x4d, 0xff, 0xfd, 0x73, 0x47, 0xff, 0xfc, 0x80, 0x55, 0xff, 0xfd, 0xef, 0xe8, 0xff, 0xfc, 0xf8, 0xf4, 0xff, 0xfb, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa1, 0x7d, 0x78, 0xff, 0x4a, 0x00, 0x00, 0xff, 0x57, 0x0d, 0x01, 0xff, 0x59, 0x10, 0x04, 0xff, 0x5c, 0x13, 0x07, 0xff, 0x5f, 0x15, 0x08, 0xff, 0x62, 0x17, 0x07, 0xff, 0x63, 0x18, 0x08, 0xff, 0x64, 0x19, 0x08, 0xff, 0x64, 0x19, 0x07, 0xff, 0x62, 0x18, 0x07, 0xff, 0x62, 0x18, 0x07, 0xff, 0x61, 0x17, 0x07, 0xff, 0x5e, 0x14, 0x07, 0xff, 0x5c, 0x12, 0x06, 0xff, 0x5b, 0x10, 0x03, 0xff, 0x59, 0x0d, 0x02, 0xff, 0x4d, 0x04, 0x01, 0xff, 0x7a, 0x26, 0x03, 0xff, 0xd3, 0x66, 0x0a, 0xff, 0x9b, 0x39, 0x09, 0xff, 0x4f, 0x07, 0x01, 0xff, 0x52, 0x09, 0x01, 0xff, 0x57, 0x0b, 0x02, 0xff, 0x58, 0x0b, 0x03, 0xff, 0x57, 0x0b, 0x02, 0xff, 0x50, 0x06, 0x00, 0xff, 0x61, 0x0e, 0x07, 0xff, 0x8c, 0x20, 0x22, 0xff, 0xb1, 0x2e, 0x42, 0xff, 0xb9, 0x31, 0x51, 0xff, 0xa5, 0x29, 0x46, 0xff, 0x7b, 0x16, 0x25, 0xff, 0x50, 0x04, 0x01, 0xff, 0x46, 0x01, 0x00, 0xff, 0x42, 0x00, 0x00, 0xff, 0x88, 0x3b, 0x01, 0xff, 0xe9, 0xa4, 0x04, 0xff, 0x7d, 0x24, 0x05, 0xff, 0x7c, 0x2a, 0x20, 0xff,
0xfe, 0xfb, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf7, 0xf4, 0xff, 0xfa, 0xf6, 0xf2, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xfa, 0xf2, 0xee, 0xff, 0xfb, 0xf1, 0xed, 0xff, 0xfc, 0xef, 0xea, 0xff, 0xfd, 0xeb, 0xe6, 0xff, 0xfd, 0xec, 0xe8, 0xff, 0xfc, 0x95, 0x87, 0xff, 0xfd, 0x62, 0x4a, 0xff, 0xfd, 0x6a, 0x52, 0xff, 0xfd, 0x6b, 0x54, 0xff, 0xfe, 0x6d, 0x55, 0xff, 0xfd, 0x6d, 0x55, 0xff, 0xfd, 0x6b, 0x53, 0xff, 0xfd, 0x6a, 0x52, 0xff, 0xfd, 0x69, 0x51, 0xff, 0xfd, 0x66, 0x4e, 0xff, 0xfd, 0x62, 0x4b, 0xff, 0xfc, 0x63, 0x4c, 0xff, 0xfd, 0x62, 0x4c, 0xff, 0xfc, 0x62, 0x4b, 0xff, 0xfc, 0x62, 0x4c, 0xff, 0xfd, 0x61, 0x4b, 0xff, 0xfd, 0x67, 0x50, 0xff, 0xfd, 0x68, 0x4f, 0xff, 0xfd, 0x69, 0x4f, 0xff, 0xfd, 0x68, 0x50, 0xff, 0xfd, 0x68, 0x50, 0xff, 0xfd, 0x6a, 0x52, 0xff, 0xfd, 0x6b, 0x53, 0xff, 0xfd, 0x6b, 0x54, 0xff, 0xfd, 0x6b, 0x54, 0xff, 0xfd, 0x6a, 0x52, 0xff, 0xfd, 0x6a, 0x51, 0xff, 0xfd, 0x6a, 0x4f, 0xff, 0xfd, 0x66, 0x4b, 0xff, 0xfd, 0x62, 0x45, 0xff, 0xfc, 0x63, 0x47, 0xff, 0xfd, 0x62, 0x47, 0xff, 0xfd, 0x62, 0x47, 0xff, 0xfc, 0x64, 0x48, 0xff, 0xfc, 0x67, 0x48, 0xff, 0xfd, 0x6c, 0x4c, 0xff, 0xfd, 0x6d, 0x4c, 0xff, 0xfd, 0x68, 0x46, 0xff, 0xfc, 0x66, 0x44, 0xff, 0xfc, 0x67, 0x45, 0xff, 0xfc, 0x67, 0x47, 0xff, 0xfc, 0x68, 0x47, 0xff, 0xfd, 0x67, 0x47, 0xff, 0xfd, 0x6c, 0x4b, 0xff, 0xfd, 0x6f, 0x4a, 0xff, 0xfd, 0x70, 0x4b, 0xff, 0xfd, 0x71, 0x4d, 0xff, 0xfd, 0x72, 0x4f, 0xff, 0xfd, 0x73, 0x50, 0xff, 0xfd, 0x74, 0x51, 0xff, 0xfd, 0x75, 0x51, 0xff, 0xfd, 0x74, 0x50, 0xff, 0xfd, 0x6f, 0x4a, 0xff, 0xfc, 0x7b, 0x57, 0xff, 0xfd, 0xf0, 0xe8, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfe, 0xfc, 0xf8, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0x6d, 0x34, 0x2e, 0xff, 0x4d, 0x03, 0x00, 0xff, 0x56, 0x0d, 0x01, 0xff, 0x59, 0x0f, 0x03, 0xff, 0x5b, 0x12, 0x06, 0xff, 0x5c, 0x14, 0x07, 0xff, 0x5d, 0x15, 0x08, 0xff, 0x5f, 0x16, 0x09, 0xff, 0x5f, 0x16, 0x09, 0xff, 0x5f, 0x16, 0x08, 0xff, 0x5f, 0x16, 0x08, 0xff, 0x5d, 0x15, 0x08, 0xff, 0x5c, 0x13, 0x07, 0xff, 0x5b, 0x12, 0x06, 0xff, 0x59, 0x10, 0x04, 0xff, 0x54, 0x0a, 0x02, 0xff, 0x54, 0x08, 0x01, 0xff, 0xa3, 0x4b, 0x03, 0xff, 0xd6, 0x73, 0x04, 0xff, 0x75, 0x25, 0x03, 0xff, 0x46, 0x02, 0x00, 0xff, 0x53, 0x0a, 0x02, 0xff, 0x56, 0x0c, 0x02, 0xff, 0x57, 0x0c, 0x03, 0xff, 0x58, 0x0c, 0x03, 0xff, 0x58, 0x0b, 0x03, 0xff, 0x55, 0x09, 0x01, 0xff, 0x4f, 0x06, 0x00, 0xff, 0x4f, 0x04, 0x00, 0xff, 0x51, 0x03, 0x00, 0xff, 0x50, 0x02, 0x00, 0xff, 0x4c, 0x02, 0x00, 0xff, 0x4a, 0x03, 0x00, 0xff, 0x49, 0x02, 0x00, 0xff, 0x47, 0x00, 0x01, 0xff, 0x94, 0x43, 0x01, 0xff, 0xeb, 0x9f, 0x03, 0xff, 0x8c, 0x34, 0x08, 0xff, 0x6e, 0x14, 0x0f, 0xff, 0xd8, 0xba, 0xb1, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf7, 0xf3, 0xff, 0xfa, 0xf6, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf3, 0xee, 0xff, 0xfa, 0xf1, 0xec, 0xff, 0xfc, 0xef, 0xe9, 0xff, 0xfe, 0xeb, 0xe6, 0xff, 0xfd, 0xeb, 0xe9, 0xff, 0xfc, 0x92, 0x89, 0xff, 0xfd, 0x5e, 0x4e, 0xff, 0xfd, 0x66, 0x55, 0xff, 0xfd, 0x67, 0x56, 0xff, 0xfd, 0x69, 0x57, 0xff, 0xfd, 0x69, 0x58, 0xff, 0xfd, 0x68, 0x56, 0xff, 0xfd, 0x67, 0x55, 0xff, 0xfd, 0x65, 0x54, 0xff, 0xfd, 0x63, 0x54, 0xff, 0xfe, 0x63, 0x53, 0xff, 0xfd, 0x64, 0x54, 0xff, 0xfd, 0x65, 0x55, 0xff, 0xfd, 0x66, 0x54, 0xff, 0xfd, 0x65, 0x54, 0xff, 0xfd, 0x66, 0x54, 0xff, 0xfd, 0x66, 0x54, 0xff, 0xfd, 0x65, 0x54, 0xff, 0xfd, 0x66, 0x55, 0xff, 0xfd, 0x66, 0x55, 0xff, 0xfd, 0x66, 0x55, 0xff, 0xfd, 0x68, 0x56, 0xff, 0xfd, 0x6a, 0x58, 0xff, 0xfd, 0x6b, 0x59, 0xff, 0xfd, 0x6b, 0x57, 0xff, 0xfd, 0x6a, 0x55, 0xff, 0xfd, 0x6a, 0x54, 0xff, 0xfd, 0x69, 0x53, 0xff, 0xfd, 0x68, 0x51, 0xff, 0xfd, 0x67, 0x51, 0xff, 0xfd, 0x68, 0x51, 0xff, 0xfd, 0x68, 0x51, 0xff, 0xfd, 0x67, 0x50, 0xff, 0xfd, 0x69, 0x50, 0xff, 0xfd, 0x6b, 0x52, 0xff, 0xfd, 0x6b, 0x53, 0xff, 0xfd, 0x6b, 0x52, 0xff, 0xfd, 0x6b, 0x51, 0xff, 0xfd, 0x6a, 0x50, 0xff, 0xfd, 0x6a, 0x50, 0xff, 0xfd, 0x6a, 0x51, 0xff, 0xfd, 0x6b, 0x50, 0xff, 0xfd, 0x6b, 0x51, 0xff, 0xfd, 0x6c, 0x51, 0xff, 0xfd, 0x6d, 0x50, 0xff, 0xfd, 0x6e, 0x51, 0xff, 0xfd, 0x6f, 0x53, 0xff, 0xfe, 0x6f, 0x54, 0xff, 0xfd, 0x6f, 0x55, 0xff, 0xfd, 0x70, 0x55, 0xff, 0xfd, 0x71, 0x54, 0xff, 0xfd, 0x71, 0x53, 0xff, 0xfd, 0x6c, 0x4c, 0xff, 0xfc, 0x77, 0x59, 0xff, 0xfd, 0xf0, 0xe8, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd4, 0xc3, 0xbe, 0xff, 0x4c, 0x06, 0x00, 0xff, 0x51, 0x09, 0x00, 0xff, 0x56, 0x0c, 0x03, 0xff, 0x58, 0x0e, 0x02, 0xff, 0x58, 0x10, 0x04, 0xff, 0x59, 0x12, 0x08, 0xff, 0x5b, 0x13, 0x09, 0xff, 0x5d, 0x14, 0x09, 0xff, 0x5d, 0x14, 0x09, 0xff, 0x5d, 0x14, 0x0a, 0xff, 0x5c, 0x14, 0x09, 0xff, 0x5a, 0x13, 0x09, 0xff, 0x59, 0x11, 0x07, 0xff, 0x58, 0x0f, 0x05, 0xff, 0x50, 0x06, 0x01, 0xff, 0x66, 0x19, 0x02, 0xff, 0xc8, 0x75, 0x03, 0xff, 0xba, 0x66, 0x03, 0xff, 0x58, 0x0f, 0x01, 0xff, 0x4a, 0x05, 0x01, 0xff, 0x52, 0x0a, 0x02, 0xff, 0x55, 0x0c, 0x03, 0xff, 0x57, 0x0c, 0x03, 0xff, 0x58, 0x0c, 0x03, 0xff, 0x58, 0x0c, 0x03, 0xff, 0x50, 0x09, 0x00, 0xff, 0x91, 0x1c, 0x23, 0xff, 0xc6, 0x2b, 0x40, 0xff, 0x64, 0x0b, 0x09, 0xff, 0x51, 0x05, 0x00, 0xff, 0x53, 0x05, 0x00, 0xff, 0x4c, 0x04, 0x00, 0xff, 0x44, 0x01, 0x00, 0xff, 0x64, 0x10, 0x04, 0xff, 0xc3, 0x67, 0x03, 0xff, 0xe4, 0x8a, 0x05, 0xff, 0x88, 0x25, 0x06, 0xff, 0x63, 0x01, 0x00, 0xff, 0xa2, 0x68, 0x5e, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf3, 0xef, 0xff, 0xf9, 0xf1, 0xec, 0xff, 0xfc, 0xee, 0xe9, 0xff, 0xfd, 0xeb, 0xe6, 0xff, 0xfd, 0xeb, 0xe9, 0xff, 0xfc, 0x8e, 0x8a, 0xff, 0xfd, 0x58, 0x50, 0xff, 0xfe, 0x60, 0x58, 0xff, 0xfd, 0x62, 0x58, 0xff, 0xfd, 0x64, 0x59, 0xff, 0xfd, 0x64, 0x5a, 0xff, 0xfd, 0x64, 0x59, 0xff, 0xfd, 0x63, 0x59, 0xff, 0xfe, 0x61, 0x57, 0xff, 0xfd, 0x61, 0x58, 0xff, 0xfd, 0x61, 0x58, 0xff, 0xfd, 0x63, 0x5a, 0xff, 0xfd, 0x65, 0x5a, 0xff, 0xfd, 0x65, 0x59, 0xff, 0xfd, 0x63, 0x59, 0xff, 0xfd, 0x63, 0x59, 0xff, 0xfd, 0x63, 0x58, 0xff, 0xfd, 0x63, 0x59, 0xff, 0xfd, 0x63, 0x59, 0xff, 0xfd, 0x64, 0x5a, 0xff, 0xfd, 0x64, 0x59, 0xff, 0xfd, 0x65, 0x5a, 0xff, 0xfd, 0x67, 0x5b, 0xff, 0xfd, 0x69, 0x5b, 0xff, 0xfd, 0x68, 0x5a, 0xff, 0xfd, 0x67, 0x59, 0xff, 0xfd, 0x66, 0x58, 0xff, 0xfd, 0x66, 0x57, 0xff, 0xfd, 0x66, 0x56, 0xff, 0xfd, 0x65, 0x56, 0xff, 0xfd, 0x66, 0x57, 0xff, 0xfd, 0x67, 0x57, 0xff, 0xfd, 0x68, 0x57, 0xff, 0xfd, 0x69, 0x57, 0xff, 0xfd, 0x69, 0x58, 0xff, 0xfe, 0x6a, 0x58, 0xff, 0xfd, 0x6a, 0x57, 0xff, 0xfd, 0x69, 0x57, 0xff, 0xfd, 0x69, 0x56, 0xff, 0xfd, 0x69, 0x56, 0xff, 0xfd, 0x69, 0x56, 0xff, 0xfd, 0x6a, 0x55, 0xff, 0xfd, 0x6b, 0x55, 0xff, 0xfe, 0x6b, 0x56, 0xff, 0xfe, 0x6b, 0x56, 0xff, 0xfd, 0x6b, 0x56, 0xff, 0xfd, 0x6b, 0x57, 0xff, 0xfd, 0x6c, 0x57, 0xff, 0xfd, 0x6c, 0x57, 0xff, 0xfd, 0x6d, 0x57, 0xff, 0xfd, 0x6f, 0x57, 0xff, 0xfd, 0x6e, 0x55, 0xff, 0xfd, 0x69, 0x4f, 0xff, 0xfc, 0x76, 0x5e, 0xff, 0xfd, 0xf0, 0xe9, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x7f, 0x7b, 0xff, 0x43, 0x00, 0x00, 0xff, 0x53, 0x0b, 0x01, 0xff, 0x54, 0x0c, 0x03, 0xff, 0x56, 0x0d, 0x03, 0xff, 0x57, 0x0f, 0x05, 0xff, 0x58, 0x11, 0x07, 0xff, 0x5a, 0x12, 0x08, 0xff, 0x5a, 0x12, 0x09, 0xff, 0x5b, 0x13, 0x0a, 0xff, 0x5b, 0x13, 0x0a, 0xff, 0x5a, 0x12, 0x09, 0xff, 0x5a, 0x11, 0x08, 0xff, 0x59, 0x10, 0x06, 0xff, 0x52, 0x07, 0x04, 0xff, 0x87, 0x34, 0x03, 0xff, 0xdb, 0x87, 0x03, 0xff, 0x92, 0x49, 0x02, 0xff, 0x48, 0x03, 0x01, 0xff, 0x4e, 0x08, 0x01, 0xff, 0x54, 0x0c, 0x03, 0xff, 0x55, 0x0d, 0x04, 0xff, 0x56, 0x0d, 0x04, 0xff, 0x57, 0x0d, 0x04, 0xff, 0x59, 0x0c, 0x04, 0xff, 0x58, 0x0b, 0x02, 0xff, 0x53, 0x09, 0x00, 0xff, 0xd2, 0x33, 0x4a, 0xff, 0xfd, 0x41, 0x64, 0xff, 0x5a, 0x08, 0x09, 0xff, 0x48, 0x02, 0x00, 0xff, 0x5c, 0x08, 0x05, 0xff, 0x7c, 0x14, 0x10, 0xff, 0xb4, 0x2b, 0x1c, 0xff, 0xd6, 0x49, 0x17, 0xff, 0xb1, 0x4c, 0x07, 0xff, 0x79, 0x0f, 0x04, 0xff, 0x9d, 0x50, 0x4d, 0xff, 0x89, 0x40, 0x35, 0xff, 0x9f, 0x6d, 0x64, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xf8, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf7, 0xf3, 0xee, 0xff, 0xf9, 0xf1, 0xed, 0xff, 0xfc, 0xee, 0xe9, 0xff, 0xfd, 0xea, 0xe6, 0xff, 0xfd, 0xeb, 0xe9, 0xff, 0xfc, 0x91, 0x92, 0xff, 0xfd, 0x52, 0x54, 0xff, 0xfd, 0x5b, 0x5b, 0xff, 0xfd, 0x5d, 0x5c, 0xff, 0xfd, 0x5f, 0x5d, 0xff, 0xfd, 0x60, 0x5e, 0xff, 0xfd, 0x60, 0x5d, 0xff, 0xfd, 0x5f, 0x5d, 0xff, 0xfd, 0x5e, 0x5c, 0xff, 0xfd, 0x5e, 0x5c, 0xff, 0xfd, 0x5e, 0x5c, 0xff, 0xfd, 0x5f, 0x5d, 0xff, 0xfd, 0x61, 0x5e, 0xff, 0xfd, 0x62, 0x5f, 0xff, 0xfd, 0x61, 0x5f, 0xff, 0xfd, 0x60, 0x5f, 0xff, 0xfd, 0x60, 0x5e, 0xff, 0xfd, 0x61, 0x5e, 0xff, 0xfd, 0x62, 0x5e, 0xff, 0xfd, 0x63, 0x5e, 0xff, 0xfd, 0x63, 0x5d, 0xff, 0xfd, 0x64, 0x5e, 0xff, 0xfd, 0x65, 0x5f, 0xff, 0xfd, 0x66, 0x5f, 0xff, 0xfd, 0x65, 0x5e, 0xff, 0xfd, 0x64, 0x5c, 0xff, 0xfc, 0x64, 0x5b, 0xff, 0xfd, 0x64, 0x5b, 0xff, 0xfc, 0x64, 0x5a, 0xff, 0xfd, 0x64, 0x5a, 0xff, 0xfd, 0x64, 0x5b, 0xff, 0xfd, 0x65, 0x5a, 0xff, 0xfd, 0x65, 0x5b, 0xff, 0xfd, 0x66, 0x5c, 0xff, 0xfd, 0x67, 0x5d, 0xff, 0xfd, 0x68, 0x5c, 0xff, 0xfd, 0x67, 0x5c, 0xff, 0xfd, 0x67, 0x5c, 0xff, 0xfd, 0x67, 0x5b, 0xff, 0xfd, 0x65, 0x5a, 0xff, 0xfd, 0x66, 0x59, 0xff, 0xfd, 0x66, 0x58, 0xff, 0xfd, 0x68, 0x59, 0xff, 0xfd, 0x68, 0x59, 0xff, 0xfd, 0x68, 0x5a, 0xff, 0xfd, 0x69, 0x59, 0xff, 0xfd, 0x67, 0x58, 0xff, 0xfd, 0x67, 0x58, 0xff, 0xfd, 0x67, 0x59, 0xff, 0xfd, 0x69, 0x59, 0xff, 0xfd, 0x6a, 0x59, 0xff, 0xfd, 0x69, 0x58, 0xff, 0xfd, 0x64, 0x53, 0xff, 0xfc, 0x78, 0x6a, 0xff, 0xfc, 0xf3, 0xee, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfb, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xd1, 0xc0, 0xbc, 0xff, 0x57, 0x17, 0x10, 0xff, 0x48, 0x00, 0x00, 0xff, 0x53, 0x0a, 0x01, 0xff, 0x55, 0x0e, 0x04, 0xff, 0x56, 0x0f, 0x05, 0xff, 0x56, 0x11, 0x07, 0xff, 0x57, 0x11, 0x07, 0xff, 0x58, 0x11, 0x09, 0xff, 0x59, 0x12, 0x09, 0xff, 0x59, 0x12, 0x0a, 0xff, 0x59, 0x12, 0x09, 0xff, 0x5a, 0x10, 0x07, 0xff, 0x56, 0x0a, 0x06, 0xff, 0x89, 0x35, 0x04, 0xff, 0xd7, 0x85, 0x03, 0xff, 0x6d, 0x26, 0x02, 0xff, 0x47, 0x02, 0x02, 0xff, 0x52, 0x0a, 0x02, 0xff, 0x53, 0x0c, 0x03, 0xff, 0x54, 0x0e, 0x05, 0xff, 0x57, 0x0f, 0x06, 0xff, 0x58, 0x0f, 0x07, 0xff, 0x58, 0x0f, 0x07, 0xff, 0x5a, 0x0d, 0x05, 0xff, 0x58, 0x0a, 0x00, 0xff, 0x66, 0x0d, 0x09, 0xff, 0xf2, 0x41, 0x66, 0xff, 0xe4, 0x37, 0x56, 0xff, 0x90, 0x13, 0x19, 0xff, 0xbe, 0x20, 0x2e, 0xff, 0xd0, 0x2c, 0x38, 0xff, 0xc4, 0x2c, 0x2f, 0xff, 0x95, 0x1d, 0x16, 0xff, 0x5b, 0x06, 0x01, 0xff, 0x6c, 0x0f, 0x0e, 0xff, 0xbd, 0x83, 0x7f, 0xff, 0xff, 0xff, 0xfa, 0xff, 0x7d, 0x42, 0x38, 0xff, 0xac, 0x85, 0x7c, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf0, 0xff, 0xf8, 0xf3, 0xee, 0xff, 0xf9, 0xf1, 0xec, 0xff, 0xfb, 0xed, 0xe8, 0xff, 0xfd, 0xe9, 0xe4, 0xff, 0xfe, 0xea, 0xe8, 0xff, 0xfc, 0x9e, 0xa3, 0xff, 0xfd, 0x4c, 0x55, 0xff, 0xfd, 0x57, 0x5d, 0xff, 0xfd, 0x58, 0x5f, 0xff, 0xfd, 0x5a, 0x61, 0xff, 0xfd, 0x5c, 0x62, 0xff, 0xfd, 0x5c, 0x62, 0xff, 0xfc, 0x5c, 0x62, 0xff, 0xfd, 0x5c, 0x61, 0xff, 0xfd, 0x5b, 0x61, 0xff, 0xfd, 0x5b, 0x61, 0xff, 0xfd, 0x5c, 0x61, 0xff, 0xfd, 0x5d, 0x61, 0xff, 0xfd, 0x5f, 0x63, 0xff, 0xfd, 0x5f, 0x64, 0xff, 0xfd, 0x5e, 0x63, 0xff, 0xfd, 0x5e, 0x62, 0xff, 0xfd, 0x5f, 0x63, 0xff, 0xfc, 0x5f, 0x64, 0xff, 0xfd, 0x60, 0x63, 0xff, 0xfd, 0x60, 0x63, 0xff, 0xfd, 0x61, 0x62, 0xff, 0xfd, 0x62, 0x62, 0xff, 0xfd, 0x62, 0x62, 0xff, 0xfd, 0x62, 0x60, 0xff, 0xfd, 0x61, 0x60, 0xff, 0xfd, 0x61, 0x5f, 0xff, 0xfd, 0x63, 0x5e, 0xff, 0xfd, 0x63, 0x5e, 0xff, 0xfd, 0x62, 0x5f, 0xff, 0xfd, 0x63, 0x5f, 0xff, 0xfd, 0x63, 0x5e, 0xff, 0xfd, 0x63, 0x5e, 0xff, 0xfd, 0x63, 0x5e, 0xff, 0xfd, 0x64, 0x5f, 0xff, 0xfd, 0x65, 0x5f, 0xff, 0xfd, 0x65, 0x5f, 0xff, 0xfd, 0x64, 0x5f, 0xff, 0xfd, 0x64, 0x5d, 0xff, 0xfd, 0x64, 0x5d, 0xff, 0xfd, 0x64, 0x5c, 0xff, 0xfd, 0x63, 0x5b, 0xff, 0xfd, 0x63, 0x5b, 0xff, 0xfd, 0x64, 0x5c, 0xff, 0xfd, 0x64, 0x5c, 0xff, 0xfd, 0x64, 0x5b, 0xff, 0xfd, 0x63, 0x5a, 0xff, 0xfd, 0x63, 0x5a, 0xff, 0xfd, 0x63, 0x5b, 0xff, 0xfd, 0x63, 0x5a, 0xff, 0xfd, 0x64, 0x5a, 0xff, 0xfd, 0x64, 0x5b, 0xff, 0xfd, 0x5d, 0x54, 0xff, 0xfc, 0x82, 0x7c, 0xff, 0xfd, 0xfa, 0xf6, 0xff, 0xfd, 0xf9, 0xf4, 0xff, 0xfc, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xea, 0xe1, 0xdd, 0xff, 0xa0, 0x77, 0x72, 0xff, 0x54, 0x0d, 0x05, 0xff, 0x53, 0x0c, 0x02, 0xff, 0x55, 0x0f, 0x05, 0xff, 0x57, 0x10, 0x06, 0xff, 0x57, 0x11, 0x07, 0xff, 0x57, 0x11, 0x08, 0xff, 0x58, 0x12, 0x09, 0xff, 0x58, 0x11, 0x09, 0xff, 0x58, 0x11, 0x08, 0xff, 0x5a, 0x10, 0x06, 0xff, 0x53, 0x08, 0x04, 0xff, 0xc1, 0x6d, 0x04, 0xff, 0x7a, 0x34, 0x02, 0xff, 0x47, 0x02, 0x01, 0xff, 0x54, 0x0c, 0x02, 0xff, 0x55, 0x0d, 0x03, 0xff, 0x56, 0x0e, 0x05, 0xff, 0x56, 0x0f, 0x07, 0xff, 0x57, 0x10, 0x08, 0xff, 0x58, 0x10, 0x08, 0xff, 0x57, 0x10, 0x08, 0xff, 0x59, 0x0e, 0x05, 0xff, 0x54, 0x08, 0x00, 0xff, 0x83, 0x18, 0x1f, 0xff, 0xff, 0x4c, 0x7d, 0xff, 0xa2, 0x24, 0x3c, 0xff, 0x44, 0x03, 0x03, 0xff, 0x66, 0x0a, 0x0c, 0xff, 0x59, 0x07, 0x05, 0xff, 0x50, 0x03, 0x00, 0xff, 0x55, 0x05, 0x00, 0xff, 0x52, 0x00, 0x00, 0xff, 0xa8, 0x7c, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9c, 0x72, 0x68, 0xff, 0x6f, 0x34, 0x2b, 0xff, 0xee, 0xe6, 0xe0, 0xff, 0xff, 0xff, 0xfd, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf9, 0xf3, 0xef, 0xff, 0xf9, 0xf1, 0xed, 0xff, 0xfb, 0xed, 0xe8, 0xff, 0xfd, 0xe9, 0xe4, 0xff, 0xfd, 0xe8, 0xe6, 0xff, 0xfc, 0xba, 0xbf, 0xff, 0xfc, 0x4a, 0x5c, 0xff, 0xfd, 0x51, 0x5e, 0xff, 0xfd, 0x53, 0x60, 0xff, 0xfd, 0x55, 0x63, 0xff, 0xfd, 0x57, 0x65, 0xff, 0xfd, 0x58, 0x65, 0xff, 0xfd, 0x59, 0x66, 0xff, 0xfd, 0x5a, 0x65, 0xff, 0xfd, 0x59, 0x65, 0xff, 0xfd, 0x59, 0x65, 0xff, 0xfd, 0x59, 0x65, 0xff, 0xfd, 0x59, 0x65, 0xff, 0xfd, 0x5b, 0x66, 0xff, 0xfd, 0x5c, 0x65, 0xff, 0xfd, 0x5c, 0x64, 0xff, 0xfd, 0x5c, 0x64, 0xff, 0xfd, 0x5d, 0x65, 0xff, 0xfd, 0x5e, 0x66, 0xff, 0xfd, 0x5e, 0x66, 0xff, 0xfd, 0x5e, 0x65, 0xff, 0xfd, 0x5e, 0x66, 0xff, 0xfd, 0x5e, 0x66, 0xff, 0xfd, 0x5f, 0x66, 0xff, 0xfd, 0x5f, 0x65, 0xff, 0xfd, 0x5f, 0x65, 0xff, 0xfd, 0x5f, 0x64, 0xff, 0xfd, 0x60, 0x64, 0xff, 0xfd, 0x61, 0x64, 0xff, 0xfd, 0x60, 0x65, 0xff, 0xfd, 0x60, 0x64, 0xff, 0xfd, 0x60, 0x63, 0xff, 0xfd, 0x60, 0x63, 0xff, 0xfd, 0x60, 0x63, 0xff, 0xfd, 0x60, 0x63, 0xff, 0xfd, 0x60, 0x62, 0xff, 0xfd, 0x60, 0x62, 0xff, 0xfd, 0x60, 0x62, 0xff, 0xfd, 0x61, 0x61, 0xff, 0xfd, 0x62, 0x60, 0xff, 0xfd, 0x62, 0x5f, 0xff, 0xfd, 0x61, 0x5e, 0xff, 0xfd, 0x60, 0x5f, 0xff, 0xfd, 0x60, 0x5f, 0xff, 0xfd, 0x61, 0x5e, 0xff, 0xfd, 0x61, 0x5e, 0xff, 0xfd, 0x60, 0x5d, 0xff, 0xfd, 0x60, 0x5d, 0xff, 0xfd, 0x5f, 0x5d, 0xff, 0xfd, 0x5f, 0x5d, 0xff, 0xfd, 0x5f, 0x5d, 0xff, 0xfd, 0x5f, 0x5d, 0xff, 0xfd, 0x54, 0x53, 0xff, 0xfc, 0x9e, 0x9c, 0xff, 0xfd, 0xff, 0xfb, 0xff, 0xfd, 0xf8, 0xf3, 0xff, 0xfb, 0xf7, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x50, 0x4b, 0xff, 0x4d, 0x03, 0x00, 0xff, 0x56, 0x0e, 0x04, 0xff, 0x57, 0x10, 0x06, 0xff, 0x58, 0x11, 0x08, 0xff, 0x57, 0x11, 0x08, 0xff, 0x57, 0x12, 0x09, 0xff, 0x58, 0x12, 0x09, 0xff, 0x57, 0x11, 0x08, 0xff, 0x57, 0x0f, 0x07, 0xff, 0x52, 0x08, 0x04, 0xff, 0xbf, 0x68, 0x04, 0xff, 0x70, 0x26, 0x04, 0xff, 0x4e, 0x08, 0x02, 0xff, 0x56, 0x0d, 0x03, 0xff, 0x57, 0x0e, 0x04, 0xff, 0x57, 0x0f, 0x06, 0xff, 0x57, 0x10, 0x07, 0xff, 0x57, 0x10, 0x08, 0xff, 0x57, 0x10, 0x08, 0xff, 0x57, 0x0f, 0x07, 0xff, 0x58, 0x0c, 0x04, 0xff, 0x50, 0x05, 0x00, 0xff, 0xad, 0x28, 0x40, 0xff, 0xff, 0x4f, 0x85, 0xff, 0x64, 0x12, 0x1f, 0xff, 0x22, 0x00, 0x00, 0xff, 0x55, 0x07, 0x06, 0xff, 0xa3, 0x1c, 0x1f, 0xff, 0x53, 0x06, 0x01, 0xff, 0x46, 0x01, 0x00, 0xff, 0x34, 0x00, 0x00, 0xff, 0x99, 0x73, 0x72, 0xff, 0xae, 0x87, 0x7f, 0xff, 0x7e, 0x47, 0x3b, 0xff, 0xec, 0xe5, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xf9, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf9, 0xf4, 0xef, 0xff, 0xf9, 0xf1, 0xed, 0xff, 0xfb, 0xed, 0xe8, 0xff, 0xfd, 0xe9, 0xe5, 0xff, 0xfd, 0xe5, 0xe2, 0xff, 0xfd, 0xd8, 0xd9, 0xff, 0xfc, 0x5d, 0x71, 0xff, 0xfd, 0x48, 0x5c, 0xff, 0xfd, 0x4d, 0x62, 0xff, 0xfd, 0x4f, 0x64, 0xff, 0xfd, 0x51, 0x66, 0xff, 0xfd, 0x53, 0x67, 0xff, 0xfd, 0x54, 0x68, 0xff, 0xfd, 0x55, 0x68, 0xff, 0xfd, 0x55, 0x68, 0xff, 0xfd, 0x55, 0x68, 0xff, 0xfd, 0x56, 0x68, 0xff, 0xfd, 0x55, 0x69, 0xff, 0xfd, 0x55, 0x69, 0xff, 0xfd, 0x56, 0x68, 0xff, 0xfd, 0x57, 0x67, 0xff, 0xfd, 0x57, 0x68, 0xff, 0xfd, 0x58, 0x68, 0xff, 0xfd, 0x58, 0x68, 0xff, 0xfd, 0x59, 0x68, 0xff, 0xfd, 0x5a, 0x68, 0xff, 0xfd, 0x5b, 0x69, 0xff, 0xfd, 0x5b, 0x69, 0xff, 0xfd, 0x5b, 0x69, 0xff, 0xfd, 0x5c, 0x68, 0xff, 0xfd, 0x5d, 0x67, 0xff, 0xfd, 0x5e, 0x67, 0xff, 0xfd, 0x5e, 0x67, 0xff, 0xfd, 0x5e, 0x68, 0xff, 0xfd, 0x5e, 0x67, 0xff, 0xfd, 0x5e, 0x66, 0xff, 0xfc, 0x5e, 0x66, 0xff, 0xfd, 0x5d, 0x65, 0xff, 0xfd, 0x5d, 0x65, 0xff, 0xfd, 0x5e, 0x64, 0xff, 0xfd, 0x5d, 0x64, 0xff, 0xfd, 0x5d, 0x64, 0xff, 0xfd, 0x5d, 0x65, 0xff, 0xfd, 0x5e, 0x65, 0xff, 0xfc, 0x5f, 0x64, 0xff, 0xfc, 0x5f, 0x64, 0xff, 0xfd, 0x5e, 0x63, 0xff, 0xfd, 0x5d, 0x63, 0xff, 0xfd, 0x5d, 0x62, 0xff, 0xfd, 0x5d, 0x62, 0xff, 0xfd, 0x5c, 0x61, 0xff, 0xfd, 0x5c, 0x60, 0xff, 0xfd, 0x5c, 0x61, 0xff, 0xfd, 0x5b, 0x61, 0xff, 0xfd, 0x5b, 0x61, 0xff, 0xfd, 0x5b, 0x61, 0xff, 0xfd, 0x59, 0x61, 0xff, 0xfc, 0x53, 0x5a, 0xff, 0xfc, 0xcb, 0xc9, 0xff, 0xfd, 0xfe, 0xf8, 0xff, 0xfc, 0xf8, 0xf3, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa2, 0x7c, 0x77, 0xff, 0x4a, 0x00, 0x00, 0xff, 0x56, 0x0d, 0x03, 0xff, 0x57, 0x0f, 0x05, 0xff, 0x57, 0x11, 0x07, 0xff, 0x58, 0x12, 0x09, 0xff, 0x58, 0x13, 0x0a, 0xff, 0x58, 0x13, 0x09, 0xff, 0x56, 0x12, 0x09, 0xff, 0x56, 0x10, 0x07, 0xff, 0x50, 0x08, 0x04, 0xff, 0xbb, 0x61, 0x06, 0xff, 0x74, 0x27, 0x05, 0xff, 0x4f, 0x08, 0x03, 0xff, 0x56, 0x0d, 0x04, 0xff, 0x58, 0x0e, 0x05, 0xff, 0x56, 0x0f, 0x07, 0xff, 0x56, 0x10, 0x08, 0xff, 0x57, 0x10, 0x08, 0xff, 0x58, 0x10, 0x08, 0xff, 0x57, 0x0f, 0x07, 0xff, 0x58, 0x0b, 0x03, 0xff, 0x55, 0x06, 0x00, 0xff, 0xd9, 0x3b, 0x65, 0xff, 0xf1, 0x45, 0x78, 0xff, 0x3c, 0x04, 0x08, 0xff, 0x41, 0x02, 0x00, 0xff, 0x7f, 0x13, 0x13, 0xff, 0xca, 0x2c, 0x34, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x46, 0x09, 0x09, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x7e, 0x4b, 0x48, 0xff, 0xf6, 0xf0, 0xe9, 0xff, 0xfc, 0xfa, 0xf4, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xfe, 0xfc, 0xf6, 0xff, 0xfe, 0xfe, 0xf9, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xfa, 0xf0, 0xec, 0xff, 0xfa, 0xed, 0xe8, 0xff, 0xfc, 0xe9, 0xe5, 0xff, 0xfd, 0xe4, 0xe0, 0xff, 0xfd, 0xe5, 0xe3, 0xff, 0xfc, 0x91, 0xa1, 0xff, 0xfc, 0x3f, 0x5c, 0xff, 0xfd, 0x49, 0x63, 0xff, 0xfd, 0x4a, 0x66, 0xff, 0xfd, 0x4c, 0x68, 0xff, 0xfd, 0x4d, 0x69, 0xff, 0xfd, 0x4f, 0x6a, 0xff, 0xfd, 0x50, 0x6b, 0xff, 0xfd, 0x50, 0x6b, 0xff, 0xfd, 0x51, 0x6b, 0xff, 0xfd, 0x52, 0x6c, 0xff, 0xfd, 0x52, 0x6c, 0xff, 0xfd, 0x51, 0x6c, 0xff, 0xfd, 0x52, 0x6b, 0xff, 0xfd, 0x53, 0x6b, 0xff, 0xfe, 0x53, 0x6c, 0xff, 0xfd, 0x54, 0x6b, 0xff, 0xfd, 0x53, 0x6b, 0xff, 0xfd, 0x54, 0x6c, 0xff, 0xfd, 0x55, 0x6c, 0xff, 0xfd, 0x56, 0x6c, 0xff, 0xfd, 0x57, 0x6b, 0xff, 0xfd, 0x56, 0x6a, 0xff, 0xfd, 0x57, 0x69, 0xff, 0xfd, 0x58, 0x6a, 0xff, 0xfd, 0x5a, 0x6b, 0xff, 0xfd, 0x5a, 0x6a, 0xff, 0xfd, 0x59, 0x6a, 0xff, 0xfd, 0x5a, 0x6a, 0xff, 0xfc, 0x5c, 0x6a, 0xff, 0xfd, 0x5a, 0x69, 0xff, 0xfd, 0x59, 0x69, 0xff, 0xfd, 0x59, 0x68, 0xff, 0xfd, 0x5a, 0x68, 0xff, 0xfd, 0x5b, 0x67, 0xff, 0xfd, 0x5a, 0x68, 0xff, 0xfd, 0x59, 0x68, 0xff, 0xfd, 0x5a, 0x67, 0xff, 0xfd, 0x5c, 0x67, 0xff, 0xfd, 0x5c, 0x66, 0xff, 0xfd, 0x5b, 0x66, 0xff, 0xfd, 0x5c, 0x66, 0xff, 0xfd, 0x5b, 0x65, 0xff, 0xfd, 0x5a, 0x65, 0xff, 0xfd, 0x59, 0x64, 0xff, 0xfd, 0x57, 0x64, 0xff, 0xfd, 0x57, 0x64, 0xff, 0xfd, 0x58, 0x65, 0xff, 0xfd, 0x58, 0x64, 0xff, 0xfd, 0x57, 0x63, 0xff, 0xfd, 0x50, 0x5e, 0xff, 0xfb, 0x74, 0x80, 0xff, 0xfd, 0xf3, 0xf0, 0xff, 0xfc, 0xf8, 0xf3, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xa9, 0xa4, 0xff, 0x4a, 0x00, 0x00, 0xff, 0x55, 0x0c, 0x03, 0xff, 0x55, 0x0d, 0x04, 0xff, 0x57, 0x10, 0x06, 0xff, 0x58, 0x12, 0x09, 0xff, 0x58, 0x13, 0x0a, 0xff, 0x59, 0x13, 0x09, 0xff, 0x56, 0x12, 0x08, 0xff, 0x55, 0x10, 0x07, 0xff, 0x51, 0x08, 0x04, 0xff, 0xbb, 0x59, 0x09, 0xff, 0x75, 0x25, 0x07, 0xff, 0x4f, 0x08, 0x03, 0xff, 0x55, 0x0d, 0x04, 0xff, 0x56, 0x0e, 0x06, 0xff, 0x56, 0x10, 0x07, 0xff, 0x56, 0x10, 0x08, 0xff, 0x57, 0x10, 0x08, 0xff, 0x58, 0x10, 0x08, 0xff, 0x58, 0x0f, 0x06, 0xff, 0x55, 0x0a, 0x01, 0xff, 0x6b, 0x0f, 0x13, 0xff, 0xfc, 0x4b, 0x86, 0xff, 0xce, 0x36, 0x61, 0xff, 0x46, 0x01, 0x00, 0xff, 0x59, 0x07, 0x04, 0xff, 0x67, 0x0f, 0x10, 0xff, 0xc6, 0x2c, 0x35, 0xff, 0x39, 0x00, 0x00, 0xff, 0x8c, 0x60, 0x5f, 0xff, 0x52, 0x19, 0x19, 0xff, 0x64, 0x28, 0x27, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfe, 0xfd, 0xf7, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf6, 0xf3, 0xee, 0xff, 0xf8, 0xf0, 0xec, 0xff, 0xf9, 0xed, 0xe9, 0xff, 0xfc, 0xe9, 0xe5, 0xff, 0xfd, 0xe5, 0xe1, 0xff, 0xfd, 0xe2, 0xde, 0xff, 0xfc, 0xd0, 0xd3, 0xff, 0xfc, 0x54, 0x74, 0xff, 0xfd, 0x40, 0x63, 0xff, 0xfd, 0x48, 0x6a, 0xff, 0xfd, 0x4a, 0x6b, 0xff, 0xfd, 0x4b, 0x6b, 0xff, 0xfd, 0x4c, 0x6c, 0xff, 0xfd, 0x4e, 0x6d, 0xff, 0xfd, 0x4e, 0x6d, 0xff, 0xfd, 0x4e, 0x6e, 0xff, 0xfd, 0x4f, 0x6e, 0xff, 0xfd, 0x50, 0x6f, 0xff, 0xfd, 0x50, 0x6f, 0xff, 0xfd, 0x50, 0x6e, 0xff, 0xfd, 0x51, 0x6d, 0xff, 0xfd, 0x51, 0x6d, 0xff, 0xfd, 0x50, 0x6e, 0xff, 0xfd, 0x51, 0x6e, 0xff, 0xfd, 0x51, 0x6e, 0xff, 0xfd, 0x51, 0x6e, 0xff, 0xfd, 0x52, 0x6e, 0xff, 0xfd, 0x52, 0x6d, 0xff, 0xfd, 0x52, 0x6c, 0xff, 0xfd, 0x53, 0x6c, 0xff, 0xfd, 0x53, 0x6d, 0xff, 0xfd, 0x54, 0x6d, 0xff, 0xfd, 0x54, 0x6d, 0xff, 0xfd, 0x54, 0x6d, 0xff, 0xfd, 0x55, 0x6e, 0xff, 0xfd, 0x57, 0x6d, 0xff, 0xfd, 0x56, 0x6d, 0xff, 0xfd, 0x55, 0x6c, 0xff, 0xfd, 0x55, 0x6d, 0xff, 0xfd, 0x56, 0x6b, 0xff, 0xfd, 0x56, 0x6b, 0xff, 0xfd, 0x57, 0x6b, 0xff, 0xfd, 0x56, 0x69, 0xff, 0xfd, 0x55, 0x69, 0xff, 0xfd, 0x57, 0x69, 0xff, 0xfd, 0x58, 0x69, 0xff, 0xfd, 0x57, 0x69, 0xff, 0xfd, 0x57, 0x68, 0xff, 0xfd, 0x57, 0x68, 0xff, 0xfd, 0x56, 0x68, 0xff, 0xfd, 0x54, 0x68, 0xff, 0xfd, 0x54, 0x68, 0xff, 0xfd, 0x54, 0x67, 0xff, 0xfd, 0x54, 0x66, 0xff, 0xfd, 0x54, 0x65, 0xff, 0xfd, 0x51, 0x63, 0xff, 0xfc, 0x4a, 0x5f, 0xff, 0xfb, 0xc1, 0xc6, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfb, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xe8, 0xdf, 0xdb, 0xff, 0x58, 0x15, 0x10, 0xff, 0x52, 0x07, 0x00, 0xff, 0x54, 0x0c, 0x03, 0xff, 0x56, 0x0e, 0x06, 0xff, 0x56, 0x11, 0x08, 0xff, 0x57, 0x12, 0x09, 0xff, 0x57, 0x12, 0x09, 0xff, 0x56, 0x11, 0x08, 0xff, 0x55, 0x10, 0x07, 0xff, 0x50, 0x09, 0x04, 0xff, 0xbc, 0x55, 0x0d, 0xff, 0x75, 0x23, 0x09, 0xff, 0x4f, 0x08, 0x03, 0xff, 0x54, 0x0c, 0x04, 0xff, 0x55, 0x0e, 0x06, 0xff, 0x57, 0x10, 0x07, 0xff, 0x58, 0x10, 0x07, 0xff, 0x59, 0x10, 0x08, 0xff, 0x59, 0x10, 0x07, 0xff, 0x5a, 0x0d, 0x05, 0xff, 0x4f, 0x07, 0x00, 0xff, 0x97, 0x22, 0x3a, 0xff, 0xff, 0x55, 0x9a, 0xff, 0xa0, 0x27, 0x45, 0xff, 0x37, 0x00, 0x00, 0xff, 0x31, 0x00, 0x00, 0xff, 0x56, 0x0b, 0x0d, 0xff, 0xcb, 0x2f, 0x3a, 0xff, 0x38, 0x00, 0x00, 0xff, 0x9f, 0x79, 0x76, 0xff, 0x67, 0x34, 0x34, 0xff, 0x4d, 0x0c, 0x0b, 0xff, 0xee, 0xe5, 0xe1, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfe, 0xfd, 0xf6, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf7, 0xf3, 0xee, 0xff, 0xf8, 0xf0, 0xec, 0xff, 0xf9, 0xed, 0xe9, 0xff, 0xfb, 0xe9, 0xe6, 0xff, 0xfd, 0xe5, 0xe2, 0xff, 0xfd, 0xe0, 0xde, 0xff, 0xfd, 0xe2, 0xe0, 0xff, 0xfc, 0xaa, 0xb8, 0xff, 0xfc, 0x3f, 0x69, 0xff, 0xfd, 0x42, 0x6c, 0xff, 0xfd, 0x46, 0x6e, 0xff, 0xfd, 0x47, 0x6f, 0xff, 0xfd, 0x47, 0x70, 0xff, 0xfd, 0x49, 0x71, 0xff, 0xfd, 0x49, 0x70, 0xff, 0xfd, 0x49, 0x71, 0xff, 0xfd, 0x4b, 0x71, 0xff, 0xfd, 0x4c, 0x73, 0xff, 0xfd, 0x4d, 0x72, 0xff, 0xfd, 0x4d, 0x71, 0xff, 0xfd, 0x4e, 0x70, 0xff, 0xfd, 0x4e, 0x70, 0xff, 0xfd, 0x4e, 0x71, 0xff, 0xfd, 0x4e, 0x72, 0xff, 0xfd, 0x4e, 0x73, 0xff, 0xfd, 0x4f, 0x71, 0xff, 0xfd, 0x4f, 0x6f, 0xff, 0xfd, 0x4e, 0x6e, 0xff, 0xfc, 0x4e, 0x6d, 0xff, 0xfd, 0x4f, 0x6e, 0xff, 0xfd, 0x51, 0x6e, 0xff, 0xfd, 0x50, 0x6f, 0xff, 0xfd, 0x50, 0x6f, 0xff, 0xfd, 0x50, 0x6f, 0xff, 0xfd, 0x51, 0x70, 0xff, 0xfd, 0x52, 0x71, 0xff, 0xfd, 0x53, 0x71, 0xff, 0xfd, 0x52, 0x70, 0xff, 0xfd, 0x51, 0x6f, 0xff, 0xfd, 0x51, 0x6e, 0xff, 0xfd, 0x52, 0x6e, 0xff, 0xfd, 0x53, 0x6f, 0xff, 0xfd, 0x53, 0x6d, 0xff, 0xfd, 0x53, 0x6c, 0xff, 0xfd, 0x53, 0x6b, 0xff, 0xfd, 0x53, 0x6a, 0xff, 0xfd, 0x53, 0x6a, 0xff, 0xfd, 0x53, 0x6a, 0xff, 0xfd, 0x53, 0x6a, 0xff, 0xfd, 0x52, 0x6b, 0xff, 0xfd, 0x50, 0x6a, 0xff, 0xfd, 0x4f, 0x6a, 0xff, 0xfd, 0x4f, 0x69, 0xff, 0xfd, 0x4f, 0x67, 0xff, 0xfd, 0x4f, 0x65, 0xff, 0xfd, 0x44, 0x5e, 0xff, 0xfb, 0x8d, 0x9b, 0xff, 0xfc, 0xf7, 0xf2, 0xff, 0xfb, 0xf5, 0xf1, 0xff, 0xfa, 0xf6, 0xf1, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xfc, 0xff, 0x7e, 0x4c, 0x49, 0xff, 0x4c, 0x00, 0x00, 0xff, 0x54, 0x0b, 0x03, 0xff, 0x54, 0x0e, 0x05, 0xff, 0x56, 0x10, 0x07, 0xff, 0x57, 0x11, 0x09, 0xff, 0x56, 0x11, 0x09, 0xff, 0x55, 0x11, 0x08, 0xff, 0x56, 0x0f, 0x07, 0xff, 0x50, 0x09, 0x04, 0xff, 0xbc, 0x4f, 0x0f, 0xff, 0x75, 0x20, 0x09, 0xff, 0x4f, 0x09, 0x03, 0xff, 0x54, 0x0c, 0x04, 0xff, 0x56, 0x0d, 0x05, 0xff, 0x57, 0x0e, 0x05, 0xff, 0x57, 0x0f, 0x06, 0xff, 0x58, 0x0f, 0x06, 0xff, 0x58, 0x0d, 0x03, 0xff, 0x50, 0x07, 0x00, 0xff, 0x61, 0x0b, 0x0c, 0xff, 0xe4, 0x43, 0x7d, 0xff, 0xff, 0x51, 0x98, 0xff, 0x5a, 0x10, 0x1d, 0xff, 0x2c, 0x00, 0x00, 0xff, 0x2a, 0x00, 0x00, 0xff, 0x71, 0x13, 0x19, 0xff, 0xc8, 0x30, 0x3c, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xa5, 0x84, 0x81, 0xff, 0x81, 0x55, 0x54, 0xff, 0x3c, 0x00, 0x00, 0xff, 0xd8, 0xc8, 0xc5, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfe, 0xfc, 0xf6, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf8, 0xf1, 0xed, 0xff, 0xf8, 0xee, 0xea, 0xff, 0xfa, 0xea, 0xe7, 0xff, 0xfc, 0xe5, 0xe3, 0xff, 0xfd, 0xe1, 0xde, 0xff, 0xfd, 0xdc, 0xdb, 0xff, 0xfd, 0xde, 0xdd, 0xff, 0xfb, 0x91, 0xa9, 0xff, 0xfc, 0x3a, 0x6d, 0xff, 0xfd, 0x3d, 0x6f, 0xff, 0xfd, 0x42, 0x72, 0xff, 0xfd, 0x43, 0x72, 0xff, 0xfd, 0x44, 0x73, 0xff, 0xfd, 0x43, 0x73, 0xff, 0xfd, 0x45, 0x72, 0xff, 0xfd, 0x47, 0x74, 0xff, 0xfd, 0x48, 0x76, 0xff, 0xfd, 0x49, 0x76, 0xff, 0xfd, 0x49, 0x75, 0xff, 0xfd, 0x49, 0x74, 0xff, 0xfd, 0x49, 0x74, 0xff, 0xfd, 0x49, 0x75, 0xff, 0xfd, 0x49, 0x75, 0xff, 0xfd, 0x4b, 0x74, 0xff, 0xfd, 0x4b, 0x74, 0xff, 0xfd, 0x4b, 0x72, 0xff, 0xfd, 0x4a, 0x72, 0xff, 0xfd, 0x4a, 0x71, 0xff, 0xfd, 0x4b, 0x71, 0xff, 0xfd, 0x4d, 0x70, 0xff, 0xfd, 0x4e, 0x71, 0xff, 0xfd, 0x4e, 0x70, 0xff, 0xfd, 0x4d, 0x71, 0xff, 0xfd, 0x4d, 0x72, 0xff, 0xfd, 0x4e, 0x74, 0xff, 0xfd, 0x4e, 0x73, 0xff, 0xfe, 0x50, 0x72, 0xff, 0xfd, 0x51, 0x72, 0xff, 0xfd, 0x51, 0x70, 0xff, 0xfd, 0x50, 0x71, 0xff, 0xfe, 0x51, 0x71, 0xff, 0xfd, 0x51, 0x70, 0xff, 0xfd, 0x51, 0x6e, 0xff, 0xfd, 0x50, 0x6d, 0xff, 0xfd, 0x4f, 0x6c, 0xff, 0xfd, 0x4f, 0x6c, 0xff, 0xfd, 0x4f, 0x6c, 0xff, 0xfd, 0x4f, 0x6c, 0xff, 0xfd, 0x4d, 0x6b, 0xff, 0xfd, 0x4c, 0x6a, 0xff, 0xfd, 0x4a, 0x6a, 0xff, 0xfd, 0x4a, 0x69, 0xff, 0xfd, 0x47, 0x68, 0xff, 0xfd, 0x3e, 0x61, 0xff, 0xfb, 0x7e, 0x92, 0xff, 0xfc, 0xee, 0xea, 0xff, 0xfc, 0xf5, 0xf0, 0xff, 0xfa, 0xf5, 0xf0, 0xff, 0xfa, 0xf6, 0xf1, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfb, 0xf8, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x9a, 0x97, 0xff, 0x49, 0x00, 0x00, 0xff, 0x54, 0x0b, 0x02, 0xff, 0x55, 0x0d, 0x04, 0xff, 0x54, 0x0f, 0x07, 0xff, 0x55, 0x11, 0x08, 0xff, 0x55, 0x11, 0x08, 0xff, 0x54, 0x10, 0x07, 0xff, 0x55, 0x0e, 0x06, 0xff, 0x50, 0x09, 0x03, 0xff, 0xbc, 0x49, 0x13, 0xff, 0x76, 0x1e, 0x09, 0xff, 0x50, 0x08, 0x02, 0xff, 0x56, 0x0b, 0x03, 0xff, 0x56, 0x0c, 0x04, 0xff, 0x56, 0x0c, 0x04, 0xff, 0x54, 0x0b, 0x01, 0xff, 0x4e, 0x08, 0x00, 0xff, 0x55, 0x08, 0x02, 0xff, 0x89, 0x1b, 0x2e, 0xff, 0xe3, 0x41, 0x7d, 0xff, 0xff, 0x55, 0xa4, 0xff, 0xaa, 0x2f, 0x5a, 0xff, 0x2f, 0x00, 0x00, 0xff, 0x32, 0x00, 0x00, 0xff, 0x66, 0x0f, 0x18, 0xff, 0xd9, 0x35, 0x4d, 0xff, 0x62, 0x0f, 0x14, 0xff, 0x38, 0x00, 0x00, 0xff, 0xb5, 0x8d, 0x89, 0xff, 0x9f, 0x7c, 0x7b, 0xff, 0x31, 0x00, 0x00, 0xff, 0xb9, 0xa1, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfe, 0xfc, 0xf6, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf8, 0xf2, 0xed, 0xff, 0xf8, 0xef, 0xeb, 0xff, 0xf8, 0xeb, 0xe8, 0xff, 0xfb, 0xe6, 0xe4, 0xff, 0xfd, 0xe1, 0xde, 0xff, 0xfd, 0xdc, 0xdb, 0xff, 0xfd, 0xd9, 0xd9, 0xff, 0xfc, 0xda, 0xda, 0xff, 0xfb, 0x96, 0xaf, 0xff, 0xfc, 0x3f, 0x75, 0xff, 0xfd, 0x35, 0x6f, 0xff, 0xfd, 0x3d, 0x73, 0xff, 0xfc, 0x40, 0x74, 0xff, 0xfd, 0x40, 0x74, 0xff, 0xfd, 0x41, 0x74, 0xff, 0xfd, 0x43, 0x75, 0xff, 0xfd, 0x45, 0x76, 0xff, 0xfd, 0x45, 0x76, 0xff, 0xfd, 0x44, 0x76, 0xff, 0xfd, 0x45, 0x76, 0xff, 0xfd, 0x45, 0x76, 0xff, 0xfd, 0x45, 0x77, 0xff, 0xfd, 0x45, 0x76, 0xff, 0xfd, 0x46, 0x75, 0xff, 0xfd, 0x47, 0x75, 0xff, 0xfd, 0x46, 0x74, 0xff, 0xfd, 0x45, 0x73, 0xff, 0xfd, 0x45, 0x73, 0xff, 0xfd, 0x46, 0x73, 0xff, 0xfd, 0x46, 0x72, 0xff, 0xfd, 0x48, 0x72, 0xff, 0xfd, 0x49, 0x71, 0xff, 0xfd, 0x47, 0x72, 0xff, 0xfd, 0x47, 0x73, 0xff, 0xfd, 0x48, 0x74, 0xff, 0xfd, 0x49, 0x74, 0xff, 0xfd, 0x4b, 0x74, 0xff, 0xfd, 0x4d, 0x73, 0xff, 0xfd, 0x4d, 0x72, 0xff, 0xfd, 0x4d, 0x72, 0xff, 0xfd, 0x4e, 0x72, 0xff, 0xfd, 0x4e, 0x72, 0xff, 0xfd, 0x4d, 0x71, 0xff, 0xfd, 0x4e, 0x70, 0xff, 0xfd, 0x4d, 0x6f, 0xff, 0xfd, 0x4c, 0x6f, 0xff, 0xfd, 0x4b, 0x6f, 0xff, 0xfd, 0x4a, 0x6e, 0xff, 0xfd, 0x49, 0x6c, 0xff, 0xfd, 0x48, 0x6b, 0xff, 0xfd, 0x46, 0x6b, 0xff, 0xfd, 0x3f, 0x67, 0xff, 0xfc, 0x43, 0x6a, 0xff, 0xfb, 0x8e, 0xa1, 0xff, 0xfc, 0xeb, 0xe8, 0xff, 0xfc, 0xf5, 0xef, 0xff, 0xfb, 0xf4, 0xee, 0xff, 0xfa, 0xf6, 0xf0, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfc, 0xf8, 0xf4, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xea, 0xe1, 0xdd, 0xff, 0x59, 0x15, 0x0f, 0xff, 0x52, 0x07, 0x00, 0xff, 0x55, 0x0c, 0x03, 0xff, 0x56, 0x0e, 0x05, 0xff, 0x54, 0x10, 0x07, 0xff, 0x53, 0x10, 0x07, 0xff, 0x53, 0x0f, 0x07, 0xff, 0x55, 0x0d, 0x05, 0xff, 0x50, 0x08, 0x03, 0xff, 0xba, 0x41, 0x15, 0xff, 0x75, 0x1b, 0x0a, 0xff, 0x50, 0x08, 0x01, 0xff, 0x55, 0x0a, 0x02, 0xff, 0x51, 0x09, 0x00, 0xff, 0x4b, 0x06, 0x00, 0xff, 0x5a, 0x0a, 0x06, 0xff, 0x93, 0x1d, 0x33, 0xff, 0xdf, 0x3c, 0x72, 0xff, 0xff, 0x50, 0x9a, 0xff, 0xf5, 0x48, 0x8d, 0xff, 0x97, 0x26, 0x4e, 0xff, 0x44, 0x06, 0x0d, 0xff, 0x34, 0x00, 0x00, 0xff, 0x33, 0x00, 0x00, 0xff, 0x8b, 0x1e, 0x2e, 0xff, 0x66, 0x0f, 0x1c, 0xff, 0x42, 0x03, 0x00, 0xff, 0x4d, 0x00, 0x00, 0xff, 0xa9, 0x89, 0x87, 0xff, 0xc0, 0xa7, 0xa3, 0xff, 0x2f, 0x00, 0x00, 0xff, 0x96, 0x72, 0x71, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfd, 0xfc, 0xf7, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xf7, 0xf2, 0xed, 0xff, 0xf7, 0xf0, 0xec, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf9, 0xe7, 0xe5, 0xff, 0xfb, 0xe2, 0xdf, 0xff, 0xfd, 0xdc, 0xdb, 0xff, 0xfd, 0xd7, 0xd8, 0xff, 0xfc, 0xd5, 0xd5, 0xff, 0xfd, 0xd7, 0xd7, 0xff, 0xfc, 0xaf, 0xbf, 0xff, 0xfc, 0x5e, 0x8e, 0xff, 0xfd, 0x35, 0x74, 0xff, 0xfd, 0x32, 0x71, 0xff, 0xfd, 0x37, 0x74, 0xff, 0xfd, 0x39, 0x76, 0xff, 0xfd, 0x3b, 0x77, 0xff, 0xfd, 0x3d, 0x77, 0xff, 0xfd, 0x3d, 0x78, 0xff, 0xfd, 0x3c, 0x78, 0xff, 0xfd, 0x3d, 0x77, 0xff, 0xfd, 0x3e, 0x76, 0xff, 0xfd, 0x3d, 0x77, 0xff, 0xfd, 0x3e, 0x77, 0xff, 0xfd, 0x3f, 0x76, 0xff, 0xfd, 0x41, 0x75, 0xff, 0xfd, 0x40, 0x74, 0xff, 0xfd, 0x40, 0x73, 0xff, 0xfd, 0x40, 0x74, 0xff, 0xfd, 0x40, 0x74, 0xff, 0xfd, 0x40, 0x72, 0xff, 0xfd, 0x40, 0x73, 0xff, 0xfd, 0x41, 0x73, 0xff, 0xfd, 0x41, 0x72, 0xff, 0xfd, 0x42, 0x72, 0xff, 0xfd, 0x42, 0x73, 0xff, 0xfd, 0x43, 0x75, 0xff, 0xfd, 0x45, 0x75, 0xff, 0xfd, 0x46, 0x75, 0xff, 0xfd, 0x46, 0x74, 0xff, 0xfd, 0x47, 0x74, 0xff, 0xfd, 0x47, 0x73, 0xff, 0xfd, 0x48, 0x73, 0xff, 0xfd, 0x49, 0x72, 0xff, 0xfd, 0x49, 0x72, 0xff, 0xfd, 0x49, 0x73, 0xff, 0xfd, 0x49, 0x72, 0xff, 0xfd, 0x48, 0x72, 0xff, 0xfd, 0x46, 0x71, 0xff, 0xfd, 0x42, 0x6e, 0xff, 0xfc, 0x39, 0x68, 0xff, 0xfc, 0x41, 0x6d, 0xff, 0xfc, 0x6d, 0x8c, 0xff, 0xfc, 0xbd, 0xc5, 0xff, 0xfd, 0xf1, 0xea, 0xff, 0xfd, 0xf2, 0xeb, 0xff, 0xfc, 0xf2, 0xed, 0xff, 0xfa, 0xf4, 0xef, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x4e, 0x4a, 0xff, 0x4b, 0x00, 0x00, 0xff, 0x55, 0x0c, 0x03, 0xff, 0x55, 0x0d, 0x04, 0xff, 0x54, 0x0f, 0x06, 0xff, 0x53, 0x0f, 0x07, 0xff, 0x54, 0x0e, 0x07, 0xff, 0x54, 0x0d, 0x05, 0xff, 0x50, 0x08, 0x02, 0xff, 0xb8, 0x36, 0x15, 0xff, 0x72, 0x17, 0x09, 0xff, 0x4b, 0x05, 0x00, 0xff, 0x4a, 0x05, 0x00, 0xff, 0x5e, 0x0b, 0x0a, 0xff, 0xa1, 0x21, 0x3d, 0xff, 0xec, 0x3e, 0x79, 0xff, 0xff, 0x4b, 0x95, 0xff, 0xe3, 0x40, 0x7d, 0xff, 0x8f, 0x22, 0x42, 0xff, 0x3d, 0x06, 0x0d, 0xff, 0x36, 0x02, 0x07, 0xff, 0xb4, 0x1f, 0x4a, 0xff, 0x38, 0x00, 0x00, 0xff, 0x36, 0x00, 0x00, 0xff, 0x37, 0x00, 0x00, 0xff, 0x7c, 0x29, 0x01, 0xff, 0x75, 0x23, 0x04, 0xff, 0x33, 0x00, 0x00, 0xff, 0xab, 0x88, 0x85, 0xff, 0xdd, 0xcf, 0xca, 0xff, 0x37, 0x00, 0x00, 0xff, 0x78, 0x48, 0x47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xf8, 0xff, 0xfd, 0xfc, 0xf7, 0xff, 0xfe, 0xfd, 0xf8, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf1, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf7, 0xf0, 0xec, 0xff, 0xf8, 0xed, 0xea, 0xff, 0xf8, 0xe9, 0xe6, 0xff, 0xf9, 0xe4, 0xe2, 0xff, 0xfb, 0xde, 0xdd, 0xff, 0xfc, 0xd9, 0xd9, 0xff, 0xfc, 0xd5, 0xd5, 0xff, 0xfd, 0xd2, 0xd3, 0xff, 0xfc, 0xd4, 0xd4, 0xff, 0xfd, 0xce, 0xd2, 0xff, 0xfd, 0xa4, 0xba, 0xff, 0xfc, 0x6e, 0x9a, 0xff, 0xfc, 0x4b, 0x85, 0xff, 0xfc, 0x3b, 0x7c, 0xff, 0xfd, 0x35, 0x78, 0xff, 0xfd, 0x32, 0x77, 0xff, 0xfd, 0x32, 0x78, 0xff, 0xfc, 0x35, 0x78, 0xff, 0xfc, 0x36, 0x77, 0xff, 0xfd, 0x35, 0x76, 0xff, 0xfd, 0x34, 0x75, 0xff, 0xfd, 0x34, 0x75, 0xff, 0xfd, 0x36, 0x76, 0xff, 0xfc, 0x37, 0x74, 0xff, 0xfd, 0x37, 0x72, 0xff, 0xfd, 0x37, 0x73, 0xff, 0xfc, 0x39, 0x75, 0xff, 0xfc, 0x38, 0x73, 0xff, 0xfd, 0x37, 0x72, 0xff, 0xfd, 0x36, 0x73, 0xff, 0xfd, 0x37, 0x71, 0xff, 0xfc, 0x38, 0x71, 0xff, 0xfc, 0x38, 0x71, 0xff, 0xfd, 0x39, 0x73, 0xff, 0xfd, 0x3a, 0x75, 0xff, 0xfd, 0x3c, 0x76, 0xff, 0xfd, 0x3e, 0x75, 0xff, 0xfc, 0x3d, 0x74, 0xff, 0xfd, 0x3a, 0x72, 0xff, 0xfd, 0x3f, 0x73, 0xff, 0xfd, 0x43, 0x72, 0xff, 0xfd, 0x44, 0x72, 0xff, 0xfd, 0x44, 0x73, 0xff, 0xfd, 0x45, 0x74, 0xff, 0xfd, 0x46, 0x73, 0xff, 0xfd, 0x45, 0x73, 0xff, 0xfd, 0x42, 0x70, 0xff, 0xfc, 0x43, 0x72, 0xff, 0xfc, 0x8a, 0xa2, 0xff, 0xfc, 0xc2, 0xc7, 0xff, 0xfd, 0xe6, 0xe1, 0xff, 0xfd, 0xee, 0xe7, 0xff, 0xfd, 0xed, 0xe7, 0xff, 0xfc, 0xf1, 0xea, 0xff, 0xfb, 0xf3, 0xed, 0xff, 0xf9, 0xf4, 0xef, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf4, 0xf0, 0xff, 0xf5, 0xf4, 0xf0, 0xff, 0xf5, 0xf5, 0xf0, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x96, 0x92, 0xff, 0x49, 0x00, 0x00, 0xff, 0x55, 0x0a, 0x02, 0xff, 0x55, 0x0c, 0x03, 0xff, 0x54, 0x0d, 0x05, 0xff, 0x54, 0x0e, 0x06, 0xff, 0x54, 0x0d, 0x06, 0xff, 0x54, 0x0b, 0x04, 0xff, 0x4e, 0x06, 0x01, 0xff, 0xb4, 0x30, 0x13, 0xff, 0x68, 0x13, 0x06, 0xff, 0x62, 0x0a, 0x0d, 0xff, 0xad, 0x22, 0x3f, 0xff, 0xf6, 0x3e, 0x77, 0xff, 0xff, 0x45, 0x88, 0xff, 0xcb, 0x33, 0x66, 0xff, 0x72, 0x16, 0x2d, 0xff, 0x33, 0x02, 0x04, 0xff, 0x22, 0x00, 0x00, 0xff, 0x24, 0x00, 0x00, 0xff, 0x46, 0x06, 0x0f, 0xff, 0xbd, 0x1e, 0x4f, 0xff, 0x3c, 0x03, 0x01, 0xff, 0x50, 0x08, 0x02, 0xff, 0x57, 0x03, 0x02, 0xff, 0xcd, 0x82, 0x03, 0xff, 0x85, 0x48, 0x01, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xa6, 0x84, 0x81, 0xff, 0xf4, 0xef, 0xea, 0xff, 0x46, 0x0b, 0x0b, 0xff, 0x5b, 0x1f, 0x1f, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xfe, 0xfe, 0xf8, 0xff, 0xfe, 0xff, 0xf8, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf3, 0xef, 0xff, 0xf7, 0xf1, 0xed, 0xff, 0xf7, 0xef, 0xec, 0xff, 0xf7, 0xeb, 0xe8, 0xff, 0xf9, 0xe7, 0xe4, 0xff, 0xfa, 0xe1, 0xdf, 0xff, 0xfb, 0xdc, 0xdb, 0xff, 0xfc, 0xd8, 0xd8, 0xff, 0xfd, 0xd6, 0xd6, 0xff, 0xfc, 0xd3, 0xd4, 0xff, 0xfd, 0xd1, 0xd3, 0xff, 0xfd, 0xd4, 0xd4, 0xff, 0xfd, 0xd3, 0xd3, 0xff, 0xfc, 0xc7, 0xcd, 0xff, 0xfc, 0xb6, 0xc3, 0xff, 0xfd, 0xa9, 0xbb, 0xff, 0xfc, 0xa3, 0xb7, 0xff, 0xfc, 0xa3, 0xb8, 0xff, 0xfc, 0xa5, 0xb9, 0xff, 0xfc, 0xa5, 0xb8, 0xff, 0xfc, 0xa7, 0xb9, 0xff, 0xfc, 0xa8, 0xbb, 0xff, 0xfd, 0xa8, 0xbb, 0xff, 0xfd, 0xa9, 0xbc, 0xff, 0xfc, 0xa9, 0xbc, 0xff, 0xfc, 0xa9, 0xba, 0xff, 0xfc, 0xaa, 0xbb, 0xff, 0xfc, 0xab, 0xbb, 0xff, 0xfd, 0xaa, 0xbb, 0xff, 0xfd, 0xa8, 0xb9, 0xff, 0xfd, 0xa7, 0xb8, 0xff, 0xfd, 0xa7, 0xb8, 0xff, 0xfd, 0xa8, 0xb9, 0xff, 0xfc, 0xa8, 0xb9, 0xff, 0xfc, 0xa8, 0xb9, 0xff, 0xfc, 0xa9, 0xba, 0xff, 0xfc, 0xaa, 0xba, 0xff, 0xfc, 0xad, 0xbb, 0xff, 0xfc, 0xb2, 0xbe, 0xff, 0xfc, 0x84, 0xa4, 0xff, 0xfc, 0x38, 0x72, 0xff, 0xfd, 0x39, 0x6e, 0xff, 0xfd, 0x3f, 0x72, 0xff, 0xfd, 0x40, 0x73, 0xff, 0xfd, 0x42, 0x74, 0xff, 0xfd, 0x42, 0x73, 0xff, 0xfd, 0x41, 0x73, 0xff, 0xfd, 0x3e, 0x71, 0xff, 0xfc, 0x44, 0x74, 0xff, 0xfc, 0xd6, 0xd5, 0xff, 0xfd, 0xed, 0xe5, 0xff, 0xfd, 0xe8, 0xe3, 0xff, 0xfd, 0xeb, 0xe5, 0xff, 0xfc, 0xef, 0xe9, 0xff, 0xfa, 0xf2, 0xec, 0xff, 0xf8, 0xf4, 0xee, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf5, 0xf4, 0xef, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xdf, 0xd2, 0xce, 0xff, 0x4f, 0x0a, 0x05, 0xff, 0x51, 0x06, 0x00, 0xff, 0x53, 0x0a, 0x02, 0xff, 0x54, 0x0b, 0x03, 0xff, 0x53, 0x0b, 0x03, 0xff, 0x51, 0x0a, 0x02, 0xff, 0x4b, 0x06, 0x00, 0xff, 0x49, 0x02, 0x00, 0xff, 0xba, 0x28, 0x25, 0xff, 0xd3, 0x2b, 0x4a, 0xff, 0xf4, 0x2d, 0x65, 0xff, 0xf3, 0x30, 0x69, 0xff, 0xad, 0x26, 0x4b, 0xff, 0x56, 0x0d, 0x1a, 0xff, 0x2a, 0x00, 0x00, 0xff, 0x25, 0x00, 0x00, 0xff, 0x2e, 0x00, 0x00, 0xff, 0x2f, 0x00, 0x00, 0xff, 0x28, 0x00, 0x00, 0xff, 0x48, 0x06, 0x10, 0xff, 0xc7, 0x21, 0x50, 0xff, 0x60, 0x0d, 0x06, 0xff, 0x50, 0x08, 0x02, 0xff, 0x3e, 0x00, 0x00, 0xff, 0xbe, 0x83, 0x02, 0xff, 0x85, 0x4a, 0x01, 0xff, 0x2e, 0x00, 0x00, 0xff, 0xa2, 0x80, 0x7c, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x2d, 0x2c, 0xff, 0x43, 0x00, 0x00, 0xff, 0xe3, 0xd5, 0xd0, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xfe, 0xfd, 0xf7, 0xff, 0xfe, 0xff, 0xf8, 0xff,
0xfe, 0xfb, 0xf6, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf8, 0xf0, 0xec, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf8, 0xe9, 0xe5, 0xff, 0xf9, 0xe4, 0xe2, 0xff, 0xfa, 0xe0, 0xde, 0xff, 0xfb, 0xdc, 0xdc, 0xff, 0xfc, 0xd9, 0xd9, 0xff, 0xfd, 0xd7, 0xd7, 0xff, 0xfc, 0xd3, 0xd5, 0xff, 0xfc, 0xd1, 0xd3, 0xff, 0xfd, 0xd0, 0xd2, 0xff, 0xfd, 0xcf, 0xd1, 0xff, 0xfd, 0xd0, 0xd1, 0xff, 0xfd, 0xd2, 0xd0, 0xff, 0xfd, 0xd3, 0xd0, 0xff, 0xfd, 0xd3, 0xd0, 0xff, 0xfe, 0xd4, 0xd1, 0xff, 0xfe, 0xd4, 0xd2, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd3, 0xd3, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd4, 0xd2, 0xff, 0xfd, 0xd4, 0xd3, 0xff, 0xfd, 0xd5, 0xd3, 0xff, 0xfd, 0xd5, 0xd3, 0xff, 0xfd, 0xd5, 0xd3, 0xff, 0xfd, 0xd5, 0xd2, 0xff, 0xfd, 0xd5, 0xd2, 0xff, 0xfd, 0xd6, 0xd3, 0xff, 0xfe, 0xd8, 0xd5, 0xff, 0xfd, 0xdb, 0xd7, 0xff, 0xfc, 0xa4, 0xb6, 0xff, 0xfc, 0x44, 0x78, 0xff, 0xfd, 0x33, 0x6b, 0xff, 0xfd, 0x3b, 0x74, 0xff, 0xfd, 0x3c, 0x76, 0xff, 0xfd, 0x3c, 0x75, 0xff, 0xfd, 0x3d, 0x73, 0xff, 0xfd, 0x3c, 0x71, 0xff, 0xfd, 0x33, 0x6a, 0xff, 0xfc, 0xb3, 0xc0, 0xff, 0xfd, 0xef, 0xe8, 0xff, 0xfd, 0xea, 0xe5, 0xff, 0xfc, 0xed, 0xe8, 0xff, 0xfa, 0xf0, 0xeb, 0xff, 0xf8, 0xf2, 0xed, 0xff, 0xf8, 0xf3, 0xef, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf4, 0xf4, 0xef, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xff, 0xfe, 0xf9, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0x65, 0x27, 0x25, 0xff, 0x41, 0x00, 0x00, 0xff, 0x4b, 0x07, 0x00, 0xff, 0x4b, 0x06, 0x00, 0xff, 0x48, 0x05, 0x00, 0xff, 0x54, 0x08, 0x03, 0xff, 0x88, 0x12, 0x1f, 0xff, 0xcc, 0x1f, 0x46, 0xff, 0xf4, 0x26, 0x5e, 0xff, 0xec, 0x35, 0x67, 0xff, 0xd0, 0x5f, 0x79, 0xff, 0xd2, 0xab, 0xae, 0xff, 0x51, 0x3c, 0x39, 0xff, 0x19, 0x00, 0x00, 0xff, 0x2d, 0x00, 0x00, 0xff, 0x30, 0x01, 0x00, 0xff, 0x31, 0x01, 0x00, 0xff, 0x2c, 0x00, 0x00, 0xff, 0x3d, 0x03, 0x01, 0xff, 0x77, 0x10, 0x1d, 0xff, 0xc9, 0x24, 0x53, 0xff, 0x49, 0x03, 0x00, 0xff, 0x45, 0x05, 0x00, 0xff, 0x40, 0x00, 0x00, 0xff, 0xbc, 0x86, 0x02, 0xff, 0x86, 0x4c, 0x01, 0xff, 0x30, 0x00, 0x00, 0xff, 0xa1, 0x7f, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x56, 0x53, 0xff, 0x31, 0x00, 0x00, 0xff, 0xc1, 0xa9, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xf7, 0xff, 0xfe, 0xff, 0xf8, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf2, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf8, 0xf4, 0xee, 0xff, 0xf7, 0xf1, 0xec, 0xff, 0xf7, 0xee, 0xea, 0xff, 0xf7, 0xeb, 0xe7, 0xff, 0xf8, 0xe8, 0xe4, 0xff, 0xf9, 0xe4, 0xe1, 0xff, 0xfa, 0xe0, 0xdf, 0xff, 0xfb, 0xde, 0xdc, 0xff, 0xfb, 0xdb, 0xda, 0xff, 0xfc, 0xd8, 0xd8, 0xff, 0xfb, 0xd6, 0xd5, 0xff, 0xfb, 0xd3, 0xd4, 0xff, 0xfb, 0xd2, 0xd3, 0xff, 0xfb, 0xd1, 0xd2, 0xff, 0xfc, 0xd1, 0xd1, 0xff, 0xfc, 0xd1, 0xd1, 0xff, 0xfc, 0xd1, 0xd0, 0xff, 0xfc, 0xd1, 0xd0, 0xff, 0xfc, 0xd2, 0xd1, 0xff, 0xfb, 0xd2, 0xd1, 0xff, 0xfb, 0xd2, 0xd1, 0xff, 0xfc, 0xd1, 0xd0, 0xff, 0xfc, 0xd1, 0xd0, 0xff, 0xfd, 0xd1, 0xd0, 0xff, 0xfc, 0xd2, 0xd1, 0xff, 0xfc, 0xd3, 0xd1, 0xff, 0xfd, 0xd3, 0xd2, 0xff, 0xfc, 0xd3, 0xd2, 0xff, 0xfa, 0xd3, 0xd2, 0xff, 0xfb, 0xd3, 0xd2, 0xff, 0xfc, 0xd3, 0xd2, 0xff, 0xfd, 0xd3, 0xd2, 0xff, 0xfc, 0xd3, 0xd3, 0xff, 0xfc, 0xd3, 0xd2, 0xff, 0xfd, 0xd2, 0xd2, 0xff, 0xfd, 0xd2, 0xd1, 0xff, 0xfd, 0xd3, 0xd1, 0xff, 0xfd, 0xd3, 0xd2, 0xff, 0xfd, 0xd5, 0xd3, 0xff, 0xfd, 0xdc, 0xd8, 0xff, 0xfc, 0xbe, 0xc6, 0xff, 0xfc, 0x58, 0x86, 0xff, 0xfd, 0x2e, 0x6e, 0xff, 0xfd, 0x37, 0x75, 0xff, 0xfd, 0x37, 0x75, 0xff, 0xfd, 0x37, 0x74, 0xff, 0xfd, 0x39, 0x72, 0xff, 0xfd, 0x2d, 0x69, 0xff, 0xfc, 0x8e, 0xa9, 0xff, 0xfd, 0xf5, 0xee, 0xff, 0xfc, 0xee, 0xe9, 0xff, 0xfa, 0xef, 0xeb, 0xff, 0xf9, 0xf1, 0xec, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd4, 0x9d, 0x9c, 0xff, 0x87, 0x09, 0x11, 0xff, 0x70, 0x00, 0x08, 0xff, 0x7a, 0x06, 0x11, 0xff, 0xa5, 0x0e, 0x28, 0xff, 0xde, 0x1b, 0x49, 0xff, 0xf9, 0x31, 0x64, 0xff, 0xeb, 0x5b, 0x7c, 0xff, 0xdf, 0x9b, 0xa5, 0xff, 0xe7, 0xda, 0xd7, 0xff, 0xf9, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x64, 0x52, 0x52, 0xff, 0x1d, 0x00, 0x00, 0xff, 0x2d, 0x01, 0x00, 0xff, 0x31, 0x01, 0x00, 0xff, 0x30, 0x00, 0x00, 0xff, 0x82, 0x10, 0x28, 0xff, 0x6e, 0x0b, 0x15, 0xff, 0x59, 0x08, 0x14, 0xff, 0xc5, 0x28, 0x5a, 0xff, 0x48, 0x04, 0x00, 0xff, 0x48, 0x06, 0x00, 0xff, 0x42, 0x00, 0x00, 0xff, 0xbd, 0x8a, 0x02, 0xff, 0x88, 0x4d, 0x01, 0xff, 0x32, 0x00, 0x00, 0xff, 0xa1, 0x7e, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa9, 0x8e, 0x8b, 0xff, 0x2d, 0x00, 0x00, 0xff, 0x97, 0x72, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xf7, 0xff, 0xff, 0xff, 0xf8, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf0, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xf7, 0xf2, 0xed, 0xff, 0xf6, 0xf0, 0xeb, 0xff, 0xf6, 0xed, 0xe9, 0xff, 0xf7, 0xeb, 0xe7, 0xff, 0xf9, 0xe8, 0xe5, 0xff, 0xf9, 0xe5, 0xe2, 0xff, 0xf9, 0xe2, 0xe0, 0xff, 0xf9, 0xdf, 0xde, 0xff, 0xfa, 0xdd, 0xdc, 0xff, 0xfa, 0xdb, 0xda, 0xff, 0xf9, 0xd9, 0xd9, 0xff, 0xf9, 0xd7, 0xd7, 0xff, 0xfa, 0xd6, 0xd6, 0xff, 0xf9, 0xd6, 0xd5, 0xff, 0xf9, 0xd5, 0xd5, 0xff, 0xf9, 0xd5, 0xd4, 0xff, 0xf9, 0xd5, 0xd4, 0xff, 0xf9, 0xd6, 0xd5, 0xff, 0xfa, 0xd7, 0xd5, 0xff, 0xfa, 0xd6, 0xd4, 0xff, 0xfa, 0xd6, 0xd5, 0xff, 0xfb, 0xd7, 0xd5, 0xff, 0xfa, 0xd7, 0xd5, 0xff, 0xfb, 0xd8, 0xd6, 0xff, 0xfc, 0xd8, 0xd7, 0xff, 0xfb, 0xd8, 0xd7, 0xff, 0xfb, 0xd9, 0xd7, 0xff, 0xfb, 0xd9, 0xd7, 0xff, 0xfb, 0xd9, 0xd7, 0xff, 0xfb, 0xd8, 0xd7, 0xff, 0xfa, 0xd8, 0xd6, 0xff, 0xfa, 0xd7, 0xd6, 0xff, 0xfa, 0xd7, 0xd6, 0xff, 0xfb, 0xd7, 0xd6, 0xff, 0xfb, 0xd7, 0xd6, 0xff, 0xfc, 0xd7, 0xd5, 0xff, 0xfc, 0xd6, 0xd5, 0xff, 0xfd, 0xd7, 0xd5, 0xff, 0xfd, 0xd6, 0xd4, 0xff, 0xfd, 0xdc, 0xd8, 0xff, 0xfd, 0xd2, 0xd4, 0xff, 0xfb, 0x73, 0x9b, 0xff, 0xfd, 0x2d, 0x70, 0xff, 0xfd, 0x31, 0x73, 0xff, 0xfd, 0x34, 0x74, 0xff, 0xfd, 0x37, 0x73, 0xff, 0xfd, 0x2f, 0x6b, 0xff, 0xfc, 0x67, 0x90, 0xff, 0xfd, 0xf3, 0xef, 0xff, 0xfd, 0xf2, 0xee, 0xff, 0xfa, 0xf2, 0xee, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xbf, 0xc7, 0xff, 0xfa, 0x6a, 0x8b, 0xff, 0xfd, 0x4d, 0x79, 0xff, 0xff, 0x5e, 0x8a, 0xff, 0xfb, 0x97, 0xb0, 0xff, 0xf2, 0xd3, 0xd7, 0xff, 0xf8, 0xfc, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x5b, 0x5a, 0xff, 0x29, 0x00, 0x00, 0xff, 0x31, 0x01, 0x00, 0xff, 0x38, 0x01, 0x00, 0xff, 0x33, 0x00, 0x00, 0xff, 0xb3, 0x1d, 0x4c, 0xff, 0x6d, 0x0d, 0x20, 0xff, 0x50, 0x08, 0x12, 0xff, 0xc7, 0x2e, 0x63, 0xff, 0x48, 0x03, 0x00, 0xff, 0x49, 0x05, 0x00, 0xff, 0x43, 0x00, 0x00, 0xff, 0xbf, 0x8a, 0x02, 0xff, 0x87, 0x4b, 0x01, 0xff, 0x32, 0x00, 0x00, 0xff, 0xa7, 0x84, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9c, 0x78, 0x75, 0xff, 0x35, 0x00, 0x00, 0xff, 0x6f, 0x3d, 0x3c, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xfe, 0xff, 0xf9, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf7, 0xf3, 0xee, 0xff, 0xf6, 0xf2, 0xed, 0xff, 0xf6, 0xef, 0xeb, 0xff, 0xf7, 0xed, 0xe9, 0xff, 0xf7, 0xeb, 0xe8, 0xff, 0xf8, 0xe9, 0xe6, 0xff, 0xf9, 0xe7, 0xe4, 0xff, 0xf8, 0xe4, 0xe2, 0xff, 0xf9, 0xe2, 0xe0, 0xff, 0xf9, 0xe0, 0xdf, 0xff, 0xfa, 0xdf, 0xde, 0xff, 0xf9, 0xdd, 0xdc, 0xff, 0xfa, 0xdc, 0xdb, 0xff, 0xf9, 0xdb, 0xda, 0xff, 0xf8, 0xdb, 0xd9, 0xff, 0xf8, 0xda, 0xd9, 0xff, 0xf8, 0xda, 0xd9, 0xff, 0xf9, 0xdb, 0xdb, 0xff, 0xf9, 0xdc, 0xdb, 0xff, 0xf9, 0xdc, 0xda, 0xff, 0xf8, 0xdc, 0xda, 0xff, 0xfa, 0xdd, 0xdb, 0xff, 0xfa, 0xdd, 0xdb, 0xff, 0xfb, 0xde, 0xdc, 0xff, 0xfa, 0xde, 0xdd, 0xff, 0xf9, 0xde, 0xdc, 0xff, 0xf9, 0xde, 0xdc, 0xff, 0xfa, 0xde, 0xdc, 0xff, 0xfa, 0xdf, 0xdb, 0xff, 0xfa, 0xde, 0xdb, 0xff, 0xf9, 0xdd, 0xdb, 0xff, 0xf9, 0xdd, 0xdb, 0xff, 0xf9, 0xdd, 0xdc, 0xff, 0xfa, 0xdd, 0xdb, 0xff, 0xf9, 0xdd, 0xdb, 0xff, 0xf9, 0xdc, 0xdb, 0xff, 0xfa, 0xdb, 0xda, 0xff, 0xfa, 0xda, 0xd8, 0xff, 0xfb, 0xd9, 0xd7, 0xff, 0xfd, 0xda, 0xd7, 0xff, 0xfe, 0xde, 0xdc, 0xff, 0xfd, 0xe1, 0xdf, 0xff, 0xfb, 0x95, 0xb1, 0xff, 0xfc, 0x31, 0x76, 0xff, 0xfd, 0x2c, 0x71, 0xff, 0xfd, 0x34, 0x73, 0xff, 0xfd, 0x32, 0x71, 0xff, 0xfc, 0x45, 0x7c, 0xff, 0xfd, 0xe4, 0xe6, 0xff, 0xfd, 0xf7, 0xf2, 0xff, 0xfa, 0xf5, 0xf0, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfd, 0xff, 0xfb, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfb, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfd, 0xfc, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb2, 0x6e, 0x6b, 0xff, 0x4a, 0x00, 0x00, 0xff, 0x35, 0x00, 0x00, 0xff, 0x3a, 0x01, 0x00, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xae, 0x1f, 0x4f, 0xff, 0x72, 0x0f, 0x24, 0xff, 0x55, 0x09, 0x13, 0xff, 0xc4, 0x2f, 0x66, 0xff, 0x46, 0x03, 0x00, 0xff, 0x4a, 0x04, 0x00, 0xff, 0x43, 0x00, 0x00, 0xff, 0xbd, 0x89, 0x02, 0xff, 0x88, 0x4c, 0x01, 0xff, 0x38, 0x00, 0x00, 0xff, 0x85, 0x57, 0x53, 0xff, 0x79, 0x4a, 0x48, 0xff, 0x41, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0xff, 0x52, 0x14, 0x12, 0xff, 0xec, 0xe6, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0xf9, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf7, 0xf3, 0xee, 0xff, 0xf7, 0xf2, 0xed, 0xff, 0xf7, 0xf0, 0xeb, 0xff, 0xf7, 0xee, 0xeb, 0xff, 0xf8, 0xec, 0xea, 0xff, 0xf7, 0xea, 0xe8, 0xff, 0xf7, 0xe9, 0xe6, 0xff, 0xf8, 0xe7, 0xe5, 0xff, 0xf9, 0xe5, 0xe4, 0xff, 0xf8, 0xe4, 0xe3, 0xff, 0xf8, 0xe3, 0xe1, 0xff, 0xf7, 0xe2, 0xe0, 0xff, 0xf7, 0xe2, 0xdf, 0xff, 0xf7, 0xe1, 0xdf, 0xff, 0xf7, 0xe1, 0xde, 0xff, 0xf7, 0xe1, 0xdf, 0xff, 0xf7, 0xe2, 0xdf, 0xff, 0xf6, 0xe1, 0xdf, 0xff, 0xf6, 0xe1, 0xde, 0xff, 0xf6, 0xe1, 0xdf, 0xff, 0xf8, 0xe2, 0xe0, 0xff, 0xf9, 0xe3, 0xe1, 0xff, 0xf9, 0xe4, 0xe1, 0xff, 0xf8, 0xe3, 0xe1, 0xff, 0xf8, 0xe3, 0xe1, 0xff, 0xf8, 0xe3, 0xe1, 0xff, 0xf8, 0xe3, 0xe0, 0xff, 0xf8, 0xe3, 0xe0, 0xff, 0xf8, 0xe3, 0xdf, 0xff, 0xf7, 0xe2, 0xe0, 0xff, 0xf7, 0xe2, 0xe0, 0xff, 0xf8, 0xe3, 0xe0, 0xff, 0xf8, 0xe3, 0xe0, 0xff, 0xf7, 0xe2, 0xdf, 0xff, 0xf7, 0xe1, 0xdf, 0xff, 0xf8, 0xdf, 0xdd, 0xff, 0xf8, 0xdd, 0xdc, 0xff, 0xf8, 0xdc, 0xdb, 0xff, 0xfa, 0xdc, 0xdb, 0xff, 0xfb, 0xdd, 0xdb, 0xff, 0xfd, 0xe0, 0xde, 0xff, 0xfd, 0xe9, 0xe4, 0xff, 0xfc, 0xb0, 0xc3, 0xff, 0xfc, 0x3f, 0x7f, 0xff, 0xfd, 0x28, 0x6f, 0xff, 0xfd, 0x32, 0x73, 0xff, 0xfd, 0x30, 0x71, 0xff, 0xfc, 0xc7, 0xd3, 0xff, 0xfc, 0xfd, 0xf6, 0xff, 0xf9, 0xf5, 0xf1, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xfb, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x78, 0x74, 0xff, 0x48, 0x00, 0x00, 0xff, 0x26, 0x00, 0x00, 0xff, 0x2b, 0x00, 0x00, 0xff, 0x44, 0x03, 0x09, 0xff, 0xd0, 0x2a, 0x6a, 0xff, 0x5c, 0x09, 0x14, 0xff, 0x58, 0x09, 0x14, 0xff, 0xc2, 0x30, 0x63, 0xff, 0x45, 0x03, 0x00, 0xff, 0x49, 0x04, 0x00, 0xff, 0x3c, 0x00, 0x01, 0xff, 0xb9, 0x86, 0x02, 0xff, 0x8c, 0x50, 0x01, 0xff, 0x43, 0x00, 0x01, 0xff, 0x46, 0x00, 0x00, 0xff, 0x43, 0x00, 0x00, 0xff, 0x4a, 0x04, 0x00, 0xff, 0x4a, 0x04, 0x00, 0xff, 0x42, 0x00, 0x00, 0xff, 0xc9, 0xb6, 0xb2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xf8, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf4, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf7, 0xf1, 0xed, 0xff, 0xf7, 0xf0, 0xeb, 0xff, 0xf7, 0xee, 0xeb, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf6, 0xeb, 0xe8, 0xff, 0xf7, 0xea, 0xe8, 0xff, 0xf7, 0xea, 0xe7, 0xff, 0xf7, 0xe9, 0xe6, 0xff, 0xf6, 0xe8, 0xe6, 0xff, 0xf6, 0xe8, 0xe5, 0xff, 0xf7, 0xe7, 0xe4, 0xff, 0xf7, 0xe7, 0xe4, 0xff, 0xf7, 0xe7, 0xe4, 0xff, 0xf7, 0xe7, 0xe4, 0xff, 0xf6, 0xe6, 0xe3, 0xff, 0xf5, 0xe6, 0xe3, 0xff, 0xf5, 0xe7, 0xe3, 0xff, 0xf6, 0xe7, 0xe3, 0xff, 0xf8, 0xe8, 0xe4, 0xff, 0xf8, 0xe8, 0xe4, 0xff, 0xf8, 0xe8, 0xe4, 0xff, 0xf8, 0xe8, 0xe4, 0xff, 0xf8, 0xe7, 0xe5, 0xff, 0xf8, 0xe7, 0xe4, 0xff, 0xf8, 0xe7, 0xe4, 0xff, 0xf7, 0xe7, 0xe4, 0xff, 0xf6, 0xe7, 0xe4, 0xff, 0xf7, 0xe7, 0xe4, 0xff, 0xf7, 0xe8, 0xe4, 0xff, 0xf7, 0xe8, 0xe4, 0xff, 0xf6, 0xe7, 0xe4, 0xff, 0xf6, 0xe5, 0xe3, 0xff, 0xf7, 0xe4, 0xe1, 0xff, 0xf6, 0xe2, 0xe0, 0xff, 0xf7, 0xe0, 0xde, 0xff, 0xf8, 0xdf, 0xdd, 0xff, 0xf8, 0xdf, 0xdd, 0xff, 0xfa, 0xe0, 0xde, 0xff, 0xfc, 0xe3, 0xe0, 0xff, 0xfd, 0xee, 0xe8, 0xff, 0xfc, 0xd2, 0xd9, 0xff, 0xfb, 0x59, 0x8e, 0xff, 0xfd, 0x20, 0x69, 0xff, 0xfc, 0x23, 0x6c, 0xff, 0xfc, 0xc2, 0xd0, 0xff, 0xfc, 0xfe, 0xf6, 0xff, 0xfa, 0xf6, 0xf2, 0xff, 0xf9, 0xf6, 0xf2, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfd, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x7a, 0x75, 0xff, 0x73, 0x09, 0x19, 0xff, 0xa3, 0x29, 0x5f, 0xff, 0xa5, 0x2a, 0x5e, 0xff, 0xcf, 0x31, 0x74, 0xff, 0x8f, 0x18, 0x3a, 0xff, 0x37, 0x00, 0x00, 0xff, 0x5d, 0x0b, 0x17, 0xff, 0xc5, 0x32, 0x62, 0xff, 0x48, 0x03, 0x00, 0xff, 0x41, 0x00, 0x00, 0xff, 0x4d, 0x09, 0x01, 0xff, 0xd9, 0xab, 0x03, 0xff, 0x70, 0x33, 0x01, 0xff, 0x45, 0x00, 0x00, 0xff, 0x4a, 0x05, 0x00, 0xff, 0x49, 0x05, 0x00, 0xff, 0x4a, 0x05, 0x00, 0xff, 0x4a, 0x06, 0x00, 0xff, 0x3e, 0x00, 0x00, 0xff, 0x98, 0x74, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xf9, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf4, 0xf5, 0xf4, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf8, 0xf3, 0xef, 0xff, 0xf7, 0xf2, 0xef, 0xff, 0xf7, 0xf2, 0xed, 0xff, 0xf7, 0xf1, 0xec, 0xff, 0xf7, 0xf0, 0xec, 0xff, 0xf6, 0xef, 0xeb, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf7, 0xee, 0xeb, 0xff, 0xf7, 0xed, 0xea, 0xff, 0xf7, 0xed, 0xea, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf7, 0xeb, 0xe8, 0xff, 0xf6, 0xea, 0xe8, 0xff, 0xf6, 0xeb, 0xe7, 0xff, 0xf6, 0xea, 0xe7, 0xff, 0xf6, 0xea, 0xe7, 0xff, 0xf6, 0xeb, 0xe8, 0xff, 0xf6, 0xec, 0xe8, 0xff, 0xf7, 0xeb, 0xe8, 0xff, 0xf7, 0xec, 0xe8, 0xff, 0xf6, 0xec, 0xe8, 0xff, 0xf6, 0xeb, 0xe8, 0xff, 0xf6, 0xeb, 0xe8, 0xff, 0xf7, 0xeb, 0xe7, 0xff, 0xf6, 0xeb, 0xe7, 0xff, 0xf7, 0xeb, 0xe7, 0xff, 0xf7, 0xec, 0xe8, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf6, 0xec, 0xe8, 0xff, 0xf6, 0xeb, 0xe8, 0xff, 0xf6, 0xea, 0xe7, 0xff, 0xf7, 0xe9, 0xe6, 0xff, 0xf7, 0xe7, 0xe4, 0xff, 0xf7, 0xe5, 0xe2, 0xff, 0xf7, 0xe3, 0xe1, 0xff, 0xf7, 0xe2, 0xdf, 0xff, 0xf7, 0xe2, 0xe0, 0xff, 0xf9, 0xe5, 0xe2, 0xff, 0xfc, 0xe9, 0xe4, 0xff, 0xfd, 0xf3, 0xec, 0xff, 0xfb, 0xe8, 0xe7, 0xff, 0xfb, 0x98, 0xb5, 0xff, 0xfb, 0xa9, 0xc2, 0xff, 0xfb, 0xf5, 0xf2, 0xff, 0xfb, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb8, 0x7e, 0x7f, 0xff, 0x51, 0x00, 0x05, 0xff, 0x6e, 0x14, 0x2d, 0xff, 0x6f, 0x14, 0x2d, 0xff, 0x5f, 0x0b, 0x1b, 0xff, 0x3c, 0x00, 0x00, 0xff, 0x41, 0x00, 0x00, 0xff, 0x63, 0x0c, 0x18, 0xff, 0xc6, 0x34, 0x61, 0xff, 0x43, 0x00, 0x00, 0xff, 0x50, 0x09, 0x01, 0xff, 0xce, 0x96, 0x03, 0xff, 0x9e, 0x67, 0x03, 0xff, 0x40, 0x00, 0x00, 0xff, 0x48, 0x05, 0x00, 0xff, 0x4a, 0x06, 0x01, 0xff, 0x50, 0x08, 0x02, 0xff, 0x57, 0x0a, 0x03, 0xff, 0x4d, 0x06, 0x01, 0xff, 0x41, 0x00, 0x00, 0xff, 0x66, 0x32, 0x30, 0xff, 0xfd, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xfa, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf6, 0xf2, 0xed, 0xff, 0xf6, 0xf2, 0xed, 0xff, 0xf7, 0xf2, 0xed, 0xff, 0xf7, 0xf1, 0xed, 0xff, 0xf7, 0xf0, 0xed, 0xff, 0xf7, 0xf0, 0xec, 0xff, 0xf7, 0xf0, 0xec, 0xff, 0xf7, 0xf0, 0xec, 0xff, 0xf7, 0xef, 0xec, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf7, 0xef, 0xea, 0xff, 0xf7, 0xee, 0xeb, 0xff, 0xf6, 0xee, 0xeb, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf7, 0xf0, 0xeb, 0xff, 0xf7, 0xf0, 0xeb, 0xff, 0xf7, 0xf0, 0xeb, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf6, 0xef, 0xea, 0xff, 0xf6, 0xee, 0xea, 0xff, 0xf7, 0xef, 0xea, 0xff, 0xf8, 0xf0, 0xeb, 0xff, 0xf7, 0xf0, 0xec, 0xff, 0xf7, 0xf0, 0xeb, 0xff, 0xf6, 0xef, 0xeb, 0xff, 0xf8, 0xee, 0xeb, 0xff, 0xf8, 0xed, 0xea, 0xff, 0xf7, 0xeb, 0xe8, 0xff, 0xf7, 0xe9, 0xe6, 0xff, 0xf8, 0xe8, 0xe5, 0xff, 0xf8, 0xe6, 0xe3, 0xff, 0xf7, 0xe5, 0xe2, 0xff, 0xf8, 0xe6, 0xe3, 0xff, 0xf8, 0xea, 0xe6, 0xff, 0xfa, 0xee, 0xea, 0xff, 0xfb, 0xf3, 0xee, 0xff, 0xfa, 0xfd, 0xf5, 0xff, 0xfa, 0xfe, 0xf6, 0xff, 0xfa, 0xf7, 0xf2, 0xff, 0xf9, 0xf7, 0xf1, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcd, 0x84, 0x8f, 0xff, 0x3e, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x45, 0x02, 0x00, 0xff, 0x4b, 0x02, 0x00, 0xff, 0x87, 0x11, 0x20, 0xff, 0x4b, 0x01, 0x00, 0xff, 0x66, 0x0c, 0x18, 0xff, 0xc6, 0x31, 0x5d, 0xff, 0x40, 0x00, 0x00, 0xff, 0xc0, 0x86, 0x02, 0xff, 0xa2, 0x6d, 0x02, 0xff, 0x38, 0x00, 0x01, 0xff, 0x44, 0x03, 0x00, 0xff, 0x4d, 0x06, 0x01, 0xff, 0x57, 0x09, 0x03, 0xff, 0x56, 0x08, 0x03, 0xff, 0x54, 0x08, 0x02, 0xff, 0x51, 0x07, 0x01, 0xff, 0x46, 0x02, 0x00, 0xff, 0x45, 0x05, 0x03, 0xff, 0xdb, 0xcf, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfd, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf7, 0xf4, 0xf0, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xf7, 0xf2, 0xef, 0xff, 0xf7, 0xf1, 0xee, 0xff, 0xf7, 0xf1, 0xee, 0xff, 0xf7, 0xf1, 0xee, 0xff, 0xf7, 0xf2, 0xed, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf7, 0xf1, 0xed, 0xff, 0xf7, 0xf1, 0xed, 0xff, 0xf6, 0xf1, 0xed, 0xff, 0xf6, 0xf1, 0xed, 0xff, 0xf6, 0xf1, 0xee, 0xff, 0xf6, 0xf1, 0xee, 0xff, 0xf7, 0xf1, 0xee, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf7, 0xf1, 0xed, 0xff, 0xf7, 0xf1, 0xed, 0xff, 0xf6, 0xf1, 0xed, 0xff, 0xf5, 0xf1, 0xed, 0xff, 0xf5, 0xf1, 0xec, 0xff, 0xf6, 0xf2, 0xed, 0xff, 0xf7, 0xf2, 0xed, 0xff, 0xf7, 0xf3, 0xee, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf8, 0xf2, 0xee, 0xff, 0xf8, 0xf1, 0xed, 0xff, 0xf8, 0xef, 0xec, 0xff, 0xf7, 0xed, 0xea, 0xff, 0xf7, 0xeb, 0xe8, 0xff, 0xf8, 0xea, 0xe7, 0xff, 0xf7, 0xe9, 0xe5, 0xff, 0xf6, 0xe9, 0xe6, 0xff, 0xf6, 0xeb, 0xe8, 0xff, 0xf8, 0xed, 0xeb, 0xff, 0xf9, 0xf1, 0xed, 0xff, 0xfa, 0xf3, 0xee, 0xff, 0xfa, 0xf5, 0xf0, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf9, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x84, 0x9b, 0xff, 0x4d, 0x00, 0x00, 0xff, 0x71, 0x12, 0x0f, 0xff, 0x55, 0x08, 0x03, 0xff, 0x55, 0x06, 0x07, 0xff, 0xbd, 0x21, 0x3c, 0xff, 0x4b, 0x01, 0x01, 0xff, 0x66, 0x0d, 0x17, 0xff, 0xc1, 0x30, 0x59, 0xff, 0x48, 0x0a, 0x00, 0xff, 0xd1, 0xa0, 0x02, 0xff, 0x94, 0x57, 0x02, 0xff, 0x69, 0x28, 0x01, 0xff, 0x43, 0x00, 0x00, 0xff, 0x4a, 0x05, 0x01, 0xff, 0x54, 0x08, 0x01, 0xff, 0x5f, 0x0b, 0x02, 0xff, 0x59, 0x09, 0x02, 0xff, 0x4f, 0x05, 0x01, 0xff, 0x48, 0x03, 0x00, 0xff, 0x3a, 0x00, 0x00, 0xff, 0xa2, 0x82, 0x80, 0xff, 0xff, 0xfc, 0xf9, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfb, 0xf5, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xf8, 0xf3, 0xef, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf7, 0xf4, 0xf0, 0xff, 0xf6, 0xf4, 0xf0, 0xff, 0xf7, 0xf4, 0xf0, 0xff, 0xf7, 0xf4, 0xf0, 0xff, 0xf6, 0xf3, 0xf0, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xf7, 0xf4, 0xf0, 0xff, 0xf7, 0xf3, 0xf0, 0xff, 0xf6, 0xf3, 0xef, 0xff, 0xf6, 0xf3, 0xef, 0xff, 0xf6, 0xf3, 0xef, 0xff, 0xf6, 0xf3, 0xef, 0xff, 0xf6, 0xf3, 0xef, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf8, 0xf3, 0xef, 0xff, 0xf7, 0xf1, 0xee, 0xff, 0xf6, 0xf0, 0xec, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf7, 0xed, 0xea, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf7, 0xec, 0xe9, 0xff, 0xf7, 0xec, 0xea, 0xff, 0xf8, 0xee, 0xeb, 0xff, 0xf8, 0xf2, 0xed, 0xff, 0xf9, 0xf4, 0xee, 0xff, 0xf9, 0xf5, 0xf0, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0x8e, 0xa7, 0xff, 0x50, 0x00, 0x04, 0xff, 0x71, 0x14, 0x11, 0xff, 0x4c, 0x06, 0x02, 0xff, 0x4f, 0x05, 0x07, 0xff, 0xc2, 0x28, 0x41, 0xff, 0x45, 0x01, 0x01, 0xff, 0x6c, 0x10, 0x1a, 0xff, 0xbd, 0x31, 0x50, 0xff, 0x43, 0x0a, 0x00, 0xff, 0xc5, 0x96, 0x02, 0xff, 0xb6, 0x81, 0x02, 0xff, 0x7c, 0x3e, 0x01, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x4e, 0x06, 0x01, 0xff, 0x54, 0x08, 0x01, 0xff, 0x4a, 0x03, 0x01, 0xff, 0x4d, 0x03, 0x01, 0xff, 0x4e, 0x04, 0x01, 0xff, 0x46, 0x03, 0x01, 0xff, 0x42, 0x00, 0x00, 0xff, 0x47, 0x0a, 0x09, 0xff, 0x53, 0x1f, 0x1d, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf8, 0xf5, 0xf0, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf9, 0xf6, 0xf2, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xf6, 0xf2, 0xed, 0xff, 0xf7, 0xf1, 0xec, 0xff, 0xf6, 0xf0, 0xec, 0xff, 0xf6, 0xef, 0xeb, 0xff, 0xf7, 0xef, 0xeb, 0xff, 0xf7, 0xf0, 0xec, 0xff, 0xf7, 0xf2, 0xee, 0xff, 0xf8, 0xf4, 0xef, 0xff, 0xfa, 0xf6, 0xf1, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf0, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfd, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xf4, 0xee, 0xff, 0xea, 0x73, 0x93, 0xff, 0x53, 0x00, 0x0a, 0xff, 0x6b, 0x14, 0x10, 0xff, 0x4e, 0x08, 0x04, 0xff, 0x5a, 0x09, 0x0d, 0xff, 0xc5, 0x29, 0x41, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x8a, 0x1f, 0x2c, 0xff, 0xa7, 0x2a, 0x3e, 0xff, 0x41, 0x0a, 0x00, 0xff, 0xc5, 0x96, 0x02, 0xff, 0xac, 0x7b, 0x02, 0xff, 0x79, 0x3b, 0x01, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x47, 0x03, 0x01, 0xff, 0x50, 0x05, 0x02, 0xff, 0x55, 0x07, 0x02, 0xff, 0x50, 0x04, 0x01, 0xff, 0x42, 0x01, 0x00, 0xff, 0x39, 0x00, 0x00, 0xff, 0x39, 0x00, 0x00, 0xff, 0x42, 0x00, 0x01, 0xff, 0x53, 0x05, 0x10, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf7, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf0, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf7, 0xf3, 0xee, 0xff, 0xf6, 0xf2, 0xee, 0xff, 0xf7, 0xf1, 0xed, 0xff, 0xf7, 0xf1, 0xee, 0xff, 0xf7, 0xf2, 0xef, 0xff, 0xf7, 0xf3, 0xef, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfe, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xdd, 0xd9, 0xff, 0x9e, 0x7b, 0x7c, 0xff, 0xb4, 0x35, 0x55, 0xff, 0xd3, 0x24, 0x54, 0xff, 0x5c, 0x0a, 0x14, 0xff, 0x63, 0x10, 0x0c, 0xff, 0x4b, 0x08, 0x02, 0xff, 0x77, 0x14, 0x1c, 0xff, 0xb2, 0x24, 0x36, 0xff, 0x32, 0x00, 0x00, 0xff, 0xbf, 0x36, 0x49, 0xff, 0x74, 0x16, 0x20, 0xff, 0x46, 0x0b, 0x00, 0xff, 0xc7, 0x92, 0x02, 0xff, 0xad, 0x7b, 0x02, 0xff, 0x79, 0x3c, 0x01, 0xff, 0x3e, 0x00, 0x01, 0xff, 0x47, 0x03, 0x01, 0xff, 0x4b, 0x04, 0x01, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x38, 0x00, 0x00, 0xff, 0x4b, 0x03, 0x08, 0xff, 0x7a, 0x16, 0x2e, 0xff, 0xb2, 0x2d, 0x5a, 0xff, 0xdf, 0x3f, 0x80, 0xff, 0xf8, 0x4b, 0x98, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf0, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf7, 0xf5, 0xf0, 0xff, 0xf7, 0xf4, 0xef, 0xff, 0xf7, 0xf4, 0xf0, 0xff, 0xf7, 0xf4, 0xf0, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf8, 0xf4, 0xf0, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xfd, 0xfd, 0xf7, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xeb, 0xf1, 0xff, 0x98, 0x78, 0x7b, 0xff, 0x45, 0x13, 0x18, 0xff, 0xb1, 0x1c, 0x44, 0xff, 0x56, 0x0b, 0x1f, 0xff, 0x8e, 0x20, 0x3d, 0xff, 0x65, 0x0e, 0x1a, 0xff, 0x5a, 0x0c, 0x07, 0xff, 0x48, 0x07, 0x01, 0xff, 0xa8, 0x25, 0x32, 0xff, 0x7c, 0x15, 0x1d, 0xff, 0x55, 0x0b, 0x0f, 0xff, 0xcf, 0x3a, 0x4f, 0xff, 0x42, 0x00, 0x02, 0xff, 0x4a, 0x0d, 0x00, 0xff, 0xc7, 0x92, 0x02, 0xff, 0xb7, 0x83, 0x02, 0xff, 0x7b, 0x40, 0x01, 0xff, 0x39, 0x00, 0x00, 0xff, 0x37, 0x00, 0x00, 0xff, 0x3c, 0x00, 0x00, 0xff, 0x67, 0x0e, 0x1e, 0xff, 0xaa, 0x2a, 0x55, 0xff, 0xe6, 0x44, 0x85, 0xff, 0xff, 0x50, 0x9d, 0xff, 0xff, 0x51, 0x9f, 0xff, 0xff, 0x4e, 0x9c, 0xff, 0xff, 0x4c, 0x9c, 0xff,
0xfd, 0xfa, 0xf5, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf8, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfe, 0xfe, 0xf8, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xfc, 0xf8, 0xf6, 0xff, 0xff, 0xa7, 0xc7, 0xff, 0xa7, 0x32, 0x55, 0xff, 0x22, 0x00, 0x00, 0xff, 0xbe, 0x2f, 0x59, 0xff, 0x62, 0x16, 0x2a, 0xff, 0x00, 0x00, 0x00, 0xff, 0x97, 0x24, 0x42, 0xff, 0x64, 0x0e, 0x1a, 0xff, 0x43, 0x02, 0x00, 0xff, 0x52, 0x08, 0x08, 0xff, 0xc9, 0x2c, 0x3d, 0xff, 0x3d, 0x02, 0x02, 0xff, 0xae, 0x2e, 0x3f, 0xff, 0x8c, 0x1f, 0x29, 0xff, 0x36, 0x00, 0x00, 0xff, 0x4d, 0x0e, 0x01, 0xff, 0xca, 0x98, 0x03, 0xff, 0x71, 0x3b, 0x01, 0xff, 0x47, 0x14, 0x00, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x7a, 0x17, 0x2e, 0xff, 0xcd, 0x36, 0x70, 0xff, 0xfd, 0x4c, 0x97, 0xff, 0xff, 0x52, 0x9f, 0xff, 0xff, 0x50, 0x9b, 0xff, 0xfe, 0x50, 0x98, 0xff, 0xfd, 0x4f, 0x98, 0xff, 0xfe, 0x4d, 0x99, 0xff, 0xfe, 0x4c, 0x9a, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf5, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xfb, 0xf9, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfd, 0xfb, 0xf7, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xdb, 0xd0, 0xcd, 0xff, 0xbb, 0xa3, 0xa2, 0xff, 0xa2, 0x84, 0x82, 0xff, 0x9b, 0x7c, 0x7a, 0xff, 0xab, 0x91, 0x8f, 0xff, 0xcf, 0xc6, 0xc1, 0xff, 0xfa, 0xd6, 0xe0, 0xff, 0xff, 0x73, 0xa7, 0xff, 0xd5, 0x2e, 0x67, 0xff, 0x25, 0x00, 0x00, 0xff, 0x9b, 0x2e, 0x4e, 0xff, 0x93, 0x2d, 0x4c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x00, 0x00, 0xff, 0xa7, 0x26, 0x44, 0xff, 0x56, 0x0a, 0x11, 0xff, 0x2f, 0x00, 0x00, 0xff, 0x90, 0x1b, 0x25, 0xff, 0x9d, 0x1f, 0x2b, 0xff, 0x54, 0x0e, 0x13, 0xff, 0xd0, 0x3a, 0x4d, 0xff, 0x45, 0x03, 0x01, 0xff, 0x40, 0x01, 0x00, 0xff, 0x44, 0x04, 0x01, 0xff, 0x53, 0x1b, 0x00, 0xff, 0x33, 0x00, 0x00, 0xff, 0x73, 0x14, 0x2f, 0xff, 0xd5, 0x3c, 0x77, 0xff, 0xff, 0x4e, 0x9e, 0xff, 0xff, 0x4e, 0xa0, 0xff, 0xfe, 0x4e, 0x9a, 0xff, 0xfd, 0x4f, 0x98, 0xff, 0xfd, 0x50, 0x98, 0xff, 0xfd, 0x50, 0x99, 0xff, 0xfc, 0x50, 0x99, 0xff, 0xfd, 0x4e, 0x9b, 0xff, 0xfe, 0x4d, 0x9c, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf5, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf4, 0xf5, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xfe, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xe3, 0xff, 0xa6, 0x86, 0x84, 0xff, 0x68, 0x2e, 0x2d, 0xff, 0x46, 0x03, 0x03, 0xff, 0x3b, 0x00, 0x00, 0xff, 0x39, 0x00, 0x00, 0xff, 0x37, 0x00, 0x00, 0xff, 0x2d, 0x00, 0x00, 0xff, 0x84, 0x1c, 0x32, 0xff, 0xfd, 0x50, 0x8e, 0xff, 0xfd, 0x45, 0x87, 0xff, 0x5a, 0x10, 0x1f, 0xff, 0x4e, 0x0f, 0x1b, 0xff, 0xd3, 0x44, 0x75, 0xff, 0x17, 0x05, 0x07, 0xff, 0x05, 0x00, 0x00, 0xff, 0x1f, 0x04, 0x08, 0xff, 0xa5, 0x21, 0x3c, 0xff, 0x37, 0x01, 0x01, 0xff, 0x43, 0x03, 0x04, 0xff, 0xce, 0x31, 0x41, 0xff, 0x48, 0x06, 0x07, 0xff, 0xb5, 0x32, 0x40, 0xff, 0x7d, 0x19, 0x1f, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x40, 0x01, 0x00, 0xff, 0x37, 0x00, 0x00, 0xff, 0x64, 0x0e, 0x22, 0xff, 0xcc, 0x3a, 0x71, 0xff, 0xff, 0x4f, 0x9c, 0xff, 0xff, 0x51, 0x9e, 0xff, 0xfe, 0x4e, 0x9a, 0xff, 0xfd, 0x4d, 0x9a, 0xff, 0xfd, 0x4e, 0x99, 0xff, 0xfd, 0x51, 0x9a, 0xff, 0xfd, 0x51, 0x9a, 0xff, 0xfd, 0x50, 0x9a, 0xff, 0xfd, 0x50, 0x9b, 0xff, 0xfd, 0x4e, 0x9c, 0xff, 0xfe, 0x4d, 0x9d, 0xff,
0xfd, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf4, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf8, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfd, 0xfc, 0xf8, 0xff, 0xaa, 0x8b, 0x87, 0xff, 0x53, 0x15, 0x12, 0xff, 0x3c, 0x00, 0x00, 0xff, 0x3c, 0x00, 0x00, 0xff, 0x42, 0x00, 0x00, 0xff, 0x44, 0x01, 0x00, 0xff, 0x41, 0x00, 0x00, 0xff, 0x35, 0x00, 0x00, 0xff, 0x81, 0x19, 0x30, 0xff, 0xfc, 0x4a, 0x89, 0xff, 0xff, 0x4e, 0x92, 0xff, 0xb1, 0x2e, 0x57, 0xff, 0x20, 0x00, 0x00, 0xff, 0xc8, 0x39, 0x68, 0xff, 0x69, 0x1f, 0x37, 0xff, 0x03, 0x00, 0x00, 0xff, 0x06, 0x00, 0x00, 0xff, 0x57, 0x0d, 0x19, 0xff, 0x70, 0x0f, 0x1b, 0xff, 0x26, 0x00, 0x00, 0xff, 0x98, 0x20, 0x25, 0xff, 0x91, 0x1f, 0x24, 0xff, 0x6c, 0x0f, 0x16, 0xff, 0xbf, 0x2c, 0x3b, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x3e, 0x00, 0x00, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x9e, 0x2a, 0x4e, 0xff, 0xfc, 0x53, 0x9a, 0xff, 0xff, 0x54, 0x9e, 0xff, 0xfd, 0x4e, 0x98, 0xff, 0xfd, 0x4e, 0x99, 0xff, 0xfd, 0x4e, 0x9a, 0xff, 0xfd, 0x4e, 0x9a, 0xff, 0xfd, 0x4e, 0x9b, 0xff, 0xfd, 0x50, 0x9b, 0xff, 0xfd, 0x51, 0x9c, 0xff, 0xfd, 0x51, 0x9d, 0xff, 0xfd, 0x52, 0x9e, 0xff, 0xfd, 0x50, 0x9e, 0xff, 0xfe, 0x4f, 0xa0, 0xff,
0xfd, 0xfb, 0xf7, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf4, 0xf4, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe4, 0xdf, 0xff, 0x77, 0x43, 0x40, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x43, 0x00, 0x00, 0xff, 0x41, 0x00, 0x01, 0xff, 0x83, 0x30, 0x01, 0xff, 0xb0, 0x57, 0x02, 0xff, 0x43, 0x03, 0x01, 0xff, 0x33, 0x00, 0x00, 0xff, 0x70, 0x14, 0x23, 0xff, 0xf9, 0x4a, 0x87, 0xff, 0xff, 0x4f, 0x90, 0xff, 0xf8, 0x49, 0x88, 0xff, 0x48, 0x0a, 0x12, 0xff, 0x62, 0x14, 0x21, 0xff, 0xcd, 0x41, 0x70, 0xff, 0x0f, 0x01, 0x02, 0xff, 0x0c, 0x00, 0x00, 0xff, 0x1e, 0x03, 0x05, 0xff, 0x84, 0x15, 0x22, 0xff, 0x32, 0x00, 0x01, 0xff, 0x4c, 0x09, 0x09, 0xff, 0xca, 0x36, 0x38, 0xff, 0x44, 0x04, 0x04, 0xff, 0xc8, 0x2a, 0x3d, 0xff, 0x64, 0x0d, 0x11, 0xff, 0x35, 0x00, 0x00, 0xff, 0x45, 0x02, 0x02, 0xff, 0xba, 0x32, 0x5f, 0xff, 0xff, 0x55, 0xa0, 0xff, 0xff, 0x51, 0x9a, 0xff, 0xfd, 0x50, 0x97, 0xff, 0xfd, 0x4d, 0x9b, 0xff, 0xfd, 0x4c, 0x9c, 0xff, 0xfe, 0x4d, 0x9c, 0xff, 0xfe, 0x4d, 0x9d, 0xff, 0xfe, 0x4e, 0x9e, 0xff, 0xfe, 0x4f, 0x9f, 0xff, 0xfe, 0x4f, 0xa1, 0xff, 0xfe, 0x51, 0xa2, 0xff, 0xfe, 0x52, 0xa2, 0xff, 0xfe, 0x51, 0xa3, 0xff, 0xff, 0x50, 0xa5, 0xff,
0xfc, 0xfb, 0xf6, 0xff, 0xfa, 0xfb, 0xf6, 0xff, 0xf8, 0xf9, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf0, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf0, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf7, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xf9, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xda, 0xd6, 0xff, 0x5e, 0x25, 0x23, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x45, 0x00, 0x00, 0xff, 0x48, 0x01, 0x01, 0xff, 0xb3, 0x52, 0x05, 0xff, 0xd6, 0x7c, 0x04, 0xff, 0x6e, 0x2f, 0x02, 0xff, 0x2f, 0x00, 0x00, 0xff, 0x51, 0x09, 0x11, 0xff, 0xec, 0x45, 0x7d, 0xff, 0xff, 0x4f, 0x8e, 0xff, 0xff, 0x50, 0x92, 0xff, 0xae, 0x2f, 0x55, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xc7, 0x3d, 0x67, 0xff, 0x67, 0x20, 0x35, 0xff, 0x05, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x62, 0x10, 0x18, 0xff, 0x60, 0x0c, 0x12, 0xff, 0x25, 0x00, 0x00, 0xff, 0xb2, 0x2f, 0x2b, 0xff, 0x78, 0x19, 0x17, 0xff, 0x83, 0x17, 0x20, 0xff, 0xac, 0x23, 0x30, 0xff, 0x2c, 0x00, 0x00, 0xff, 0x45, 0x03, 0x04, 0xff, 0xc8, 0x37, 0x68, 0xff, 0xff, 0x51, 0x9d, 0xff, 0xfe, 0x4d, 0x96, 0xff, 0xfd, 0x4a, 0x96, 0xff, 0xfd, 0x46, 0x9f, 0xff, 0xff, 0x4c, 0xa0, 0xff, 0xff, 0x4f, 0x9e, 0xff, 0xfb, 0x4b, 0x99, 0xff, 0xf8, 0x4a, 0x97, 0xff, 0xf8, 0x4c, 0x98, 0xff, 0xf8, 0x4c, 0x9b, 0xff, 0xf8, 0x4c, 0x9d, 0xff, 0xf8, 0x4d, 0x9f, 0xff, 0xf8, 0x4e, 0xa0, 0xff, 0xfa, 0x4f, 0xa1, 0xff, 0xfa, 0x4c, 0xa0, 0xff,
0xfc, 0xfb, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf0, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xeb, 0xe4, 0xdf, 0xff, 0x5c, 0x25, 0x23, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x45, 0x00, 0x01, 0xff, 0x48, 0x02, 0x02, 0xff, 0xc6, 0x56, 0x1a, 0xff, 0xb7, 0x59, 0x10, 0xff, 0x37, 0x05, 0x01, 0xff, 0x29, 0x00, 0x00, 0xff, 0x45, 0x06, 0x05, 0xff, 0xd4, 0x3a, 0x66, 0xff, 0xff, 0x4e, 0x90, 0xff, 0xff, 0x4d, 0x8c, 0xff, 0xfa, 0x4b, 0x89, 0xff, 0x4e, 0x0b, 0x14, 0xff, 0x5a, 0x13, 0x22, 0xff, 0xd7, 0x47, 0x7a, 0xff, 0x17, 0x03, 0x05, 0xff, 0x13, 0x00, 0x00, 0xff, 0x1d, 0x01, 0x01, 0xff, 0x66, 0x10, 0x15, 0xff, 0x30, 0x00, 0x00, 0xff, 0x51, 0x0c, 0x0a, 0xff, 0xb3, 0x2e, 0x27, 0xff, 0x4a, 0x07, 0x08, 0xff, 0xce, 0x32, 0x41, 0xff, 0x46, 0x04, 0x04, 0xff, 0x3f, 0x02, 0x04, 0xff, 0xcb, 0x36, 0x69, 0xff, 0xff, 0x50, 0x9a, 0xff, 0xfe, 0x4d, 0x92, 0xff, 0xfd, 0x4a, 0x95, 0xff, 0xfd, 0x49, 0x94, 0xff, 0xff, 0x82, 0x59, 0xff, 0xf0, 0x80, 0x37, 0xff, 0xc9, 0x3b, 0x49, 0xff, 0xb4, 0x29, 0x3e, 0xff, 0xae, 0x27, 0x38, 0xff, 0xad, 0x26, 0x3a, 0xff, 0xac, 0x25, 0x3a, 0xff, 0xac, 0x25, 0x3a, 0xff, 0xaa, 0x25, 0x39, 0xff, 0xa7, 0x25, 0x38, 0xff, 0xa4, 0x23, 0x36, 0xff, 0xa3, 0x21, 0x32, 0xff,
0xfb, 0xfa, 0xf5, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf1, 0xf2, 0xf0, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf2, 0xf3, 0xf1, 0xff, 0xf2, 0xf3, 0xf1, 0xff, 0xf2, 0xf3, 0xf1, 0xff, 0xf2, 0xf3, 0xf1, 0xff, 0xf2, 0xf3, 0xf1, 0xff, 0xf1, 0xf2, 0xf1, 0xff, 0xf1, 0xf2, 0xf1, 0xff, 0xf3, 0xf3, 0xf0, 0xff, 0xf5, 0xf4, 0xf0, 0xff, 0xf5, 0xf6, 0xf0, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf5, 0xf4, 0xef, 0xff, 0xf5, 0xf4, 0xef, 0xff, 0xf5, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf5, 0xf5, 0xf0, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xfd, 0xf9, 0xff, 0xff, 0xff, 0xfb, 0xff, 0x77, 0x49, 0x46, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x45, 0x02, 0x01, 0xff, 0x40, 0x00, 0x00, 0xff, 0xbb, 0x47, 0x1f, 0xff, 0xb0, 0x4b, 0x1e, 0xff, 0x2c, 0x00, 0x00, 0xff, 0x33, 0x00, 0x00, 0xff, 0x2a, 0x00, 0x00, 0xff, 0x82, 0x1e, 0x35, 0xff, 0xff, 0x4f, 0x8e, 0xff, 0xfd, 0x4b, 0x8a, 0xff, 0xff, 0x4e, 0x91, 0xff, 0xb4, 0x30, 0x59, 0xff, 0x21, 0x00, 0x00, 0xff, 0xc1, 0x38, 0x67, 0xff, 0x83, 0x27, 0x47, 0xff, 0x09, 0x00, 0x00, 0xff, 0x1e, 0x00, 0x00, 0xff, 0x23, 0x00, 0x00, 0xff, 0x26, 0x00, 0x00, 0xff, 0x2b, 0x00, 0x00, 0xff, 0x35, 0x01, 0x01, 0xff, 0x34, 0x01, 0x00, 0xff, 0x42, 0x05, 0x06, 0xff, 0x52, 0x0a, 0x0a, 0xff, 0x3e, 0x01, 0x04, 0xff, 0xcd, 0x37, 0x6a, 0xff, 0xff, 0x51, 0x98, 0xff, 0xfd, 0x4b, 0x91, 0xff, 0xfd, 0x47, 0x95, 0xff, 0xfd, 0x4d, 0x8f, 0xff, 0xff, 0xa4, 0x31, 0xff, 0xdc, 0x8e, 0x0c, 0xff, 0xac, 0x2c, 0x28, 0xff, 0xa4, 0x1e, 0x2c, 0xff, 0xa2, 0x1b, 0x2c, 0xff, 0xa7, 0x20, 0x2a, 0xff, 0xa9, 0x26, 0x27, 0xff, 0xa7, 0x25, 0x27, 0xff, 0xa7, 0x26, 0x26, 0xff, 0xa8, 0x27, 0x27, 0xff, 0xa3, 0x25, 0x26, 0xff, 0x9f, 0x23, 0x23, 0xff, 0x9e, 0x21, 0x1f, 0xff,
0xfa, 0xfa, 0xf5, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf2, 0xf3, 0xf0, 0xff, 0xef, 0xf2, 0xef, 0xff, 0xee, 0xf1, 0xef, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xf0, 0xf2, 0xf0, 0xff, 0xf1, 0xf3, 0xef, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf0, 0xf2, 0xf0, 0xff, 0xf1, 0xf2, 0xf0, 0xff, 0xef, 0xf1, 0xf0, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xf0, 0xf1, 0xef, 0xff, 0xf2, 0xf2, 0xf0, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf4, 0xf5, 0xf0, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf4, 0xf5, 0xf0, 0xff, 0xf4, 0xf3, 0xee, 0xff, 0xf3, 0xf2, 0xed, 0xff, 0xf2, 0xf2, 0xed, 0xff, 0xf2, 0xf2, 0xee, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf6, 0xf6, 0xf1, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf5, 0xf4, 0xf0, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf5, 0xf1, 0xff, 0xf7, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xfb, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfd, 0xfb, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb2, 0x97, 0x94, 0xff, 0x39, 0x00, 0x00, 0xff, 0x45, 0x01, 0x00, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x8f, 0x2a, 0x14, 0xff, 0xc9, 0x51, 0x25, 0xff, 0x32, 0x01, 0x00, 0xff, 0x31, 0x00, 0x00, 0xff, 0x31, 0x00, 0x00, 0xff, 0x44, 0x07, 0x0c, 0xff, 0xe9, 0x44, 0x79, 0xff, 0xff, 0x4c, 0x8a, 0xff, 0xfd, 0x4a, 0x89, 0xff, 0xff, 0x4e, 0x8f, 0xff, 0x87, 0x1f, 0x35, 0xff, 0x45, 0x06, 0x10, 0xff, 0xff, 0x4f, 0x92, 0xff, 0x7b, 0x21, 0x3f, 0xff, 0x12, 0x00, 0x00, 0xff, 0x1d, 0x00, 0x00, 0xff, 0x22, 0x00, 0x00, 0xff, 0x24, 0x00, 0x00, 0xff, 0x28, 0x00, 0x00, 0xff, 0x29, 0x00, 0x00, 0xff, 0x29, 0x00, 0x00, 0xff, 0x2d, 0x00, 0x00, 0xff, 0x54, 0x0b, 0x17, 0xff, 0xd5, 0x3c, 0x71, 0xff, 0xff, 0x51, 0x96, 0xff, 0xfd, 0x4d, 0x8e, 0xff, 0xfd, 0x48, 0x93, 0xff, 0xfd, 0x4c, 0x8d, 0xff, 0xff, 0xa8, 0x2a, 0xff, 0xd6, 0x82, 0x10, 0xff, 0xa3, 0x1e, 0x2f, 0xff, 0xa3, 0x1d, 0x2f, 0xff, 0xad, 0x26, 0x2c, 0xff, 0xd7, 0x6d, 0x16, 0xff, 0xec, 0x9f, 0x0a, 0xff, 0xec, 0xa9, 0x0a, 0xff, 0xec, 0xad, 0x0b, 0xff, 0xed, 0xae, 0x0a, 0xff, 0xee, 0xad, 0x0a, 0xff, 0xed, 0xac, 0x09, 0xff, 0xed, 0xac, 0x08, 0xff, 0xef, 0xa9, 0x07, 0xff,
0xf9, 0xfa, 0xf4, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf0, 0xf2, 0xf0, 0xff, 0xee, 0xf0, 0xef, 0xff, 0xee, 0xf0, 0xee, 0xff, 0xed, 0xf0, 0xee, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xf0, 0xf2, 0xef, 0xff, 0xf2, 0xf2, 0xef, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf2, 0xf3, 0xf0, 0xff, 0xf2, 0xf4, 0xf0, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf1, 0xf3, 0xf1, 0xff, 0xf0, 0xf2, 0xf0, 0xff, 0xef, 0xf2, 0xf0, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xef, 0xf0, 0xef, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xf0, 0xf1, 0xef, 0xff, 0xf1, 0xf2, 0xf0, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf3, 0xf4, 0xef, 0xff, 0xf2, 0xf2, 0xee, 0xff, 0xf1, 0xf1, 0xec, 0xff, 0xf1, 0xf0, 0xec, 0xff, 0xf2, 0xf1, 0xed, 0xff, 0xf3, 0xf2, 0xee, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf5, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf4, 0xf5, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf7, 0xf5, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf3, 0xee, 0xea, 0xff, 0x58, 0x1e, 0x1d, 0xff, 0x40, 0x00, 0x00, 0xff, 0x42, 0x00, 0x00, 0xff, 0x56, 0x0a, 0x05, 0xff, 0xdc, 0x56, 0x2c, 0xff, 0x50, 0x11, 0x08, 0xff, 0x2d, 0x00, 0x00, 0xff, 0x34, 0x01, 0x00, 0xff, 0x27, 0x00, 0x00, 0xff, 0xa0, 0x2b, 0x4a, 0xff, 0xff, 0x50, 0x8e, 0xff, 0xfd, 0x49, 0x85, 0xff, 0xfd, 0x48, 0x86, 0xff, 0xff, 0x47, 0x8b, 0xff, 0xe1, 0x61, 0x45, 0xff, 0xc0, 0x42, 0x46, 0xff, 0xff, 0x4c, 0x95, 0xff, 0xf6, 0x48, 0x88, 0xff, 0xca, 0x39, 0x6b, 0xff, 0xc4, 0x38, 0x69, 0xff, 0xc5, 0x38, 0x69, 0xff, 0xc6, 0x39, 0x6a, 0xff, 0xc6, 0x3a, 0x6c, 0xff, 0xc5, 0x3a, 0x6c, 0xff, 0xc4, 0x39, 0x6a, 0xff, 0xcc, 0x39, 0x6d, 0xff, 0xf7, 0x49, 0x8b, 0xff, 0xff, 0x4f, 0x94, 0xff, 0xfc, 0x4c, 0x8e, 0xff, 0xfd, 0x47, 0x92, 0xff, 0xfd, 0x52, 0x89, 0xff, 0xff, 0xae, 0x27, 0xff, 0xd3, 0x7b, 0x13, 0xff, 0xa4, 0x1c, 0x30, 0xff, 0xa1, 0x1d, 0x2d, 0xff, 0xaf, 0x28, 0x2b, 0xff, 0xec, 0x8d, 0x0f, 0xff, 0xdd, 0x87, 0x0c, 0xff, 0xaa, 0x3e, 0x1d, 0xff, 0xa2, 0x32, 0x24, 0xff, 0xa7, 0x36, 0x27, 0xff, 0xaa, 0x38, 0x27, 0xff, 0xab, 0x39, 0x27, 0xff, 0xaa, 0x39, 0x26, 0xff, 0xaa, 0x38, 0x23, 0xff, 0x84, 0x29, 0x12, 0xff,
0xfa, 0xf9, 0xf4, 0xff, 0xf7, 0xf8, 0xf2, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xef, 0xf2, 0xef, 0xff, 0xed, 0xf0, 0xee, 0xff, 0xed, 0xef, 0xed, 0xff, 0xed, 0xef, 0xed, 0xff, 0xee, 0xf0, 0xee, 0xff, 0xef, 0xf1, 0xee, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf1, 0xf3, 0xee, 0xff, 0xf1, 0xf3, 0xee, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf2, 0xf3, 0xf1, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf1, 0xf3, 0xf1, 0xff, 0xf0, 0xf2, 0xf0, 0xff, 0xf0, 0xf2, 0xef, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xf0, 0xf1, 0xef, 0xff, 0xef, 0xf1, 0xef, 0xff, 0xf0, 0xf2, 0xef, 0xff, 0xf2, 0xf3, 0xf0, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf1, 0xf1, 0xec, 0xff, 0xf0, 0xef, 0xeb, 0xff, 0xf0, 0xf0, 0xeb, 0xff, 0xf1, 0xf1, 0xec, 0xff, 0xf2, 0xf2, 0xee, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf2, 0xf4, 0xf0, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0x9b, 0x98, 0xff, 0x3c, 0x00, 0x00, 0xff, 0x47, 0x03, 0x00, 0xff, 0x3d, 0x00, 0x00, 0xff, 0xa7, 0x35, 0x1d, 0xff, 0xa0, 0x38, 0x1e, 0xff, 0x27, 0x00, 0x00, 0xff, 0x34, 0x01, 0x00, 0xff, 0x2d, 0x00, 0x00, 0xff, 0x46, 0x09, 0x0f, 0xff, 0xf1, 0x47, 0x7e, 0xff, 0xff, 0x4b, 0x87, 0xff, 0xfd, 0x49, 0x84, 0xff, 0xfd, 0x47, 0x83, 0xff, 0xfc, 0x3f, 0x88, 0xff, 0xff, 0x94, 0x36, 0xff, 0xff, 0x73, 0x58, 0xff, 0xfc, 0x40, 0x8b, 0xff, 0xff, 0x48, 0x88, 0xff, 0xff, 0x4c, 0x8d, 0xff, 0xff, 0x4e, 0x8f, 0xff, 0xff, 0x4e, 0x91, 0xff, 0xff, 0x4f, 0x93, 0xff, 0xff, 0x4f, 0x95, 0xff, 0xff, 0x4f, 0x94, 0xff, 0xff, 0x4e, 0x94, 0xff, 0xff, 0x4d, 0x94, 0xff, 0xff, 0x4a, 0x90, 0xff, 0xfd, 0x49, 0x8e, 0xff, 0xfd, 0x44, 0x92, 0xff, 0xfd, 0x53, 0x84, 0xff, 0xff, 0xb7, 0x23, 0xff, 0xd2, 0x7a, 0x16, 0xff, 0xa3, 0x19, 0x30, 0xff, 0xa2, 0x1c, 0x2d, 0xff, 0xaf, 0x24, 0x2b, 0xff, 0xee, 0x7a, 0x1d, 0xff, 0xd0, 0x64, 0x19, 0xff, 0x90, 0x14, 0x26, 0xff, 0xa5, 0x1f, 0x2a, 0xff, 0xab, 0x27, 0x2b, 0xff, 0x99, 0x20, 0x2e, 0xff, 0x9e, 0x22, 0x2f, 0xff, 0x9f, 0x23, 0x30, 0xff, 0xa0, 0x23, 0x30, 0xff, 0x89, 0x1a, 0x23, 0xff, 0x3a, 0x00, 0x02, 0xff,
0xfa, 0xf9, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xef, 0xf1, 0xee, 0xff, 0xed, 0xef, 0xed, 0xff, 0xec, 0xee, 0xed, 0xff, 0xec, 0xef, 0xed, 0xff, 0xed, 0xef, 0xed, 0xff, 0xef, 0xf0, 0xed, 0xff, 0xf0, 0xf2, 0xed, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf1, 0xf3, 0xef, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf0, 0xf3, 0xf0, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf0, 0xf3, 0xf0, 0xff, 0xf0, 0xf2, 0xf0, 0xff, 0xf0, 0xf2, 0xf0, 0xff, 0xf0, 0xf2, 0xef, 0xff, 0xf1, 0xf2, 0xef, 0xff, 0xf1, 0xf3, 0xef, 0xff, 0xf2, 0xf3, 0xf0, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf2, 0xee, 0xff, 0xf1, 0xf0, 0xec, 0xff, 0xf0, 0xef, 0xeb, 0xff, 0xf0, 0xef, 0xeb, 0xff, 0xf0, 0xf0, 0xec, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf2, 0xf4, 0xef, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf6, 0xf5, 0xf4, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xfa, 0xf8, 0xf3, 0xff, 0xfe, 0xfc, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x75, 0x48, 0x46, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x44, 0x03, 0x00, 0xff, 0x4e, 0x06, 0x04, 0xff, 0xd8, 0x47, 0x30, 0xff, 0x4e, 0x0d, 0x08, 0xff, 0x2e, 0x00, 0x00, 0xff, 0x33, 0x01, 0x01, 0xff, 0x26, 0x00, 0x00, 0xff, 0x9a, 0x26, 0x44, 0xff, 0xff, 0x4c, 0x8b, 0xff, 0xfd, 0x48, 0x83, 0xff, 0xfe, 0x48, 0x83, 0xff, 0xfd, 0x47, 0x82, 0xff, 0xfd, 0x3f, 0x82, 0xff, 0xfc, 0xac, 0x22, 0xff, 0xf7, 0x58, 0x6a, 0xff, 0xf9, 0x34, 0x8b, 0xff, 0xfd, 0x3a, 0x89, 0xff, 0xfd, 0x3c, 0x8c, 0xff, 0xfe, 0x3d, 0x8e, 0xff, 0xfd, 0x3f, 0x90, 0xff, 0xfd, 0x3f, 0x92, 0xff, 0xfd, 0x3e, 0x93, 0xff, 0xfd, 0x3f, 0x91, 0xff, 0xfd, 0x3f, 0x90, 0xff, 0xfd, 0x40, 0x91, 0xff, 0xfd, 0x41, 0x92, 0xff, 0xfd, 0x3d, 0x95, 0xff, 0xfe, 0x50, 0x83, 0xff, 0xff, 0xb9, 0x1e, 0xff, 0xd3, 0x7b, 0x17, 0xff, 0xa7, 0x19, 0x34, 0xff, 0xa3, 0x1d, 0x2e, 0xff, 0xaa, 0x1f, 0x2d, 0xff, 0xee, 0x64, 0x2d, 0xff, 0xd6, 0x57, 0x26, 0xff, 0x95, 0x14, 0x27, 0xff, 0xb1, 0x25, 0x28, 0xff, 0xfb, 0x4e, 0x2d, 0xff, 0xd6, 0x3f, 0x2f, 0xff, 0x9c, 0x25, 0x2f, 0xff, 0xa0, 0x28, 0x2f, 0xff, 0xa3, 0x29, 0x31, 0xff, 0xa2, 0x28, 0x30, 0xff, 0x53, 0x0b, 0x0b, 0xff, 0x35, 0x00, 0x00, 0xff,
0xf9, 0xfa, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf0, 0xf1, 0xef, 0xff, 0xed, 0xef, 0xec, 0xff, 0xed, 0xee, 0xec, 0xff, 0xec, 0xee, 0xec, 0xff, 0xed, 0xef, 0xec, 0xff, 0xee, 0xf0, 0xec, 0xff, 0xef, 0xf1, 0xed, 0xff, 0xf1, 0xf2, 0xed, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf1, 0xf3, 0xee, 0xff, 0xf1, 0xf3, 0xef, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf1, 0xf4, 0xf1, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf1, 0xf3, 0xf1, 0xff, 0xf1, 0xf3, 0xf0, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf2, 0xf4, 0xf0, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf1, 0xf0, 0xec, 0xff, 0xf0, 0xef, 0xeb, 0xff, 0xf0, 0xef, 0xeb, 0xff, 0xf1, 0xf0, 0xec, 0xff, 0xf2, 0xf2, 0xee, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xee, 0xea, 0xe6, 0xff, 0x4f, 0x17, 0x16, 0xff, 0x41, 0x00, 0x00, 0xff, 0x3e, 0x01, 0x00, 0xff, 0x78, 0x17, 0x15, 0xff, 0xc4, 0x39, 0x33, 0xff, 0x2d, 0x00, 0x00, 0xff, 0x32, 0x01, 0x01, 0xff, 0x2e, 0x00, 0x00, 0xff, 0x3d, 0x05, 0x09, 0xff, 0xe9, 0x40, 0x74, 0xff, 0xff, 0x48, 0x85, 0xff, 0xfd, 0x48, 0x82, 0xff, 0xfd, 0x47, 0x83, 0xff, 0xfd, 0x46, 0x82, 0xff, 0xfd, 0x3b, 0x83, 0xff, 0xfc, 0x92, 0x38, 0xff, 0xfb, 0xb0, 0x21, 0xff, 0xfb, 0x8e, 0x3b, 0xff, 0xfc, 0x8e, 0x3c, 0xff, 0xfc, 0x8c, 0x40, 0xff, 0xfc, 0x89, 0x45, 0xff, 0xfc, 0x88, 0x4a, 0xff, 0xfc, 0x86, 0x4b, 0xff, 0xfc, 0x7e, 0x4f, 0xff, 0xfc, 0x79, 0x53, 0xff, 0xfd, 0x79, 0x55, 0xff, 0xfd, 0x78, 0x59, 0xff, 0xfd, 0x76, 0x5c, 0xff, 0xfd, 0x7e, 0x59, 0xff, 0xff, 0xbf, 0x1e, 0xff, 0xd2, 0x77, 0x19, 0xff, 0xa3, 0x17, 0x33, 0xff, 0xa5, 0x1e, 0x30, 0xff, 0xa8, 0x1c, 0x2e, 0xff, 0xe7, 0x4e, 0x3a, 0xff, 0xd9, 0x4f, 0x34, 0xff, 0x99, 0x1a, 0x29, 0xff, 0xb5, 0x28, 0x28, 0xff, 0xfb, 0x4c, 0x2d, 0xff, 0xda, 0x40, 0x30, 0xff, 0xa0, 0x26, 0x30, 0xff, 0x9f, 0x27, 0x2f, 0xff, 0xa2, 0x29, 0x30, 0xff, 0xa6, 0x2a, 0x33, 0xff, 0x7d, 0x1c, 0x20, 0xff, 0x38, 0x00, 0x00, 0xff, 0x3c, 0x00, 0x00, 0xff,
0xfa, 0xfa, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf1, 0xf1, 0xef, 0xff, 0xee, 0xef, 0xed, 0xff, 0xed, 0xee, 0xec, 0xff, 0xec, 0xee, 0xec, 0xff, 0xed, 0xef, 0xec, 0xff, 0xed, 0xef, 0xec, 0xff, 0xef, 0xf0, 0xec, 0xff, 0xf0, 0xf1, 0xed, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf1, 0xf3, 0xef, 0xff, 0xf1, 0xf4, 0xf0, 0xff, 0xf2, 0xf4, 0xf0, 0xff, 0xf2, 0xf4, 0xf0, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf2, 0xf5, 0xf1, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf2, 0xf5, 0xf2, 0xff, 0xf2, 0xf5, 0xf2, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf1, 0xf1, 0xed, 0xff, 0xf0, 0xf0, 0xec, 0xff, 0xf0, 0xf0, 0xec, 0xff, 0xf1, 0xf1, 0xec, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf3, 0xf3, 0xf0, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd4, 0xc7, 0xc4, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x42, 0x02, 0x00, 0xff, 0x3c, 0x00, 0x00, 0xff, 0x9f, 0x25, 0x30, 0xff, 0x9b, 0x25, 0x32, 0xff, 0x27, 0x00, 0x00, 0xff, 0x31, 0x00, 0x02, 0xff, 0x25, 0x00, 0x00, 0xff, 0x81, 0x1e, 0x34, 0xff, 0xff, 0x4a, 0x87, 0xff, 0xfd, 0x47, 0x81, 0xff, 0xfd, 0x47, 0x81, 0xff, 0xfd, 0x46, 0x81, 0xff, 0xfd, 0x45, 0x80, 0xff, 0xfd, 0x41, 0x7e, 0xff, 0xfd, 0x42, 0x79, 0xff, 0xfd, 0x79, 0x50, 0xff, 0xfd, 0x8c, 0x43, 0xff, 0xfd, 0x8e, 0x44, 0xff, 0xfc, 0x90, 0x45, 0xff, 0xfc, 0x90, 0x44, 0xff, 0xfc, 0x92, 0x41, 0xff, 0xfc, 0x94, 0x3d, 0xff, 0xfd, 0x95, 0x3b, 0xff, 0xfd, 0x96, 0x39, 0xff, 0xfc, 0x99, 0x39, 0xff, 0xfd, 0x9f, 0x37, 0xff, 0xfd, 0xa4, 0x33, 0xff, 0xff, 0xa5, 0x37, 0xff, 0xd7, 0x60, 0x37, 0xff, 0xa6, 0x1a, 0x33, 0xff, 0xa6, 0x1e, 0x30, 0xff, 0xa4, 0x1b, 0x2e, 0xff, 0xdd, 0x3b, 0x3c, 0xff, 0xe2, 0x48, 0x3c, 0xff, 0x9b, 0x20, 0x2c, 0xff, 0x9a, 0x1f, 0x2b, 0xff, 0xe7, 0x43, 0x2c, 0xff, 0xd9, 0x3e, 0x30, 0xff, 0x9d, 0x25, 0x30, 0xff, 0x9f, 0x26, 0x30, 0xff, 0xa2, 0x29, 0x32, 0xff, 0xa4, 0x2a, 0x33, 0xff, 0xa4, 0x29, 0x32, 0xff, 0x54, 0x0b, 0x0b, 0xff, 0x3c, 0x01, 0x00, 0xff, 0x40, 0x01, 0x00, 0xff,
0xfa, 0xfa, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf2, 0xf2, 0xf0, 0xff, 0xef, 0xf0, 0xee, 0xff, 0xee, 0xef, 0xed, 0xff, 0xed, 0xef, 0xec, 0xff, 0xed, 0xef, 0xec, 0xff, 0xee, 0xf0, 0xed, 0xff, 0xef, 0xf0, 0xec, 0xff, 0xf0, 0xf1, 0xed, 0xff, 0xf1, 0xf2, 0xed, 0xff, 0xf1, 0xf3, 0xee, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf2, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf2, 0xf5, 0xf1, 0xff, 0xf2, 0xf5, 0xf1, 0xff, 0xf2, 0xf5, 0xf1, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf2, 0xf5, 0xf2, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf1, 0xf1, 0xed, 0xff, 0xf1, 0xf1, 0xed, 0xff, 0xf1, 0xf1, 0xed, 0xff, 0xf2, 0xf2, 0xee, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf5, 0xf4, 0xf1, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfa, 0xfa, 0xf4, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc5, 0xb4, 0xb2, 0xff, 0x38, 0x00, 0x00, 0xff, 0x42, 0x01, 0x00, 0xff, 0x3a, 0x00, 0x00, 0xff, 0xb4, 0x2d, 0x4c, 0xff, 0x7d, 0x1c, 0x2f, 0xff, 0x26, 0x00, 0x00, 0xff, 0x2f, 0x00, 0x01, 0xff, 0x29, 0x00, 0x00, 0xff, 0xc9, 0x36, 0x61, 0xff, 0xff, 0x48, 0x83, 0xff, 0xfd, 0x46, 0x7e, 0xff, 0xfd, 0x46, 0x7e, 0xff, 0xfd, 0x46, 0x7f, 0xff, 0xfd, 0x46, 0x7f, 0xff, 0xfd, 0x44, 0x7e, 0xff, 0xfd, 0x42, 0x7e, 0xff, 0xfd, 0x3b, 0x82, 0xff, 0xfd, 0x3b, 0x84, 0xff, 0xfd, 0x3d, 0x86, 0xff, 0xfd, 0x3e, 0x87, 0xff, 0xfd, 0x3d, 0x87, 0xff, 0xfd, 0x3a, 0x87, 0xff, 0xfc, 0x3a, 0x87, 0xff, 0xfd, 0x3c, 0x88, 0xff, 0xfd, 0x3d, 0x87, 0xff, 0xfd, 0x3c, 0x85, 0xff, 0xfd, 0x3b, 0x84, 0xff, 0xff, 0x3c, 0x87, 0xff, 0xe9, 0x2c, 0x70, 0xff, 0xa9, 0x19, 0x36, 0xff, 0xa7, 0x21, 0x31, 0xff, 0xa5, 0x1d, 0x2f, 0xff, 0xd0, 0x2e, 0x3c, 0xff, 0xeb, 0x43, 0x43, 0xff, 0xa2, 0x23, 0x2d, 0xff, 0x9c, 0x23, 0x2d, 0xff, 0x9e, 0x23, 0x2d, 0xff, 0xa7, 0x27, 0x2f, 0xff, 0xa0, 0x25, 0x31, 0xff, 0x9f, 0x27, 0x31, 0xff, 0xa1, 0x28, 0x32, 0xff, 0xa3, 0x29, 0x33, 0xff, 0xa7, 0x2a, 0x35, 0xff, 0x90, 0x21, 0x28, 0xff, 0x40, 0x03, 0x01, 0xff, 0x42, 0x03, 0x00, 0xff, 0x41, 0x02, 0x01, 0xff,
0xfa, 0xfa, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf2, 0xf3, 0xf1, 0xff, 0xf0, 0xf2, 0xef, 0xff, 0xef, 0xf1, 0xee, 0xff, 0xef, 0xf1, 0xee, 0xff, 0xef, 0xf1, 0xed, 0xff, 0xef, 0xf1, 0xed, 0xff, 0xef, 0xf1, 0xed, 0xff, 0xf0, 0xf1, 0xed, 0xff, 0xf1, 0xf2, 0xed, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf3, 0xf4, 0xef, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf2, 0xf5, 0xf1, 0xff, 0xf2, 0xf5, 0xf2, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf3, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf4, 0xf7, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf2, 0xf5, 0xf2, 0xff, 0xf2, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf2, 0xf5, 0xf3, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf2, 0xf2, 0xee, 0xff, 0xf2, 0xf2, 0xee, 0xff, 0xf2, 0xf3, 0xef, 0xff, 0xf2, 0xf4, 0xef, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf3, 0xf4, 0xf1, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf7, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0xb9, 0xb5, 0xff, 0x38, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x37, 0x00, 0x00, 0xff, 0xb6, 0x2d, 0x55, 0xff, 0x71, 0x18, 0x2d, 0xff, 0x25, 0x00, 0x00, 0xff, 0x29, 0x00, 0x00, 0xff, 0x4f, 0x0d, 0x16, 0xff, 0xf9, 0x45, 0x7c, 0xff, 0xff, 0x45, 0x7d, 0xff, 0xfd, 0x44, 0x7c, 0xff, 0xfd, 0x45, 0x7d, 0xff, 0xfd, 0x46, 0x7d, 0xff, 0xfd, 0x46, 0x7e, 0xff, 0xfd, 0x44, 0x7e, 0xff, 0xfd, 0x42, 0x7e, 0xff, 0xfd, 0x41, 0x7d, 0xff, 0xfd, 0x42, 0x7e, 0xff, 0xfd, 0x44, 0x80, 0xff, 0xfd, 0x45, 0x81, 0xff, 0xfd, 0x45, 0x80, 0xff, 0xfd, 0x45, 0x80, 0xff, 0xfd, 0x44, 0x80, 0xff, 0xfd, 0x45, 0x80, 0xff, 0xfd, 0x44, 0x80, 0xff, 0xfd, 0x44, 0x7f, 0xff, 0xfd, 0x43, 0x7f, 0xff, 0xfc, 0x40, 0x7b, 0xff, 0xb9, 0x23, 0x40, 0xff, 0xa4, 0x1f, 0x30, 0xff, 0xa5, 0x1f, 0x31, 0xff, 0xc2, 0x28, 0x39, 0xff, 0xf3, 0x40, 0x48, 0xff, 0xac, 0x25, 0x31, 0xff, 0x9a, 0x22, 0x2c, 0xff, 0x9f, 0x25, 0x2f, 0xff, 0xa0, 0x26, 0x30, 0xff, 0xa0, 0x26, 0x30, 0xff, 0xa1, 0x27, 0x31, 0xff, 0xa1, 0x28, 0x32, 0xff, 0xa3, 0x29, 0x33, 0xff, 0xa4, 0x29, 0x34, 0xff, 0xaa, 0x2b, 0x37, 0xff, 0x77, 0x17, 0x1c, 0xff, 0x3c, 0x01, 0x00, 0xff, 0x43, 0x04, 0x01, 0xff, 0x43, 0x02, 0x01, 0xff,
0xfa, 0xfa, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf5, 0xf7, 0xf3, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf1, 0xf4, 0xf1, 0xff, 0xf1, 0xf4, 0xf1, 0xff, 0xf0, 0xf3, 0xf0, 0xff, 0xf1, 0xf3, 0xef, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf1, 0xf2, 0xee, 0xff, 0xf1, 0xf2, 0xed, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf3, 0xf4, 0xef, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf3, 0xf6, 0xf3, 0xff, 0xf3, 0xf6, 0xf3, 0xff, 0xf4, 0xf7, 0xf3, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf5, 0xf7, 0xf3, 0xff, 0xf4, 0xf7, 0xf3, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf2, 0xf5, 0xf2, 0xff, 0xf2, 0xf5, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf1, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf2, 0xf5, 0xf3, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf3, 0xf4, 0xf2, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf4, 0xf4, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf6, 0xf4, 0xf3, 0xff, 0xf6, 0xf4, 0xf3, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xfb, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xe4, 0xdb, 0xd7, 0xff, 0x41, 0x09, 0x09, 0xff, 0x3b, 0x00, 0x00, 0xff, 0x35, 0x00, 0x00, 0xff, 0xac, 0x26, 0x4f, 0xff, 0x7d, 0x18, 0x35, 0xff, 0x1d, 0x00, 0x00, 0xff, 0x21, 0x00, 0x00, 0xff, 0x91, 0x21, 0x3b, 0xff, 0xff, 0x47, 0x82, 0xff, 0xfd, 0x43, 0x79, 0xff, 0xfd, 0x43, 0x7a, 0xff, 0xfd, 0x44, 0x7c, 0xff, 0xfd, 0x43, 0x7d, 0xff, 0xfd, 0x44, 0x7e, 0xff, 0xfd, 0x43, 0x7d, 0xff, 0xfd, 0x42, 0x7d, 0xff, 0xfd, 0x43, 0x7d, 0xff, 0xfc, 0x44, 0x7d, 0xff, 0xfd, 0x45, 0x7f, 0xff, 0xfd, 0x45, 0x80, 0xff, 0xfd, 0x46, 0x80, 0xff, 0xfd, 0x46, 0x80, 0xff, 0xfd, 0x45, 0x80, 0xff, 0xfd, 0x44, 0x7f, 0xff, 0xfd, 0x42, 0x7f, 0xff, 0xfd, 0x42, 0x7e, 0xff, 0xff, 0x43, 0x81, 0xff, 0xdf, 0x32, 0x60, 0xff, 0xa5, 0x1e, 0x31, 0xff, 0xa6, 0x20, 0x33, 0xff, 0xb3, 0x22, 0x36, 0xff, 0xf4, 0x3f, 0x4b, 0xff, 0xbf, 0x2c, 0x39, 0xff, 0x9a, 0x21, 0x2d, 0xff, 0x9f, 0x25, 0x2f, 0xff, 0xa0, 0x26, 0x30, 0xff, 0xa1, 0x27, 0x31, 0xff, 0xa2, 0x27, 0x32, 0xff, 0xa3, 0x28, 0x32, 0xff, 0xa3, 0x2a, 0x33, 0xff, 0xa3, 0x2a, 0x34, 0xff, 0xa4, 0x2a, 0x34, 0xff, 0xab, 0x2b, 0x36, 0xff, 0x66, 0x11, 0x13, 0xff, 0x3c, 0x02, 0x00, 0xff, 0x42, 0x04, 0x02, 0xff, 0x42, 0x02, 0x01, 0xff,
0xfa, 0xfa, 0xf5, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf3, 0xf6, 0xf3, 0xff, 0xf2, 0xf6, 0xf3, 0xff, 0xf2, 0xf6, 0xf3, 0xff, 0xf2, 0xf6, 0xf2, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf2, 0xf4, 0xef, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf2, 0xf3, 0xee, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf3, 0xf4, 0xef, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf2, 0xf5, 0xf1, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf4, 0xf7, 0xf4, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf5, 0xf8, 0xf3, 0xff, 0xf4, 0xf7, 0xf3, 0xff, 0xf4, 0xf7, 0xf3, 0xff, 0xf3, 0xf6, 0xf2, 0xff, 0xf2, 0xf5, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf0, 0xf4, 0xf1, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf2, 0xf5, 0xf3, 0xff, 0xf3, 0xf5, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf4, 0xf1, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf3, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf6, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf8, 0xf8, 0xf2, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfd, 0xfc, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0x54, 0x53, 0xff, 0x2f, 0x00, 0x00, 0xff, 0x32, 0x00, 0x00, 0xff, 0x79, 0x14, 0x2b, 0xff, 0xca, 0x28, 0x61, 0xff, 0x24, 0x00, 0x00, 0xff, 0x1c, 0x00, 0x00, 0xff, 0xcd, 0x34, 0x5d, 0xff, 0xff, 0x44, 0x7c, 0xff, 0xfd, 0x43, 0x76, 0xff, 0xfd, 0x44, 0x77, 0xff, 0xfd, 0x44, 0x79, 0xff, 0xfd, 0x43, 0x7c, 0xff, 0xfd, 0x42, 0x7e, 0xff, 0xfd, 0x42, 0x7d, 0xff, 0xfd, 0x43, 0x7d, 0xff, 0xfd, 0x45, 0x7c, 0xff, 0xfd, 0x46, 0x7d, 0xff, 0xfd, 0x46, 0x7f, 0xff, 0xfd, 0x45, 0x80, 0xff, 0xfd, 0x46, 0x81, 0xff, 0xfd, 0x46, 0x80, 0xff, 0xfd, 0x45, 0x80, 0xff, 0xfd, 0x44, 0x7f, 0xff, 0xfd, 0x42, 0x7d, 0xff, 0xfe, 0x42, 0x7e, 0xff, 0xfd, 0x40, 0x7c, 0xff, 0xbb, 0x25, 0x41, 0xff, 0xa5, 0x1f, 0x30, 0xff, 0xa7, 0x1e, 0x32, 0xff, 0xe4, 0x3c, 0x48, 0xff, 0xd9, 0x38, 0x44, 0xff, 0x9e, 0x21, 0x31, 0xff, 0xa1, 0x25, 0x31, 0xff, 0xa0, 0x27, 0x32, 0xff, 0xa1, 0x28, 0x32, 0xff, 0xa1, 0x28, 0x33, 0xff, 0xa1, 0x28, 0x32, 0xff, 0xa3, 0x29, 0x33, 0xff, 0xa4, 0x2a, 0x34, 0xff, 0xa3, 0x2b, 0x34, 0xff, 0xa4, 0x2b, 0x35, 0xff, 0xaa, 0x2c, 0x36, 0xff, 0x61, 0x0f, 0x11, 0xff, 0x3a, 0x01, 0x00, 0xff, 0x41, 0x04, 0x01, 0xff, 0x41, 0x02, 0x01, 0xff,
0xfa, 0xfa, 0xf5, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf4, 0xf6, 0xf4, 0xff, 0xf3, 0xf6, 0xf4, 0xff, 0xf4, 0xf6, 0xf4, 0xff, 0xf4, 0xf7, 0xf5, 0xff, 0xf4, 0xf6, 0xf4, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf4, 0xf4, 0xf0, 0xff, 0xf4, 0xf4, 0xee, 0xff, 0xf3, 0xf3, 0xee, 0xff, 0xf3, 0xf3, 0xee, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf3, 0xf5, 0xf1, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf4, 0xf7, 0xf3, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf6, 0xf8, 0xf4, 0xff, 0xf5, 0xf8, 0xf4, 0xff, 0xf5, 0xf7, 0xf3, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf2, 0xf4, 0xf1, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf1, 0xf4, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf4, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf4, 0xf6, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xed, 0xdc, 0xdd, 0xff, 0x58, 0x14, 0x1d, 0xff, 0x26, 0x00, 0x00, 0xff, 0x2c, 0x00, 0x00, 0xff, 0xa9, 0x20, 0x4d, 0xff, 0xc2, 0x24, 0x5d, 0xff, 0x58, 0x0d, 0x1f, 0xff, 0xef, 0x3e, 0x6f, 0xff, 0xff, 0x43, 0x77, 0xff, 0xfd, 0x43, 0x75, 0xff, 0xfd, 0x44, 0x77, 0xff, 0xfd, 0x45, 0x78, 0xff, 0xfd, 0x44, 0x79, 0xff, 0xfd, 0x42, 0x79, 0xff, 0xfd, 0x43, 0x7a, 0xff, 0xfd, 0x44, 0x7c, 0xff, 0xfd, 0x45, 0x7c, 0xff, 0xfd, 0x46, 0x7d, 0xff, 0xfd, 0x46, 0x7d, 0xff, 0xfd, 0x45, 0x7d, 0xff, 0xfd, 0x45, 0x7e, 0xff, 0xfd, 0x46, 0x80, 0xff, 0xfd, 0x46, 0x80, 0xff, 0xfd, 0x44, 0x7e, 0xff, 0xfd, 0x41, 0x7d, 0xff, 0xff, 0x42, 0x7e, 0xff, 0xe9, 0x37, 0x68, 0xff, 0xa7, 0x1e, 0x31, 0xff, 0xa4, 0x1d, 0x2f, 0xff, 0xcb, 0x30, 0x40, 0xff, 0xef, 0x46, 0x4e, 0xff, 0xa3, 0x22, 0x32, 0xff, 0x9f, 0x24, 0x32, 0xff, 0xa2, 0x27, 0x33, 0xff, 0xa2, 0x28, 0x35, 0xff, 0xa3, 0x2a, 0x35, 0xff, 0xa4, 0x2a, 0x35, 0xff, 0xa3, 0x29, 0x33, 0xff, 0xa3, 0x29, 0x33, 0xff, 0xa3, 0x29, 0x33, 0xff, 0xa3, 0x29, 0x33, 0xff, 0xa3, 0x2a, 0x34, 0xff, 0xaa, 0x2b, 0x36, 0xff, 0x6c, 0x13, 0x16, 0xff, 0x38, 0x02, 0x00, 0xff, 0x40, 0x04, 0x02, 0xff, 0x41, 0x02, 0x01, 0xff,
0xf9, 0xfa, 0xf5, 0xff, 0xf8, 0xf9, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf7, 0xf5, 0xff, 0xf4, 0xf6, 0xf4, 0xff, 0xf4, 0xf7, 0xf5, 0xff, 0xf5, 0xf7, 0xf5, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf5, 0xf6, 0xf1, 0xff, 0xf5, 0xf5, 0xf0, 0xff, 0xf4, 0xf4, 0xef, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf4, 0xf3, 0xef, 0xff, 0xf3, 0xf3, 0xef, 0xff, 0xf3, 0xf4, 0xf0, 0xff, 0xf4, 0xf5, 0xf1, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf5, 0xf7, 0xf3, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf7, 0xf9, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf3, 0xf5, 0xf2, 0xff, 0xf2, 0xf4, 0xf2, 0xff, 0xf2, 0xf4, 0xf2, 0xff, 0xf2, 0xf4, 0xf2, 0xff, 0xf4, 0xf5, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf5, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf5, 0xff, 0xf5, 0xf6, 0xf5, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf5, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf4, 0xf5, 0xf4, 0xff, 0xf4, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xfc, 0xfa, 0xf5, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xdc, 0xc4, 0xc6, 0xff, 0xcd, 0x34, 0x6e, 0xff, 0x7c, 0x16, 0x36, 0xff, 0x1f, 0x00, 0x00, 0xff, 0x17, 0x00, 0x00, 0xff, 0x79, 0x14, 0x35, 0xff, 0xd5, 0x28, 0x60, 0xff, 0xfe, 0x3f, 0x72, 0xff, 0xfd, 0x41, 0x74, 0xff, 0xfd, 0x42, 0x75, 0xff, 0xfd, 0x43, 0x76, 0xff, 0xfd, 0x43, 0x76, 0xff, 0xfd, 0x43, 0x76, 0xff, 0xfd, 0x43, 0x76, 0xff, 0xfd, 0x44, 0x78, 0xff, 0xfd, 0x44, 0x7b, 0xff, 0xfd, 0x45, 0x7b, 0xff, 0xfd, 0x46, 0x7a, 0xff, 0xfd, 0x46, 0x79, 0xff, 0xfd, 0x45, 0x7a, 0xff, 0xfd, 0x45, 0x7b, 0xff, 0xfc, 0x45, 0x7c, 0xff, 0xfd, 0x44, 0x7d, 0xff, 0xfd, 0x43, 0x7c, 0xff, 0xfd, 0x41, 0x7a, 0xff, 0xff, 0x40, 0x7b, 0xff, 0xc5, 0x29, 0x4a, 0xff, 0x9f, 0x1d, 0x2c, 0xff, 0xb1, 0x21, 0x32, 0xff, 0xf4, 0x48, 0x50, 0xff, 0xb8, 0x2e, 0x3a, 0xff, 0x9b, 0x22, 0x2f, 0xff, 0xa1, 0x26, 0x32, 0xff, 0xa1, 0x28, 0x33, 0xff, 0xa2, 0x29, 0x36, 0xff, 0xa4, 0x2a, 0x36, 0xff, 0xa5, 0x2b, 0x35, 0xff, 0xa3, 0x28, 0x32, 0xff, 0xa2, 0x24, 0x2e, 0xff, 0xa2, 0x24, 0x2e, 0xff, 0xa1, 0x26, 0x30, 0xff, 0xa1, 0x26, 0x30, 0xff, 0xa6, 0x25, 0x30, 0xff, 0x74, 0x12, 0x13, 0xff, 0x37, 0x00, 0x00, 0xff, 0x3f, 0x02, 0x01, 0xff, 0x41, 0x01, 0x00, 0xff,
0xfa, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf2, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf6, 0xf5, 0xf0, 0xff, 0xf5, 0xf4, 0xf0, 0xff, 0xf5, 0xf4, 0xef, 0xff, 0xf5, 0xf4, 0xef, 0xff, 0xf5, 0xf4, 0xf0, 0xff, 0xf5, 0xf5, 0xf1, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf8, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf9, 0xf5, 0xff, 0xf9, 0xf9, 0xf5, 0xff, 0xf9, 0xf9, 0xf5, 0xff, 0xf8, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf4, 0xf5, 0xf2, 0xff, 0xf5, 0xf5, 0xf2, 0xff, 0xf5, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf6, 0xf5, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf6, 0xf4, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf5, 0xf6, 0xf4, 0xff, 0xf4, 0xf6, 0xf3, 0xff, 0xf5, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf8, 0xf7, 0xf3, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfd, 0xfb, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x61, 0x5c, 0xff, 0x4d, 0x00, 0x09, 0xff, 0xc6, 0x2f, 0x67, 0xff, 0xba, 0x2a, 0x62, 0xff, 0x42, 0x0a, 0x16, 0xff, 0x00, 0x00, 0x00, 0xff, 0x93, 0x21, 0x3d, 0xff, 0xff, 0x41, 0x76, 0xff, 0xfd, 0x3f, 0x71, 0xff, 0xfd, 0x40, 0x72, 0xff, 0xfd, 0x41, 0x73, 0xff, 0xfd, 0x42, 0x74, 0xff, 0xfd, 0x42, 0x74, 0xff, 0xfd, 0x44, 0x75, 0xff, 0xfd, 0x44, 0x77, 0xff, 0xfd, 0x45, 0x7a, 0xff, 0xfd, 0x46, 0x7a, 0xff, 0xfd, 0x46, 0x78, 0xff, 0xfd, 0x45, 0x77, 0xff, 0xfd, 0x44, 0x77, 0xff, 0xfd, 0x44, 0x79, 0xff, 0xfd, 0x44, 0x7a, 0xff, 0xfd, 0x43, 0x7a, 0xff, 0xfd, 0x40, 0x78, 0xff, 0xff, 0x3f, 0x78, 0xff, 0xf4, 0x37, 0x6e, 0xff, 0xa9, 0x20, 0x33, 0xff, 0x9d, 0x1d, 0x2b, 0xff, 0xd8, 0x33, 0x3c, 0xff, 0xde, 0x3c, 0x40, 0xff, 0x9b, 0x22, 0x2c, 0xff, 0x9f, 0x24, 0x30, 0xff, 0xa0, 0x26, 0x31, 0xff, 0xa1, 0x27, 0x32, 0xff, 0xa1, 0x28, 0x33, 0xff, 0xa3, 0x29, 0x34, 0xff, 0xa3, 0x27, 0x32, 0xff, 0xa8, 0x3b, 0x44, 0xff, 0xaf, 0x54, 0x5c, 0xff, 0xae, 0x4e, 0x55, 0xff, 0xaa, 0x41, 0x49, 0xff, 0xac, 0x41, 0x4a, 0xff, 0xa4, 0x44, 0x49, 0xff, 0x85, 0x32, 0x2f, 0xff, 0x65, 0x32, 0x30, 0xff, 0x43, 0x07, 0x06, 0xff, 0x40, 0x00, 0x00, 0xff,
0xfb, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf6, 0xf7, 0xf4, 0xff, 0xf6, 0xf7, 0xf5, 0xff, 0xf7, 0xf7, 0xf4, 0xff, 0xf7, 0xf8, 0xf4, 0xff, 0xf8, 0xf8, 0xf4, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf7, 0xf2, 0xff, 0xf8, 0xf7, 0xf1, 0xff, 0xf7, 0xf7, 0xf1, 0xff, 0xf7, 0xf6, 0xf1, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xf9, 0xfa, 0xf5, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf6, 0xf6, 0xf3, 0xff, 0xf6, 0xf7, 0xf3, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf7, 0xf7, 0xf2, 0xff, 0xf6, 0xf7, 0xf2, 0xff, 0xf6, 0xf6, 0xf2, 0xff, 0xf7, 0xf7, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf9, 0xf5, 0xff, 0xf9, 0xf8, 0xf4, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xf9, 0xf9, 0xf4, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf7, 0xf8, 0xf3, 0xff, 0xf8, 0xf8, 0xf3, 0xff, 0xf9, 0xf8, 0xf2, 0xff, 0xf9, 0xf9, 0xf3, 0xff, 0xfa, 0xf9, 0xf4, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf7, 0xf5, 0xf2, 0xff, 0x59, 0x24, 0x23, 0xff, 0x37, 0x00, 0x00, 0xff, 0x3b, 0x00, 0x00, 0xff, 0x84, 0x18, 0x35, 0xff, 0xae, 0x20, 0x4a, 0xff, 0x24, 0x00, 0x00, 0xff, 0xb9, 0x2c, 0x4e, 0xff, 0xff, 0x3f, 0x73, 0xff, 0xfd, 0x3d, 0x6d, 0xff, 0xfd, 0x3e, 0x6e, 0xff, 0xfd, 0x3f, 0x6e, 0xff, 0xfd, 0x40, 0x70, 0xff, 0xfd, 0x41, 0x71, 0xff, 0xfd, 0x42, 0x73, 0xff, 0xfd, 0x43, 0x75, 0xff, 0xfd, 0x44, 0x77, 0xff, 0xfd, 0x45, 0x77, 0xff, 0xfd, 0x45, 0x76, 0xff, 0xfd, 0x44, 0x74, 0xff, 0xfd, 0x43, 0x74, 0xff, 0xfd, 0x43, 0x75, 0xff, 0xfd, 0x42, 0x76, 0xff, 0xfd, 0x41, 0x76, 0xff, 0xfd, 0x3f, 0x73, 0xff, 0xff, 0x3e, 0x76, 0xff, 0xd7, 0x2d, 0x55, 0xff, 0x9d, 0x1e, 0x2b, 0xff, 0xab, 0x23, 0x2f, 0xff, 0xf3, 0x45, 0x42, 0xff, 0xb3, 0x29, 0x30, 0xff, 0x9b, 0x21, 0x2c, 0xff, 0x9e, 0x24, 0x2e, 0xff, 0x9e, 0x25, 0x2f, 0xff, 0x9f, 0x26, 0x30, 0xff, 0xa0, 0x26, 0x30, 0xff, 0xa2, 0x27, 0x31, 0xff, 0xa0, 0x22, 0x2c, 0xff, 0xae, 0x51, 0x58, 0xff, 0xc2, 0x8f, 0x94, 0xff, 0xc2, 0x8d, 0x91, 0xff, 0xbc, 0x7a, 0x80, 0xff, 0xbe, 0x7c, 0x81, 0xff, 0xa6, 0x6f, 0x6e, 0xff, 0xaa, 0x79, 0x77, 0xff, 0xa8, 0x84, 0x83, 0xff, 0x47, 0x0e, 0x0e, 0xff, 0x3e, 0x00, 0x00, 0xff,
0xfc, 0xfd, 0xf8, 0xff, 0xfd, 0xfc, 0xf9, 0xff, 0xfc, 0xfc, 0xf8, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfa, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfb, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfb, 0xfa, 0xf7, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfb, 0xfa, 0xf6, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfa, 0xfa, 0xf5, 0xff, 0xfa, 0xf9, 0xf5, 0xff, 0xf9, 0xf9, 0xf5, 0xff, 0xfa, 0xfa, 0xf6, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfb, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf7, 0xff, 0xfd, 0xfc, 0xf7, 0xff, 0xfd, 0xfc, 0xf7, 0xff, 0xfc, 0xfc, 0xf7, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfc, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfc, 0xfb, 0xf5, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfc, 0xfb, 0xf6, 0xff, 0xfd, 0xfb, 0xf6, 0xff, 0xfd, 0xfc, 0xf7, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0xc3, 0xc0, 0xff, 0x3d, 0x00, 0x00, 0xff, 0x43, 0x00, 0x00, 0xff, 0x40, 0x00, 0x00, 0xff, 0x32, 0x00, 0x00, 0xff, 0xa1, 0x10, 0x29, 0xff, 0xb1, 0x13, 0x31, 0xff, 0xe9, 0x37, 0x61, 0xff, 0xff, 0x3e, 0x6e, 0xff, 0xfe, 0x3c, 0x6b, 0xff, 0xfe, 0x3c, 0x6b, 0xff, 0xfd, 0x3d, 0x6b, 0xff, 0xfd, 0x3e, 0x6b, 0xff, 0xfd, 0x3f, 0x6b, 0xff, 0xfd, 0x41, 0x6d, 0xff, 0xfd, 0x42, 0x6f, 0xff, 0xfd, 0x41, 0x71, 0xff, 0xfe, 0x42, 0x72, 0xff, 0xfd, 0x43, 0x71, 0xff, 0xfd, 0x42, 0x70, 0xff, 0xfd, 0x42, 0x70, 0xff, 0xfe, 0x42, 0x71, 0xff, 0xfd, 0x41, 0x73, 0xff, 0xfd, 0x40, 0x72, 0xff, 0xfe, 0x3f, 0x71, 0xff, 0xfd, 0x3c, 0x6f, 0xff, 0xb3, 0x25, 0x39, 0xff, 0x9a, 0x1d, 0x29, 0xff, 0xca, 0x31, 0x34, 0xff, 0xe9, 0x44, 0x3b, 0xff, 0x9e, 0x1f, 0x29, 0xff, 0x9d, 0x21, 0x2b, 0xff, 0x9d, 0x22, 0x2c, 0xff, 0x9d, 0x22, 0x2d, 0xff, 0x9e, 0x23, 0x2d, 0xff, 0xa0, 0x25, 0x2e, 0xff, 0xa2, 0x25, 0x2e, 0xff, 0xa2, 0x24, 0x2d, 0xff, 0xa3, 0x2a, 0x34, 0xff, 0xa5, 0x31, 0x3b, 0xff, 0xa3, 0x31, 0x39, 0xff, 0xa4, 0x2d, 0x36, 0xff, 0x95, 0x25, 0x2b, 0xff, 0x77, 0x20, 0x1b, 0xff, 0x79, 0x22, 0x1f, 0xff, 0x7a, 0x1f, 0x1b, 0xff, 0x51, 0x09, 0x07, 0xff, 0x3d, 0x00, 0x00, 0xff,
0xfe, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfd, 0xfd, 0xfa, 0xff, 0xfe, 0xfd, 0xf8, 0xff, 0xfe, 0xfc, 0xf8, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfe, 0xfd, 0xf8, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfd, 0xfa, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfd, 0xfa, 0xff, 0xfe, 0xfd, 0xf8, 0xff, 0xfd, 0xfd, 0xf8, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfd, 0xfa, 0xff, 0xfe, 0xfd, 0xfa, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xff, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfc, 0xf8, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfc, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfb, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfe, 0xf9, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfe, 0xfe, 0xfa, 0xff, 0xfd, 0xfd, 0xf9, 0xff, 0xfe, 0xfd, 0xf9, 0xff, 0xfe, 0xfe, 0xfc, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9d, 0x7d, 0x7b, 0xff, 0x37, 0x00, 0x00, 0xff, 0x43, 0x01, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x54, 0x05, 0x09, 0xff, 0xcf, 0x1c, 0x40, 0xff, 0xca, 0x1a, 0x3f, 0xff, 0xfb, 0x3b, 0x68, 0xff, 0xff, 0x3c, 0x6b, 0xff, 0xfe, 0x3b, 0x68, 0xff, 0xfe, 0x3a, 0x68, 0xff, 0xfe, 0x3b, 0x69, 0xff, 0xfe, 0x3c, 0x69, 0xff, 0xfe, 0x3d, 0x68, 0xff, 0xfe, 0x3e, 0x68, 0xff, 0xfe, 0x3e, 0x69, 0xff, 0xfe, 0x3d, 0x6c, 0xff, 0xfe, 0x3f, 0x6e, 0xff, 0xfe, 0x3f, 0x6e, 0xff, 0xfe, 0x3f, 0x6c, 0xff, 0xfe, 0x3f, 0x6c, 0xff, 0xfe, 0x3f, 0x6e, 0xff, 0xfd, 0x3f, 0x70, 0xff, 0xfd, 0x3f, 0x71, 0xff, 0xff, 0x40, 0x74, 0xff, 0xe8, 0x36, 0x5f, 0xff, 0x9e, 0x1f, 0x2a, 0xff, 0xa0, 0x1e, 0x2b, 0xff, 0xea, 0x42, 0x38, 0xff, 0xc7, 0x33, 0x2e, 0xff, 0x9b, 0x1e, 0x27, 0xff, 0x9d, 0x20, 0x2a, 0xff, 0x9d, 0x20, 0x2a, 0xff, 0x9d, 0x20, 0x2b, 0xff, 0x9e, 0x22, 0x2c, 0xff, 0xa0, 0x23, 0x2d, 0xff, 0xa1, 0x23, 0x2d, 0xff, 0xa1, 0x23, 0x2d, 0xff, 0xa0, 0x20, 0x2b, 0xff, 0x9f, 0x1e, 0x28, 0xff, 0x9f, 0x1e, 0x27, 0xff, 0xa1, 0x1f, 0x28, 0xff, 0x7f, 0x12, 0x13, 0xff, 0x66, 0x09, 0x04, 0xff, 0x69, 0x0a, 0x05, 0xff, 0x6b, 0x0b, 0x07, 0xff, 0x68, 0x0c, 0x08, 0xff, 0x46, 0x03, 0x02, 0xff,
};
const lv_image_dsc_t img_app_pos = {
.header.cf = LV_COLOR_FORMAT_ARGB8888,
.header.magic = LV_IMAGE_HEADER_MAGIC,
.header.w = 112,
.header.h = 112,
.data_size = 12544 * 4,
.data = output_112x112_map,
};
@@ -0,0 +1,10 @@
#ifndef VOLC_LVGL_SOURCE_H__
#define VOLC_LVGL_SOURCE_H__
#include "lvgl.h"
extern lv_font_t echoear_font_16;
extern lv_image_dsc_t img_app_pos;
#endif
@@ -0,0 +1,60 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include "volc_hal_file.h"
#include "volc_hal.h"
#include "volc_osal.h"
#include "driver/gpio.h"
#include "esp_mac.h"
#include <stdio.h>
#include "audio_processor.h"
#include "basic_board.h"
#define DEVICE_NAME_PREFIX "esp32_"
volc_hal_context_t* global_context = NULL;
basic_board_periph_t global_periph = {0};
static void __gmf_audio_init()
{
audio_manager_config_t config = DEFAULT_AUDIO_MANAGER_CONFIG();
basic_board_init(&global_periph);
config.play_dev = global_periph.play_dev;
config.rec_dev = global_periph.rec_dev;
strcpy(config.mic_layout, global_periph.mic_layout);
config.board_sample_rate = global_periph.sample_rate;
config.board_bits = global_periph.sample_bits;
config.board_channels = global_periph.channels;
audio_manager_init(&config);
}
static void __generate_device_name(char* device_name){
uint8_t mac[6] = {0};
ESP_ERROR_CHECK(esp_read_mac(mac, ESP_MAC_WIFI_STA));
// printf("WIFI_STA MAC 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x \n",
// mac[0], mac[1], mac[2],
// mac[3], mac[4], mac[5]);
snprintf(device_name,VOLC_DEVICE_NAME_LENGTH,"%s%02X%02X%02X%02X%02X%02X",DEVICE_NAME_PREFIX,mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
int volc_hal_init(void) {
if(global_context == NULL){
global_context = (volc_hal_context_t*) volc_osal_calloc(1,sizeof(volc_hal_context_t));
}
__gmf_audio_init();
volc_hal_file_system_init();
__generate_device_name(global_context->device_name);
return 0;
}
volc_hal_context_t* volc_get_global_hal_context(){
return global_context;
}
void volc_hal_fini(void) {
volc_osal_free(global_context);
global_context = NULL;
return;
}
@@ -0,0 +1,136 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include <stddef.h>
#include "volc_hal.h"
#include "volc_hal_button.h"
#include "iot_button.h"
#include "button_gpio.h"
#include "util/volc_log.h"
#include "volc_osal.h"
typedef struct {
button_handle_t btn;
volc_hal_button_config_t config;
} volc_hal_button_impl_t;
static void __button_event_cb_adapter(void* btn_handle, void* usr_data)
{
if (NULL == usr_data) {
return;
}
struct {
volc_hal_button_impl_t* button_impl;
button_event_t event;
} *adapter_data = (void*)usr_data;
if (NULL != adapter_data->button_impl && NULL != adapter_data->button_impl->config.event_cb) {
adapter_data->button_impl->config.event_cb(
(volc_hal_button_t)adapter_data->button_impl,
(volc_hal_button_event_e)adapter_data->event,
adapter_data->button_impl->config.user_data
);
}
}
volc_hal_button_t volc_hal_button_create(volc_hal_button_config_t* config)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return NULL;
}
if (NULL == config) {
LOGW("invalid input config %p", config);
return NULL;
}
volc_hal_button_impl_t *button_impl = (volc_hal_button_impl_t *)volc_osal_malloc(sizeof(volc_hal_button_impl_t));
if (NULL == button_impl) {
LOGE("memory alloc failed");
return NULL;
}
button_impl->config.gpio_num = config->gpio_num;
button_impl->config.active_level = config->active_level;
button_impl->config.long_press_ms = config->long_press_ms;
button_impl->config.short_press_ms = config->short_press_ms;
button_impl->config.enable_power_save = config->enable_power_save;
button_impl->config.user_data = config->user_data;
button_impl->config.event_cb = config->event_cb;
button_config_t btn_config = {
// .type = BUTTON_TYPE_GPIO,
// .gpio_button_config.gpio_num = button_impl->config.gpio_num,
// .gpio_button_config.active_level = button_impl->config.active_level,
.long_press_time = button_impl->config.long_press_ms,
.short_press_time = button_impl->config.short_press_ms
};
button_driver_t driver_config = {
.enable_power_save = button_impl->config.enable_power_save,
.get_key_level = NULL,
.enter_power_save = NULL,
.del = NULL,
};
iot_button_create(&btn_config,&driver_config,&button_impl->btn);
if (NULL == button_impl->btn) {
LOGE("button create failed");
volc_osal_free(button_impl);
return NULL;
}
struct {
volc_hal_button_impl_t* button_impl;
button_event_t event;
} *adapter_data = NULL;
button_event_t events[] = {
BUTTON_PRESS_DOWN,
BUTTON_PRESS_UP,
BUTTON_PRESS_REPEAT,
BUTTON_PRESS_REPEAT_DONE,
BUTTON_SINGLE_CLICK,
BUTTON_DOUBLE_CLICK,
BUTTON_MULTIPLE_CLICK,
BUTTON_LONG_PRESS_START,
BUTTON_LONG_PRESS_HOLD,
BUTTON_LONG_PRESS_UP,
BUTTON_PRESS_END
};
for (int i = 0; i < sizeof(events)/sizeof(events[0]); i++) {
adapter_data = (void*)volc_osal_malloc(sizeof(*adapter_data));
if (NULL == adapter_data) {
LOGE("Failed to allocate adapter data for event %d", events[i]);
continue;
}
adapter_data->button_impl = button_impl;
adapter_data->event = events[i];
iot_button_register_cb(button_impl->btn, events[i], NULL,__button_event_cb_adapter, adapter_data);
}
g_hal_context->button_handle = (volc_hal_button_t)button_impl;
return (volc_hal_button_t)button_impl;
}
void volc_hal_button_destroy(volc_hal_button_t button)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return;
}
if (NULL == button) {
LOGW("invalid input button %p", button);
return;
}
volc_hal_button_impl_t *button_impl = (volc_hal_button_impl_t *)button;
if (NULL != button_impl->btn) {
iot_button_delete(button_impl->btn);
button_impl->btn = NULL;
}
g_hal_context->button_handle = NULL;
volc_osal_free(button_impl);
}
@@ -0,0 +1,286 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include <stddef.h>
#include "volc_hal.h"
#include "volc_hal_capture.h"
#include "volc_osal.h"
#include "audio_processor.h"
#include "av_processor_type.h"
#include "basic_board.h"
#include "esp_codec_dev.h"
#include "util/volc_log.h"
typedef enum {
WAKEUP = 0,
CAPTURE,
INITED,
} audio_pipeline_state_e;
typedef struct {
av_processor_encoder_config_t recorder_cfg;
audio_pipeline_state_e state;
} volc_hal_audio_capture_config_t;
typedef struct {
//TODO: add video capture config
void* video_capture_config;
} volc_hal_video_capture_config_t;
typedef struct {
volc_media_type_e media_type;
union {
volc_hal_audio_capture_config_t audio_capture_config;
volc_hal_video_capture_config_t video_capture_config;
};
volc_hal_capture_data_cb_t data_cb; // Data callback function
volc_hal_audio_wakeup_cb_t audio_wakeup_cb; // audio wakeup cb
void* user_data; // User data pointer
volc_osal_tid_t capture_thread;
volatile bool is_started;
} volc_hal_capture_impl_t;
extern basic_board_periph_t global_periph;
static int __volc_capture_get_default_read_size(volc_hal_capture_t capture)
{
// 60ms
#if (CONFIG_VOLC_AUDIO_G711A)
return (160*3);
#else
// 60 ms of 16 kHz mono PCM16: consume the complete encoder frame.
return 16000 * 60 / 1000 * sizeof(int16_t);
#endif
}
static void __volc_audio_capture_task(void *arg)
{
volc_hal_capture_impl_t *impl = (volc_hal_capture_impl_t *)arg;
LOGI("capture task started...");
int read_size = __volc_capture_get_default_read_size(impl);
uint8_t *read_buf = volc_osal_malloc(read_size);
// mem_assert(read_buf);
while(impl->is_started) {
int ret = audio_recorder_read_data(read_buf, read_size);
if (ret > 0 && impl->data_cb && impl->audio_capture_config.state == CAPTURE) {
#ifdef CONFIG_VOLC_AUDIO_G711A
volc_hal_frame_info_t frame_info = {
.data_type = VOLC_AUDIO_DATA_TYPE_G711A,
.user_data = impl->user_data,
};
impl->data_cb(impl, (const void *)read_buf, ret, &frame_info);
#else
volc_hal_frame_info_t frame_info = {
.data_type = VOLC_AUDIO_DATA_TYPE_PCM,
.user_data = impl->user_data,
};
impl->data_cb(impl, (const void *)read_buf, ret, &frame_info);
#endif
}
}
// audio_recorder_pause();
if (impl->capture_thread) {
volc_osal_thread_destroy(impl->capture_thread);
impl->capture_thread = NULL;
}
volc_osal_free(read_buf);
volc_osal_thread_exit(NULL);
}
volc_hal_capture_t volc_hal_capture_create(volc_hal_capture_config_t *config)
{
volc_hal_context_t *g_hal_context = volc_get_global_hal_context();
if (g_hal_context == NULL)
{
return NULL;
}
volc_hal_capture_impl_t *capture = (volc_hal_capture_impl_t *)volc_osal_calloc(1, sizeof(volc_hal_capture_impl_t));
// config
capture->is_started = false;
capture->media_type = config->media_type;
capture->data_cb = config->data_cb;
capture->audio_wakeup_cb = config->audio_wakeup_cb;
capture->user_data = config->user_data;
esp_codec_dev_set_in_gain(global_periph.rec_dev, 52.0);
switch (capture->media_type)
{
case VOLC_MEDIA_TYPE_AUDIO:
#if (CONFIG_VOLC_AUDIO_G711A)
capture->audio_capture_config.recorder_cfg.format = AV_PROCESSOR_FORMAT_ID_G711A;
#else
capture->audio_capture_config.recorder_cfg.format = AV_PROCESSOR_FORMAT_ID_PCM;
#endif
capture->audio_capture_config.recorder_cfg.params.g711.audio_info.sample_rate = 16000;
capture->audio_capture_config.recorder_cfg.params.g711.audio_info.sample_bits = 16;
capture->audio_capture_config.recorder_cfg.params.g711.audio_info.channels = 1;
capture->audio_capture_config.recorder_cfg.params.g711.audio_info.frame_duration = 60;
capture->audio_capture_config.state = INITED;
g_hal_context->capture_handle[VOLC_HAL_CAPTURE_AUDIO] = (volc_hal_capture_t)capture;
break;
case VOLC_MEDIA_TYPE_VIDEO:
// TODO: Add video capture support
LOGE("Video capture is not supported yet");
break;
default:
break;
}
return (volc_hal_capture_t)capture;
}
static void __start_audio_capture(volc_hal_capture_impl_t *capture)
{
// audio_pipeline_unlink(impl->audio_capture_config.audio_pipeline);
av_processor_afe_config_t afe_config = DEFAULT_AV_PROCESSOR_AFE_CONFIG();
afe_config.ai_mode_wakeup = false;
audio_recorder_config_t recorder_config = DEFAULT_AUDIO_RECORDER_CONFIG();
memcpy((void *)&recorder_config.encoder_cfg, &capture->audio_capture_config.recorder_cfg, sizeof(av_processor_encoder_config_t));
memcpy(&recorder_config.afe_config, &afe_config, sizeof(av_processor_afe_config_t));
recorder_config.recorder_event_cb = capture->audio_wakeup_cb;
recorder_config.recorder_ctx = NULL;
audio_recorder_open(&recorder_config);
volc_osal_thread_param_t param = {0};
snprintf(param.name, sizeof(param.name), "%s", "volc_capture_task");
param.stack_size = 4 * 1024;
param.priority = 5;
param.stack_in_ext = 1;
capture->is_started = true;
capture->audio_capture_config.state = CAPTURE;
esp_err_t ret = volc_osal_thread_create(&capture->capture_thread, &param, __volc_audio_capture_task, capture);
LOGI("capture task start... mode: CAPTURE");
return;
}
static void __start_audio_wake(volc_hal_capture_impl_t *capture)
{
av_processor_afe_config_t afe_config = DEFAULT_AV_PROCESSOR_AFE_CONFIG();
afe_config.ai_mode_wakeup = true;
audio_recorder_config_t recorder_config = DEFAULT_AUDIO_RECORDER_CONFIG();
memcpy((void *)&recorder_config.encoder_cfg, &capture->audio_capture_config.recorder_cfg, sizeof(av_processor_encoder_config_t));
memcpy(&recorder_config.afe_config, &afe_config, sizeof(av_processor_afe_config_t));
recorder_config.recorder_event_cb = capture->audio_wakeup_cb;
recorder_config.recorder_ctx = NULL;
audio_recorder_open(&recorder_config);
volc_osal_thread_param_t param = {0};
snprintf(param.name, sizeof(param.name), "%s", "volc_capture_task");
param.stack_size = 4 * 1024;
param.priority = 5;
param.stack_in_ext = 1;
capture->is_started = true;
capture->audio_capture_config.state = WAKEUP;
esp_err_t ret = volc_osal_thread_create(&capture->capture_thread, &param, __volc_audio_capture_task, capture);
LOGI("capture task start... mode: WAKEUP");
return;
}
int volc_hal_capture_start(volc_hal_capture_t capture,volc_hal_audio_capture_mode_e mode)
{
if(capture == NULL){
return -1;
}
volc_hal_capture_impl_t *impl = (volc_hal_capture_impl_t *)capture;
if (impl->media_type == VOLC_MEDIA_TYPE_AUDIO && impl->audio_capture_config.state == INITED) {
switch (mode)
{
case VOLC_AUDIO_MODE_WAKEUP:
__start_audio_wake(impl);
break;
case VOLC_AUDIO_MODE_CAPTURE:
__start_audio_capture(impl);
break;
default:
break;
}
}
return 0;
}
int volc_hal_capture_stop(volc_hal_capture_t capture)
{
volc_hal_capture_impl_t *impl = (volc_hal_capture_impl_t *)capture;
if (!impl || !impl->is_started) {
return 0;
}
// stop thread
impl->is_started = false;
switch (impl->media_type) {
case VOLC_MEDIA_TYPE_AUDIO:
// audio_recorder_pause();
// audio_recorder_resume();
audio_recorder_close();
impl->audio_capture_config.state = INITED;
break;
case VOLC_MEDIA_TYPE_VIDEO:
// TODO: Add video capture support
LOGE("Video capture is not supported yet");
break;
default:
break;
}
return 0;
}
void volc_hal_capture_destroy(volc_hal_capture_t capture)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return;
}
volc_hal_capture_impl_t *impl = (volc_hal_capture_impl_t *)capture;
if (!impl) {
return;
}
volc_hal_capture_stop(capture);
switch (impl->media_type) {
case VOLC_MEDIA_TYPE_AUDIO:
g_hal_context->capture_handle[VOLC_HAL_CAPTURE_AUDIO] = NULL;
break;
case VOLC_MEDIA_TYPE_VIDEO:
// TODO: Add video capture support
LOGE("Video capture is not supported yet");
break;
default:
break;
}
volc_osal_free(impl);
}
int volc_hal_capture_update_config(volc_hal_capture_t capture, volc_hal_capture_config_t* config) {
volc_hal_capture_impl_t *impl = (volc_hal_capture_impl_t *)capture;
if (!impl || !config) {
LOGE("capture or config is NULL");
return -1;
}
if (impl->media_type != config->media_type) {
LOGE("media_type not match");
return -1;
}
if (impl->user_data != config->user_data) {
LOGE("user_data not match");
return -1;
}
if (impl->is_started) {
LOGE("capture is started, can not update config");
return -1;
}
if(config->data_cb){
impl->data_cb = config->data_cb;
}
if(config->audio_wakeup_cb){
impl->audio_wakeup_cb = config->audio_wakeup_cb;
}
return 0;
}
@@ -0,0 +1,354 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include "volc_hal.h"
#include "volc_hal_display.h"
#include "volc_lvgl_source.h"
#include "hw_init.h"
#include "esp_lcd_panel_ops.h"
#include "esp_mmap_assets.h"
#include "esp_board_manager.h"
#include "dev_display_lcd_spi.h"
#include "freertos/semphr.h"
#include "esp_heap_caps.h"
#include "dev_ledc_ctrl.h"
#include "gfx.h"
#include "lvgl.h"
#include <stddef.h>
#include "volc_osal.h"
#include <string.h>
#include "basic_board.h"
#include "mmap_generate_eaf.h"
typedef struct volc_hal_display_impl {
volatile bool is_init;
/* Global state */
esp_lcd_panel_handle_t s_panel;
mmap_assets_handle_t s_assets;
gfx_handle_t s_gfx;
gfx_obj_t *s_anim;
gfx_obj_t *s_label;
gfx_obj_t *s_subtitle;
gfx_obj_t *s_setup_hint;
esp_lcd_panel_io_handle_t display_io_handle;
SemaphoreHandle_t flush_done;
int s_current_emote;
volc_osal_tid_t display_thread;
} volc_hal_display_impl_t;
static volc_hal_display_impl_t* global_display_impl = NULL;
extern basic_board_periph_t global_periph;
static esp_lv_adapter_rotation_t __get_configured_rotation(void)
{
#if CONFIG_EXAMPLE_DISPLAY_ROTATION_0
return ESP_LV_ADAPTER_ROTATE_0;
#elif CONFIG_EXAMPLE_DISPLAY_ROTATION_90
return ESP_LV_ADAPTER_ROTATE_90;
#elif CONFIG_EXAMPLE_DISPLAY_ROTATION_180
return ESP_LV_ADAPTER_ROTATE_180;
#elif CONFIG_EXAMPLE_DISPLAY_ROTATION_270
return ESP_LV_ADAPTER_ROTATE_270;
#else
return ESP_LV_ADAPTER_ROTATE_0;
#endif
}
/* ========== Asset Management ========== */
static esp_err_t __mount_assets(void)
{
mmap_assets_config_t cfg = {
.partition_label = "eaf",
.max_files = MMAP_EAF_FILES,
.checksum = MMAP_EAF_CHECKSUM,
.flags = {
.mmap_enable = 1,
},
};
return mmap_assets_new(&cfg, &global_display_impl->s_assets);
}
/* ========== GFX Emote Engine ========== */
static bool __lcd_flush_done(esp_lcd_panel_io_handle_t io, esp_lcd_panel_io_event_data_t *event, void *context)
{
volc_hal_display_impl_t *display = context;
BaseType_t wake = pdFALSE;
xSemaphoreGiveFromISR(display->flush_done, &wake);
return wake == pdTRUE;
}
static void __gfx_flush_cb(gfx_handle_t handle, int x1, int y1, int x2, int y2, const void *data)
{
if (global_display_impl->s_panel) {
if (esp_lcd_panel_draw_bitmap(global_display_impl->s_panel, x1, y1, x2, y2, data) == ESP_OK) {
// GFX's own wait expires after 20 ms; wait here until DMA really finishes.
xSemaphoreTake(global_display_impl->flush_done, portMAX_DELAY);
}
}
gfx_emote_flush_ready(handle, true);
}
static esp_err_t __init_gfx_engine(void)
{
gfx_core_config_t cfg = {
.flush_cb = __gfx_flush_cb,
.user_data = global_display_impl->s_panel,
.flags = {
.swap = 1,
.double_buffer = 0,
.buff_dma = 1,
.buff_spiram = 0,
},
.h_res = HW_LCD_H_RES,
.v_res = HW_LCD_V_RES,
.fps = 15,
.task = {
.task_priority = 4,
.task_stack = 7168,
.task_affinity = 1,
.task_stack_caps = MALLOC_CAP_SPIRAM,
},
.buffers = {
.buf_pixels = HW_LCD_H_RES * 20,
},
};
global_display_impl->s_gfx = gfx_emote_init(&cfg);
return global_display_impl->s_gfx ? ESP_OK : ESP_FAIL;
}
static esp_err_t __create_animation(void)
{
/* Get EAF data from mmap */
const uint8_t *eaf_data = mmap_assets_get_mem(global_display_impl->s_assets, global_display_impl->s_current_emote);
int eaf_size = mmap_assets_get_size(global_display_impl->s_assets, global_display_impl->s_current_emote);
gfx_emote_lock(global_display_impl->s_gfx);
/* Create animation object */
global_display_impl->s_anim = gfx_anim_create(global_display_impl->s_gfx);
if (!global_display_impl->s_anim) {
gfx_emote_unlock(global_display_impl->s_gfx);
return ESP_FAIL;
}
/* Set animation source */
esp_err_t ret = gfx_anim_set_src(global_display_impl->s_anim, eaf_data, eaf_size);
if (ret != ESP_OK) {
gfx_obj_delete(global_display_impl->s_anim);
global_display_impl->s_anim = NULL;
gfx_emote_unlock(global_display_impl->s_gfx);
return ret;
}
gfx_anim_set_mirror(global_display_impl->s_anim, true, 50); /* Enable mirror for dual-eye display */
if(global_display_impl->s_current_emote == 0){
gfx_obj_align(global_display_impl->s_anim, GFX_ALIGN_LEFT_MID, 35, 0);
} else {
gfx_obj_align(global_display_impl->s_anim, GFX_ALIGN_CENTER, 0, 0);
}
gfx_anim_set_segment(global_display_impl->s_anim, 0, UINT32_MAX, 30, true); /* All frames, 30 FPS, loop */
gfx_emote_unlock(global_display_impl->s_gfx);
return ESP_OK;
}
static void __emote_task(void *arg)
{
/* Start animation playback */
gfx_emote_lock(global_display_impl->s_gfx);
gfx_anim_start(global_display_impl->s_anim);
gfx_emote_unlock(global_display_impl->s_gfx);
/* The display task owns animation playback for the lifetime of the app. */
while (1) {
vTaskDelay(pdMS_TO_TICKS(100));
}
}
static void __clear_panel(void)
{
const int rows = 20;
uint16_t *black = heap_caps_calloc(HW_LCD_H_RES * rows, sizeof(uint16_t), MALLOC_CAP_DMA);
if (!black) return;
for (int y = 0; y < HW_LCD_V_RES; y += rows) {
int y2 = y + rows > HW_LCD_V_RES ? HW_LCD_V_RES : y + rows;
if (esp_lcd_panel_draw_bitmap(global_display_impl->s_panel, 0, y, HW_LCD_H_RES, y2, black) != ESP_OK) break;
xSemaphoreTake(global_display_impl->flush_done, portMAX_DELAY);
}
free(black);
}
static esp_err_t __switch_animation(int emote_index)
{
if (!global_display_impl->s_anim || !global_display_impl->s_gfx) {
return ESP_FAIL;
}
/* Get new EAF data from mmap */
const uint8_t *eaf_data = mmap_assets_get_mem(global_display_impl->s_assets, emote_index);
int eaf_size = mmap_assets_get_size(global_display_impl->s_assets, emote_index);
if(global_display_impl->s_current_emote == emote_index) {
return ESP_OK;
}
gfx_emote_lock(global_display_impl->s_gfx);
/* Stop current animation */
gfx_anim_stop(global_display_impl->s_anim);
/* Update animation source */
esp_err_t ret = gfx_anim_set_src(global_display_impl->s_anim, eaf_data, eaf_size);
if (ret != ESP_OK) {
gfx_emote_unlock(global_display_impl->s_gfx);
return ret;
}
/* gfx_draw_animation() derives the object size from the decoded frame. */
global_display_impl->s_anim->width = 0;
global_display_impl->s_anim->height = 0;
gfx_anim_set_mirror(global_display_impl->s_anim, true, 50); /* Enable mirror for dual-eye display */
if(emote_index == 0){
gfx_obj_align(global_display_impl->s_anim, GFX_ALIGN_LEFT_MID, 35, 0);
} else {
gfx_obj_align(global_display_impl->s_anim, GFX_ALIGN_CENTER, 0, 0);
}
gfx_anim_set_segment(global_display_impl->s_anim, 0, UINT32_MAX, 30, true); /* All frames, 30 FPS, loop */
/* Restart animation */
gfx_anim_start(global_display_impl->s_anim);
gfx_emote_unlock(global_display_impl->s_gfx);
global_display_impl->s_current_emote = emote_index;
return ESP_OK;
}
volc_hal_display_t volc_hal_display_create(volc_hal_display_config_t* config)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return NULL;
}
global_display_impl = (volc_hal_display_impl_t*)volc_osal_calloc(1,sizeof(volc_hal_display_impl_t));
// init display
esp_lv_adapter_rotation_t rotation = __get_configured_rotation();
/* Determine tear avoid mode based on LCD interface */
#if CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI
esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode = ESP_LV_ADAPTER_TEAR_AVOID_MODE_DEFAULT_MIPI_DSI;
#elif CONFIG_EXAMPLE_LCD_INTERFACE_RGB
esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode = ESP_LV_ADAPTER_TEAR_AVOID_MODE_DEFAULT_RGB;
#else
esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode = ESP_LV_ADAPTER_TEAR_AVOID_MODE_DEFAULT;
#endif
// ESP_ERROR_CHECK(hw_lcd_init(&global_display_impl->s_panel, &global_display_impl->display_io_handle, tear_avoid_mode, rotation));
global_display_impl->s_panel = global_periph.lcd_pannel;
dev_display_lcd_spi_handles_t *lcd = NULL;
ESP_ERROR_CHECK(esp_board_manager_get_device_handle("display_lcd", (void **)&lcd));
global_display_impl->display_io_handle = lcd->io_handle;
global_display_impl->flush_done = xSemaphoreCreateBinary();
if (!global_display_impl->flush_done) return NULL;
esp_lcd_panel_io_callbacks_t callbacks = {.on_color_trans_done = __lcd_flush_done};
ESP_ERROR_CHECK(esp_lcd_panel_io_register_event_callbacks(lcd->io_handle, &callbacks, global_display_impl));
__clear_panel();
ESP_ERROR_CHECK(__mount_assets());
ESP_ERROR_CHECK(__init_gfx_engine());
/*
* The upstream 360x360 boot asset is not rendered reliably on every
* EchoEar panel revision and can leave uninitialised-looking pixels at
* the bottom of the round display. Start with the compact built-in eye
* animation instead; application status text explains the setup state.
*/
global_display_impl->s_current_emote = MMAP_EAF_HAPPY_EAF;
__create_animation();
volc_osal_thread_param_t param = {0};
snprintf(param.name, sizeof(param.name), "%s", "volc_capture_task");
param.stack_size = 8 * 1024;
param.priority = 4;
param.stack_in_ext = 1;
esp_err_t ret = volc_osal_thread_create(&global_display_impl->display_thread, &param, __emote_task, NULL);
global_display_impl->is_init = true;
g_hal_context->display_handle = (volc_hal_display_t)global_display_impl;
volc_hal_display_set_brightness(global_display_impl,80);
return (volc_hal_display_t)global_display_impl;
}
int volc_hal_display_set_brightness(volc_hal_display_t display, int brightness)
{
if(display == NULL) return -1;
if (brightness > 100) {
brightness = 100;
}
if (brightness < 0) {
brightness = 0;
}
periph_ledc_handle_t *ledc_handle = NULL;
esp_board_manager_get_device_handle("lcd_brightness", (void **)&ledc_handle);
dev_ledc_ctrl_config_t *dev_ledc_cfg = NULL;
esp_err_t config_ret = esp_board_manager_get_device_config("lcd_brightness", (void*)&dev_ledc_cfg);
if (config_ret != ESP_OK) {
return -1;
}
// ESP_LOGI(TAG, "dev_ledc_cfg.ledc_name: %s, name: %s, type: %s", dev_ledc_cfg->ledc_name, dev_ledc_cfg->name, dev_ledc_cfg->type);
periph_ledc_config_t *ledc_config = NULL;
esp_board_manager_get_periph_config(dev_ledc_cfg->ledc_name, (void**)&ledc_config);
uint32_t duty = (brightness * ((1 << (uint32_t)ledc_config->duty_resolution) - 1)) / 100;
// ESP_LOGI(TAG, "duty_cycle: %" PRIu32 ", speed_mode: %d, channel: %d, duty_resolution: %d", duty, ledc_handle->speed_mode, ledc_handle->channel, ledc_config->duty_resolution);
// ESP_BOARD_RETURN_ON_ERROR(ledc_set_duty(ledc_handle->speed_mode, ledc_handle->channel, duty), TAG, "LEDC set duty failed");
ledc_set_duty(ledc_handle->speed_mode, ledc_handle->channel, duty);
// ESP_BOARD_RETURN_ON_ERROR(ledc_update_duty(ledc_handle->speed_mode, ledc_handle->channel), TAG, "LEDC update duty failed");
ledc_update_duty(ledc_handle->speed_mode, ledc_handle->channel);
return 0;
// return bsp_display_brightness_set(brightness);
}
void volc_hal_display_destroy(volc_hal_display_t display)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return;
}
volc_hal_display_impl_t* global_display_impl = (volc_hal_display_impl_t*)display;
if(global_display_impl && global_display_impl->is_init){
global_display_impl->is_init = false;
}
volc_osal_free(global_display_impl);
global_display_impl = NULL;
g_hal_context->display_handle = NULL;
return;
}
int volc_hal_display_set_content(volc_hal_display_t display, volc_hal_display_obj_e obj, volc_hal_display_type_e type, const void* content)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL || g_hal_context->display_handle == NULL){
return -1;
}
volc_hal_display_impl_t* global_display_impl = (volc_hal_display_impl_t*)(g_hal_context->display_handle);
if(obj == VOLC_DISPLAY_OBJ_STATUS && type == VOLC_DISPLAY_TEXT){
ESP_LOGI("DISPLAY", "Status: %s", (const char *)content);
}
if(obj == VOLC_DISPLAY_OBJ_SUBTITLE && type == VOLC_DISPLAY_TEXT){
ESP_LOGI("DISPLAY", "Subtitle: %s", (const char *)content);
}
if(obj == VOLC_DISPLAY_OBJ_MAIN && type == VOLC_DISPLAY_IMAGE){
int index = *((int*)content);
if(index < MMAP_EAF_FILES){
__switch_animation(index);
}
}
return 0;
}
@@ -0,0 +1,176 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include "volc_hal.h"
#include "volc_hal_display.h"
#include "volc_lvgl_source.h"
#include "lvgl.h"
#include "bsp/echoear.h"
#include <stddef.h>
#include "volc_osal.h"
#include <string.h>
#define LVGL_TASK_PRIORITY 1
#define LVGL_TASK_CORE_ID 1
#define LVGL_TASK_STACK_SIZE 8 * 1024
#define LVGL_TASK_MAX_SLEEP_MS 500
#define LVGL_TASK_TIMER_PERIOD_MS 50
#define LVGL_TIMER_INTERVAL 500
typedef struct volc_hal_display_impl {
lv_obj_t* screen;
lv_obj_t* display_obj[VOLC_DISPLAY_OBJ_MAX];
// use for display subtitle
lv_timer_t* text_timer;
char subtitle_texts[64];
char status_texts[64];
volatile bool is_init;
} volc_hal_display_impl_t;
static volc_hal_display_impl_t* global_display_impl = NULL;
volc_hal_display_t global_display = NULL;
static void __subtitle_update_cb(lv_timer_t* timer)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return;
}
volc_hal_display_impl_t* global_display_impl = (volc_hal_display_impl_t*)(g_hal_context->display_handle);
if(global_display_impl && global_display_impl->is_init){
lv_label_set_text(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_SUBTITLE], global_display_impl->subtitle_texts);
lv_label_set_text(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_STATUS], global_display_impl->status_texts);
lv_obj_remove_flag(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_SUBTITLE], LV_OBJ_FLAG_HIDDEN);
lv_obj_remove_flag(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_STATUS], LV_OBJ_FLAG_HIDDEN);
}
}
static void __status_obj_init(volc_hal_display_impl_t* global_display_impl)
{
if(global_display_impl && global_display_impl->display_obj[VOLC_DISPLAY_OBJ_STATUS] == NULL){
global_display_impl->display_obj[VOLC_DISPLAY_OBJ_STATUS] = lv_label_create(global_display_impl->screen);
lv_obj_set_style_text_font(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_STATUS], &echoear_font_16, 0);
lv_obj_align(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_STATUS], LV_ALIGN_TOP_MID, 0, 50);
lv_obj_set_height(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_STATUS], 30); // 设置固定高度度
}
}
static void __subtitle_obj_init(volc_hal_display_impl_t* global_display_impl)
{
if(global_display_impl && global_display_impl->display_obj[VOLC_DISPLAY_OBJ_SUBTITLE] == NULL){
global_display_impl->display_obj[VOLC_DISPLAY_OBJ_SUBTITLE] = lv_label_create(global_display_impl->screen);
lv_obj_set_style_text_font(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_SUBTITLE], &echoear_font_16, 0);
lv_obj_align(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_SUBTITLE], LV_ALIGN_BOTTOM_MID, 0, -50);
lv_obj_set_height(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_SUBTITLE], 30); // 设置固定高度度
}
if(global_display_impl && global_display_impl->text_timer == NULL){
global_display_impl->text_timer = lv_timer_create(__subtitle_update_cb, LVGL_TIMER_INTERVAL, NULL);
}
}
static void __main_obj_init(volc_hal_display_impl_t* global_display_impl)
{
if(global_display_impl && global_display_impl->display_obj[VOLC_DISPLAY_OBJ_MAIN] == NULL){
global_display_impl->display_obj[VOLC_DISPLAY_OBJ_MAIN] = lv_img_create(global_display_impl->screen);
// size需要调整
lv_obj_set_size(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_MAIN], 250, 250);
lv_obj_align(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_MAIN], LV_ALIGN_CENTER, 0, 0);
}
}
volc_hal_display_t volc_hal_display_create(volc_hal_display_config_t* config)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return NULL;
}
volc_hal_display_impl_t* global_display_impl = (volc_hal_display_impl_t*)volc_osal_calloc(1,sizeof(volc_hal_display_impl_t));
// init display
// bsp_display_cfg_t cfg = {
// .lvgl_port_cfg = {
// .task_priority = LVGL_TASK_PRIORITY,
// .task_stack = LVGL_TASK_STACK_SIZE,
// .task_affinity = LVGL_TASK_CORE_ID,
// .task_max_sleep_ms = LVGL_TASK_MAX_SLEEP_MS,
// .task_stack_caps = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT,
// .timer_period_ms = LVGL_TASK_TIMER_PERIOD_MS,
// },
// .buffer_size = BSP_LCD_H_RES * 50,
// .double_buffer = true,
// .flags = {
// .buff_spiram = false,
// // .default_dummy_draw = default_dummy_draw, // Avoid white screen during initialization
// },
// };
// lv_disp_t *disp = bsp_display_start_with_config(&cfg);
// // bsp_display_brightness_init();
// bsp_display_backlight_on();
global_display_impl->screen = lv_scr_act();
// printf("global_display_impl->screen %p \n",global_display_impl->screen);
__subtitle_obj_init(global_display_impl);
__status_obj_init(global_display_impl);
__main_obj_init(global_display_impl);
global_display_impl->is_init = true;
g_hal_context->display_handle = (volc_hal_display_t)global_display_impl;
return (volc_hal_display_t)global_display_impl;
}
int volc_hal_display_set_brightness(volc_hal_display_t display, int brightness)
{
if(display == NULL) return -1;
if (brightness > 100) {
brightness = 100;
}
if (brightness < 0) {
brightness = 0;
}
return bsp_display_brightness_set(brightness);
}
void volc_hal_display_destroy(volc_hal_display_t display)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return;
}
volc_hal_display_impl_t* global_display_impl = (volc_hal_display_impl_t*)display;
if(global_display_impl && global_display_impl->is_init){
global_display_impl->is_init = false;
lv_timer_del(global_display_impl->text_timer);
lv_obj_del(global_display_impl->screen);
}
volc_osal_free(global_display_impl);
global_display_impl = NULL;
g_hal_context->display_handle = NULL;
return;
}
int volc_hal_display_set_content(volc_hal_display_t display, volc_hal_display_obj_e obj, volc_hal_display_type_e type, const void* content)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL || g_hal_context->display_handle == NULL){
return -1;
}
volc_hal_display_impl_t* global_display_impl = (volc_hal_display_impl_t*)(g_hal_context->display_handle);
if(obj == VOLC_DISPLAY_OBJ_STATUS && type == VOLC_DISPLAY_TEXT){
memset(global_display_impl->status_texts, 0, 64);
int count = strlen(content) >= 63 ? 63 : strlen(content);
memcpy(global_display_impl->status_texts,content,count);
}
if(obj == VOLC_DISPLAY_OBJ_SUBTITLE && type == VOLC_DISPLAY_TEXT){
memset(global_display_impl->subtitle_texts, 0, 64);
int count = strlen(content) >= 63 ? 63 : strlen(content);
memcpy(global_display_impl->subtitle_texts,content,count);
}
if(obj == VOLC_DISPLAY_OBJ_MAIN && type == VOLC_DISPLAY_IMAGE){
lv_image_dsc_t* img_app_pos = (lv_image_dsc_t*)content;
// lv_obj_set_size(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_MAIN], 112, 112);
lv_img_set_src(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_MAIN], img_app_pos);
lv_obj_remove_flag(global_display_impl->display_obj[VOLC_DISPLAY_OBJ_MAIN] ,LV_OBJ_FLAG_HIDDEN);
}
return 0;
}
@@ -0,0 +1,55 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include <stdio.h>
#include "volc_hal_file.h"
// #include "board.h"
// #include "esp_peripherals.h"
#include "util/volc_log.h"
#include "basic_board.h"
#include "audio_processor.h"
int volc_hal_file_system_init()
{
return 0;
}
volc_hal_file_t volc_hal_file_open(char* file_name, char* mode)
{
FILE* file = fopen(file_name,mode);
if (file == NULL) {
LOGE("volc_hal_file_open failed");
return NULL;
}
return (volc_hal_file_t)file;
}
uint64_t volc_hal_file_read(volc_hal_file_t file, void *data, uint64_t size)
{
return fread(data,1,size,(FILE*)file);
}
uint64_t volc_hal_file_write(volc_hal_file_t file, void *data, uint64_t size)
{
return fwrite(data,1,size,(FILE*)file);
}
uint64_t volc_hal_file_get_size(volc_hal_file_t file)
{
uint64_t file_offset = ftell((FILE*)file);
fseek((FILE*)file, 0, SEEK_END);
uint64_t file_size_long = ftell((FILE*)file);
fseek((FILE*)file,file_offset,SEEK_SET);
return file_size_long;
}
int volc_hal_file_seek(volc_hal_file_t file,uint64_t offset)
{
return fseek((FILE*)file,offset,SEEK_SET);
}
int volc_hal_file_close(volc_hal_file_t file)
{
return fclose((FILE*)file);
}
@@ -0,0 +1,18 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include "volc_hal_led.h"
#include <stddef.h>
volc_led_t volc_led_create(volc_led_config_t* config) {
return NULL;
}
void volc_led_destroy(volc_led_t led) {
}
void volc_led_set_state(volc_led_t led, volc_led_state_e state) {
}
@@ -0,0 +1,315 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include <stddef.h>
#include "volc_hal.h"
#include "volc_hal_player.h"
#include "volc_osal.h"
#include "basic_board.h"
#include "audio_processor.h"
#include "esp_codec_dev.h"
#include "util/volc_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/stream_buffer.h"
#include "freertos/semphr.h"
#include "esp_heap_caps.h"
#define DEFAULT_AUDIO_VOL 70
#define PCM_QUEUE_BYTES (256 * 1024)
#define PCM_PREBUFFER_BYTES (16000 * 2 * 750 / 1000)
#define PCM_PREBUFFER_WAIT_MS 1500
#define PCM_REPRIME_IDLE_MS 600
typedef struct {
av_processor_decoder_config_t feeder_cfg;
int volume;
} audio_player_config_t;
typedef struct {
//TODO: add video player config
void* video_player_config;
} video_player_config_t;
typedef struct {
volc_media_type_e media_type; // Media type
union {
audio_player_config_t audio_player_config;
video_player_config_t video_player_config;
};
volatile bool is_started;
StreamBufferHandle_t pcm_stream;
StaticStreamBuffer_t stream_state;
uint8_t *stream_storage;
SemaphoreHandle_t worker_stopped;
volatile bool discard_pending;
volatile bool segment_complete;
} volc_player_impl_t;
extern basic_board_periph_t global_periph;
static void pcm_playback_task(void *arg)
{
volc_player_impl_t *impl = arg;
uint8_t pcm[1024];
bool primed = false;
uint64_t first_byte_ms = 0;
uint64_t last_feed_ms = 0;
while (impl->is_started) {
if (impl->discard_pending) {
while (xStreamBufferReceive(impl->pcm_stream, pcm, sizeof(pcm), 0)) {}
impl->discard_pending = false;
impl->segment_complete = false;
primed = false;
first_byte_ms = 0;
}
size_t available = xStreamBufferBytesAvailable(impl->pcm_stream);
if (!primed) {
if (!available) {
vTaskDelay(pdMS_TO_TICKS(10));
continue;
}
if (!first_byte_ms) first_byte_ms = volc_osal_get_time_ms();
if (available < PCM_PREBUFFER_BYTES && !impl->segment_complete &&
volc_osal_get_time_ms() - first_byte_ms < PCM_PREBUFFER_WAIT_MS) {
vTaskDelay(pdMS_TO_TICKS(10));
continue;
}
primed = true;
LOGI("PLAYBACK start source=16000Hz mono PCM16 buffered=%u wait_ms=%u complete=%d",
(unsigned)available, (unsigned)(volc_osal_get_time_ms() - first_byte_ms), impl->segment_complete);
}
size_t count = xStreamBufferReceive(impl->pcm_stream, pcm, sizeof(pcm), pdMS_TO_TICKS(30));
if (!count) {
/* An empty ingress queue does not mean the speaker has run dry:
* the downstream feeder may still hold 256 ms of PCM. Keep feeding
* arriving chunks immediately instead of inserting another prefill
* delay after every short network gap. */
if (volc_osal_get_time_ms() - last_feed_ms >= PCM_REPRIME_IDLE_MS) {
primed = false;
first_byte_ms = 0;
LOGI("PLAYBACK idle after %u ms without PCM", PCM_REPRIME_IDLE_MS);
}
continue;
}
if (audio_feeder_feed_data(pcm, count) == ESP_OK) {
last_feed_ms = volc_osal_get_time_ms();
} else if (impl->is_started) {
LOGE("PLAYBACK feeder write failed");
}
}
xSemaphoreGive(impl->worker_stopped);
vTaskDelete(NULL);
}
volc_hal_player_t volc_hal_player_create(volc_hal_player_config_t* config)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return NULL;
}
volc_player_impl_t* impl = volc_osal_calloc(1, sizeof(volc_player_impl_t));
if (!impl) return NULL;
// mem_assert(impl);
impl->media_type = config->media_type;
switch (impl->media_type) {
case VOLC_MEDIA_TYPE_AUDIO:
if(global_periph.play_dev){
esp_codec_dev_set_out_vol(global_periph.play_dev, DEFAULT_AUDIO_VOL);
}
impl->audio_player_config.volume = DEFAULT_AUDIO_VOL;
#if (CONFIG_VOLC_AUDIO_G711A)
impl->audio_player_config.feeder_cfg.format = AV_PROCESSOR_FORMAT_ID_G711A;
impl->audio_player_config.feeder_cfg.params.g711.audio_info.sample_rate = 8000;
impl->audio_player_config.feeder_cfg.params.g711.audio_info.sample_bits = 16;
impl->audio_player_config.feeder_cfg.params.g711.audio_info.channels = 1;
impl->audio_player_config.feeder_cfg.params.g711.audio_info.frame_duration = 20;
#else
impl->audio_player_config.feeder_cfg.format = AV_PROCESSOR_FORMAT_ID_PCM;
/* Hardware gateway PCM16 is 16 kHz, as in the low-load SDK and
* desktop client. The underlying model's 24 kHz output is not the
* sample rate of this gateway stream. */
impl->audio_player_config.feeder_cfg.params.pcm.audio_info.sample_rate = 16000;
impl->audio_player_config.feeder_cfg.params.pcm.audio_info.sample_bits = 16;
impl->audio_player_config.feeder_cfg.params.pcm.audio_info.channels = 1;
impl->audio_player_config.feeder_cfg.params.pcm.audio_info.frame_duration = 20;
#endif
audio_feeder_config_t feeder_config = DEFAULT_AUDIO_FEEDER_CONFIG();
memcpy((void *)&feeder_config.decoder_cfg, &impl->audio_player_config.feeder_cfg, sizeof(av_processor_decoder_config_t));
if (audio_feeder_open(&feeder_config) != ESP_OK) {
volc_osal_free(impl);
return NULL;
}
impl->stream_storage = heap_caps_malloc(PCM_QUEUE_BYTES + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
impl->worker_stopped = xSemaphoreCreateBinary();
if (impl->stream_storage) {
impl->pcm_stream = xStreamBufferCreateStatic(PCM_QUEUE_BYTES + 1, 1,
impl->stream_storage, &impl->stream_state);
}
if (!impl->pcm_stream || !impl->worker_stopped) {
if (impl->pcm_stream) vStreamBufferDelete(impl->pcm_stream);
if (impl->worker_stopped) vSemaphoreDelete(impl->worker_stopped);
heap_caps_free(impl->stream_storage);
audio_feeder_close();
volc_osal_free(impl);
return NULL;
}
// audio_processor_mixer_open();
impl->is_started = false;
g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO] = impl;
break;
case VOLC_MEDIA_TYPE_VIDEO:
// TODO: Add video player support
break;
default:
break;
}
return (volc_hal_player_t)impl;
}
int volc_hal_set_audio_player_volume(volc_hal_player_t player, int volume){
volc_player_impl_t* impl = (volc_player_impl_t*)player;
if (impl == NULL) {
return -1;
}
if(impl->media_type == VOLC_MEDIA_TYPE_AUDIO){
impl->audio_player_config.volume = volume;
return esp_codec_dev_set_out_vol(global_periph.play_dev, volume);
} else if(impl->media_type == VOLC_MEDIA_TYPE_VIDEO){
LOGE("media type %d not supported set volume", impl->media_type);
return -1;
}
}
int volc_hal_get_audio_player_volume(volc_hal_player_t player){
volc_player_impl_t* impl = (volc_player_impl_t*)player;
if (impl == NULL) {
return -1;
}
return impl->audio_player_config.volume;
}
void volc_hal_player_destroy(volc_hal_player_t player)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return;
}
volc_player_impl_t* impl = (volc_player_impl_t*)player;
if (impl == NULL) {
return;
}
volc_hal_player_stop(impl);
switch (impl->media_type) {
case VOLC_MEDIA_TYPE_AUDIO:
audio_feeder_close();
vStreamBufferDelete(impl->pcm_stream);
vSemaphoreDelete(impl->worker_stopped);
heap_caps_free(impl->stream_storage);
g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO] = NULL;
break;
case VOLC_MEDIA_TYPE_VIDEO:
// TODO: Add video player support
break;
default:
break;
}
volc_osal_free(impl);
}
int volc_hal_player_start(volc_hal_player_t player)
{
volc_player_impl_t* impl = (volc_player_impl_t*)player;
if (impl == NULL) {
LOGE("volc_hal_player_start: impl is NULL");
return -1;
}
if(impl->is_started) return 0;
switch (impl->media_type) {
case VOLC_MEDIA_TYPE_AUDIO:
if (audio_feeder_run() != ESP_OK) return -1;
xStreamBufferReset(impl->pcm_stream);
impl->is_started = true;
if (xTaskCreatePinnedToCore(pcm_playback_task, "pcm_playback", 4096, impl, 5, NULL, 1) != pdPASS) {
impl->is_started = false;
audio_feeder_stop();
return -1;
}
return 0;
case VOLC_MEDIA_TYPE_VIDEO:
// TODO: Add video player support
break;
default:
break;
}
LOGE("media type %d not supported", impl->media_type);
return -1;
}
int volc_hal_player_stop(volc_hal_player_t player)
{
volc_player_impl_t* impl = (volc_player_impl_t*)player;
if (impl == NULL) {
LOGE("volc_hal_player_stop: impl is NULL");
return -1;
}
if(impl->is_started == false) return 0;
switch (impl->media_type) {
case VOLC_MEDIA_TYPE_AUDIO:
impl->is_started = false;
/* Stop the feeder first to release any in-flight blocking write. */
int ret = audio_feeder_stop();
xSemaphoreTake(impl->worker_stopped, portMAX_DELAY);
return ret;
break;
case VOLC_MEDIA_TYPE_VIDEO:
// TODO: Add video player support
break;
default:
break;
}
LOGE("media type %d not supported", impl->media_type);
return -1;
}
int volc_hal_player_play_data(volc_hal_player_t player, const void* data, int len)
{
if (player == NULL || data == NULL || len <= 0) {
LOGE("player play data failed, player is %p, data is %p, len is %d", player, data, len);
return -1;
}
volc_player_impl_t* impl = (volc_player_impl_t*)player;
switch (impl->media_type) {
case VOLC_MEDIA_TYPE_AUDIO:
if (!impl->is_started || impl->discard_pending) return 0;
if ((len & 1) || xStreamBufferSpacesAvailable(impl->pcm_stream) < (size_t)len) {
LOGE("PLAYBACK queue overflow or unaligned PCM: bytes=%d free=%u", len,
(unsigned)xStreamBufferSpacesAvailable(impl->pcm_stream));
return -1;
}
impl->segment_complete = false;
return xStreamBufferSend(impl->pcm_stream, data, len, 0) == (size_t)len ? 0 : -1;
break;
case VOLC_MEDIA_TYPE_VIDEO:
// TODO: Add video player support
break;
default:
break;
}
LOGE("media type %d not supported", impl->media_type);
return -1;
}
void volc_hal_player_discard_pending(volc_hal_player_t player)
{
volc_player_impl_t *impl = player;
if (impl && impl->is_started) impl->discard_pending = true;
}
void volc_hal_player_finish_segment(volc_hal_player_t player)
{
volc_player_impl_t *impl = player;
if (impl && impl->is_started) impl->segment_complete = true;
}
@@ -0,0 +1,12 @@
# Copyright (2025) Beijing Volcano Engine Technology Ltd.
# SPDX-License-Identifier: Apache License 2.0
file(GLOB SERVICE_SRCS_COMMON "${CMAKE_CURRENT_LIST_DIR}/src/*.c")
file(GLOB SERVICE_SRCS_CONV "${CMAKE_CURRENT_LIST_DIR}/conv_service/src/*.c")
file(GLOB SERVICE_SRCS_FUNCTION_CALL "${CMAKE_CURRENT_LIST_DIR}/function_call_service/src/*.c")
set(SERVICE_SRCS ${SERVICE_SRCS_COMMON} ${SERVICE_SRCS_CONV} ${SERVICE_SRCS_FUNCTION_CALL})
set(SERVICE_INC "${CMAKE_CURRENT_LIST_DIR}/inc"
"${CMAKE_CURRENT_LIST_DIR}/conv_service/inc"
"${CMAKE_CURRENT_LIST_DIR}/function_call_service/inc")
@@ -0,0 +1,10 @@
# Service
## brief introduction
This directory presents the business module division of the Hardware Conversational Agent Development Kit for AI conversation services. All business modules are named "service", and different services communicate through event subscription (sub) and publication (pub) at the framework layer. The main modules are as follows:
- conv_service:The core module of the AI Conversational Agent, responsible for the initiation, operation, and termination of AI conversation services.
- function_call_service:Interacts with the conv\_service module, responsible for executing function calls and returning the results to the agent.
- local_logic_service:A local module based on predefined business logic (not the agent's business logic). It performs tasks such as parsing subtitles and taking certain actions based on quick responses to the subtitles (different from function calls).
- src: An externally exposed module responsible for initiating the AI conversation.
@@ -0,0 +1,11 @@
# Service
## 目录简介
本目录是硬件对话智能体开发套件对于ai对话业务进行的业务模块划分,不同的业务模块我们以service命名;不同的service通过framework层event的sub和pub进行通信。主要分为一下模块
- conv_service: 智能体ai对话的主要模块,负责ai对话业务的开始,运行,与结束。
- function_call_service: 与conv_service模块交互,负责function call的执行并将结果返回给智能体
- local_logic_service: 本地基于既定业务逻辑(非智能体的业务逻辑)的模块,例如解析字幕并根据字幕快速响应做出某些action等(区别于function call)
- src: 对外暴露的模块,负责ai对话的拉起
@@ -0,0 +1,19 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef VOLC_CONV_SERVICE_H__
#define VOLC_CONV_SERVICE_H__
#include "volc_conv_ai.h"
typedef struct {
volc_event_handler_t volc_event_handler;
volc_engine_t engine;
int wait_time;
} volc_conv_service_t;
void conv_ai_service_task(void *pvParameters);
void conv_ai_service_task_stop();
void conv_ai_service_init();
volc_conv_service_t get_conv_ai_service();
#endif /* VOLC_CONV_SERVICE_H__ */
@@ -0,0 +1,12 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef VOLC_CONV_SERVICE_MANAGER_H__
#define VOLC_CONV_SERVICE_MANAGER_H__
#include <stdio.h>
#include "aios.h"
void volc_conv_service_manager_init(void);
#endif // VOLC_CONV_SERVICE_MANAGER_H__
@@ -0,0 +1,523 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include <stdio.h>
#include <string.h>
#include "aios.h"
#include "cJSON.h"
#include "volc_hal.h"
#include "volc_osal.h"
#include "util/volc_log.h"
#include "volc_service_common.h"
#include "volc_conv.h"
#include "volc_hal.h"
#include "volc_hal_capture.h"
#include "volc_hal_display.h"
#include "volc_hal_player.h"
// #include "volc_hal_file.h"
#include "volc_local_function_list.h"
#include "mmap_generate_eaf.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
extern int8_t get_rssi(void);
#if __cplusplus
extern "C" {
#endif
#define CONV_AI_CONFIG_FORMAT "{\
\"ver\": 1,\
\"iot\": {\
\"instance_id\": \"%s\",\
\"product_key\": \"%s\",\
\"device_secret\": \"%s\",\
\"device_name\": \"%s\"\
},\
\"rtc\": {\
\"log_level\": 3,\
\"audio\": {\
\"publish\": true,\
\"subscribe\": true,\
\"codec\": 3\
},\
\"video\": {\
\"publish\": false,\
\"subscribe\": false,\
\"codec\": 1\
},\
\"params\":[\
\"{\\\"debug\\\":{\\\"log_to_console\\\":1}}\",\
\"{\\\"rtc\\\":{\\\"access\\\":{\\\"concurrent_requests\\\":1}}}\",\
\"{\\\"rtc\\\":{\\\"ice\\\":{\\\"concurrent_agents\\\":1}}}\",\
\"{\\\"rtc\\\":{\\\"thread\\\":{\\\"stack_in_ext\\\":1}}}\",\
\"{\\\"rtc\\\":{\\\"network\\\":{\\\"enable_audio_jitter2\\\":0}}}\",\
\"{\\\"rtc\\\":{\\\"report\\\":{\\\"enable\\\":0}}}\",\
\"{\\\"audio\\\":{\\\"codec\\\":{\\\"pcma\\\":{\\\"s_samples_per_frame\\\":480}}}}\"\
]\
}\
}"
#define CONV_SERVICE_TIMEOUT 60
static char config_buf[1024] = {0};
static volc_conv_service_t conv_service = {0};
static volatile bool is_stop = false;
static volatile bool provider_disconnected = false;
static volc_hal_display_t global_display = NULL;
static bool session_started_reported = false;
static QueueHandle_t platform_report_queue;
static volatile bool diagnostic_say_pending;
void conv_ai_service_diagnostic_say(void)
{
diagnostic_say_pending = true;
aios_event_pub(VOLC_SERVICE_AI_CONVERSATION, NULL, NULL);
}
/* Implemented by the platform client in the top-level firmware component. */
extern const char *platform_runtime_instance_id(void);
extern const char *platform_runtime_product_key(void);
extern const char *platform_runtime_device_name(void);
extern const char *platform_runtime_device_secret(void);
extern int platform_conversation_begin(void);
extern const char *platform_last_error_code(void);
extern const char *platform_conversation_bot_id(void);
extern const char *platform_conversation_update_json(void);
extern int platform_conversation_started(const char *provider_connection_ref);
extern int platform_conversation_poll(void);
extern int platform_conversation_turn(const char *speaker, const char *source_id, const char *text);
extern void platform_conversation_finish(bool failed, const char *error_code);
volc_conv_service_t get_conv_ai_service()
{
return conv_service;
}
// use dump audio
// volc_hal_file_t* audioFile = NULL;
// int a_cnt = 0;
static void __audio_capture_cb(volc_hal_capture_t capture, const void* data, int len, volc_hal_frame_info_t* frame_info){
volc_audio_frame_info_t info = {0};
info.commit = false;
info.data_type = frame_info->data_type;
if(!is_stop)
{
static uint64_t report_ms, magnitude;
static unsigned samples, peak, frames, failures, max_send_ms;
const int16_t *pcm = data;
if (frame_info->data_type == VOLC_AUDIO_DATA_TYPE_PCM) {
for (int i = 0; i < len / sizeof(int16_t); ++i) {
unsigned value = pcm[i] < 0 ? -(int)pcm[i] : pcm[i];
magnitude += value;
if (value > peak) peak = value;
samples++;
}
}
uint64_t before = volc_osal_get_time_ms();
int sent = volc_send_audio_data(conv_service.engine, data, len, &info);
unsigned elapsed = volc_osal_get_time_ms() - before;
if (elapsed > max_send_ms) max_send_ms = elapsed;
frames++;
if (sent < 0) failures++;
if (before - report_ms >= 2000) {
int rssi = get_rssi();
LOGI("UPLINK mean=%u peak=%u frames=%u failed=%u max_send_ms=%u rssi=%d",
samples ? (unsigned)(magnitude / samples) : 0, peak, frames, failures, max_send_ms, rssi);
report_ms = before;
magnitude = samples = peak = frames = failures = max_send_ms = 0;
}
// if(audioFile == NULL){
// audioFile = volc_hal_file_open("/sdcard/cap.pcm","wb");
// volc_hal_file_write(audioFile,data,len);
// }
}
}
static void __on_volc_event(volc_engine_t handle, volc_event_t *event, void *user_data)
{
switch (event->code)
{
case VOLC_EV_CONNECTED:
LOGI("Volc Engine connected");
break;
case VOLC_EV_DISCONNECTED:
LOGI( "Volc Engine disconnected");
provider_disconnected = true;
is_stop = true;
break;
default:
LOGI("Volc Engine event: %d", event->code);
break;
}
}
static void __on_volc_conversation_status(volc_engine_t handle, volc_conv_status_e status, void *user_data)
{
int index = MMAP_EAF_HAPPY_EAF;
switch (status)
{
case VOLC_CONV_STATUS_LISTENING:
index = MMAP_EAF_EMOTION_BLINK_FAST_284_126_EAF;
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_MAIN,VOLC_DISPLAY_IMAGE,&index);
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_STATUS,VOLC_DISPLAY_TEXT,"智能体聆听中");
break;
case VOLC_CONV_STATUS_THINKING:
index = MMAP_EAF_EMOTION_DIZZY_284_126_EAF;
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_MAIN,VOLC_DISPLAY_IMAGE,&index);
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_STATUS,VOLC_DISPLAY_TEXT,"智能体思考中");
break;
case VOLC_CONV_STATUS_ANSWERING:
index = MMAP_EAF_HAPPY_EAF;
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_MAIN,VOLC_DISPLAY_IMAGE,&index);
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_STATUS,VOLC_DISPLAY_TEXT,"智能体说话中");
break;
case VOLC_CONV_STATUS_INTERRUPTED:
{
volc_hal_context_t *hal = volc_get_global_hal_context();
if (hal) volc_hal_player_discard_pending(hal->player_handle[VOLC_HAL_PLAYER_AUDIO]);
}
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_STATUS,VOLC_DISPLAY_TEXT,"智能体被打断");
break;
case VOLC_CONV_STATUS_ANSWER_FINISH:
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_STATUS,VOLC_DISPLAY_TEXT,"智能体说话完成");
break;
default:
break;
}
return;
}
static void __on_volc_audio_data(volc_engine_t handle, const void *data_ptr, size_t data_len, volc_audio_frame_info_t *info_ptr, void *user_data)
{
int error = 0;
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if (g_hal_context == NULL) {
LOGE("volc_get_global_hal_context failed");
return;
}
volc_hal_player_t player_handle = g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO];
if (player_handle == NULL)
{
LOGE("player pipeline is NULL");
return;
}
if(!is_stop){
volc_hal_player_play_data(player_handle, data_ptr, data_len);
}
}
static void __on_volc_video_data(volc_engine_t handle, const void *data_ptr, size_t data_len, volc_video_frame_info_t *info_ptr, void *user_data)
{
}
static int sub_offset = 0;
static void __on_subtitle_message_received(const cJSON* root) {
/*
{
"data" :
[
{
"definite" : false,
"language" : "zh",
"mode" : 1,
"paragraph" : false,
"sequence" : 0,
"text" : "\\u4f60\\u597d",
"userId" : "voiceChat_xxxxx"
}
],
"type" : "subtitle"
}
*/
cJSON * type_obj = cJSON_GetObjectItem(root, "type");
if (type_obj != NULL && strcmp("subtitle", cJSON_GetStringValue(type_obj)) == 0) {
cJSON* data_obj_arr = cJSON_GetObjectItem(root, "data");
cJSON* obji = NULL;
cJSON_ArrayForEach(obji, data_obj_arr) {
cJSON* user_id_obj = cJSON_GetObjectItem(obji, "userId");
cJSON* text_obj = cJSON_GetObjectItem(obji, "text");
cJSON* definite_obj = cJSON_GetObjectItem(obji, "definite");
char* sub = cJSON_GetStringValue(text_obj);
// print_string(sub + sub_offset -1);
if(cJSON_IsTrue(definite_obj)){
sub_offset = sub_offset == 0 ? 0 : sub_offset -1;
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_SUBTITLE,VOLC_DISPLAY_TEXT,sub + sub_offset);
sub_offset = 0;
aios_event_pub(VOLC_LOCAL_LOGIC_PROCESS_SUBTITLE, sub, NULL);
} else if(strlen(sub) - sub_offset > 18){
sub_offset = sub_offset == 0 ? 0 : sub_offset -1;
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_SUBTITLE,VOLC_DISPLAY_TEXT,sub + sub_offset);
if(strlen(sub) - sub_offset > 36){
sub_offset = strlen(sub);
}
}
}
}
}
/* HTTPS reporting must never run inside the WebSocket receive mutex. */
static void process_platform_reports(void)
{
cJSON *root;
while (platform_report_queue && xQueueReceive(platform_report_queue, &root, 0) == pdTRUE) {
cJSON *type_obj = cJSON_GetObjectItemCaseSensitive(root, "type");
const char *type = cJSON_IsString(type_obj) ? type_obj->valuestring : "";
if ((strcmp(type, "session.updated") == 0 || strcmp(type, "session.created") == 0) && !session_started_reported) {
cJSON *session = cJSON_GetObjectItemCaseSensitive(root, "session");
cJSON *id = cJSON_IsObject(session) ? cJSON_GetObjectItemCaseSensitive(session, "id") : NULL;
cJSON *job_id = cJSON_GetObjectItemCaseSensitive(root, "job_id");
const char *provider_ref = cJSON_IsString(id) && id->valuestring[0] ? id->valuestring :
(cJSON_IsString(job_id) ? job_id->valuestring : NULL);
if (provider_ref && provider_ref[0] && platform_conversation_started(provider_ref) == 0) {
session_started_reported = true;
LOGI("Platform confirmed dynamic session configuration");
}
} else if (strcmp(type, "conversation.item.input_audio_transcription.completed") == 0) {
cJSON *text = cJSON_GetObjectItemCaseSensitive(root, "transcript");
cJSON *source = cJSON_GetObjectItemCaseSensitive(root, "event_id");
if (cJSON_IsString(text) && text->valuestring[0]) {
(void)platform_conversation_turn("subject", cJSON_IsString(source) ? source->valuestring : "subject", text->valuestring);
}
} else if (strcmp(type, "response.audio_transcript.done") == 0) {
cJSON *text = cJSON_GetObjectItemCaseSensitive(root, "transcript");
cJSON *source = cJSON_GetObjectItemCaseSensitive(root, "response_id");
if (cJSON_IsString(text) && text->valuestring[0]) {
(void)platform_conversation_turn("agent", cJSON_IsString(source) ? source->valuestring : "agent", text->valuestring);
}
}
cJSON_Delete(root);
}
}
static void __on_volc_message_data(volc_engine_t handle, const void *message, size_t size, volc_message_info_t *info_ptr, void *user_data)
{
static char message_buffer[4096];
if (size > 0 && size < sizeof(message_buffer) - 1) {
memcpy(message_buffer, message, size);
message_buffer[size] = 0;
const bool standard_protocol = message_buffer[0] == '{';
if (!standard_protocol && size < 8) return;
cJSON *root = cJSON_Parse(standard_protocol ? message_buffer : message_buffer + 8);
if (root != NULL) {
if (standard_protocol) {
const char *type = cJSON_GetStringValue(cJSON_GetObjectItem(root, "type"));
if (type && (!strcmp(type, "error") || !strcmp(type, "conversation.item.created"))) {
LOGI("Provider control event: %s", message_buffer);
}
if (type && !strcmp(type, "response.audio.done") && !is_stop) {
/* Flush the final sub-frame through the PCM decoder. */
static const uint8_t silence[2048] = {0};
volc_hal_context_t *hal = volc_get_global_hal_context();
if (hal) {
volc_hal_player_t player = hal->player_handle[VOLC_HAL_PLAYER_AUDIO];
volc_hal_player_play_data(player, silence, sizeof(silence));
volc_hal_player_finish_segment(player);
}
}
if (type && (strstr(type, "speech_") || strstr(type, "response."))) {
conv_service.wait_time = 0;
}
bool report = type && (!strcmp(type, "session.created") || !strcmp(type, "session.updated") ||
!strcmp(type, "conversation.item.input_audio_transcription.completed") ||
!strcmp(type, "response.audio_transcript.done"));
if (report && platform_report_queue && xQueueSend(platform_report_queue, &root, 0) == pdTRUE) {
root = NULL; /* Conversation task owns queued messages. */
} else if (report) {
LOGE("Platform report queue unavailable or full");
}
cJSON_Delete(root);
} else if (message_buffer[0] == 's' && message_buffer[1] == 'u' && message_buffer[2] == 'b' && message_buffer[3] == 'v') {
__on_subtitle_message_received(root);
conv_service.wait_time = 0;
} else if (message_buffer[0] == 't' && message_buffer[1] == 'o' && message_buffer[2] == 'o' && message_buffer[3] == 'l') {
// function calling 消息
aios_event_pub(VOLC_FUNCTION_CALL_EXEC, root, NULL);
}else if (message_buffer[0] == 'i' && message_buffer[1] == 'n' && message_buffer[2] == 'f' && message_buffer[3] == 'o') {
aios_event_pub(VOLC_FUNCTION_CALL_TRIGGER, root, NULL);
}
}
}
}
void conv_ai_service_init()
{
if (!platform_report_queue) platform_report_queue = xQueueCreate(8, sizeof(cJSON *));
snprintf(config_buf, sizeof(config_buf), CONV_AI_CONFIG_FORMAT,
platform_runtime_instance_id(),
platform_runtime_product_key(),
platform_runtime_device_secret(),
platform_runtime_device_name());
conv_service.volc_event_handler = (volc_event_handler_t){
.on_volc_event = __on_volc_event,
.on_volc_conversation_status = __on_volc_conversation_status,
.on_volc_audio_data = __on_volc_audio_data,
.on_volc_video_data = __on_volc_video_data,
.on_volc_message_data = __on_volc_message_data,
};
int ret = volc_create(&conv_service.engine, config_buf, &conv_service.volc_event_handler, &conv_service);
if (ret != 0) {
LOGE("volc_create failed, ret: %d", ret);
return;
} else {
LOGE("volc_create success");
}
}
void conv_ai_service_task(void *pvParameters)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
char* status_str = NULL;
bool provider_started = false;
bool audio_started = false;
session_started_reported = false;
provider_disconnected = false;
if (g_hal_context == NULL) {
LOGE("volc_get_global_hal_context failed");
status_str = "系统未初始化,ai对话连接失败";
goto CONV_AI_QUIT;
}
global_display = g_hal_context->display_handle;
int ret = 0;
volc_hal_display_set_content(global_display, VOLC_DISPLAY_OBJ_STATUS,VOLC_DISPLAY_TEXT, "ai对话创建中");
ret = platform_conversation_begin();
if (ret != 0) {
LOGE("platform_conversation_begin failed, ret: %d", ret);
status_str = "平台会话创建失败";
if (strcmp(platform_last_error_code(), "FIRMWARE_UPDATE_REQUIRED") == 0) {
status_str = "平台要求更新固件";
}
goto CONV_AI_QUIT;
}
/* Capture may run while the WebSocket is still handshaking. Hold frames
* until volc_start has moved the engine into STARTED state. */
is_stop = true;
// step 1: start audio capture & play
volc_hal_capture_config_t capture_audio_config = {0};
capture_audio_config.media_type = VOLC_MEDIA_TYPE_AUDIO;
capture_audio_config.data_cb = __audio_capture_cb;
// capture_audio_config.audio_wakeup_cb = (volc_hal_audio_wakeup_cb_t)rec_engine_cb;
capture_audio_config.user_data = g_hal_context;
volc_hal_capture_t capture_handle = g_hal_context->capture_handle[VOLC_HAL_PLAYER_AUDIO];
if (g_hal_context->capture_handle[VOLC_HAL_PLAYER_AUDIO] == NULL) {
g_hal_context->capture_handle[VOLC_HAL_PLAYER_AUDIO] = volc_hal_capture_create(&capture_audio_config);
capture_handle = g_hal_context->capture_handle[VOLC_HAL_PLAYER_AUDIO];
}
audio_started = true;
volc_hal_capture_stop(g_hal_context->capture_handle[VOLC_HAL_CAPTURE_AUDIO]);
volc_hal_capture_update_config(capture_handle, &capture_audio_config);
volc_hal_capture_start(g_hal_context->capture_handle[VOLC_HAL_PLAYER_AUDIO], VOLC_AUDIO_MODE_CAPTURE);
volc_hal_player_config_t player_audio_config = {0};
player_audio_config.media_type = VOLC_MEDIA_TYPE_AUDIO;
if (g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO] == NULL) {
g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO] = volc_hal_player_create(&player_audio_config);
}
volc_hal_display_set_content(global_display, VOLC_DISPLAY_OBJ_STATUS, VOLC_DISPLAY_TEXT, "ai对话连接中");
volc_hal_player_start(g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO]);
// step 2: start ai conversation
const char *session_update = platform_conversation_update_json();
size_t params_size = strlen(session_update) + 64;
char *params = volc_osal_malloc(params_size);
if (params == NULL) {
status_str = "会话配置内存不足";
goto CONV_AI_QUIT;
}
snprintf(params, params_size, "{\"audio\":{\"codec\":0},\"session_update\":%s}", session_update);
volc_opt_t opt = {
.mode = VOLC_MODE_WS,
.bot_id = (char *)platform_conversation_bot_id(),
.params = params,
};
#if defined ENABLE_PLAY_WELCOME
aios_event_pub(VOLC_LOCAL_LOGIC_PLAY_WELCOME, NULL, NULL);
#endif
ret = volc_start(conv_service.engine, &opt);
volc_osal_free(params);
if (ret != 0) {
LOGE("volc_start failed, ret: %d", ret);
status_str = "ai对话连接失败,准备退出";
goto CONV_AI_QUIT;
}
provider_started = true;
volc_hal_display_set_content(global_display, VOLC_DISPLAY_OBJ_STATUS, VOLC_DISPLAY_TEXT, "ai对话已连接");
is_stop = false;
while (!is_stop && !provider_disconnected) {
process_platform_reports();
if (session_started_reported && platform_conversation_poll()) {
status_str = "平台已结束本次对话";
goto CONV_AI_QUIT;
}
if (diagnostic_say_pending && session_started_reported) {
diagnostic_say_pending = false;
char request[640];
snprintf(request, sizeof(request), "{\"event_id\":\"diag-%llu\",\"type\":\"conversation.item.create\",\"item\":{\"type\":\"message\",\"role\":\"user\",\"content\":[{\"type\":\"input_text\",\"text\":\"请只说这句话:你好,这是语音播放测试。现在使用自然的语速,连续清楚地说完这句话。\"}],\"interrupt_mode\":1}}", (unsigned long long)volc_osal_get_time_ms());
volc_message_info_t info = {.is_binary = false};
int sent = volc_send_message(conv_service.engine, request, strlen(request), &info);
LOGI("PLAYBACK diagnostic sentence requested ret=%d", sent);
const char *respond = "{\"type\":\"response.create\",\"response\":{\"modalities\":[\"text\",\"audio\"]}}";
volc_send_message(conv_service.engine, respond, strlen(respond), &info);
conv_service.wait_time = 0;
}
sleep(1);
conv_service.wait_time++;
if(conv_service.wait_time >= CONV_SERVICE_TIMEOUT){
status_str = "ai对话已超时,准备退出";
goto CONV_AI_QUIT;
}
}
status_str = "ai对话已断开";
CONV_AI_QUIT:
is_stop = true;
// volc_hal_file_close(audioFile);
volc_stop(conv_service.engine);
process_platform_reports();
platform_conversation_finish(!provider_started || !session_started_reported,
!provider_started ? "VOLC_START_FAILED" : (!session_started_reported ? "SESSION_UPDATE_NOT_CONFIRMED" : NULL));
if (g_hal_context && audio_started) {
volc_hal_capture_stop(g_hal_context->capture_handle[VOLC_HAL_CAPTURE_AUDIO]);
if (g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO]) {
volc_hal_player_stop(g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO]);
volc_hal_player_destroy(g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO]);
g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO] = NULL;
}
}
if(status_str != NULL){
volc_hal_display_set_content(global_display, VOLC_DISPLAY_OBJ_STATUS, VOLC_DISPLAY_TEXT, status_str);
}
volc_hal_display_set_content(global_display, VOLC_DISPLAY_OBJ_SUBTITLE, VOLC_DISPLAY_TEXT, "");
conv_service.wait_time = 0;
// just show the status: Ai对话已断开
sleep(1);
if (g_hal_context && audio_started) {
volc_hal_capture_start(g_hal_context->capture_handle[VOLC_HAL_CAPTURE_AUDIO],VOLC_AUDIO_MODE_WAKEUP);
}
aios_event_pub(VOLC_SERVICE_AI_CONVERSATION_OVER, NULL, NULL);
volc_osal_thread_exit(NULL);
}
void conv_ai_service_task_stop(void)
{
// sleep for AI Agent say goodbye
sleep(1);
is_stop = true;
}
#if __cplusplus
}
#endif
@@ -0,0 +1,84 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include <stdio.h>
#include "aios.h"
#include "volc_hal.h"
#include "volc_osal.h"
#include "volc_hal_display.h"
#include "volc_hal_file.h"
#include "volc_service_common.h"
#include "volc_conv_service.h"
#include "volc_conv.h"
#if __cplusplus
extern "C" {
#endif
typedef struct volc_conv_service_manager {
aios_session_t super;
volc_osal_tid_t conv_thread_id;
} volc_conv_service_manager_t;
volc_conv_service_manager_t volc_conv_service_manager;
static aios_ret_t __state_conversation(volc_conv_service_manager_t * const me, aios_event_t const * const e)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if (g_hal_context == NULL) {
return AIOS_Ret_NotHandled;
}
volc_hal_display_t global_display = g_hal_context->display_handle;
switch (e->id) {
case VOLC_SERVICE_AI_CONVERSATION_START:
if (me->conv_thread_id == NULL) {
volc_osal_thread_param_t param = {0};
volc_hal_display_set_content(global_display,VOLC_DISPLAY_OBJ_STATUS,VOLC_DISPLAY_TEXT,"ai对话启动中");
snprintf(param.name, sizeof(param.name), "%s", "conv_ai");
param.stack_size = 8*1024;
param.priority = 5;
param.stack_in_ext = 1;
volc_osal_thread_create(&me->conv_thread_id, &param, conv_ai_service_task,NULL);
}
return AIOS_Ret_Handled;
case VOLC_SERVICE_AI_CONVERSATION_INTERRUPT:
return AIOS_Ret_Handled;
// control the Ai_Conversation task quit
case VOLC_SERVICE_AI_CONVERSATION_QUIT:
if (me->conv_thread_id != NULL) {
conv_ai_service_task_stop();
me->conv_thread_id = NULL;
}
return AIOS_Ret_Handled;
// notice the Ai_Conversation over by task
case VOLC_SERVICE_AI_CONVERSATION_OVER:
if (me->conv_thread_id != NULL) {
me->conv_thread_id = NULL;
}
return AIOS_Ret_Handled;
default:
return AIOS_Ret_NotHandled;
}
}
static aios_ret_t __state_init(volc_conv_service_manager_t * const me, aios_event_t const * const e)
{
AIOS_EVENT_SUB(VOLC_SERVICE_AI_CONVERSATION_START); // 订阅事件
AIOS_EVENT_SUB(VOLC_SERVICE_AI_CONVERSATION_INTERRUPT); // 订阅事件
AIOS_EVENT_SUB(VOLC_SERVICE_AI_CONVERSATION_QUIT); // 订阅事件
AIOS_EVENT_SUB(VOLC_SERVICE_AI_CONVERSATION_OVER); // 订阅事件
me->conv_thread_id = NULL;
conv_ai_service_init();
return AIOS_TRAN(__state_conversation);
}
void volc_conv_service_manager_init(void)
{
aios_session_init(&volc_conv_service_manager.super, VOLC_SERVICE_PRIORITY_AI_CONVERSATION, NULL);
aios_session_start(&volc_conv_service_manager.super, AIOS_STATE_CAST(__state_init));
}
#if __cplusplus
}
#endif
@@ -0,0 +1,9 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef VOLC_FUNCTION_CALL_SERVICE_H__
#define VOLC_FUNCTION_CALL_SERVICE_H__
void function_call_service_init();
#endif /* VOLC_FUNCTION_CALL_SERVICE_H__ */
@@ -0,0 +1,9 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef VOLC_LOCAL_FUNCTION_LIST_H__
#define VOLC_LOCAL_FUNCTION_LIST_H__
void adjust_audio_val(const char* action);
#endif
@@ -0,0 +1,134 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include <string.h>
#include "cJSON.h"
#include "volc_service_common.h"
#include "volc_conv.h"
#include "volc_function_call_service.h"
#include "volc_local_function_list.h"
#include "aios.h"
#include <stdio.h>
#if __cplusplus
extern "C" {
#endif
typedef struct volc_function_call_service {
aios_session_t super;
} volc_function_call_service_t;
volc_function_call_service_t g_volc_function_call_service;
static void __on_function_calling_message_received(const cJSON *root)
{
/*
{
"subscriber_user_id" : "",
"tool_calls" :
[
{
"function" :
{
"arguments" : "{\\"location\\": \\"\\u5317\\u4eac\\u5e02\\"}",
"name" : "get_current_weather"
},
"id" : "call_py400kek0e3pczrqdxgnb3lo",
"type" : "function"
}
]
}
*/
cJSON *tool_obj_arr = cJSON_GetObjectItem(root, "tool_calls");
cJSON *obji = NULL;
cJSON_ArrayForEach(obji, tool_obj_arr)
{
cJSON *id_obj = cJSON_GetObjectItem(obji, "id");
cJSON *function_obj = cJSON_GetObjectItem(obji, "function");
if (id_obj && function_obj)
{
cJSON *arguments_obj = cJSON_GetObjectItem(function_obj, "arguments");
cJSON *name_obj = cJSON_GetObjectItem(function_obj, "name");
char *arguments_json_str = cJSON_GetStringValue(arguments_obj);
const char *func_name = cJSON_GetStringValue(name_obj);
const char *func_id = cJSON_GetStringValue(id_obj);
if (strcmp(func_name, "adjust_audio_val") == 0 && arguments_json_str)
{
cJSON *arguments_json = cJSON_Parse(arguments_json_str);
cJSON *action_obj = cJSON_GetObjectItem(arguments_json, "action");
const char *action = (action_obj->valuestring);
adjust_audio_val(action);
volc_conv_service_t conv_service = get_conv_ai_service();
cJSON *fc_obj = cJSON_CreateObject();
cJSON_AddStringToObject(fc_obj, "ToolCallID", func_id);
cJSON_AddStringToObject(fc_obj, "Content", "音量已经调整了");
char *json_string = cJSON_Print(fc_obj);
static char fc_message_buffer[256] = {'f', 'u', 'n', 'c'};
int json_str_len = strlen(json_string);
fc_message_buffer[4] = (json_str_len >> 24) & 0xff;
fc_message_buffer[5] = (json_str_len >> 16) & 0xff;
fc_message_buffer[6] = (json_str_len >> 8) & 0xff;
fc_message_buffer[7] = (json_str_len >> 0) & 0xff;
memcpy(fc_message_buffer + 8, json_string, json_str_len);
cJSON_Delete(fc_obj);
volc_message_info_t info = {0};
info.is_binary = 1;
volc_send_message(conv_service.engine, fc_message_buffer, json_str_len + 8, &info);
}
}
}
cJSON_Delete(root);
}
void __on_function_calling_trigger(const cJSON *root)
{
/*
{
"event_type": "function_calling", // 事件类型,固定为此值
"function": "get_current_weather", // 被触发的函数名,与您在 StartVoiceChat 中定义的名称一致
"tool_call_id": "call_12345", // 本次函数调用的唯一ID,后续回传结果时需要用到
"response_id": "resp_abcde" // 本次响应的唯一ID,可用于问题排查
}
*/
cJSON *event_type_obj = cJSON_GetObjectItemCaseSensitive(root, "event_type");
if(event_type_obj && strcmp(event_type_obj->valuestring, "function_calling") == 0 ) {
cJSON *function_obj = cJSON_GetObjectItemCaseSensitive(root, "function");
if(function_obj && strcmp(function_obj->valuestring, "adjust_audio_val") == 0){
volc_conv_service_t conv_service = get_conv_ai_service();
volc_send_text_to_agent(conv_service.engine, "别着急,我来给你调整音量", VOLC_AGENT_TYPE_TTS,2);
}
}
cJSON_Delete(root);
}
static aios_ret_t __state_conversation(volc_function_call_service_t * const me, aios_event_t const * const e)
{
switch (e->id) {
case VOLC_FUNCTION_CALL_EXEC:
__on_function_calling_message_received((const cJSON *)e->data);
return AIOS_Ret_Handled;
case VOLC_FUNCTION_CALL_TRIGGER:
__on_function_calling_trigger((const cJSON *)e->data);
return AIOS_Ret_Handled;
}
}
static aios_ret_t __state_init(volc_function_call_service_t * const me, aios_event_t const * const e)
{
AIOS_EVENT_SUB(VOLC_FUNCTION_CALL_EXEC); // 订阅事件
AIOS_EVENT_SUB(VOLC_FUNCTION_CALL_TRIGGER); // 订阅事件
return AIOS_TRAN(__state_conversation);
}
void function_call_service_init(void){
aios_session_init(&g_volc_function_call_service.super, VOLC_SERVICE_PRIORITY_FUNCTION_CALL, NULL);
aios_session_start(&g_volc_function_call_service.super, AIOS_STATE_CAST(__state_init));
}
#if __cplusplus
}
#endif
@@ -0,0 +1,41 @@
#include "volc_local_function_list.h"
#include "volc_hal.h"
#include "volc_hal_player.h"
#include <string.h>
void __volc_up_audio_val()
{
volc_hal_context_t *g_hal_context = volc_get_global_hal_context();
if (g_hal_context == NULL)
{
return;
}
int volc_audio_vol = volc_hal_get_audio_player_volume(g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO]);
volc_audio_vol = (volc_audio_vol + 10) <= 100 ? (volc_audio_vol + 10) : 100;
volc_hal_set_audio_player_volume(g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO], volc_audio_vol);
}
void __volc_down_audio_val()
{
volc_hal_context_t *g_hal_context = volc_get_global_hal_context();
if (g_hal_context == NULL)
{
return;
}
int volc_audio_vol = volc_hal_get_audio_player_volume(g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO]);
volc_audio_vol = (volc_audio_vol - 10) <= 0 ? 0 : (volc_audio_vol - 10);
volc_hal_set_audio_player_volume(g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO], volc_audio_vol);
}
void adjust_audio_val(const char *action)
{
if (strcmp(action, "up") == 0)
{
__volc_up_audio_val();
}
else if (strcmp(action, "down") == 0)
{
__volc_down_audio_val();
}
}
@@ -0,0 +1,11 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef VOLC_SERVICE_MANAGER_H__
#define VOLC_SERVICE_MANAGER_H__
#include <stdbool.h>
#include "aios.h"
void volc_service_manager_init(void);
#endif /* VOLC_SERVICE_MANAGER_H__ */
@@ -0,0 +1,38 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef VOLC_CONV_COMMON_H__
#define VOLC_CONV_COMMON_H__
#include "aios.h"
enum {
VOLC_SERVICE_EVENT_TEST = Event_User,
VOLC_SERVICE_NETWORK_CONFIG,
VOLC_SERVICE_AI_CONVERSATION,
// Ai_Conversation event:
VOLC_SERVICE_AI_CONVERSATION_START = 100,
VOLC_SERVICE_AI_CONVERSATION_INTERRUPT = 101,
VOLC_SERVICE_AI_CONVERSATION_QUIT = 102, // control the Ai_Conversation task quit
VOLC_SERVICE_AI_CONVERSATION_OVER = 103, // notice the Ai_Conversation over by task
// function_call event:
VOLC_FUNCTION_CALL_EXEC = 200,
VOLC_FUNCTION_CALL_TRIGGER = 201,
// local logic event:
VOLC_LOCAL_LOGIC_PLAY_WELCOME = 300,
VOLC_LOCAL_LOGIC_PROCESS_SUBTITLE = 301,
VOLC_SERVICE_EVENT_MAX,
};
enum {
VOLC_SERVICE_PRIORITY_AI_CONVERSATION = 0,
VOLC_SERVICE_PRIORITY_FUNCTION_CALL,
VOLC_SERVICE_PRIORITY_LOCAL_LOGIC,
VOLC_SERVICE_PRIORITY_APP_MANAGER,
};
#endif /* VOLC_CONV_COMMON_H__ */
@@ -0,0 +1,9 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#ifndef VOLC_LOCAL_LOGIC_SERVICE_H__
#define VOLC_LOCAL_LOGIC_SERVICE_H__
void local_logic_service_init();
#endif /* VOLC_LOCAL_LOGIC_SERVICE_H__ */
@@ -0,0 +1,99 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include <string.h>
#include "volc_conv_ai.h"
#include "volc_service_common.h"
#include "aios.h"
#include "volc_conv.h"
#include "volc_hal.h"
#include "volc_hal_file.h"
#include "volc_hal_player.h"
#if __cplusplus
extern "C" {
#endif
static const char *welcome_audio_file_name = "/sdcard/wel.pcm";
typedef struct volc_local_logic_service {
aios_session_t super;
} volc_local_logic_service_t;
volc_local_logic_service_t g_volc_local_logic_service;
static int has_quit = 0;
static void __play_welcome(){
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL) return;
volc_hal_player_t player = g_hal_context->player_handle[VOLC_HAL_PLAYER_AUDIO];
volc_hal_file_t* audioFile = volc_hal_file_open(welcome_audio_file_name, "rb");
if(audioFile == NULL) return;
char audio_data[160];
if(player){
int offset = 0;
uint64_t size = volc_hal_file_get_size(audioFile);
while(offset < size - 160){
volc_hal_file_read(audioFile,audio_data,160);
volc_hal_player_play_data(player, audio_data, 160);
offset += 160;
}
}
volc_hal_file_close(audioFile);
return;
}
static int __has_substring(const char *haystack, const char *needle) {
// 处理边界:子串为空串,按惯例返回包含(可根据需求调整)
if (needle[0] == '\0') {
return 1;
}
// strstr 返回非 NULL 表示找到子串
return strstr(haystack, needle) != NULL ? 1 : 0;
}
static void __parser_and_process_subtitle(char *subtitle)
{
volc_conv_service_t conv_service = get_conv_ai_service();
if (__has_substring(subtitle, "退下吧") || __has_substring(subtitle, "拜拜"))
{
if (!has_quit)
{
volc_send_text_to_agent(conv_service.engine, "好的拜拜", VOLC_AGENT_TYPE_TTS, 1);
has_quit = 1;
}
}
if (__has_substring(subtitle, "好的拜拜"))
{
aios_event_pub(VOLC_SERVICE_AI_CONVERSATION_QUIT, NULL, NULL);
has_quit = 0;
}
}
static aios_ret_t __state_conversation(volc_local_logic_service_t * const me, aios_event_t const * const e)
{
switch (e->id) {
case VOLC_LOCAL_LOGIC_PLAY_WELCOME:
__play_welcome();
return AIOS_Ret_Handled;
case VOLC_LOCAL_LOGIC_PROCESS_SUBTITLE:
__parser_and_process_subtitle(e->data);
return AIOS_Ret_Handled;
}
}
static aios_ret_t __state_init(volc_local_logic_service_t * const me, aios_event_t const * const e)
{
AIOS_EVENT_SUB(VOLC_LOCAL_LOGIC_PLAY_WELCOME); // 订阅事件
AIOS_EVENT_SUB(VOLC_LOCAL_LOGIC_PROCESS_SUBTITLE); // 订阅事件
return AIOS_TRAN(__state_conversation);
}
void local_logic_service_init(void){
aios_session_init(&g_volc_local_logic_service.super, VOLC_SERVICE_PRIORITY_LOCAL_LOGIC, NULL);
aios_session_start(&g_volc_local_logic_service.super, AIOS_STATE_CAST(__state_init));
}
#if __cplusplus
}
#endif
@@ -0,0 +1,43 @@
// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0
#include "volc_hal.h"
#include "volc_manager_service.h"
#include "volc_conv_service.h"
#include "volc_service_common.h"
typedef struct volc_service_manager {
aios_session_t super;
} volc_service_manager_t;
volc_service_manager_t volc_service_manager;
static aios_ret_t __state_wait_service_event(volc_service_manager_t* const me, aios_event_t const * const e)
{
volc_hal_context_t* g_hal_context = volc_get_global_hal_context();
if(g_hal_context == NULL){
return AIOS_Ret_NotHandled;
}
switch ((int)e->id) {
case VOLC_SERVICE_NETWORK_CONFIG:
return AIOS_Ret_Handled;
case VOLC_SERVICE_AI_CONVERSATION:
aios_event_pub(VOLC_SERVICE_AI_CONVERSATION_START, NULL, NULL);
return AIOS_Ret_Handled;
default:
return AIOS_Ret_NotHandled;
}
}
static aios_ret_t __state_init(volc_service_manager_t* const me, aios_event_t const * const e)
{
AIOS_EVENT_SUB(VOLC_SERVICE_NETWORK_CONFIG); // 订阅事件
AIOS_EVENT_SUB(VOLC_SERVICE_AI_CONVERSATION); // 订阅事件
return AIOS_TRAN(__state_wait_service_event);
}
void volc_service_manager_init(void)
{
aios_session_init(&volc_service_manager.super, VOLC_SERVICE_PRIORITY_APP_MANAGER, NULL);
aios_session_start(&volc_service_manager.super, AIOS_STATE_CAST(__state_init));
}
@@ -0,0 +1,8 @@
#ifndef __VOLC_CONFIG_H__
#define __VOLC_CONFIG_H__
#ifndef VOLC_LCD_DISPLAY
#define VOLC_LCD_DISPLAY 1(CONFIG_)
#endif
#endif
@@ -0,0 +1 @@
**/gen_bmgr_codes/
@@ -0,0 +1,7 @@
# Changelog
## v0.1.0
### Features
- Initial version of `av_processor`
@@ -0,0 +1,7 @@
idf_component_register(
INCLUDE_DIRS "include" "./"
PRIV_INCLUDE_DIRS "private_include"
SRC_DIRS "./"
REQUIRES esp_capture esp_video_codec
)
@@ -0,0 +1,82 @@
menu "Audio/Video Processor Configuration"
# Media Dump Configuration
menu "Media Dump"
config MEDIA_DUMP_ENABLE
bool "Enable Media Dump"
default n
help
Enable media dump feature. When disabled, related options are hidden.
# Audio AEC Save Point
choice MEDIA_DUMP_AUDIO_POINT
prompt "Audio Save Mode (AEC point)"
depends on MEDIA_DUMP_ENABLE
default MEDIA_DUMP_AUDIO_NONE
help
Select which audio to save for media dump with respect to AEC processing.
Only one can be selected, or select None to disable both.
config MEDIA_DUMP_AUDIO_BEFORE_AEC
bool "Save Before AEC"
help
Save raw microphone audio before AEC processing for media dump.
config MEDIA_DUMP_AUDIO_AFTER_AEC
bool "Save After AEC"
help
Save audio after AEC processing for media dump.
config MEDIA_DUMP_AUDIO_NONE
bool "None"
help
Do not save audio for media dump.
endchoice
config MEDIA_DUMP_DURATION_SEC
int "Dump Duration (seconds)"
depends on MEDIA_DUMP_ENABLE
default 20
range 1 3600
help
Maximum duration to capture media dump in seconds. Default 20s.
choice MEDIA_DUMP_SINK
prompt "Media Dump Output Method"
depends on MEDIA_DUMP_ENABLE
default MEDIA_DUMP_SINK_SDCARD
help
Select where to save media dump data.
config MEDIA_DUMP_SINK_UDP
bool "UDP"
config MEDIA_DUMP_SINK_SDCARD
bool "SD Card File"
endchoice
if MEDIA_DUMP_SINK_UDP
config MEDIA_DUMP_UDP_IP
string "UDP Destination IP"
default "192.168.1.100"
help
Destination IPv4 address for UDP media dump.
config MEDIA_DUMP_UDP_PORT
int "UDP Destination Port"
default 5000
range 1 65535
help
Destination UDP port for media dump.
endif
if MEDIA_DUMP_SINK_SDCARD
config MEDIA_DUMP_SDCARD_FILENAME
string "SD Card File Name"
default "/sdcard/media_dump.bin"
help
File path on SD card to save media dump data. Ensure SD is mounted.
endif
endmenu
endmenu
@@ -0,0 +1,22 @@
Espressif Modified MIT License
Copyright (c) 2025 Espressif Systems (Shanghai) CO., LTD
Permission is hereby granted for use EXCLUSIVELY with Espressif Systems products.
This includes the right to use, copy, modify, merge, publish, distribute, and sublicense
the Software, subject to the following conditions:
1. This Software MUST BE USED IN CONJUNCTION WITH ESPRESSIF SYSTEMS PRODUCTS.
2. The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
3. Redistribution of the Software in source or binary form FOR USE WITH NON-ESPRESSIF PRODUCTS
is strictly prohibited.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
@@ -0,0 +1,332 @@
# AV Processor Component (Audio/Video Processing)
This component provides a unified encapsulation for audio recording/playback/data feeding and video capture/decoding/rendering on ESP platforms, implemented based on middleware such as GMF (General Media Framework), esp-audio-render, esp-video-codec, and esp-capture.
## Feature Overview 🎛️
- **Audio 🎧**:
- Recording (AEC/VAD/AFE optional)
- Playback (supports URL and local files, decoding depends on configuration)
- Data feeding (feeder, suitable for scenarios like RTC/streaming where receiving and playing happen simultaneously)
- Optional mixer with volume fade and focus control between multiple streams
- **Video 🎥**:
- Multi-channel video capture
- Video decoding and rendering callbacks
---
## Quick Start
### 1. Audio Usage
1. Initialize audio manager:
```c
// Method 1: Use default configuration macro (recommended)
audio_manager_config_t cfg = DEFAULT_AUDIO_MANAGER_CONFIG();
cfg.play_dev = your_play_dev;
cfg.rec_dev = your_rec_dev;
strcpy(cfg.mic_layout, "RMNM"); // Microphone layout (optional, for AFE configuration)
cfg.board_sample_rate = 16000;
cfg.board_bits = 32;
cfg.board_channels = 2;
cfg.play_volume = 80;
cfg.rec_volume = 60;
cfg.rec_ref_volume = 60;
cfg.enable_mixer = true; // Enable when mixing feeder and playback is needed
audio_manager_init(&cfg);
```
2. Recording (polling read):
```c
// Recording event callback (optional)
void recorder_event_cb(void *event, void *ctx) {
// Handle recording events (e.g., AFE events)
}
// Configure recorder (using default configuration macro)
audio_recorder_config_t recorder_cfg = DEFAULT_AUDIO_RECORDER_CONFIG();
// Optional: Configure AFE (runtime configuration, takes priority over Kconfig)
recorder_cfg.afe_config.vad_enable = true;
recorder_cfg.afe_config.vad_mode = 4;
recorder_cfg.afe_config.agc_enable = true;
recorder_cfg.recorder_event_cb = recorder_event_cb;
// Open recorder
audio_recorder_open(&recorder_cfg);
uint8_t buf[2048];
audio_recorder_read_data(buf, sizeof(buf));
audio_recorder_close();
```
3. Feeder playback (suitable for external stream → local playback):
```c
// Configure feeder (using default configuration macro)
audio_feeder_config_t feeder_cfg = DEFAULT_AUDIO_FEEDER_CONFIG();
// Optional: When using OPUS decoder, task_stack is recommended to be >= 4096 * 10
// feeder_cfg.feeder_task_config.task_stack = 4096 * 10;
audio_feeder_open(&feeder_cfg);
audio_feeder_run();
// Feed external data blocks multiple times as needed
audio_feeder_feed_data(pkt, pkt_len);
audio_feeder_stop();
audio_feeder_close();
```
4. Normal playback (URL or local):
```c
// Configure player (using default configuration macro)
audio_playback_config_t playback_cfg = DEFAULT_AUDIO_PLAYBACK_CONFIG();
audio_playback_open(&playback_cfg);
audio_playback_play("http://<ip>:<port>/audio.mp3");
audio_playback_pause();
audio_playback_resume();
audio_playback_stop();
audio_playback_close();
```
5. Focus/fade control (when mixer is enabled):
```c
// Note: Mixer must be opened after both playback and feeder are opened
audio_processor_mixer_open();
audio_processor_ramp_control(AUDIO_MIXER_FOCUS_FEEDER); // Focus on feeder audio
audio_processor_ramp_control(AUDIO_MIXER_FOCUS_PLAYBACK); // Focus on playback audio
audio_processor_mixer_close();
```
### 2. Video Usage
1. Render (decode) callback:
```c
void decoded_cb(void *ctx, const uint8_t *data, size_t size) {
// Handle decoded frame data
}
video_render_config_t rcfg = {
.decode_cfg = your_vdec_cfg,
.resolution = {.width = 640, .height = 480},
.decode_cb = decoded_cb,
};
video_render_handle_t r = video_render_open(&rcfg);
video_render_start(r);
video_frame_t f = {.data = enc_frame, .size = enc_size};
video_render_frame_feed(r, &f);
video_render_stop(r);
video_render_close(r);
```
1. Capture (multi-channel):
```c
void capture_cb(void *ctx, int index, video_frame_t *frame) {
// Handle captured video frame
}
video_capture_config_t ccfg = {0};
ccfg.camera_config = &your_cam_cfg;
ccfg.sink_num = 2;
ccfg.sink_cfg[0] = your_sink0_cfg;
ccfg.sink_cfg[1] = your_sink1_cfg;
ccfg.capture_frame_cb = capture_cb;
video_capture_handle_t c = video_capture_open(&ccfg);
video_capture_start(c);
video_capture_stop(c);
video_capture_close(c);
```
---
## Media Dump 💾
- Enable condition ✅: Takes effect after enabling `MEDIA_DUMP_ENABLE` in `menuconfig`.
- Save methods 📤: Supports SD card and UDP outputs (choose one).
- SD card 💾: Enable `CONFIG_MEDIA_DUMP_SINK_SDCARD`, output to file `CONFIG_MEDIA_DUMP_SDCARD_FILENAME`, duration controlled by `CONFIG_MEDIA_DUMP_DURATION_SEC`.
- UDP 📡: Enable `CONFIG_MEDIA_DUMP_SINK_UDP`, send raw media data via `CONFIG_MEDIA_DUMP_UDP_IP` and `CONFIG_MEDIA_DUMP_UDP_PORT` (can use `script/udp_reciver.py` script).
- Save point 🎚️ (before/after AEC processing): Select in "Audio Save Mode (AEC point)" in `menuconfig`
- `MEDIA_DUMP_AUDIO_BEFORE_AEC` (Save Before AEC): Save raw microphone audio before AEC (for analyzing noise/feedback)
- `MEDIA_DUMP_AUDIO_AFTER_AEC` (Save After AEC): Save audio after AEC processing (for evaluating AEC effectiveness)
- Typical usage 🔍: Export raw audio/video data when reproducing issues, check saturation, feedback, and format correctness offline using tools like Audacity.
## Configuration ⚙️
### Runtime Configuration (Recommended)
AFE configuration can be set at runtime via the `afe_config` field in the `audio_recorder_config_t` structure, which takes priority over Kconfig configuration:
```c
audio_recorder_config_t recorder_cfg = DEFAULT_AUDIO_RECORDER_CONFIG();
// Configure AFE
recorder_cfg.afe_config.ai_mode_wakeup = false; // AI mode: true=wakeup mode, false=direct mode
recorder_cfg.afe_config.vad_enable = true; // Enable VAD
recorder_cfg.afe_config.vad_mode = 4; // VAD mode (1-4), larger values are more sensitive
recorder_cfg.afe_config.vad_min_speech_ms = 64; // Minimum speech duration (ms)
recorder_cfg.afe_config.vad_min_noise_ms = 1000; // Minimum noise duration (ms)
recorder_cfg.afe_config.agc_enable = true; // Enable AGC
recorder_cfg.afe_config.enable_vcmd_detect = false; // Enable VCMD
recorder_cfg.afe_config.vcmd_timeout_ms = 5000; // VCMD timeout (ms)
recorder_cfg.afe_config.mn_language = "cn"; // Model language: "cn" or "en"
recorder_cfg.afe_config.wakeup_time_ms = 10000; // Wakeup time (ms)
recorder_cfg.afe_config.wakeup_end_time_ms = 2000; // Wakeup end time (ms)
// Pass configuration when opening recorder
audio_recorder_open(&recorder_cfg);
```
### Kconfig Configuration (Alternative)
If fields in `audio_recorder_config_t.afe_config` use default values or are not set, Kconfig configuration will be used. Configure via `idf.py menuconfig`:
#### 💾 Media Dump Configuration
Configure under **"Component config" -> "Audio/Video Processor Configuration" -> "Media Dump"** in `menuconfig`:
- **`MEDIA_DUMP_ENABLE`**: Enable media data dump functionality, disabled by default
- When enabled, raw audio/video data can be saved for debugging and analysis
- **`MEDIA_DUMP_AUDIO_POINT`**: Audio save point selection (choice type)
- **`MEDIA_DUMP_AUDIO_BEFORE_AEC`**: Save raw audio before AEC processing
- Useful for analyzing noise and feedback issues
- **`MEDIA_DUMP_AUDIO_AFTER_AEC`**: Save audio after AEC processing
- Useful for evaluating AEC processing effectiveness
- **`MEDIA_DUMP_AUDIO_NONE`**: Do not save audio (default)
- **`MEDIA_DUMP_DURATION_SEC`**: Save duration in seconds, default 20
- Type: integer (int)
- Range: 1-3600 seconds
- **`MEDIA_DUMP_SINK`**: Save method selection (choice type)
- **`MEDIA_DUMP_SINK_SDCARD`**: Save to SD card file (default)
- File path configuration: `CONFIG_MEDIA_DUMP_SDCARD_FILENAME` (default: `/sdcard/media_dump.bin`)
- Ensure SD card is properly mounted
- **`MEDIA_DUMP_SINK_UDP`**: Send via UDP
- Target IP configuration: `CONFIG_MEDIA_DUMP_UDP_IP` (default: `192.168.1.100`)
- Target port configuration: `CONFIG_MEDIA_DUMP_UDP_PORT` (default: 5000)
- Can use `script/udp_reciver.py` script to receive data
### Task Configuration
The audio processing component uses multiple FreeRTOS tasks internally, which can be customized via task configuration fields in each module's configuration structure:
#### Task Configuration for Each Module
- **Recorder** (`audio_recorder_config_t`):
- `afe_feed_task_config`: AFE feed task configuration (default stack size 3KB)
- `afe_fetch_task_config`: AFE fetch task configuration (default stack size 3KB)
- `recorder_task_config`: Recorder task configuration (default stack size 5KB, recommend >= 40KB when using OPUS encoder)
- **Player** (`audio_playback_config_t`):
- `playback_task_config`: Playback task configuration (default stack size 4KB)
- **Feeder** (`audio_feeder_config_t`):
- `feeder_task_config`: Feeder task configuration (default stack size 5KB, recommend >= 40KB when using OPUS decoder)
**Important Notes**:
- When using OPUS encoder or decoder, `task_stack` of `recorder_task_config` and `feeder_task_config` should be set to at least `4096 * 10` bytes (40KB).
- When `task_stack` in task configuration is set to 0, default values will be used.
- When `task_stack_in_ext` is set to `true`, task stack will be allocated in external memory, helping to save internal RAM.
- Task configuration should be set in each module's configuration structure (e.g., `audio_recorder_config_t`, `audio_playback_config_t`, `audio_feeder_config_t`), not in `audio_manager_config_t`.
---
## API Reference 📚
Header files:
- `include/audio_processor.h`
- `include/video_processor.h`
- `include/av_processor_type.h`
Common functions (selection):
- Audio management:
- `audio_manager_init`/`audio_manager_deinit`: Initialize/deinitialize audio manager
- Recording:
- `audio_recorder_open`: Open recorder (supports encoder configuration and event callback)
- `audio_recorder_read_data`: Read recording data
- `audio_recorder_pause`/`audio_recorder_resume`: Pause/resume recording
- `audio_recorder_get_afe_manager_handle`: Get AFE manager handle
- `audio_recorder_close`: Close recorder
- Feeder:
- `audio_feeder_open`: Open feeder (supports decoder configuration)
- `audio_feeder_run`: Start feeder
- `audio_feeder_feed_data`: Feed audio data
- `audio_feeder_stop`: Stop feeder
- `audio_feeder_close`: Close feeder
- Playback:
- `audio_playback_open`/`audio_playback_close`: Open/close player
- `audio_playback_play`: Play audio (supports URL or local file, e.g., `http://...` or `file:///sdcard/...`)
- `audio_playback_stop`: Stop playback
- `audio_playback_pause`/`audio_playback_resume`: Pause/resume playback
- `audio_playback_get_state`: Get playback state
- Mixer:
- `audio_processor_mixer_open`: Open mixer (must be called after both playback and feeder are opened)
- `audio_processor_mixer_close`: Close mixer
- `audio_processor_ramp_control`: Control audio focus and volume fade
- Video rendering:
- `video_render_open`/`video_render_close`: Open/close video renderer
- `video_render_start`/`video_render_stop`: Start/stop rendering
- `video_render_frame_feed`: Feed video frame
- Video capture:
- `video_capture_open`/`video_capture_close`: Open/close video capturer
- `video_capture_start`/`video_capture_stop`: Start/stop capture
---
## FAQ ❓
### Audio Issues
- **"Self-questioning" phenomenon occurs (device playback sound is repeatedly captured by microphone)**:
- Enable `MEDIA_DUMP_ENABLE` in `menuconfig`, reproduce the issue and export saved audio data for further analysis
- Open the exported audio file using [Audacity](https://www.audacityteam.org/download/), observe waveform/spectrum to determine if saturation or feedback exists
- If saturation clipping occurs, reduce microphone gain (`esp_codec_dev_set_in_gain`); or appropriately reduce speaker volume (`esp_codec_dev_set_out_vol`) to avoid excessive feedback
- **Stack overflow when using OPUS encoder/decoder**:
- Ensure `task_stack` of `recorder_task_config` and `feeder_task_config` is set to at least `4096 * 10` bytes (40KB)
- Consider allocating task stack in external memory (set `task_stack_in_ext = true`)
- **Mixer not working properly**:
- Ensure that both player (`audio_playback_open`) and feeder (`audio_feeder_open`) are opened before calling `audio_processor_mixer_open()`
- Ensure `enable_mixer = true` is set when calling `audio_manager_init`
### Development and Debugging
- **Modifying component source code (espressif__av_processor)**:
- If you need to modify code within `espressif__av_processor`, you can execute the `script/move_av_processor.py` script
- The script will copy `managed_components/espressif__av_processor` to your project's `PROJECT_DIR/components/espressif__av_processor` directory
- The script will automatically delete the original directory under `managed_components` and update `idf_component.yml`
- Before using, set the environment variable: `export PROJECT_DIR=/path/to/project`
- **Media data dump (Media Dump)**:
- UDP method: Can use `script/udp_reciver.py` script to receive UDP data
- SD card method: Ensure SD card is properly mounted and file path is accessible
---
## Version Information
Current version: v0.5.0
## License
This component follows the Apache-2.0 license. See the `LICENSE` file included in the repository for details.
## Related Resources
- Project repository: https://github.com/espressif/esp-gmf/tree/main/components/av_processor
- Issue reporting: https://github.com/espressif/esp-gmf/issues
- Documentation: https://github.com/espressif/esp-gmf/blob/main/components/av_processor/README.md
@@ -0,0 +1,346 @@
# AV Processor 组件(音视频处理)
本组件提供在 ESP 平台上进行音频录制/播放/喂数以及视频捕获/解码/渲染的统一封装,基于 GMF(General Media Framework)、esp-audio-render、esp-video-codec、esp-capture 等中间组件实现。
## 功能概览 🎛️
- **音频 🎧**:
- 录音(AEC/VAD/AFE 可选)
- 播放(支持 URL、本地文件,解码由配置决定)
- 数据喂入(feeder,适合边接收边播放的场景,如 RTC/流媒体)
- 可选混音器,多路流间音量渐变(fade)与焦点控制
- **视频 🎥**:
- 多路视频采集
- 视频解码与渲染回调
---
## 快速开始
### 1. 音频使用
1. 初始化音频管理器:
```c
// 方式一:使用默认配置宏(推荐)
audio_manager_config_t cfg = DEFAULT_AUDIO_MANAGER_CONFIG();
cfg.play_dev = your_play_dev;
cfg.rec_dev = your_rec_dev;
strcpy(cfg.mic_layout, "RMNM"); // 麦克风布局(可选,用于 AFE 配置)
cfg.board_sample_rate = 16000;
cfg.board_bits = 32;
cfg.board_channels = 2;
cfg.play_volume = 80;
cfg.rec_volume = 60;
cfg.rec_ref_volume = 60;
cfg.enable_mixer = true; // 需要 feeder 与 playback 混音时开启
audio_manager_init(&cfg);
```
2. 录音(可轮询读取):
```c
// 录音事件回调(可选)
void recorder_event_cb(void *event, void *ctx) {
// 处理录音事件(如 AFE 事件)
}
// 配置录音器(使用默认配置宏)
audio_recorder_config_t recorder_cfg = DEFAULT_AUDIO_RECORDER_CONFIG();
// 可选:配置 AFE(运行时配置,优先级高于 Kconfig)
recorder_cfg.afe_config.vad_enable = true;
recorder_cfg.afe_config.vad_mode = 4;
recorder_cfg.afe_config.agc_enable = true;
recorder_cfg.recorder_event_cb = recorder_event_cb;
// 打开录音器
audio_recorder_open(&recorder_cfg);
uint8_t buf[2048];
audio_recorder_read_data(buf, sizeof(buf));
audio_recorder_close();
```
3. 喂数播放(feeder,适合外部码流→本地播放):
```c
// 配置 feeder(使用默认配置宏)
audio_feeder_config_t feeder_cfg = DEFAULT_AUDIO_FEEDER_CONFIG();
// 可选:使用 OPUS 解码器时,task_stack 建议 >= 4096 * 10
// feeder_cfg.feeder_task_config.task_stack = 4096 * 10;
audio_feeder_open(&feeder_cfg);
audio_feeder_run();
// 按需多次喂入外部数据块
audio_feeder_feed_data(pkt, pkt_len);
audio_feeder_stop();
audio_feeder_close();
```
4. 普通播放(URL 或本地):
```c
// 配置播放器(使用默认配置宏)
audio_playback_config_t playback_cfg = DEFAULT_AUDIO_PLAYBACK_CONFIG();
audio_playback_open(&playback_cfg);
audio_playback_play("http://<ip>:<port>/audio.mp3");
audio_playback_pause();
audio_playback_resume();
audio_playback_stop();
audio_playback_close();
```
5. 提示播放
```c
// 配置播放器(使用默认配置宏)
audio_prompt_config_t prompt_cfg = DEFAULT_AUDIO_PROMPT_CONFIG();
audio_prompt_open(&prompt_cfg);
audio_prompt_play("spiffs://audio.mp3");
audio_prompt_close();
```
> 提示播放 和 配置播放器是相似的,只是 `提示播放` 是阻塞式的播放,适合使用短音频的播放。目的是在使用 普通播放 的播放的时候又需要播放
> 提示音,可以有很好的相应
6. 焦点/渐变控制(启用混音器时):
```c
// 注意:使用混音器前需要先打开播放器和 feeder
audio_processor_mixer_open();
audio_processor_ramp_control(AUDIO_MIXER_FOCUS_FEEDER); // 侧重喂数音频
audio_processor_ramp_control(AUDIO_MIXER_FOCUS_PLAYBACK); // 侧重音频播放
audio_processor_mixer_close();
```
### 2. 视频使用
1. 渲染(解码)回调:
```c
void decoded_cb(void *ctx, const uint8_t *data, size_t size) {
// 处理解码后的帧数据
}
video_render_config_t rcfg = {
.decode_cfg = your_vdec_cfg,
.resolution = {.width = 640, .height = 480},
.decode_cb = decoded_cb,
};
video_render_handle_t r = video_render_open(&rcfg);
video_render_start(r);
video_frame_t f = {.data = enc_frame, .size = enc_size};
video_render_frame_feed(r, &f);
video_render_stop(r);
video_render_close(r);
```
1. 采集(多路):
```c
void capture_cb(void *ctx, int index, video_frame_t *frame) {
// 处理采集到的视频帧
}
video_capture_config_t ccfg = {0};
ccfg.camera_config = &your_cam_cfg;
ccfg.sink_num = 2;
ccfg.sink_cfg[0] = your_sink0_cfg;
ccfg.sink_cfg[1] = your_sink1_cfg;
ccfg.capture_frame_cb = capture_cb;
video_capture_handle_t c = video_capture_open(&ccfg);
video_capture_start(c);
video_capture_stop(c);
video_capture_close(c);
```
---
## 媒体数据保存(Media Dump)💾
- 使能条件 ✅:在 `menuconfig` 勾选 `MEDIA_DUMP_ENABLE` 后生效。
- 保存方式 📤:支持 SD 卡与 UDP 两种输出(可二选一)。
- SD 卡 💾:开启 `CONFIG_MEDIA_DUMP_SINK_SDCARD`,输出到文件 `CONFIG_MEDIA_DUMP_SDCARD_FILENAME`,时长由 `CONFIG_MEDIA_DUMP_DURATION_SEC` 控制。
- UDP 📡:开启 `CONFIG_MEDIA_DUMP_SINK_UDP`,通过 `CONFIG_MEDIA_DUMP_UDP_IP` 与 `CONFIG_MEDIA_DUMP_UDP_PORT` 发送原始媒体数据(可使用 `script/udp_reciver.py` 脚本)。
- 保存点位 🎚️(AEC 处理前/后):在 `menuconfig` 的“Audio Save Mode (AEC point)”中选择
- `MEDIA_DUMP_AUDIO_BEFORE_AEC`(Save Before AEC):保存 AEC 前的麦克风原始音频(便于分析底噪/回授)
- `MEDIA_DUMP_AUDIO_AFTER_AEC`(Save After AEC):保存 AEC 处理后的音频(便于评估 AEC 效果)
- 典型用途 🔍:问题复现时导出原始音/视频数据,离线用 Audacity 等工具检查饱和、回授、格式是否正确。
## 配置说明 ⚙️
### 运行时配置(推荐)
AFE 配置可以通过 `audio_recorder_config_t` 结构体中的 `afe_config` 字段在运行时配置,优先级高于 Kconfig 配置:
```c
audio_recorder_config_t recorder_cfg = DEFAULT_AUDIO_RECORDER_CONFIG();
// 配置 AFE
recorder_cfg.afe_config.ai_mode_wakeup = false; // AI 模式:true=唤醒模式,false=直连模式
recorder_cfg.afe_config.vad_enable = true; // 使能 VAD
recorder_cfg.afe_config.vad_mode = 4; // VAD 模式(1-4),值越大越敏感
recorder_cfg.afe_config.vad_min_speech_ms = 64; // 最小语音时长(ms)
recorder_cfg.afe_config.vad_min_noise_ms = 1000; // 最小噪声时长(ms)
recorder_cfg.afe_config.agc_enable = true; // 使能 AGC
recorder_cfg.afe_config.enable_vcmd_detect = false; // 使能 VCMD
recorder_cfg.afe_config.vcmd_timeout_ms = 5000; // VCMD 超时(ms)
recorder_cfg.afe_config.mn_language = "cn"; // 模型语言:"cn" 或 "en"
recorder_cfg.afe_config.wakeup_time_ms = 10000; // 唤醒时间(ms)
recorder_cfg.afe_config.wakeup_end_time_ms = 2000; // 唤醒结束时间(ms)
// 打开录音器时传入配置
audio_recorder_open(&recorder_cfg);
```
### Kconfig 配置(备选)
如果 `audio_recorder_config_t.afe_config` 中的字段使用默认值或未设置,则使用 Kconfig 配置。通过 `idf.py menuconfig` 进入配置菜单进行配置。
#### 💾 Media Dump 配置
在 `menuconfig` 的 **"Component config" -> "Audio/Video Processor Configuration" -> "Media Dump"** 下配置:
- **`MEDIA_DUMP_ENABLE`**:使能媒体数据保存功能,默认关闭
- 启用后可以保存原始音频/视频数据用于调试分析
- **`MEDIA_DUMP_AUDIO_POINT`**:音频保存点位选择(choice 类型)
- **`MEDIA_DUMP_AUDIO_BEFORE_AEC`**:保存 AEC 处理前的原始音频
- 便于分析底噪、回授等问题
- **`MEDIA_DUMP_AUDIO_AFTER_AEC`**:保存 AEC 处理后的音频
- 便于评估 AEC 处理效果
- **`MEDIA_DUMP_AUDIO_NONE`**:不保存音频(默认)
- **`MEDIA_DUMP_DURATION_SEC`**:保存时长(秒),默认 20
- 类型:整数(int)
- 范围:1-3600 秒
- **`MEDIA_DUMP_SINK`**:保存方式选择(choice 类型)
- **`MEDIA_DUMP_SINK_SDCARD`**:保存到 SD 卡文件(默认)
- 文件路径配置项:`CONFIG_MEDIA_DUMP_SDCARD_FILENAME`(默认:`/sdcard/media_dump.bin`)
- 需要确保 SD 卡已正确挂载
- **`MEDIA_DUMP_SINK_UDP`**:通过 UDP 发送
- 目标 IP 配置项:`CONFIG_MEDIA_DUMP_UDP_IP`(默认:`192.168.1.100`)
- 目标端口配置项:`CONFIG_MEDIA_DUMP_UDP_PORT`(默认:5000)
- 可使用 `script/udp_reciver.py` 脚本接收数据
### 任务配置说明
音频处理组件内部使用多个 FreeRTOS 任务,可以通过各功能模块的配置结构体中的任务配置字段进行自定义:
#### 各功能模块任务配置
- **录音器**(`audio_recorder_config_t`):
- `afe_feed_task_config`:AFE feed 任务配置(默认栈大小 3KB)
- `afe_fetch_task_config`:AFE fetch 任务配置(默认栈大小 3KB)
- `recorder_task_config`:录音任务配置(默认栈大小 5KB,使用 OPUS 编码器时建议 >= 40KB)
- **播放器**(`audio_playback_config_t`):
- `playback_task_config`:播放任务配置(默认栈大小 4KB)
- **Feeder**(`audio_feeder_config_t`):
- `feeder_task_config`:Feeder 任务配置(默认栈大小 5KB,使用 OPUS 解码器时建议 >= 40KB)
**重要提示**:
- 当使用 OPUS 编码器或解码器时,`recorder_task_config` 和 `feeder_task_config` 的 `task_stack` 需要设置为至少 `4096 * 10` 字节(40KB)。
- 任务配置中的 `task_stack` 设置为 0 时,将使用默认值。
- `task_stack_in_ext` 设置为 `true` 时,任务栈将分配在外部内存中,有助于节省内部 RAM。
- 任务配置应在各自模块的配置结构体中设置(如 `audio_recorder_config_t`、`audio_playback_config_t`、`audio_feeder_config_t`),而不是在 `audio_manager_config_t` 中。
---
## API 参考 📚
头文件:
- `include/audio_processor.h`
- `include/video_processor.h`
- `include/av_processor_type.h`
常用函数(节选):
- 音频管理:
- `audio_manager_init`/`audio_manager_deinit`:初始化/反初始化音频管理器
- 录音:
- `audio_recorder_open`:打开录音器(支持编码器配置和事件回调)
- `audio_recorder_read_data`:读取录音数据
- `audio_recorder_pause`/`audio_recorder_resume`:暂停/恢复录音
- `audio_recorder_get_afe_manager_handle`:获取 AFE manager 句柄
- `audio_recorder_close`:关闭录音器
- 喂数:
- `audio_feeder_open`:打开 feeder(支持解码器配置)
- `audio_feeder_run`:启动 feeder
- `audio_feeder_feed_data`:喂入音频数据
- `audio_feeder_stop`:停止 feeder
- `audio_feeder_close`:关闭 feeder
- 播放:
- `audio_playback_open`/`audio_playback_close`:打开/关闭播放器
- `audio_playback_play`:播放音频(支持 URL 或本地文件,如 `http://...` 或 `file:///sdcard/...`)
- `audio_playback_stop`:停止播放
- `audio_playback_pause`/`audio_playback_resume`:暂停/恢复播放
- `audio_playback_get_state`:获取播放状态
- 混音器:
- `audio_processor_mixer_open`:打开混音器(必须在 playback 和 feeder 都打开后调用)
- `audio_processor_mixer_close`:关闭混音器
- `audio_processor_ramp_control`:控制音频焦点和音量渐变
- 视频渲染:
- `video_render_open`/`video_render_close`:打开/关闭视频渲染器
- `video_render_start`/`video_render_stop`:启动/停止渲染
- `video_render_frame_feed`:喂入视频帧
- 视频采集:
- `video_capture_open`/`video_capture_close`:打开/关闭视频采集器
- `video_capture_start`/`video_capture_stop`:启动/停止采集
---
## 常见问题 ❓
### 音频问题
- **出现"自问自答"现象(设备播放的声音被麦克风重复收录)**:
- 在 `menuconfig` 使能 `MEDIA_DUMP_ENABLE`,复现问题并导出保存的音频数据以便进一步分析
- 使用 [Audacity](https://www.audacityteam.org/download/) 打开导出的音频文件,观察波形/频谱判断是否存在饱和或回授
- 如出现饱和剪切,调低麦克风增益(`esp_codec_dev_set_in_gain`);或适当减小扬声器音量(`esp_codec_dev_set_out_vol`),避免过度回授
- **OPUS 编解码器使用时出现栈溢出**:
- 确保 `recorder_task_config` 和 `feeder_task_config` 的 `task_stack` 设置为至少 `4096 * 10` 字节(40KB)
- 考虑将任务栈分配在外部内存(设置 `task_stack_in_ext = true`)
- **混音器无法正常工作**:
- 确保在调用 `audio_processor_mixer_open()` 之前,已经打开了播放器(`audio_playback_open`)和 feeder(`audio_feeder_open`)
- 确保在 `audio_manager_init` 时设置了 `enable_mixer = true`
### 开发调试
- **修改组件源码(espressif__av_processor)**:
- 如需修改 `espressif__av_processor` 内的代码,可执行 `script/move_av_processor.py` 脚本
- 脚本会将 `managed_components/espressif__av_processor` 复制到你的工程 `PROJECT_DIR/components/espressif__av_processor` 下
- 脚本会自动删除 `managed_components` 下的原目录,并更新 `idf_component.yml`
- 使用前需要设置环境变量:`export PROJECT_DIR=/path/to/project`
- **媒体数据保存(Media Dump)**:
- UDP 方式:可使用 `script/udp_reciver.py` 脚本接收 UDP 数据
- SD 卡方式:确保 SD 卡已正确挂载,文件路径可访问
---
## 版本信息
当前版本:v0.5.0
## 许可证
本组件遵循 Apache-2.0 许可证,详见仓库随附的 `LICENSE`。
## 相关资源
- 项目仓库:https://github.com/espressif/esp-gmf/tree/main/components/av_processor
- 问题反馈:https://github.com/espressif/esp-gmf/issues
- 文档:https://github.com/espressif/esp-gmf/blob/main/components/av_processor/README.md
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,182 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_err.h"
#include "esp_log.h"
#include "esp_audio_dec_default.h"
#include "esp_audio_enc_default.h"
#include "esp_audio_simple_dec_default.h"
#include "esp_gmf_audio_dec.h"
#include "esp_gmf_audio_enc.h"
#include "esp_gmf_ch_cvt.h"
#include "esp_gmf_bit_cvt.h"
#include "esp_gmf_rate_cvt.h"
#include "esp_gmf_pool.h"
#include "esp_gmf_element.h"
#include "esp_gmf_fade.h"
#include "esp_gmf_err.h"
#include "av_processor_type.h"
static char *TAG = "AV_PIPELINE_POOL";
esp_err_t av_audio_playback_pool_init(esp_gmf_pool_handle_t *pool)
{
*pool = NULL;
esp_gmf_err_t ret = ESP_GMF_ERR_OK;
esp_gmf_element_handle_t hd = NULL;
esp_err_t err = esp_gmf_pool_init(pool);
ESP_GMF_RET_ON_NOT_OK(TAG, err, {return err;}, "Failed to initialize GMF pool");
esp_audio_simple_dec_cfg_t es_dec_cfg = DEFAULT_ESP_GMF_AUDIO_DEC_CONFIG();
esp_gmf_audio_dec_init(&es_dec_cfg, &hd);
esp_gmf_pool_register_element(*pool, hd, NULL);
return ret;
}
esp_err_t av_audio_playback_pool_deinit(esp_gmf_pool_handle_t pool)
{
return esp_gmf_pool_deinit(pool);
}
esp_err_t av_audio_feeder_pool_init(esp_gmf_pool_handle_t *pool, const av_processor_decoder_config_t *decoder_cfg)
{
*pool = NULL;
esp_err_t ret = ESP_OK;
esp_audio_simple_dec_cfg_t dec_cfg = DEFAULT_ESP_GMF_AUDIO_DEC_CONFIG();
esp_gmf_element_handle_t el = NULL;
esp_gmf_pool_init(pool);
// Default to PCM if no config provided
av_processor_format_id_t format = AV_PROCESSOR_FORMAT_ID_PCM;
if (decoder_cfg) {
format = decoder_cfg->format;
}
switch (format) {
case AV_PROCESSOR_FORMAT_ID_PCM:
dec_cfg.dec_type = ESP_AUDIO_SIMPLE_DEC_TYPE_PCM;
break;
case AV_PROCESSOR_FORMAT_ID_G711A: {
dec_cfg.dec_type = ESP_AUDIO_SIMPLE_DEC_TYPE_G711A;
esp_g711_dec_cfg_t g711_dec_cfg = {0};
g711_dec_cfg.channel = decoder_cfg ? decoder_cfg->params.g711.audio_info.channels : 1;
dec_cfg.dec_cfg = &g711_dec_cfg;
dec_cfg.cfg_size = sizeof(esp_g711_dec_cfg_t);
break;
}
case AV_PROCESSOR_FORMAT_ID_G711U: {
dec_cfg.dec_type = ESP_AUDIO_SIMPLE_DEC_TYPE_G711U;
esp_g711_dec_cfg_t g711_dec_cfg = {0};
g711_dec_cfg.channel = decoder_cfg ? decoder_cfg->params.g711.audio_info.channels : 1;
dec_cfg.dec_cfg = &g711_dec_cfg;
dec_cfg.cfg_size = sizeof(esp_g711_dec_cfg_t);
break;
}
case AV_PROCESSOR_FORMAT_ID_OPUS: {
dec_cfg.dec_type = ESP_AUDIO_SIMPLE_DEC_TYPE_RAW_OPUS;
esp_opus_dec_cfg_t opus_dec_cfg = ESP_OPUS_DEC_CONFIG_DEFAULT();
if (decoder_cfg) {
// Convert frame_duration from int to esp_opus_enc_frame_duration_t
int frame_duration = decoder_cfg->params.opus.audio_info.frame_duration;
switch (frame_duration) {
case 2: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_2_5_MS; break;
case 5: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_5_MS; break;
case 10: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_10_MS; break;
case 20: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_20_MS; break;
case 40: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_40_MS; break;
case 60: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_60_MS; break;
case 80: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_80_MS; break;
case 100: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_100_MS; break;
case 120: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_120_MS; break;
default: opus_dec_cfg.frame_duration = ESP_OPUS_DEC_FRAME_DURATION_60_MS; break;
}
opus_dec_cfg.channel = decoder_cfg->params.opus.audio_info.channels;
opus_dec_cfg.sample_rate = decoder_cfg->params.opus.audio_info.sample_rate;
}
dec_cfg.dec_cfg = &opus_dec_cfg;
dec_cfg.cfg_size = sizeof(esp_opus_dec_cfg_t);
break;
}
case AV_PROCESSOR_FORMAT_ID_AAC:
dec_cfg.dec_type = ESP_AUDIO_SIMPLE_DEC_TYPE_AAC;
esp_aac_dec_cfg_t aac_dec_cfg = {0};
aac_dec_cfg.no_adts_header = decoder_cfg->params.aac.no_adts_header;
aac_dec_cfg.aac_plus_enable = decoder_cfg->params.aac.aac_plus_enable;
dec_cfg.dec_cfg = &aac_dec_cfg;
dec_cfg.cfg_size = sizeof(esp_aac_dec_cfg_t);
break;
default:
ESP_LOGE(TAG, "Unsupported format: %d", format);
return ESP_ERR_NOT_SUPPORTED;
}
esp_gmf_audio_dec_init(&dec_cfg, &el);
esp_gmf_pool_register_element(*pool, el, NULL);
esp_ae_ch_cvt_cfg_t es_ch_cvt_cfg = DEFAULT_ESP_GMF_CH_CVT_CONFIG();
ret = esp_gmf_ch_cvt_init(&es_ch_cvt_cfg, &el);
ESP_GMF_RET_ON_ERROR(TAG, ret, return ret, "Failed to init audio ch cvt");
ret = esp_gmf_pool_register_element(*pool, el, NULL);
ESP_GMF_RET_ON_ERROR(TAG, ret, return ret, "Failed to register element in pool");
esp_ae_bit_cvt_cfg_t es_bit_cvt_cfg = DEFAULT_ESP_GMF_BIT_CVT_CONFIG();
ret = esp_gmf_bit_cvt_init(&es_bit_cvt_cfg, &el);
ESP_GMF_RET_ON_ERROR(TAG, ret, return ret, "Failed to init audio bit cvt");
ret = esp_gmf_pool_register_element(*pool, el, NULL);
ESP_GMF_RET_ON_ERROR(TAG, ret, return ret, "Failed to register element in pool");
esp_ae_rate_cvt_cfg_t es_rate_cvt_cfg = DEFAULT_ESP_GMF_RATE_CVT_CONFIG();
esp_gmf_rate_cvt_init(&es_rate_cvt_cfg, &el);
esp_gmf_pool_register_element(*pool, el, NULL);
return ret;
}
esp_err_t av_audio_feeder_pool_deinit(esp_gmf_pool_handle_t pool)
{
return esp_gmf_pool_deinit(pool);
}
esp_err_t av_audio_recorder_pool_init(esp_gmf_pool_handle_t *pool, const av_processor_encoder_config_t *encoder_cfg)
{
*pool = NULL;
esp_gmf_err_t ret = ESP_GMF_ERR_OK;
esp_audio_enc_config_t enc_cfg = DEFAULT_ESP_GMF_AUDIO_ENC_CONFIG();
esp_gmf_element_handle_t el = NULL;
esp_err_t err = esp_gmf_pool_init(pool);
ESP_GMF_RET_ON_NOT_OK(TAG, err, {return err;}, "Failed to initialize GMF pool");
esp_gmf_audio_enc_init(&enc_cfg, &el);
esp_gmf_pool_register_element(*pool, el, NULL);
esp_ae_ch_cvt_cfg_t es_ch_cvt_cfg = DEFAULT_ESP_GMF_CH_CVT_CONFIG();
ret = esp_gmf_ch_cvt_init(&es_ch_cvt_cfg, &el);
ESP_GMF_RET_ON_ERROR(TAG, ret, return ret, "Failed to init audio ch cvt");
ret = esp_gmf_pool_register_element(*pool, el, NULL);
ESP_GMF_RET_ON_ERROR(TAG, ret, return ret, "Failed to register element in pool");
esp_ae_bit_cvt_cfg_t es_bit_cvt_cfg = DEFAULT_ESP_GMF_BIT_CVT_CONFIG();
ret = esp_gmf_bit_cvt_init(&es_bit_cvt_cfg, &el);
ESP_GMF_RET_ON_ERROR(TAG, ret, return ret, "Failed to init audio bit cvt");
ret = esp_gmf_pool_register_element(*pool, el, NULL);
ESP_GMF_RET_ON_ERROR(TAG, ret, return ret, "Failed to register element in pool");
esp_ae_rate_cvt_cfg_t es_rate_cvt_cfg = DEFAULT_ESP_GMF_RATE_CVT_CONFIG();
esp_gmf_rate_cvt_init(&es_rate_cvt_cfg, &el);
esp_gmf_pool_register_element(*pool, el, NULL);
return err;
}
esp_err_t av_audio_recorder_pool_deinit(esp_gmf_pool_handle_t pool)
{
return esp_gmf_pool_deinit(pool);
}
@@ -0,0 +1,31 @@
dependencies:
espressif/gmf_ai_audio:
version: '~0.7'
public: true
rules:
- if: "target in [esp32p4, esp32s3, esp32]"
espressif/esp_audio_simple_player:
version: '^0.9.4'
public: true
espressif/gmf_loader:
version: "^0.7"
public: true
espressif/esp_video_codec:
public: true
version: "^0.5"
espressif/esp_capture:
public: true
version: "^0.7"
espressif/esp_audio_render:
public: true
version: "^0.7.0"
description: Audio/Video Processor module for ESP-ADF
documentation: https://github.com/espressif/esp-adf/blob/master/components/av_processor/README.md
issues: https://github.com/espressif/esp-adf/issues
repository: git://github.com/espressif/esp-adf.git
tags:
- gmf_multimedia
- av_processor
url: https://github.com/espressif/esp-adf/tree/master/components/av_processor
version: 0.1.0
@@ -0,0 +1,488 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "esp_err.h"
#include "esp_gmf_afe_manager.h"
#include "esp_audio_simple_player_advance.h"
#include "av_processor_type.h"
/* Brief: Default audio manager configuration
* Note: When use OPUS decoder or OPUS encoder, the recorder_task_config and feeder_task_config
* task stack size need be set to more than 4096 * 10 bytes.
*/
#define DEFAULT_AUDIO_MANAGER_CONFIG() { \
.play_dev = NULL, \
.rec_dev = NULL, \
.mic_layout = {0}, \
.board_sample_rate = 16000, \
.board_bits = 32, \
.board_channels = 2, \
}
#define DEFAULT_AUDIO_FEEDER_CONFIG() { \
.feeder_task_config = { \
.task_stack = 0, \
.task_prio = 0, \
.task_core = 0, \
.task_stack_in_ext = true, \
}, \
.feeder_mixer_gain = { \
.initial_gain = 0.0, \
.target_gain = 0.5, \
.transition_time = 1500 \
}, \
}
#define DEFAULT_AUDIO_PLAYBACK_CONFIG() { \
.playback_task_config = { \
.task_stack = 4096, \
.task_prio = 5, \
.task_core = 0, \
.task_stack_in_ext = true, \
}, \
.playback_mixer_gain = { \
.initial_gain = 0.0, \
.target_gain = 1.0, \
.transition_time = 1500 \
} \
}
#define DEFAULT_AUDIO_PROMPT_CONFIG() { \
.prompt_task_config = { \
.task_stack = 4096, \
.task_prio = 5, \
.task_core = 0, \
.task_stack_in_ext = true \
} \
}
#define DEFAULT_AUDIO_RECORDER_CONFIG() { \
.afe_feed_task_config = { \
.task_stack = 40 * 1024, \
.task_prio = 5, \
.task_core = 0, \
.task_stack_in_ext = true, \
}, \
.afe_fetch_task_config = { \
.task_stack = 6 * 1024, \
.task_prio = 5, \
.task_core = 1, \
.task_stack_in_ext = true \
}, \
.recorder_task_config = { \
.task_stack = 4096, \
.task_prio = 5, \
.task_core = 0, \
.task_stack_in_ext = true \
}, \
.recorder_event_cb = NULL, \
.recorder_ctx = NULL, \
}
/**
* @brief Default AFE configuration macro
*/
#define DEFAULT_AV_PROCESSOR_AFE_CONFIG() { \
.model = "model", \
.ai_mode_wakeup = false, \
.vad_enable = true, \
.vad_mode = 4, \
.vad_min_speech_ms = 64, \
.vad_min_noise_ms = 1000, \
.agc_enable = true, \
.afe_type = AFE_TYPE_SR, \
.enable_vcmd_detect = false, \
.vcmd_timeout_ms = 5000, \
.mn_language = "cn", \
.wakeup_end_time_ms = 2000, \
.wakeup_time_ms = 10000 \
}
/**
* @brief Type definition for the audio recorder event callback function
*
* @param[in] event Pointer to the event data, which can contain information about the recorder's state
* @param[in] ctx User-defined context pointer, passed when registering the callback
*/
typedef void (*recorder_event_callback_t)(void *event, void *ctx);
/**
* @brief AFE (Audio Front-End) configuration structure
*
* This structure contains all AFE-related configuration parameters that were previously
* configured via Kconfig. These parameters control the behavior of the audio front-end
* processing including wake word detection, VAD, AGC, and other audio processing features.
*/
typedef struct {
const char *model; /*!< Model path/name for SR model initialization */
bool ai_mode_wakeup; /*!< AI mode: true for WAKEUP mode, false for DIRECT mode */
bool vad_enable; /*!< Enable Voice Activity Detection (VAD) */
int vad_mode; /*!< VAD mode value (1-4), larger values are more sensitive to human voice */
int vad_min_speech_ms; /*!< Minimum speech duration in milliseconds */
int vad_min_noise_ms; /*!< Minimum noise duration in milliseconds */
bool agc_enable; /*!< Enable Automatic Gain Control (AGC) */
afe_type_t afe_type; /*!< AFE type: AFE_TYPE_SR (0) or AFE_TYPE_VC (1) */
bool enable_vcmd_detect; /*!< Enable Voice Command Detection */
int vcmd_timeout_ms; /*!< Voice command detection timeout in milliseconds */
const char *mn_language; /*!< Model language (e.g., "cn", "en") */
int wakeup_end_time_ms; /*!< Wakeup end time in milliseconds */
int wakeup_time_ms; /*!< Wakeup time in milliseconds */
} av_processor_afe_config_t;
/* Brief: Audio mixer gain configuration */
typedef struct {
float initial_gain; /*!< Initial gain value (0.0 - 1.0) */
float target_gain; /*!< Target gain value (0.0 - 1.0) */
int transition_time; /*!< Transition time in milliseconds */
} audio_mixer_gain_config_t;
/* Brief: Common task configuration */
typedef struct {
int task_stack; /*!< Task stack size (0 means use default) */
int task_prio; /*!< Task priority */
int task_core; /*!< Task core ID */
bool task_stack_in_ext; /*!< Whether to allocate task stack in external memory */
} audio_task_config_t;
typedef struct {
audio_task_config_t feeder_task_config; /*!< Feeder task configuration */
av_processor_decoder_config_t decoder_cfg; /*!< Decoder configuration */
audio_mixer_gain_config_t feeder_mixer_gain; /*!< Feeder mixer gain configuration */
} audio_feeder_config_t;
typedef struct {
audio_task_config_t playback_task_config; /*!< Playback task configuration */
audio_mixer_gain_config_t playback_mixer_gain; /*!< Playback mixer gain configuration */
} audio_playback_config_t;
typedef struct {
audio_task_config_t prompt_task_config; /*!< Prompt task configuration */
} audio_prompt_config_t;
typedef struct {
audio_task_config_t afe_feed_task_config; /*!< AFE feed task configuration */
av_processor_afe_config_t afe_config; /*!< AFE configuration */
audio_task_config_t afe_fetch_task_config; /*!< AFE fetch task configuration */
audio_task_config_t recorder_task_config; /*!< Recorder task configuration */
av_processor_encoder_config_t encoder_cfg; /*!< Encoder configuration */
recorder_event_callback_t recorder_event_cb; /*!< Recorder event callback */
void *recorder_ctx; /*!< Recorder context */
} audio_recorder_config_t;
/* Brief: Audio manager configuration */
typedef struct {
void *play_dev;
void *rec_dev;
char mic_layout[8];
int board_sample_rate;
int board_bits;
int board_channels;
} audio_manager_config_t;
/**
* @brief Audio focus control mode - determines which audio stream gets priority
*/
typedef enum {
AUDIO_MIXER_FOCUS_FEEDER = 0, /*!< Focus on FEEDER stream - boost feeder, reduce playback */
AUDIO_MIXER_FOCUS_PLAYBACK = 1, /*!< Focus on PLAYBACK stream - boost playback, reduce feeder */
AUDIO_MIXER_FOCUS_BALANCED = 2, /*!< Balanced mode - both streams at equal levels */
} audio_mixer_focus_mode_t;
enum audio_player_state_e {
AUDIO_RUN_STATE_IDLE,
AUDIO_RUN_STATE_PLAYING,
AUDIO_RUN_STATE_CLOSED,
AUDIO_RUN_STATE_PAUSED,
};
/**
* @brief Initializes the audio manager module.
*
* @param[in] config Pointer to the audio manager configuration structure
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_manager_init(audio_manager_config_t *config);
/**
* @brief Deinitializes the audio manager component
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_manager_deinit();
/**
* @brief Opens the audio recorder and registers an event callback
*
* @param[in] config Pointer to the audio recorder configuration structure.
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_recorder_open(audio_recorder_config_t *config);
/**
* @brief Pauses the audio recorder system
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_recorder_pause(void);
/**
* @brief Resumes the audio recorder system
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_recorder_resume(void);
/**
* @brief Get the AFE manager handle of the audio recorder
*
* @param[out] afe_manager_handle Pointer to the AFE manager handle
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_recorder_get_afe_manager_handle(esp_gmf_afe_manager_handle_t *afe_manager_handle);
/**
* @brief Closes the audio recorder
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_recorder_close(void);
/**
* @brief Reads audio data from the recorder.
*
* @param[out] data Pointer to the buffer where the audio data will be stored
* @param[in] data_size Size of the buffer to store the audio data.
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_recorder_read_data(uint8_t *data, int data_size);
/**
* @brief Opens the audio feeder system
*
* @param[in] config Pointer to the audio feeder configuration structure.
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_feeder_open(audio_feeder_config_t *config);
/**
* @brief Closes the audio feeder module
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_feeder_close(void);
/**
* @brief Starts the audio feeder operation.
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_feeder_run(void);
/**
* @brief Stops the ongoing audio feeder
*
* @return
* - ESP_OK On successfully stopping the audio playback
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_feeder_stop(void);
/**
* @brief Feeds audio data into the feeder system
*
* @param[in] data Pointer to the audio data to be fed into the feeder system
* @param[in] data_size Size of the audio data to be fed into the feeder system
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_feeder_feed_data(uint8_t *data, int data_size);
/**
* @brief Open the audio playback module
*
* @param[in] config Pointer to the audio playback configuration structure.
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_playback_open(audio_playback_config_t *config);
/**
* @brief Close the audio playback module
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_playback_close(void);
/**
* @brief Play an audio playback from the specified URL. Eg: "http://192.168.1.100:8000/audio.mp3", "file:///sdcard/audio.mp3"
*
* @param[in] url URL pointing to the audio playback file to be played
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_playback_play(const char *url);
/**
* @brief Wait for the audio playback to end. This function will block until the audio playback is ended.
*
* @param[in] url URL pointing to the audio playback file to be played
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_playback_play_wait_end(const char *url);
/**
* @brief Pauses the audio playback module
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_playback_pause(void);
/**
* @brief Resumes the audio playback module
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_playback_resume(void);
/**
* @brief Get the state of the audio playback module
*
* @return
* - enum audio_player_state_e Playback state
*/
enum audio_player_state_e audio_playback_get_state(void);
/**
* @brief Stop the currently playing audio playback module
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_playback_stop(void);
/**
* @brief Open the audio prompt module
* @note This function not provide pause and resume functionality, because the prompt is played to end automatically.
* This function's priority is higher than the audio playback and feeder, so when the prompt is playing, the audio playback
* and feeder decoded data will be ignored.
*
* @param[in] config Pointer to the audio prompt configuration structure.
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_prompt_open(audio_prompt_config_t *config);
/**
* @brief Close the audio prompt module
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_prompt_close(void);
/**
* @brief Play an audio prompt from the specified URL.
*
* @param[in] url URL pointing to the audio prompt file to be played
* @note Audio prompt is not supported mixer, so when play prompt, the audio playback and feeder decoded data will be ignored.
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_prompt_play(const char *url);
/**
* @brief Open the audio mixer module
*
* @note This function must be called after audio_playback_open and audio_feeder_open and the audio_mixer must be enabled
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_processor_mixer_open(void);
/**
* @brief Close the audio mixer module
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t audio_processor_mixer_close(void);
/**
* @brief Control audio focus between FEEDER and PLAYBACK streams
*
* @note This function controls the fade processors for both feeder and playback streams
* to create smooth volume transitions and focus on the desired audio source.
*
* @param[in] mode The focus control mode:
* - AUDIO_FOCUS_FEEDER: Focus on FEEDER stream (boost feeder, reduce playback)
* - AUDIO_FOCUS_PLAYBACK: Focus on PLAYBACK stream (boost playback, reduce feeder)
* - AUDIO_FOCUS_BALANCED: Balanced mode (both streams at equal levels)
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG Invalid mode parameter
* - ESP_ERR_INVALID_STATE Audio render not initialized or streams not available
* - ESP_FAIL Failed to control fade processors
*/
esp_err_t audio_processor_ramp_control(audio_mixer_focus_mode_t mode);
#ifdef __cplusplus
}
#endif /* __cplusplus */
@@ -0,0 +1,145 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stdint.h>
#include <stdbool.h>
#include "esp_afe_config.h"
/**
* @brief AV Processor FourCC definition
*/
#define AV_PROCESSOR_FOURCC(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
/**
* @brief AV Processor format ID definition
*
* @note Aligned with GMF FourCC definition for audio video codecs and formats
* Detailed info refer to `https://github.com/espressif/esp-gmf/blob/main/gmf_core/helpers/include/esp_fourcc.h`
*/
typedef enum {
AV_PROCESSOR_FORMAT_ID_PCM = AV_PROCESSOR_FOURCC('P', 'C', 'M', ' '), /*!< PCM (Uncompressed) encoder */
AV_PROCESSOR_FORMAT_ID_G711A = AV_PROCESSOR_FOURCC('A', 'L', 'A', 'U'), /*!< G.711 A-law encoder */
AV_PROCESSOR_FORMAT_ID_G711U = AV_PROCESSOR_FOURCC('U', 'L', 'A', 'W'), /*!< G.711 μ-law encoder */
AV_PROCESSOR_FORMAT_ID_OPUS = AV_PROCESSOR_FOURCC('O', 'P', 'U', 'S'), /*!< OPUS encoder */
AV_PROCESSOR_FORMAT_ID_AAC = AV_PROCESSOR_FOURCC('A', 'A', 'C', ' '), /*!< AAC encoder */
} av_processor_format_id_t;
/**
* @brief Audio encoder format type
*/
typedef enum {
AV_PROCESSOR_ENCODER_PCM = 0, /*!< PCM (Uncompressed) encoder */
AV_PROCESSOR_ENCODER_G711A, /*!< G.711 A-law encoder */
AV_PROCESSOR_ENCODER_G711U, /*!< G.711 μ-law encoder */
AV_PROCESSOR_ENCODER_OPUS, /*!< OPUS encoder */
AV_PROCESSOR_ENCODER_MAX, /*!< Maximum encoder type */
} av_processor_encoder_format_t;
/**
* @brief Audio decoder format type
*/
typedef enum {
AV_PROCESSOR_DECODER_PCM = 0, /*!< PCM (Uncompressed) decoder */
AV_PROCESSOR_DECODER_G711A, /*!< G.711 A-law decoder */
AV_PROCESSOR_DECODER_G711U, /*!< G.711 μ-law decoder */
AV_PROCESSOR_DECODER_OPUS, /*!< OPUS decoder */
AV_PROCESSOR_DECODER_AAC, /*!< AAC decoder */
AV_PROCESSOR_DECODER_MAX, /*!< Maximum decoder type */
} av_processor_decoder_format_t;
typedef struct {
uint32_t sample_rate; /*!< Sample rate in Hz (e.g., 8000, 16000, 24000, 32000, 44100, 48000) */
uint8_t sample_bits; /*!< Sample bits in bits (e.g., 8, 16, 24, 32) */
uint8_t channels; /*!< Number of audio channels (1-4) */
int frame_duration; /*!< Frame duration in milliseconds */
} av_processor_audio_info_t;
/**
* @brief PCM encoder/decoder configuration
*/
typedef struct {
av_processor_audio_info_t audio_info;
} av_processor_pcm_config_t;
/**
* @brief OPUS encoder configuration
*/
typedef struct {
av_processor_audio_info_t audio_info;
bool enable_vbr; /*!< Enable Variable Bit Rate (VBR) */
int bitrate; /*!< Bitrate in bps */
} av_processor_opus_encoder_config_t;
/**
* @brief OPUS decoder configuration
*/
typedef struct {
av_processor_audio_info_t audio_info;
} av_processor_opus_decoder_config_t;
/**
* @brief AAC decoder configuration
*/
typedef struct {
av_processor_audio_info_t audio_info;
bool no_adts_header; /*!< Set if AAC frame data not contain ADTS header */
bool aac_plus_enable; /*!< Set if need AAC-Plus support */
} av_processor_aac_decoder_config_t;
/**
* @brief G.711 encoder/decoder configuration
*/
typedef struct {
av_processor_audio_info_t audio_info;
} av_processor_g711_config_t;
typedef struct {
av_processor_audio_info_t audio_info;
int bitrate; /*!< Bitrate in bps */
bool adts_used; /*!< Whether write ADTS header: true - add ADTS header, false - raw aac data only */
} av_processor_aac_encoder_config_t;
/**
* @brief Audio encoder configuration structure
*
* This structure contains the encoder format type and corresponding format-specific parameters.
* Only the parameters for the selected format (indicated by format) should be used.
*/
typedef struct {
av_processor_format_id_t format; /*!< Encoder format ID */
union {
av_processor_pcm_config_t pcm; /*!< PCM encoder configuration (used when format == AV_PROCESSOR_FORMAT_ID_PCM) */
av_processor_opus_encoder_config_t opus; /*!< OPUS encoder configuration (used when format == AV_PROCESSOR_FORMAT_ID_OPUS) */
av_processor_g711_config_t g711; /*!< G.711 encoder configuration (used when format == AV_PROCESSOR_FORMAT_ID_G711A or AV_PROCESSOR_FORMAT_ID_G711U) */
av_processor_aac_encoder_config_t aac; /*!< AAC encoder configuration (used when format == AV_PROCESSOR_FORMAT_ID_AAC) */
} params; /*!< Format-specific encoder parameters */
} av_processor_encoder_config_t;
/**
* @brief Audio decoder configuration structure
*
* This structure contains the decoder format type and corresponding format-specific parameters.
* Only the parameters for the selected format (indicated by format) should be used.
*/
typedef struct {
av_processor_format_id_t format; /*!< Decoder format ID */
union {
av_processor_pcm_config_t pcm; /*!< PCM decoder configuration (used when format == AV_PROCESSOR_FORMAT_ID_PCM) */
av_processor_opus_decoder_config_t opus; /*!< OPUS decoder configuration (used when format == AV_PROCESSOR_FORMAT_ID_OPUS) */
av_processor_g711_config_t g711; /*!< G.711 decoder configuration (used when format == AV_PROCESSOR_FORMAT_ID_G711A or AV_PROCESSOR_FORMAT_ID_G711U) */
av_processor_aac_decoder_config_t aac; /*!< AAC decoder configuration (used when format == AV_PROCESSOR_FORMAT_ID_AAC) */
} params; /*!< Format-specific decoder parameters */
} av_processor_decoder_config_t;
#ifdef __cplusplus
}
#endif /* __cplusplus */
@@ -0,0 +1,174 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
* SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
*
* See LICENSE file for details.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "esp_capture_sink.h"
#include "esp_err.h"
#include "esp_video_dec.h"
/**
* @brief Default maximum number of video paths
*/
#define DEFAULT_VID_MAX_PATH 2
/**
* @brief Video capture handle type
*/
typedef void *video_capture_handle_t;
/**
* @brief Video render handle type
*/
typedef void *video_render_handle_t;
/**
* @brief Video frame structure
*/
typedef struct {
uint8_t *data; /*!< Frame data buffer */
size_t size; /*!< Frame data size */
} video_frame_t;
/**
* @brief Video render decode callback function type
*
* @param[in] ctx User context pointer
* @param[in] data Decoded frame data
* @param[in] size Size of decoded frame data
*/
typedef void (*video_render_decode_callback_t)(void *ctx, const uint8_t *data, size_t size);
/**
* @brief Video capture frame callback function type
*
* @param[in] ctx User context pointer
* @param[in] index Frame index
* @param[in] vid_frame Captured video frame
*/
typedef void (*video_capture_frame_callback_t)(void *ctx, int index, video_frame_t *vid_frame);
/**
* @brief Video render configuration structure
*/
typedef struct {
esp_video_dec_cfg_t decode_cfg; /*!< Video decoder configuration */
esp_video_codec_resolution_t resolution; /*!< Video resolution */
video_render_decode_callback_t decode_cb; /*!< Decode callback function */
void *decode_cb_ctx; /*!< Decode callback context */
} video_render_config_t;
/**
* @brief Video capture configuration structure
*/
typedef struct {
void *camera_config; /*!< Camera configuration */
int sink_num; /*!< Number of sinks */
esp_capture_sink_cfg_t sink_cfg[DEFAULT_VID_MAX_PATH]; /*!< Sink configurations */
video_capture_frame_callback_t capture_frame_cb; /*!< Capture frame callback function */
void *capture_frame_cb_ctx; /*!< Capture frame callback context */
} video_capture_config_t;
/**
* @brief Opens a video capture session
*
* @param[in] config Video capture configuration
*
* @return
* - video_capture_handle On success
* - NULL On failure
*/
video_capture_handle_t video_capture_open(video_capture_config_t *config);
/**
* @brief Closes a video capture session
*
* @param[in] handle Video capture handle
*/
void video_capture_close(video_capture_handle_t handle);
/**
* @brief Starts video capture
*
* @param[in] handle Video capture handle
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t video_capture_start(video_capture_handle_t handle);
/**
* @brief Stops video capture
*
* @param[in] handle Video capture handle
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t video_capture_stop(video_capture_handle_t handle);
/**
* @brief Opens a video render session
*
* @param[in] config Video render configuration
*
* @return
* - video_render_handle On success
* - NULL On failure
*/
video_render_handle_t video_render_open(video_render_config_t *config);
/**
* @brief Closes a video render session
*
* @param[in] handle Video render handle
*/
void video_render_close(video_render_handle_t handle);
/**
* @brief Starts video rendering
*
* @param[in] handle Video render handle
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t video_render_start(video_render_handle_t handle);
/**
* @brief Stops video rendering
*
* @param[in] handle Video render handle
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t video_render_stop(video_render_handle_t handle);
/**
* @brief Feeds a video frame to the render pipeline
*
* @param[in] handle Video render handle
* @param[in] frame Video frame to feed
*
* @return
* - ESP_OK On success
* - Other Appropriate esp_err_t error code on failure
*/
esp_err_t video_render_frame_feed(video_render_handle_t handle, video_frame_t *frame);
#ifdef __cplusplus
}
#endif /* __cplusplus */
@@ -0,0 +1,224 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
* SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
*
* See LICENSE file for details.
*/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include "esp_log.h"
#include "esp_timer.h"
#include "sdkconfig.h"
#include "media_dump.h"
#if CONFIG_MEDIA_DUMP_SINK_UDP
#include "lwip/inet.h"
#include "lwip/sockets.h"
#endif /* CONFIG_MEDIA_DUMP_SINK_UDP */
#if CONFIG_MEDIA_DUMP_ENABLE
static const char *TAG = "MEDIA_DUMP";
typedef struct {
bool opened;
int64_t start_time_us;
int64_t max_duration_us;
bool expired;
bool notified;
#if CONFIG_MEDIA_DUMP_SINK_SDCARD
FILE *fp;
#endif /* CONFIG_MEDIA_DUMP_SINK_SDCARD */
#if CONFIG_MEDIA_DUMP_SINK_UDP
int sock;
struct sockaddr_in dest;
#endif /* CONFIG_MEDIA_DUMP_SINK_UDP */
} media_dump_ctx_t;
static media_dump_ctx_t s_ctx = {0};
static inline bool media_dump_time_exceeded(void)
{
media_dump_ctx_t *ctx = &s_ctx;
if (!ctx->opened) {
return false;
}
int64_t now = esp_timer_get_time();
if ((now - ctx->start_time_us) >= ctx->max_duration_us) {
ctx->expired = true;
if (!ctx->notified) {
ESP_LOGI(TAG, "Dump duration reached (%ds)", (int)CONFIG_MEDIA_DUMP_DURATION_SEC);
ctx->notified = true;
}
return true;
}
return false;
}
static void media_dump_release(media_dump_ctx_t *ctx)
{
#if CONFIG_MEDIA_DUMP_SINK_SDCARD
if (ctx->fp) {
fflush(ctx->fp);
fclose(ctx->fp);
ctx->fp = NULL;
}
#endif /* CONFIG_MEDIA_DUMP_SINK_SDCARD */
#if CONFIG_MEDIA_DUMP_SINK_UDP
if (ctx->sock >= 0) {
close(ctx->sock);
ctx->sock = -1;
}
#endif /* CONFIG_MEDIA_DUMP_SINK_UDP */
ctx->opened = false;
}
int media_dump_open(const char *filename)
{
media_dump_ctx_t *ctx = &s_ctx;
/* allow re-open anytime: close existing and start a new session */
if (ctx->opened) {
media_dump_release(ctx);
}
/* reset state and start fresh */
memset(ctx, 0, sizeof(*ctx));
ctx->max_duration_us = (int64_t)CONFIG_MEDIA_DUMP_DURATION_SEC * 1000000LL;
ctx->start_time_us = esp_timer_get_time();
#if CONFIG_MEDIA_DUMP_SINK_SDCARD
const char *path = NULL;
if (filename) {
path = filename;
} else {
path = CONFIG_MEDIA_DUMP_SDCARD_FILENAME;
}
ctx->fp = fopen(path, "wb");
if (!ctx->fp) {
ESP_LOGE(TAG, "Dump open file failed: %s, error: %s", path, strerror(errno));
return -1;
}
ESP_LOGI(TAG, "Dump file: %s, %ds", path, CONFIG_MEDIA_DUMP_DURATION_SEC);
#endif /* CONFIG_MEDIA_DUMP_SINK_SDCARD */
#if CONFIG_MEDIA_DUMP_SINK_UDP
ctx->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (ctx->sock < 0) {
ESP_LOGE(TAG, "Dump create UDP socket failed");
return -1;
}
memset(&ctx->dest, 0, sizeof(ctx->dest));
ctx->dest.sin_family = AF_INET;
ctx->dest.sin_port = htons(CONFIG_MEDIA_DUMP_UDP_PORT);
ctx->dest.sin_addr.s_addr = inet_addr(CONFIG_MEDIA_DUMP_UDP_IP);
ESP_LOGI(TAG, "Dump UDP %s:%d, %ds", CONFIG_MEDIA_DUMP_UDP_IP,
CONFIG_MEDIA_DUMP_UDP_PORT, CONFIG_MEDIA_DUMP_DURATION_SEC);
#endif /* CONFIG_MEDIA_DUMP_SINK_UDP */
ctx->opened = true;
return 0;
}
int media_dump_write(const uint8_t *data, size_t size)
{
media_dump_ctx_t *ctx = &s_ctx;
if (!ctx->opened || ctx->expired || !data || size == 0) {
return -1;
}
if (media_dump_time_exceeded()) {
ESP_LOGW(TAG, "Dump duration reached, ignore write");
return 0;
}
#if CONFIG_MEDIA_DUMP_SINK_SDCARD
if (ctx->fp) {
size_t w = fwrite(data, 1, size, ctx->fp);
if (w != size) {
ESP_LOGW(TAG, "Dump short file write: %u/%u", (unsigned)w, (unsigned)size);
}
return (int)w;
}
#endif /* CONFIG_MEDIA_DUMP_SINK_SDCARD */
#if CONFIG_MEDIA_DUMP_SINK_UDP
if (ctx->sock >= 0) {
int sent = sendto(ctx->sock, data, size, 0, (struct sockaddr *)&ctx->dest, sizeof(ctx->dest));
if (sent < 0) {
ESP_LOGW(TAG, "Dump UDP send failed");
return -1;
}
return sent;
}
#endif /* CONFIG_MEDIA_DUMP_SINK_UDP */
return -1;
}
int media_dump_close(void)
{
media_dump_ctx_t *ctx = &s_ctx;
if (!ctx->opened) {
return 0;
}
/* normal close: always release immediately */
media_dump_release(ctx);
return 0;
}
int media_dump_feed(const char *filename, const uint8_t *data, size_t size)
{
media_dump_ctx_t *ctx = &s_ctx;
/* feed mode: maintain a single open session across calls */
if (ctx->expired) {
return 0;
}
if (!ctx->opened) {
if (media_dump_open(filename) != 0) {
return -1;
}
}
ESP_LOGI(TAG, "Dump duration not reached, write now");
int ret = media_dump_write(data, size);
/* If duration reached during this write, close now */
if (ctx->expired && ctx->opened) {
(void)media_dump_close();
ESP_LOGI(TAG, "Dump duration reached, close now");
}
return ret;
}
#else /* !CONFIG_MEDIA_DUMP_ENABLE */
int media_dump_open(const char *filename)
{
return 0;
}
int media_dump_write(const uint8_t *data, size_t size)
{
(void)data;
(void)size;
return 0;
}
int media_dump_close(void)
{
return 0;
}
int media_dump_feed(const char *filename, const uint8_t *data, size_t size)
{
(void)filename;
(void)data;
(void)size;
return 0;
}
#endif /* CONFIG_MEDIA_DUMP_ENABLE */
@@ -0,0 +1,101 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
* SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
*
* See LICENSE file for details.
*/
#pragma once
#include "esp_err.h"
#include "esp_gmf_pool.h"
#include "av_processor_type.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @brief Initialize audio playback pool
*
* Creates and initializes a memory pool for audio playback operations.
* This pool manages memory for audio data that is being played back from
* various sources (files, streams, etc.).
*
* @param pool Pointer to store the created pool handle
* @return
* - ESP_OK Pool initialized successfully
* - ESP_ERR_NO_MEM Insufficient memory to create pool
* - ESP_ERR_INVALID_ARG Invalid parameter provided
*/
esp_err_t av_audio_playback_pool_init(esp_gmf_pool_handle_t *pool);
/**
* @brief Deinitialize audio playback pool
*
* Destroys the audio playback pool and frees all associated memory.
*
* @param pool Handle of the pool to deinitialize
* @return
* - ESP_OK Pool deinitialized successfully
* - ESP_ERR_INVALID_ARG Invalid pool handle
*/
esp_err_t av_audio_playback_pool_deinit(esp_gmf_pool_handle_t pool);
/**
* @brief Initialize audio recorder pool
*
* @param pool Pointer to store the created pool handle
* @param encoder_cfg Pointer to encoder configuration. If NULL, default PCM configuration will be used.
* @return
* - ESP_OK Pool initialized successfully
* - ESP_ERR_NO_MEM Insufficient memory to create pool
* - ESP_ERR_INVALID_ARG Invalid parameter provided
*/
esp_err_t av_audio_recorder_pool_init(esp_gmf_pool_handle_t *pool, const av_processor_encoder_config_t *encoder_cfg);
/**
* @brief Deinitialize audio recorder pool
*
* Destroys the audio recorder pool and frees all associated memory.
* Make sure encoder is not running or else may cause memory violation error
*
* @param pool Handle of the pool to deinitialize
* @return
* - ESP_OK Pool deinitialized successfully
* - ESP_ERR_INVALID_ARG Invalid pool handle
*/
esp_err_t av_audio_recorder_pool_deinit(esp_gmf_pool_handle_t pool);
/**
* @brief Initialize audio feeder pool
*
* Creates and initializes a memory pool for audio feeder operations.
* This pool manages memory for audio data that is being fed into
* various processing pipelines or output streams.
*
* @param pool Pointer to store the created pool handle
* @param decoder_cfg Pointer to decoder configuration. If NULL, default PCM configuration will be used.
* @return
* - ESP_OK Pool initialized successfully
* - ESP_ERR_NO_MEM Insufficient memory to create pool
* - ESP_ERR_INVALID_ARG Invalid parameter provided
*/
esp_err_t av_audio_feeder_pool_init(esp_gmf_pool_handle_t *pool, const av_processor_decoder_config_t *decoder_cfg);
/**
* @brief Deinitialize audio feeder pool
*
* Destroys the audio feeder pool and frees all associated memory.
* Make sure decoder is not running or else may cause memory violation error
*
* @param pool Handle of the pool to deinitialize
* @return
* - ESP_OK Pool deinitialized successfully
* - ESP_ERR_INVALID_ARG Invalid pool handle
*/
esp_err_t av_audio_feeder_pool_deinit(esp_gmf_pool_handle_t pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */
@@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
* SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
*
* See LICENSE file for details.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
/**
* @brief Open a media dump session
*
* When enabled by Kconfig, subsequent writes are dumped to the selected sink.
* If a session is already open, it will be closed and a new one started.
* The session duration is limited by `CONFIG_MEDIA_DUMP_DURATION_SEC`; after
* the timeout is reached, additional writes are not accepted.
*
* Sinks:
* - SDCARD: write to `CONFIG_MEDIA_DUMP_SDCARD_FILENAME`
* - UDP: send to `CONFIG_MEDIA_DUMP_UDP_ADDRESS` (format: IP:Port, e.g., "192.168.1.100:5000")
*
* @param[in] filename Optional filename for the dump file
* - If NULL, use `CONFIG_MEDIA_DUMP_SDCARD_FILENAME`
* - If not NULL, use the filename as the dump file name
* @return
* - 0: Session opened successfully
* - -1: Failed to open (e.g., file/socket creation failure)
*/
int media_dump_open(const char *filename);
/**
* @brief Write media data to the dump sink
*
* Effective only when a session is open and not expired.
*
* @param[in] data Pointer to the data buffer to write
* @param[in] size Number of bytes in the buffer
* @return
* - >0: Bytes actually written/sent (depends on sink)
* - 0: Maximum duration reached, this write is ignored
* - -1: Session not open, already expired, or parameters invalid
*/
int media_dump_write(const uint8_t *data, size_t size);
/**
* @brief Close the current media dump session and release resources
*
* Calling multiple times is safe; if no session is open, it returns immediately.
*
* @return
* - 0: Always returns 0
*/
int media_dump_close(void);
/**
* @brief Feed data with auto open/close behavior
*
* If no session is open, media_dump_open() is called automatically. After the
* write, if the session duration has been reached, the session is closed
* automatically. If the session is already expired, this function returns 0.
* If want to call this function, can use `extern int media_dump_feed(const char *filename, const uint8_t *data, size_t size);` in the file.
*
* @param[in] filename Optional filename for the dump file
* - If NULL, use `CONFIG_MEDIA_DUMP_SDCARD_FILENAME`
* - If not NULL, use the filename as the dump file name
* @param[in] data Pointer to the data buffer to write
* @param[in] size Number of bytes in the buffer
* @return
* - Same return semantics as media_dump_write()
* - -1: Auto open failed
*/
int media_dump_feed(const char *filename, const uint8_t *data, size_t size);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,107 @@
#!/usr/bin/env python3
import os
import shutil
import sys
import logging
from pathlib import Path
def main() -> int:
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s: %(message)s",
)
# Compute source directory (parent of this script's directory, i.e. espressif__av_processor)
script_path = Path(__file__).resolve()
av_processor_dir = script_path.parent.parent
if av_processor_dir.name != "espressif__av_processor":
logging.error("Failed to resolve source directory. Expected 'espressif__av_processor', got: %s", av_processor_dir)
return 1
# Ensure source espressif__av_processor is under managed_components
if av_processor_dir.parent.name != "managed_components":
logging.error("This script must be run when espressif__av_processor is under 'managed_components'. Current path: %s", av_processor_dir)
return 1
# Read PROJECT_DIR environment variable
project_dir_env = os.environ.get("PROJECT_DIR")
if not project_dir_env:
logging.error("PROJECT_DIR is not set. Example: export PROJECT_DIR=/path/to/project")
return 1
project_dir = Path(project_dir_env).resolve()
if not project_dir.exists() or not project_dir.is_dir():
logging.error("PROJECT_DIR does not exist or is not a directory: %s", project_dir)
return 1
# Target components directory
components_dir = project_dir / "components"
try:
components_dir.mkdir(parents=True, exist_ok=True)
except Exception as e:
logging.error("Failed to create target directory: %s -> %s", components_dir, e)
return 1
# Destination espressif__av_processor path
dest_dir = components_dir / "espressif__av_processor"
# If destination exists, remove it before copying
if dest_dir.exists():
logging.info("Destination exists, removing: %s", dest_dir)
try:
shutil.rmtree(dest_dir)
except Exception as e:
logging.error("Failed to remove existing destination: %s -> %s", dest_dir, e)
return 1
# Perform copy
logging.info("Copying %s -> %s", av_processor_dir, dest_dir)
try:
shutil.copytree(av_processor_dir, dest_dir)
except Exception as e:
logging.error("Copy failed: %s", e)
return 1
# Switch to a safe working directory to avoid deleting the running/current dir
try:
os.chdir(project_dir)
except Exception as e:
logging.error("Failed to change working directory: %s -> %s", project_dir, e)
return 1
# Remove source directory (parent av_processor)
logging.info("Removing source directory: %s", av_processor_dir)
try:
shutil.rmtree(av_processor_dir)
except Exception as e:
logging.error("Failed to remove source directory: %s -> %s", av_processor_dir, e)
logging.info("Copy completed, but source removal failed. Please clean up manually.")
return 1
# Update PROJECT_DIR/main/idf_component.yml to remove 'espressif/av_processor'
idf_component_path = project_dir / "main" / "idf_component.yml"
if idf_component_path.exists():
try:
content = idf_component_path.read_text(encoding="utf-8")
lines = content.splitlines()
new_lines = [line for line in lines if "espressif/av_processor" not in line]
if len(new_lines) != len(lines):
idf_component_path.write_text("\n".join(new_lines) + ("\n" if content.endswith("\n") else ""), encoding="utf-8")
logging.info("Removed 'espressif/av_processor' from %s", idf_component_path)
else:
logging.info("No 'espressif/av_processor' entry found in %s", idf_component_path)
except Exception as e:
logging.error("Failed to update %s: %s", idf_component_path, e)
return 1
else:
logging.info("idf_component.yml not found at %s, skipping update", idf_component_path)
logging.info("Copied espressif__av_processor to PROJECT_DIR/components, removed original directory, and updated idf_component.yml.")
return 0
if __name__ == "__main__":
sys.exit(main())
@@ -0,0 +1,93 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
# SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
#
# See LICENSE file for details.
#!/usr/bin/env python3
import argparse
import socket
import sys
from pathlib import Path
import os
from datetime import datetime
import logging
def get_primary_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(("8.8.8.8", 80))
return s.getsockname()[0]
except Exception:
return "127.0.0.1"
finally:
s.close()
def gen_filename():
ts = datetime.now().strftime("%Y%m%d%H%M%S")
return f"media_dump_{ts}.bin"
BUF_SIZE = 10240
def main():
logging.basicConfig(level=logging.INFO, format="[%(levelname)s] %(message)s")
parser = argparse.ArgumentParser(description="Receive UDP media dump and save to file")
parser.add_argument("--port", type=int, default=5000, help="UDP port (default: 5000)")
args = parser.parse_args()
primary_ip = get_primary_ip()
logging.info(f"Host primary IP: {primary_ip}, port: {args.port} (set MEDIA_DUMP_UDP_IP:PORT to this)")
out_path = Path(gen_filename())
out_path.parent.mkdir(parents=True, exist_ok=True)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.bind(("0.0.0.0", args.port))
except OSError as e:
logging.error(f"Bind failed on 0.0.0.0:{args.port} - {e}")
sys.exit(1)
logging.info(f"Listening on 0.0.0.0:{args.port}, output file: {out_path.name} (created on first packet), buf={BUF_SIZE}")
total = 0
f = None
try:
while True:
try:
data, addr = sock.recvfrom(BUF_SIZE)
except OSError:
break
if not data:
logging.info("\nClose received, finishing and exiting")
break
if f is None:
f = open(out_path, "wb")
logging.info(f"Receiving... writing to {out_path.resolve()}")
f.write(data)
total += len(data)
sys.stdout.write(f"\r[INFO] recv={len(data)} bytes, total={total} bytes")
sys.stdout.flush()
except KeyboardInterrupt:
pass
finally:
sock.close()
# ensure the progress line ends with newline
try:
sys.stdout.write("\n")
sys.stdout.flush()
except Exception:
pass
try:
if f is not None:
f.flush()
os.fsync(f.fileno())
f.close()
logging.info(f"Saved file: {out_path.resolve()}")
else:
logging.info("No packets received, no file saved")
except Exception as e:
logging.error(f"Finalize file failed: {e}")
logging.info(f"Done. Total bytes received: {total}")
sys.exit(0)
if __name__ == "__main__":
main()
@@ -0,0 +1,470 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_gmf_oal_thread.h"
#include "esp_gmf_oal_mem.h"
#include "esp_video_dec.h"
#include "esp_video_dec_reg.h"
#include "esp_video_enc_default.h"
#include "esp_video_codec_utils.h"
#include "esp_video_dec_default.h"
#include "esp_video_codec_version.h"
#include "esp_video_codec_types.h"
#include "esp_capture.h"
#include "esp_capture_defaults.h"
#include "video_processor.h"
static const char *TAG = "VIDEO_PROCESSOR";
#define VIDEO_RENDER_QUEUE_DEFAULT_SIZE (5)
#define _EVENT_GROUP_STOP_BIT (1 << 0)
#define VIDEO_DECODER_WORKER_TASK_STACK_SIZE (4096 * 10)
#define VIDEO_DECODER_WORKER_TASK_PRIORITY (12)
#define VIDEO_DECODER_WORKER_TASK_CORE (0)
#define VIDEO_DECODER_WORKER_TASK_NAME "video_decoder_worker"
#define VIDEO_CAPTURE_WORKER_TASK_STACK_SIZE (4096 * 10)
#define VIDEO_CAPTURE_WORKER_TASK_PRIORITY (12)
#define VIDEO_CAPTURE_WORKER_TASK_CORE (0)
#define VIDEO_CAPTURE_WORKER_TASK_NAME "video_capture_worker"
typedef enum {
VID_PROCESSOR_CMD_STOP,
VID_PROCESSOR_CMD_DATA,
VID_PROCESSOR_CMD_MAX,
} video_processor_cmd_t;
typedef struct {
video_processor_cmd_t cmd;
video_frame_t frame;
} video_processor_event_t;
/**
* @brief Video render internal structure
*/
typedef struct {
video_render_config_t config; /*!< Render configuration */
esp_gmf_oal_thread_t vdec_thread; /*!< Decoder thread handle */
QueueHandle_t frame_queue; /*!< Frame queue handle */
EventGroupHandle_t event_group; /*!< Event group handle */
video_frame_t out_frame; /*!< Output frame buffer */
void *ctx; /*!< User context */
esp_video_dec_handle_t dec_handle; /*!< Decoder handle */
bool is_running; /*!< Running state flag */
} video_render_t;
/**
* @brief Video capture internal structure
*/
typedef struct {
video_capture_config_t config; /*!< Capture configuration */
esp_capture_handle_t capture; /*!< Capture handle */
esp_capture_audio_src_if_t *aud_src; /*!< Audio source interface */
esp_capture_video_src_if_t *vid_src; /*!< Video source interface */
esp_capture_sink_handle_t sink[DEFAULT_VID_MAX_PATH]; /*!< Sink handles */
esp_gmf_oal_thread_t capture_thread; /*!< Capture thread handle */
EventGroupHandle_t event_group; /*!< Event group handle */
QueueHandle_t frame_queue; /*!< Frame queue handle */
bool is_running; /*!< Running state flag */
} video_capture_t;
static esp_capture_video_src_if_t *create_video_source(void *cam_config)
{
#if CONFIG_IDF_TARGET_ESP32S3
return esp_capture_new_video_dvp_src((esp_capture_video_dvp_src_cfg_t *)cam_config);
#else
ESP_LOGE(TAG, "Video source not supported for this target");
return NULL;
#endif /* CONFIG_IDF_TARGET_ESP32S3 */
}
static void decoder_worker_thread(void *arg)
{
video_render_t *render = (video_render_t *)arg;
if (!render) {
ESP_LOGE(TAG, "Invalid render handle");
esp_gmf_oal_thread_delete(NULL);
}
if (!render->out_frame.data) {
ESP_LOGE(TAG, "Failed to allocate memory for output frame");
esp_gmf_oal_thread_delete(NULL);
}
render->is_running = true;
video_processor_event_t evt_frame = {0};
while (render->is_running) {
if (xQueueReceive(render->frame_queue, &evt_frame, portMAX_DELAY) == pdPASS) {
ESP_LOGD(TAG, "vdec_task: %d", evt_frame.cmd);
switch (evt_frame.cmd) {
case VID_PROCESSOR_CMD_DATA:
ESP_LOGD(TAG, "Processing video frame, size: %zu", evt_frame.frame.size);
esp_video_dec_in_frame_t in_frame = {
.pts = 0,
.data = evt_frame.frame.data,
.size = evt_frame.frame.size,
};
esp_video_dec_out_frame_t out_frame = {
.data = render->out_frame.data,
.size = render->out_frame.size,
};
int ret = esp_video_dec_process(render->dec_handle, &in_frame, &out_frame);
if (ret != ESP_VC_ERR_OK) {
ESP_LOGE(TAG, "Failed to decode frame. ret: %d", ret);
break;
}
if (render->config.decode_cb) {
render->config.decode_cb(render->config.decode_cb_ctx, out_frame.data, out_frame.size);
}
break;
case VID_PROCESSOR_CMD_STOP:
ESP_LOGI(TAG, "Received stop command, exiting decoder thread");
render->is_running = false;
break;
default:
ESP_LOGE(TAG, "Unknown command: %d", evt_frame.cmd);
break;
}
if (evt_frame.frame.data) {
esp_gmf_oal_free(evt_frame.frame.data);
evt_frame.frame.data = NULL;
}
}
}
xEventGroupClearBits(render->event_group, _EVENT_GROUP_STOP_BIT);
ESP_LOGI(TAG, "Decoder thread exiting");
vTaskDelete(NULL);
}
static void capture_worker_thread(void *arg)
{
video_capture_t *capture = (video_capture_t *)arg;
if (!capture) {
ESP_LOGE(TAG, "Invalid capture handle");
esp_gmf_oal_thread_delete(NULL);
}
for (int i = 0; i < capture->config.sink_num; i++) {
esp_capture_sink_enable(capture->sink[i], ESP_CAPTURE_RUN_MODE_ALWAYS);
}
capture->is_running = true;
ESP_LOGI(TAG, "Capture thread started");
uint32_t gcd_fps = capture->config.sink_cfg[0].video_info.fps;
for (int i = 1; i < capture->config.sink_num; i++) {
uint32_t current_fps = capture->config.sink_cfg[i].video_info.fps;
uint32_t a = gcd_fps, b = current_fps;
while (b != 0) {
uint32_t temp = b;
b = a % b;
a = temp;
}
gcd_fps = a;
}
uint32_t base_delay_ms = 1000 / gcd_fps;
ESP_LOGI(TAG, "Multi-path capture: %d paths, gcd_fps: %" PRIu32 ", base_delay: %" PRIu32 "ms",
capture->config.sink_num, gcd_fps, base_delay_ms);
while (capture->is_running) {
for (int i = 0; i < capture->config.sink_num; i++) {
esp_capture_stream_frame_t frame = {0};
frame.stream_type = ESP_CAPTURE_STREAM_TYPE_VIDEO;
// Acquire frame from sink
esp_err_t ret = esp_capture_sink_acquire_frame(capture->sink[i], &frame, true);
if (ret != ESP_CAPTURE_ERR_OK) {
ESP_LOGD(TAG, "Acquire frame from sink %d timeout", i);
vTaskDelay(pdMS_TO_TICKS(base_delay_ms));
continue;
}
if (frame.stream_type == ESP_CAPTURE_STREAM_TYPE_VIDEO && frame.data && frame.size > 0) {
if (capture->config.capture_frame_cb) {
video_frame_t vid_frame = {
.data = frame.data,
.size = frame.size,
};
capture->config.capture_frame_cb(capture->config.capture_frame_cb_ctx, i, &vid_frame);
}
}
esp_capture_sink_release_frame(capture->sink[i], &frame);
}
}
ESP_LOGI(TAG, "Capture thread exiting");
xEventGroupSetBits(capture->event_group, _EVENT_GROUP_STOP_BIT);
esp_gmf_oal_thread_delete(NULL);
}
video_render_handle_t video_render_open(video_render_config_t *config)
{
if (!config) {
ESP_LOGE(TAG, "Invalid config");
return NULL;
}
esp_video_dec_register_default();
video_render_t *render = esp_gmf_oal_calloc(1, sizeof(video_render_t));
if (!render) {
ESP_LOGE(TAG, "Failed to allocate memory for render");
return NULL;
}
render->config.decode_cb_ctx = config->decode_cb_ctx;
render->config.decode_cb = config->decode_cb;
render->config.decode_cfg = config->decode_cfg;
render->config.resolution.width = config->resolution.width;
render->config.resolution.height = config->resolution.height;
render->frame_queue = xQueueCreate(VIDEO_RENDER_QUEUE_DEFAULT_SIZE, sizeof(video_processor_event_t));
if (!render->frame_queue) {
goto __exit;
}
render->event_group = xEventGroupCreate();
if (!render->event_group) {
goto __exit;
}
ESP_LOGI(TAG, "Video render opened successfully");
return render;
__exit:
if (render->frame_queue) {
vQueueDelete(render->frame_queue);
render->frame_queue = NULL;
}
if (render->event_group) {
vEventGroupDelete(render->event_group);
render->event_group = NULL;
}
if (render) {
esp_gmf_oal_free(render);
render = NULL;
}
return NULL;
}
esp_err_t video_render_start(video_render_handle_t handle)
{
video_render_t *render = (video_render_t *)handle;
if (!render) {
return ESP_ERR_INVALID_ARG;
}
uint32_t actual_size = 0;
render->out_frame.size = esp_video_codec_get_image_size(render->config.decode_cfg.out_fmt, &render->config.resolution);
render->out_frame.data = esp_video_codec_align_alloc(128, render->out_frame.size, &actual_size);
if (!render->out_frame.data) {
ESP_LOGE(TAG, "Failed to allocate memory for output frame");
return ESP_ERR_NO_MEM;
}
ESP_LOGI(TAG, "Output frame buffer allocated, size: %zu", render->out_frame.size);
int ret = esp_video_dec_open(&render->config.decode_cfg, &render->dec_handle);
if (!render->dec_handle || ret != ESP_VC_ERR_OK) {
ESP_LOGE(TAG, "Failed to open video decoder, error: %d", ret);
esp_gmf_oal_free(render->out_frame.data);
render->out_frame.data = NULL;
return ESP_ERR_NO_MEM;
}
esp_gmf_oal_thread_create(&render->vdec_thread, VIDEO_DECODER_WORKER_TASK_NAME,
decoder_worker_thread, (void *)render,
VIDEO_DECODER_WORKER_TASK_STACK_SIZE, VIDEO_DECODER_WORKER_TASK_PRIORITY,
true, VIDEO_DECODER_WORKER_TASK_CORE);
ESP_LOGI(TAG, "Video render started successfully");
return ESP_OK;
}
esp_err_t video_render_frame_feed(video_render_handle_t handle, video_frame_t *vid_frame)
{
video_render_t *render = (video_render_t *)handle;
if (!render) {
ESP_LOGE(TAG, "Invalid render handle");
return ESP_ERR_INVALID_ARG;
}
if (!vid_frame || !vid_frame->data || vid_frame->size == 0) {
ESP_LOGE(TAG, "Invalid frame data");
return ESP_ERR_INVALID_ARG;
}
video_processor_event_t evt_frame = {0};
evt_frame.cmd = VID_PROCESSOR_CMD_DATA;
evt_frame.frame.data = esp_gmf_oal_malloc(vid_frame->size);
if (!evt_frame.frame.data) {
ESP_LOGE(TAG, "Failed to allocate memory for frame data");
return ESP_ERR_NO_MEM;
}
memcpy(evt_frame.frame.data, vid_frame->data, vid_frame->size);
evt_frame.frame.size = vid_frame->size;
if (xQueueSend(render->frame_queue, &evt_frame, portMAX_DELAY) != pdPASS) {
ESP_LOGE(TAG, "Failed to send frame to queue");
esp_gmf_oal_free(evt_frame.frame.data);
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t video_render_stop(video_render_handle_t handle)
{
video_render_t *render = (video_render_t *)handle;
if (!render) {
ESP_LOGE(TAG, "Invalid render handle");
return ESP_ERR_INVALID_ARG;
}
if (!render->is_running) {
ESP_LOGW(TAG, "Video render is not running");
return ESP_OK;
}
video_processor_event_t evt_frame = {0};
evt_frame.cmd = VID_PROCESSOR_CMD_STOP;
if (xQueueSend(render->frame_queue, &evt_frame, portMAX_DELAY) != pdPASS) {
ESP_LOGE(TAG, "Failed to send stop command to queue");
return ESP_FAIL;
}
xEventGroupWaitBits(render->event_group, _EVENT_GROUP_STOP_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
ESP_LOGI(TAG, "Video render stopped successfully");
return ESP_OK;
}
void video_render_close(video_render_handle_t handle)
{
video_render_t *render = (video_render_t *)handle;
if (!render) {
ESP_LOGE(TAG, "Invalid render handle");
return;
}
if (render->is_running) {
video_render_stop(handle);
}
if (render->dec_handle) {
esp_video_dec_close(render->dec_handle);
render->dec_handle = NULL;
}
if (render->out_frame.data) {
esp_gmf_oal_free(render->out_frame.data);
render->out_frame.data = NULL;
}
if (render->frame_queue) {
vQueueDelete(render->frame_queue);
render->frame_queue = NULL;
}
esp_gmf_oal_free(render);
ESP_LOGI(TAG, "Video render closed successfully");
}
video_capture_handle_t video_capture_open(video_capture_config_t *config)
{
if (!config) {
ESP_LOGE(TAG, "Invalid config");
return NULL;
}
// capture structure
video_capture_t *capture = esp_gmf_oal_calloc(1, sizeof(video_capture_t));
if (!capture) {
ESP_LOGE(TAG, "Failed to allocate memory for capture");
return NULL;
}
capture->config = *config;
capture->frame_queue = xQueueCreate(2, sizeof(video_processor_event_t));
if (!capture->frame_queue) {
ESP_LOGE(TAG, "Failed to create frame queue");
goto __exit;
}
capture->event_group = xEventGroupCreate();
if (!capture->event_group) {
goto __exit;
}
esp_video_enc_register_default();
return capture;
__exit:
if (capture->frame_queue) {
vQueueDelete(capture->frame_queue);
capture->frame_queue = NULL;
}
if (capture->event_group) {
vEventGroupDelete(capture->event_group);
capture->event_group = NULL;
}
if (capture) {
esp_gmf_oal_free(capture);
capture = NULL;
}
return NULL;
}
esp_err_t video_capture_start(video_capture_handle_t handle)
{
video_capture_t *capture = (video_capture_t *)handle;
if (!capture) {
ESP_LOGE(TAG, "Invalid capture handle");
return ESP_ERR_INVALID_ARG;
}
capture->vid_src = create_video_source(capture->config.camera_config);
if (!capture->vid_src) {
ESP_LOGE(TAG, "Failed to create video source or not support");
return ESP_ERR_NO_MEM;
}
for (int i = 0; i < capture->config.sink_num; i++) {
// TODO: support other format
esp_capture_video_info_t fixed_caps = {
.format_id = ESP_CAPTURE_FMT_ID_RGB565_BE,
.width = capture->config.sink_cfg[i].video_info.width,
.height = capture->config.sink_cfg[i].video_info.height,
.fps = capture->config.sink_cfg[i].video_info.fps,
};
capture->vid_src->set_fixed_caps(capture->vid_src, &fixed_caps);
}
esp_capture_cfg_t capture_cfg = {
.video_src = capture->vid_src,
};
esp_capture_open(&capture_cfg, &capture->capture);
if (capture->capture == NULL) {
ESP_LOGE(TAG, "Fail to create capture");
return ESP_ERR_NO_MEM;
}
for (int i = 0; i < capture->config.sink_num; i++) {
esp_capture_sink_cfg_t sink_cfg = capture->config.sink_cfg[i];
esp_capture_sink_setup(capture->capture, i, &sink_cfg, &capture->sink[i]);
esp_capture_sink_enable(capture->sink[i], ESP_CAPTURE_RUN_MODE_ALWAYS);
}
esp_capture_start(capture->capture);
esp_gmf_oal_thread_create(&capture->capture_thread, VIDEO_CAPTURE_WORKER_TASK_NAME, capture_worker_thread,
(void *)capture, VIDEO_CAPTURE_WORKER_TASK_STACK_SIZE, VIDEO_CAPTURE_WORKER_TASK_PRIORITY,
true, VIDEO_CAPTURE_WORKER_TASK_CORE);
return ESP_OK;
}
void video_capture_close(video_capture_handle_t handle)
{
video_capture_t *capture = (video_capture_t *)handle;
if (!capture) {
ESP_LOGE(TAG, "Invalid capture handle");
return;
}
if (capture->capture) {
esp_capture_stop(capture->capture);
esp_capture_close(capture->capture);
}
capture->is_running = false;
xEventGroupWaitBits(capture->event_group, _EVENT_GROUP_STOP_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
if (capture->vid_src) {
capture->vid_src = NULL;
}
if (capture->frame_queue) {
vQueueDelete(capture->frame_queue);
}
esp_gmf_oal_free(capture);
}
@@ -0,0 +1,6 @@
idf_component_register(
SRCS "echoear.c"
INCLUDE_DIRS "include"
PRIV_INCLUDE_DIRS "priv_include"
REQUIRES driver esp_lcd fatfs
)
@@ -0,0 +1,108 @@
menu "Board Support Package(EchoEar)"
choice BSP_PCB_VERSION
prompt "PCB version"
default BSP_PCB_VERSION_V1_2
config BSP_PCB_VERSION_V1_0
bool "V1.0"
config BSP_PCB_VERSION_V1_2
bool "V1.2"
endchoice
config BSP_ERROR_CHECK
bool "Enable error check in BSP"
default y
help
Error check assert the application before returning the error code.
menu "I2C"
config BSP_I2C_NUM
int "I2C peripheral index"
default 1
range 0 1
help
ESP32S3 has two I2C peripherals, pick the one you want to use.
config BSP_I2C_FAST_MODE
bool "Enable I2C fast mode"
default y
help
I2C has two speed modes: normal (100kHz) and fast (400kHz).
config BSP_I2C_CLK_SPEED_HZ
int
default 400000 if BSP_I2C_FAST_MODE
default 100000
endmenu
menu "SPIFFS - Virtual File System"
config BSP_SPIFFS_FORMAT_ON_MOUNT_FAIL
bool "Format SPIFFS if mounting fails"
default n
help
Format SPIFFS if it fails to mount the filesystem.
config BSP_SPIFFS_MOUNT_POINT
string "SPIFFS mount point"
default "/spiffs"
help
Mount point of SPIFFS in the Virtual File System.
config BSP_SPIFFS_PARTITION_LABEL
string "Partition label of SPIFFS"
default "storage"
help
Partition label which stores SPIFFS.
config BSP_SPIFFS_MAX_FILES
int "Max files supported for SPIFFS VFS"
default 5
help
Supported max files for SPIFFS in the Virtual File System.
endmenu
menu "SD card - Virtual File System"
config BSP_SD_FORMAT_ON_MOUNT_FAIL
bool "Format SD card if mounting fails"
default n
help
The SDMMC host will format (FAT) the SD card if it fails to mount the filesystem.
config BSP_SD_MOUNT_POINT
string "SD card mount point"
default "/sdcard"
help
Mount point of the SD card in the Virtual File System
endmenu
menu "Display"
config BSP_DISPLAY_BRIGHTNESS_LEDC_CH
int "LEDC channel index"
default 1
range 0 7
help
LEDC channel is used to generate PWM signal that controls display brightness.
Set LEDC index that should be used.
config BSP_LCD_DRAW_BUF_HEIGHT
int "LCD framebuf height"
default 100
range 10 360
help
Framebuf is used for lvgl rendering output.
config BSP_LCD_DRAW_BUF_DOUBLE
bool "LCD double framebuf"
default n
help
Whether to enable double framebuf.
endmenu
config BSP_HEAD_LED_LEDC_CH
int "LEDC channel index"
default 2
range 0 7
help
LEDC channel is used to generate PWM signal that controls led brightness.
endmenu
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall release
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,650 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "driver/spi_master.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "bsp/esp-bsp.h"
#include "bsp/display.h"
#include "bsp/touch.h"
#include "esp_lcd_st77916.h"
#include "esp_lcd_touch_cst816s.h"
#include "esp_lvgl_port.h"
#include "bsp_err_check.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include "driver/uart.h"
#include "esp_sleep.h"
#include "esp_timer.h"
#include "sdkconfig.h"
#define GPIO_WAKEUP_LEVEL 0
static const char *TAG = "BSP";
static lv_disp_t *disp;
static lv_indev_t *disp_indev = NULL;
static esp_lcd_touch_handle_t tp; // LCD touch handle
static esp_lcd_panel_handle_t panel_handle = NULL;
static i2c_master_bus_handle_t i2c_handle = NULL;
static sdmmc_card_t *bsp_sdcard = NULL; // Global uSD card handler
static bool i2c_initialized = false;
esp_err_t bsp_i2c_init(void)
{
/* I2C was initialized before */
if (i2c_initialized) {
return ESP_OK;
}
const i2c_master_bus_config_t i2c_config = {
.i2c_port = BSP_I2C_NUM,
.sda_io_num = BSP_I2C_SDA,
.scl_io_num = BSP_I2C_SCL,
.clk_source = I2C_CLK_SRC_DEFAULT,
};
BSP_ERROR_CHECK_RETURN_ERR(i2c_new_master_bus(&i2c_config, &i2c_handle));
i2c_initialized = true;
return ESP_OK;
}
esp_err_t bsp_i2c_deinit(void)
{
BSP_ERROR_CHECK_RETURN_ERR(i2c_del_master_bus(i2c_handle));
i2c_initialized = false;
return ESP_OK;
}
i2c_master_bus_handle_t bsp_i2c_get_handle(void)
{
bsp_i2c_init();
return i2c_handle;
}
void bsp_i2c_set_handle(i2c_master_bus_handle_t handle)
{
i2c_handle = handle;
i2c_initialized = true;
}
// Bit number used to represent command and parameter
#define LCD_CMD_BITS 32
#define LCD_PARAM_BITS 8
#define LCD_LEDC_CH CONFIG_BSP_DISPLAY_BRIGHTNESS_LEDC_CH
esp_err_t bsp_display_brightness_init(void)
{
// Setup LEDC peripheral for PWM backlight control
const ledc_channel_config_t LCD_backlight_channel = {
.gpio_num = BSP_LCD_BACKLIGHT,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LCD_LEDC_CH,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0
};
const ledc_timer_config_t LCD_backlight_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_10_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 4000,
.clk_cfg = LEDC_AUTO_CLK
};
BSP_ERROR_CHECK_RETURN_ERR(ledc_timer_config(&LCD_backlight_timer));
BSP_ERROR_CHECK_RETURN_ERR(ledc_channel_config(&LCD_backlight_channel));
return ESP_OK;
}
esp_err_t bsp_display_brightness_set(int brightness_percent)
{
if (brightness_percent > 100) {
brightness_percent = 100;
}
if (brightness_percent < 0) {
brightness_percent = 0;
}
ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent);
uint32_t duty_cycle = (1023 * brightness_percent) / 100; // LEDC resolution set to 10bits, thus: 100% = 1023
BSP_ERROR_CHECK_RETURN_ERR(ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty_cycle));
BSP_ERROR_CHECK_RETURN_ERR(ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH));
return ESP_OK;
}
esp_err_t bsp_display_backlight_off(void)
{
return bsp_display_brightness_set(0);
}
esp_err_t bsp_display_backlight_on(void)
{
return bsp_display_brightness_set(100);
}
static const st77916_lcd_init_cmd_t vendor_specific_init_default[] = {
{0xF0, (uint8_t []){0x28}, 1, 0},
{0xF2, (uint8_t []){0x28}, 1, 0},
{0x73, (uint8_t []){0xF0}, 1, 0},
{0x7C, (uint8_t []){0xD1}, 1, 0},
{0x83, (uint8_t []){0xE0}, 1, 0},
{0x84, (uint8_t []){0x61}, 1, 0},
{0xF2, (uint8_t []){0x82}, 1, 0},
{0xF0, (uint8_t []){0x00}, 1, 0},
{0xF0, (uint8_t []){0x01}, 1, 0},
{0xF1, (uint8_t []){0x01}, 1, 0},
{0xB0, (uint8_t []){0x56}, 1, 0},
{0xB1, (uint8_t []){0x4D}, 1, 0},
{0xB2, (uint8_t []){0x24}, 1, 0},
{0xB4, (uint8_t []){0x87}, 1, 0},
{0xB5, (uint8_t []){0x44}, 1, 0},
{0xB6, (uint8_t []){0x8B}, 1, 0},
{0xB7, (uint8_t []){0x40}, 1, 0},
{0xB8, (uint8_t []){0x86}, 1, 0},
{0xBA, (uint8_t []){0x00}, 1, 0},
{0xBB, (uint8_t []){0x08}, 1, 0},
{0xBC, (uint8_t []){0x08}, 1, 0},
{0xBD, (uint8_t []){0x00}, 1, 0},
{0xC0, (uint8_t []){0x80}, 1, 0},
{0xC1, (uint8_t []){0x10}, 1, 0},
{0xC2, (uint8_t []){0x37}, 1, 0},
{0xC3, (uint8_t []){0x80}, 1, 0},
{0xC4, (uint8_t []){0x10}, 1, 0},
{0xC5, (uint8_t []){0x37}, 1, 0},
{0xC6, (uint8_t []){0xA9}, 1, 0},
{0xC7, (uint8_t []){0x41}, 1, 0},
{0xC8, (uint8_t []){0x01}, 1, 0},
{0xC9, (uint8_t []){0xA9}, 1, 0},
{0xCA, (uint8_t []){0x41}, 1, 0},
{0xCB, (uint8_t []){0x01}, 1, 0},
{0xD0, (uint8_t []){0x91}, 1, 0},
{0xD1, (uint8_t []){0x68}, 1, 0},
{0xD2, (uint8_t []){0x68}, 1, 0},
{0xF5, (uint8_t []){0x00, 0xA5}, 2, 0},
{0xDD, (uint8_t []){0x4F}, 1, 0},
{0xDE, (uint8_t []){0x4F}, 1, 0},
{0xF1, (uint8_t []){0x10}, 1, 0},
{0xF0, (uint8_t []){0x00}, 1, 0},
{0xF0, (uint8_t []){0x02}, 1, 0},
{0xE0, (uint8_t []){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0},
{0xE1, (uint8_t []){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0},
{0xF0, (uint8_t []){0x10}, 1, 0},
{0xF3, (uint8_t []){0x10}, 1, 0},
{0xE0, (uint8_t []){0x07}, 1, 0},
{0xE1, (uint8_t []){0x00}, 1, 0},
{0xE2, (uint8_t []){0x00}, 1, 0},
{0xE3, (uint8_t []){0x00}, 1, 0},
{0xE4, (uint8_t []){0xE0}, 1, 0},
{0xE5, (uint8_t []){0x06}, 1, 0},
{0xE6, (uint8_t []){0x21}, 1, 0},
{0xE7, (uint8_t []){0x01}, 1, 0},
{0xE8, (uint8_t []){0x05}, 1, 0},
{0xE9, (uint8_t []){0x02}, 1, 0},
{0xEA, (uint8_t []){0xDA}, 1, 0},
{0xEB, (uint8_t []){0x00}, 1, 0},
{0xEC, (uint8_t []){0x00}, 1, 0},
{0xED, (uint8_t []){0x0F}, 1, 0},
{0xEE, (uint8_t []){0x00}, 1, 0},
{0xEF, (uint8_t []){0x00}, 1, 0},
{0xF8, (uint8_t []){0x00}, 1, 0},
{0xF9, (uint8_t []){0x00}, 1, 0},
{0xFA, (uint8_t []){0x00}, 1, 0},
{0xFB, (uint8_t []){0x00}, 1, 0},
{0xFC, (uint8_t []){0x00}, 1, 0},
{0xFD, (uint8_t []){0x00}, 1, 0},
{0xFE, (uint8_t []){0x00}, 1, 0},
{0xFF, (uint8_t []){0x00}, 1, 0},
{0x60, (uint8_t []){0x40}, 1, 0},
{0x61, (uint8_t []){0x04}, 1, 0},
{0x62, (uint8_t []){0x00}, 1, 0},
{0x63, (uint8_t []){0x42}, 1, 0},
{0x64, (uint8_t []){0xD9}, 1, 0},
{0x65, (uint8_t []){0x00}, 1, 0},
{0x66, (uint8_t []){0x00}, 1, 0},
{0x67, (uint8_t []){0x00}, 1, 0},
{0x68, (uint8_t []){0x00}, 1, 0},
{0x69, (uint8_t []){0x00}, 1, 0},
{0x6A, (uint8_t []){0x00}, 1, 0},
{0x6B, (uint8_t []){0x00}, 1, 0},
{0x70, (uint8_t []){0x40}, 1, 0},
{0x71, (uint8_t []){0x03}, 1, 0},
{0x72, (uint8_t []){0x00}, 1, 0},
{0x73, (uint8_t []){0x42}, 1, 0},
{0x74, (uint8_t []){0xD8}, 1, 0},
{0x75, (uint8_t []){0x00}, 1, 0},
{0x76, (uint8_t []){0x00}, 1, 0},
{0x77, (uint8_t []){0x00}, 1, 0},
{0x78, (uint8_t []){0x00}, 1, 0},
{0x79, (uint8_t []){0x00}, 1, 0},
{0x7A, (uint8_t []){0x00}, 1, 0},
{0x7B, (uint8_t []){0x00}, 1, 0},
{0x80, (uint8_t []){0x48}, 1, 0},
{0x81, (uint8_t []){0x00}, 1, 0},
{0x82, (uint8_t []){0x06}, 1, 0},
{0x83, (uint8_t []){0x02}, 1, 0},
{0x84, (uint8_t []){0xD6}, 1, 0},
{0x85, (uint8_t []){0x04}, 1, 0},
{0x86, (uint8_t []){0x00}, 1, 0},
{0x87, (uint8_t []){0x00}, 1, 0},
{0x88, (uint8_t []){0x48}, 1, 0},
{0x89, (uint8_t []){0x00}, 1, 0},
{0x8A, (uint8_t []){0x08}, 1, 0},
{0x8B, (uint8_t []){0x02}, 1, 0},
{0x8C, (uint8_t []){0xD8}, 1, 0},
{0x8D, (uint8_t []){0x04}, 1, 0},
{0x8E, (uint8_t []){0x00}, 1, 0},
{0x8F, (uint8_t []){0x00}, 1, 0},
{0x90, (uint8_t []){0x48}, 1, 0},
{0x91, (uint8_t []){0x00}, 1, 0},
{0x92, (uint8_t []){0x0A}, 1, 0},
{0x93, (uint8_t []){0x02}, 1, 0},
{0x94, (uint8_t []){0xDA}, 1, 0},
{0x95, (uint8_t []){0x04}, 1, 0},
{0x96, (uint8_t []){0x00}, 1, 0},
{0x97, (uint8_t []){0x00}, 1, 0},
{0x98, (uint8_t []){0x48}, 1, 0},
{0x99, (uint8_t []){0x00}, 1, 0},
{0x9A, (uint8_t []){0x0C}, 1, 0},
{0x9B, (uint8_t []){0x02}, 1, 0},
{0x9C, (uint8_t []){0xDC}, 1, 0},
{0x9D, (uint8_t []){0x04}, 1, 0},
{0x9E, (uint8_t []){0x00}, 1, 0},
{0x9F, (uint8_t []){0x00}, 1, 0},
{0xA0, (uint8_t []){0x48}, 1, 0},
{0xA1, (uint8_t []){0x00}, 1, 0},
{0xA2, (uint8_t []){0x05}, 1, 0},
{0xA3, (uint8_t []){0x02}, 1, 0},
{0xA4, (uint8_t []){0xD5}, 1, 0},
{0xA5, (uint8_t []){0x04}, 1, 0},
{0xA6, (uint8_t []){0x00}, 1, 0},
{0xA7, (uint8_t []){0x00}, 1, 0},
{0xA8, (uint8_t []){0x48}, 1, 0},
{0xA9, (uint8_t []){0x00}, 1, 0},
{0xAA, (uint8_t []){0x07}, 1, 0},
{0xAB, (uint8_t []){0x02}, 1, 0},
{0xAC, (uint8_t []){0xD7}, 1, 0},
{0xAD, (uint8_t []){0x04}, 1, 0},
{0xAE, (uint8_t []){0x00}, 1, 0},
{0xAF, (uint8_t []){0x00}, 1, 0},
{0xB0, (uint8_t []){0x48}, 1, 0},
{0xB1, (uint8_t []){0x00}, 1, 0},
{0xB2, (uint8_t []){0x09}, 1, 0},
{0xB3, (uint8_t []){0x02}, 1, 0},
{0xB4, (uint8_t []){0xD9}, 1, 0},
{0xB5, (uint8_t []){0x04}, 1, 0},
{0xB6, (uint8_t []){0x00}, 1, 0},
{0xB7, (uint8_t []){0x00}, 1, 0},
{0xB8, (uint8_t []){0x48}, 1, 0},
{0xB9, (uint8_t []){0x00}, 1, 0},
{0xBA, (uint8_t []){0x0B}, 1, 0},
{0xBB, (uint8_t []){0x02}, 1, 0},
{0xBC, (uint8_t []){0xDB}, 1, 0},
{0xBD, (uint8_t []){0x04}, 1, 0},
{0xBE, (uint8_t []){0x00}, 1, 0},
{0xBF, (uint8_t []){0x00}, 1, 0},
{0xC0, (uint8_t []){0x10}, 1, 0},
{0xC1, (uint8_t []){0x47}, 1, 0},
{0xC2, (uint8_t []){0x56}, 1, 0},
{0xC3, (uint8_t []){0x65}, 1, 0},
{0xC4, (uint8_t []){0x74}, 1, 0},
{0xC5, (uint8_t []){0x88}, 1, 0},
{0xC6, (uint8_t []){0x99}, 1, 0},
{0xC7, (uint8_t []){0x01}, 1, 0},
{0xC8, (uint8_t []){0xBB}, 1, 0},
{0xC9, (uint8_t []){0xAA}, 1, 0},
{0xD0, (uint8_t []){0x10}, 1, 0},
{0xD1, (uint8_t []){0x47}, 1, 0},
{0xD2, (uint8_t []){0x56}, 1, 0},
{0xD3, (uint8_t []){0x65}, 1, 0},
{0xD4, (uint8_t []){0x74}, 1, 0},
{0xD5, (uint8_t []){0x88}, 1, 0},
{0xD6, (uint8_t []){0x99}, 1, 0},
{0xD7, (uint8_t []){0x01}, 1, 0},
{0xD8, (uint8_t []){0xBB}, 1, 0},
{0xD9, (uint8_t []){0xAA}, 1, 0},
{0xF3, (uint8_t []){0x01}, 1, 0},
{0xF0, (uint8_t []){0x00}, 1, 0},
{0x21, (uint8_t []){}, 0, 0},
{0x11, (uint8_t []){}, 0, 0},
{0x00, (uint8_t []){}, 0, 120},
};
esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io)
{
esp_err_t ret = ESP_OK;
assert(config != NULL && config->max_transfer_sz > 0);
ESP_RETURN_ON_ERROR(bsp_display_brightness_init(), TAG, "Brightness init failed");
/* Initialize I2C */
BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init());
ESP_LOGD(TAG, "Initialize SPI bus");
const spi_bus_config_t buscfg = {
.sclk_io_num = BSP_LCD_PCLK,
.data0_io_num = BSP_LCD_DATA0,
.data1_io_num = BSP_LCD_DATA1,
.data2_io_num = BSP_LCD_DATA2,
.data3_io_num = BSP_LCD_DATA3,
.max_transfer_sz = config->max_transfer_sz,
};
ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed");
ESP_LOGD(TAG, "Install panel IO");
const esp_lcd_panel_io_spi_config_t io_config = {
.dc_gpio_num = BSP_LCD_DC,
.cs_gpio_num = BSP_LCD_CS,
.pclk_hz = BSP_LCD_PIXEL_CLOCK_HZ,
.lcd_cmd_bits = LCD_CMD_BITS,
.lcd_param_bits = LCD_PARAM_BITS,
.spi_mode = 0,
.trans_queue_depth = 1,
.flags = {
.quad_mode = true,
},
};
ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed");
ESP_LOGD(TAG, "Install LCD driver");
const st77916_vendor_config_t vendor_config = {
.init_cmds = vendor_specific_init_default,
.init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(vendor_specific_init_default[0]),
.flags = {
.use_qspi_interface = 1,
},
};
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = BSP_LCD_RST, // Shared with Touch reset
.color_space = BSP_LCD_COLOR_SPACE,
.bits_per_pixel = BSP_LCD_BITS_PER_PIXEL,
.flags = {
.reset_active_high = true,
},
.vendor_config = (void *) &vendor_config,
};
ESP_LOGI(TAG, "Install st77916 panel driver");
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(*ret_io, (const esp_lcd_panel_dev_config_t *)&panel_config, ret_panel));
esp_lcd_panel_reset(*ret_panel);
esp_lcd_panel_init(*ret_panel);
esp_lcd_panel_disp_on_off(*ret_panel, true);
return ret;
err:
if (*ret_panel) {
esp_lcd_panel_del(*ret_panel);
}
if (*ret_io) {
esp_lcd_panel_io_del(*ret_io);
}
spi_bus_free(BSP_LCD_SPI_NUM);
return ret;
}
static lv_disp_t *bsp_display_lcd_init(const bsp_display_cfg_t *cfg)
{
assert(cfg != NULL);
esp_lcd_panel_io_handle_t io_handle = NULL;
const bsp_display_config_t bsp_disp_cfg = {
.max_transfer_sz = (BSP_LCD_H_RES * CONFIG_BSP_LCD_DRAW_BUF_HEIGHT) * sizeof(uint16_t),
};
BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&bsp_disp_cfg, &panel_handle, &io_handle));
esp_lcd_panel_disp_on_off(panel_handle, true);
/* Add LCD screen */
ESP_LOGD(TAG, "Add LCD screen");
const lvgl_port_display_cfg_t disp_cfg = {
.io_handle = io_handle,
.panel_handle = panel_handle,
.buffer_size = cfg->buffer_size,
.double_buffer = cfg->double_buffer,
.hres = BSP_LCD_H_RES,
.vres = BSP_LCD_V_RES,
.monochrome = false,
/* Rotation values must be same as used in esp_lcd for initial settings of the screen */
.rotation = {
.swap_xy = false,
.mirror_x = false,
.mirror_y = false,
},
.flags = {
.buff_dma = cfg->flags.buff_dma,
.buff_spiram = cfg->flags.buff_spiram,
.swap_bytes = true,
// .default_dummy_draw = cfg->flags.default_dummy_draw,
}
};
return lvgl_port_add_disp(&disp_cfg);
}
esp_err_t bsp_touch_new(const bsp_touch_config_t *config, esp_lcd_touch_handle_t *ret_touch)
{
/* Initialize I2C */
BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init());
/* Initialize touch */
esp_lcd_touch_config_t tp_cfg = {
.x_max = BSP_LCD_H_RES,
.y_max = BSP_LCD_V_RES,
.rst_gpio_num = GPIO_NUM_NC, // Shared with LCD reset
.int_gpio_num = BSP_LCD_TOUCH_INT,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
ESP_RETURN_ON_ERROR(esp_lcd_new_panel_io_i2c_v2(i2c_handle, &tp_io_config, &tp_io_handle), TAG, "");
ESP_RETURN_ON_ERROR(esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, ret_touch), TAG, "New CST816S failed");
return ESP_OK;
}
static lv_indev_t *bsp_display_indev_init(lv_disp_t *disp)
{
BSP_ERROR_CHECK_RETURN_NULL(bsp_touch_new(NULL, &tp));
assert(tp);
/* Add touch input (for selected screen) */
const lvgl_port_touch_cfg_t touch_cfg = {
.disp = disp,
.handle = tp,
};
return lvgl_port_add_touch(&touch_cfg);
}
lv_disp_t *bsp_display_start(void)
{
bsp_display_cfg_t cfg = {
.lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG(),
.buffer_size = BSP_LCD_H_RES * CONFIG_BSP_LCD_DRAW_BUF_HEIGHT,
#if CONFIG_BSP_LCD_DRAW_BUF_DOUBLE
.double_buffer = 1,
#else
.double_buffer = 0,
#endif
.flags = {
.buff_dma = true,
.buff_spiram = false,
}
};
return bsp_display_start_with_config(&cfg);
}
lv_disp_t *bsp_display_start_with_config(const bsp_display_cfg_t *cfg)
{
assert(cfg != NULL);
(lvgl_port_init(&cfg->lvgl_port_cfg));
BSP_ERROR_CHECK_RETURN_NULL(bsp_display_brightness_init());
BSP_NULL_CHECK(disp = bsp_display_lcd_init(cfg), NULL);
lv_display_set_user_data(disp, (void *)panel_handle);
BSP_NULL_CHECK(disp_indev = bsp_display_indev_init(disp), NULL);
return disp;
}
lv_indev_t *bsp_display_get_input_dev(void)
{
return disp_indev;
}
bool bsp_display_lock(uint32_t timeout_ms)
{
return lvgl_port_lock(timeout_ms);
}
void bsp_display_unlock(void)
{
lvgl_port_unlock();
}
esp_err_t bsp_power_init(bool power_en)
{
gpio_config_t power_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = BIT64(BSP_POWER_OFF),
};
#if defined(BSP_POWER_CODEC_EN)
power_gpio_config.pin_bit_mask |= BIT64(BSP_POWER_CODEC_EN);
#endif
ESP_ERROR_CHECK(gpio_config(&power_gpio_config));
gpio_set_level(BSP_POWER_OFF, !power_en);
#if defined(BSP_POWER_CODEC_EN)
gpio_set_level(BSP_POWER_CODEC_EN, power_en);
ESP_LOGI(TAG, "Using PCB version V1.2");
#else
ESP_LOGI(TAG, "Using PCB version V1.0");
#endif
vTaskDelay(pdMS_TO_TICKS(100));
return ESP_OK;
}
sdmmc_card_t *bsp_sdcard_get_handle(void)
{
return bsp_sdcard;
}
void bsp_sdcard_get_sdmmc_host(const int slot, sdmmc_host_t *config)
{
assert(config);
sdmmc_host_t host_config = SDMMC_HOST_DEFAULT();
memcpy(config, &host_config, sizeof(sdmmc_host_t));
}
void bsp_sdcard_sdmmc_get_slot(const int slot, sdmmc_slot_config_t *config)
{
assert(config);
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
/* SD card is connected to Slot 0 pins. Slot 0 uses IO MUX, so not specifying the pins here */
slot_config.cmd = BSP_SD_CMD;
slot_config.clk = BSP_SD_CLK;
slot_config.d0 = BSP_SD_D0;
slot_config.width = 1;
slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
*config = slot_config;
}
esp_err_t bsp_sdcard_sdmmc_mount(bsp_sdcard_cfg_t *cfg)
{
sdmmc_host_t sdhost = {0};
sdmmc_slot_config_t sdslot = {0};
const esp_vfs_fat_sdmmc_mount_config_t mount_config = {
#ifdef CONFIG_BSP_SD_FORMAT_ON_MOUNT_FAIL
.format_if_mount_failed = true,
#else
.format_if_mount_failed = false,
#endif
.max_files = 5,
.allocation_unit_size = 16 * 1024
};
assert(cfg);
if (!cfg->mount) {
cfg->mount = &mount_config;
}
if (!cfg->host) {
bsp_sdcard_get_sdmmc_host(SDMMC_HOST_SLOT_0, &sdhost);
cfg->host = &sdhost;
}
if (!cfg->slot.sdmmc) {
bsp_sdcard_sdmmc_get_slot(SDMMC_HOST_SLOT_0, &sdslot);
cfg->slot.sdmmc = &sdslot;
}
#if CONFIG_FATFS_LFN_NONE
ESP_LOGW(TAG, "Warning: Long filenames on SD card are disabled in menuconfig!");
#endif
return esp_vfs_fat_sdmmc_mount(BSP_SD_MOUNT_POINT, cfg->host, cfg->slot.sdmmc, cfg->mount, &bsp_sdcard);
}
esp_err_t bsp_sdcard_mount(void)
{
bsp_sdcard_cfg_t cfg = {0};
return bsp_sdcard_sdmmc_mount(&cfg);
}
esp_err_t bsp_sdcard_unmount(void)
{
esp_err_t ret = ESP_OK;
ret |= esp_vfs_fat_sdcard_unmount(BSP_SD_MOUNT_POINT, bsp_sdcard);
bsp_sdcard = NULL;
return ret;
}
esp_err_t bsp_set_head_led(bool on)
{
return gpio_set_level(BSP_HEAD_LED, !on);
}
esp_err_t bsp_set_peripheral_power(bool on)
{
return gpio_set_level(BSP_POWER_OFF, !on);
}
@@ -0,0 +1,20 @@
targets:
- esp32s3
tags:
- bsp
dependencies:
idf: ">=4.4.5"
lvgl/lvgl: "9.2.*"
espressif/esp_lcd_st77916: "^1.0.1"
espressif/esp_lcd_touch_cst816s:
version: "^1.1.0"
public: true
espressif/esp_lvgl_port:
version: "^2.6.0"
public: true
@@ -0,0 +1,110 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief BSP LCD
*
* This file offers API for basic LCD control.
* It is useful for users who want to use the LCD without the default Graphical Library LVGL.
*
* For standard LCD initialization with LVGL graphical library, you can call all-in-one function bsp_display_start().
*/
#pragma once
#include "esp_lcd_types.h"
/* LCD color formats */
#define ESP_LCD_COLOR_FORMAT_RGB565 (1)
#define ESP_LCD_COLOR_FORMAT_RGB888 (2)
/* LCD display color format */
#define BSP_LCD_COLOR_FORMAT (ESP_LCD_COLOR_FORMAT_RGB565)
/* LCD display color bytes endianness */
#define BSP_LCD_BIGENDIAN (1)
/* LCD display color bits */
#define BSP_LCD_BITS_PER_PIXEL (16)
/* LCD display color space */
#define BSP_LCD_COLOR_SPACE (ESP_LCD_COLOR_SPACE_RGB)
/* LCD definition */
#define BSP_LCD_H_RES (360)
#define BSP_LCD_V_RES (360)
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief BSP display configuration structure
*
*/
typedef struct {
int max_transfer_sz; /*!< Maximum transfer size, in bytes. */
} bsp_display_config_t;
/**
* @brief Create new display panel
*
* For maximum flexibility, this function performs only reset and initialization of the display.
* You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off().
* The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(),
* bsp_display_brightness_set() (on supported boards) or implement your own backlight control.
*
* If you want to free resources allocated by this function, you can use esp_lcd API, ie.:
*
* \code{.c}
* esp_lcd_panel_del(panel);
* esp_lcd_panel_io_del(io);
* spi_bus_free(spi_num_from_configuration);
* \endcode
*
* @param[in] config display configuration
* @param[out] ret_panel esp_lcd panel handle
* @param[out] ret_io esp_lcd IO handle
* @return
* - ESP_OK On success
* - Else esp_lcd failure
*/
esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io);
/**
* @brief Set display's brightness
*
* Brightness is controlled with PWM signal to a pin controlling backlight.
* Display must be already initialized by calling bsp_display_new()
*
* @param[in] brightness_percent Brightness in [%]
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t bsp_display_brightness_set(int brightness_percent);
/**
* @brief Turn on display backlight
*
* Display must be already initialized by calling bsp_display_new()
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t bsp_display_backlight_on(void);
/**
* @brief Turn off display backlight
*
* Display must be already initialized by calling bsp_display_new()
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t bsp_display_backlight_off(void);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,345 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#include "soc/usb_pins.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#include "esp_vfs_fat.h"
#include "lvgl.h"
#include "esp_lvgl_port.h"
#include "bsp/display.h"
/**************************************************************************************************
* BSP Capabilities
**************************************************************************************************/
#define BSP_CAPS_DISPLAY 1
#define BSP_CAPS_TOUCH 1
#define BSP_CAPS_BUTTONS 0
#define BSP_CAPS_AUDIO 0
#define BSP_CAPS_AUDIO_SPEAKER 0
#define BSP_CAPS_AUDIO_MIC 0
#define BSP_CAPS_SDCARD 1
#define BSP_CAPS_IMU 0
/* I2C */
#define BSP_I2C_SCL (GPIO_NUM_1)
#define BSP_I2C_SDA (GPIO_NUM_2)
#define BSP_IMU_INT (GPIO_NUM_21)
/* Audio */
#define BSP_I2S_SCLK (GPIO_NUM_40) // BCLK
#define BSP_I2S_MCLK (GPIO_NUM_42)
#define BSP_I2S_LCLK (GPIO_NUM_39) // WS
#define BSP_I2S_DOUT (GPIO_NUM_41) // To Codec ES8311
#define BSP_I2S_DSIN (GPIO_NUM_3)
#define BSP_POWER_AMP_IO (GPIO_NUM_15)
#define BSP_POWER_CODEC_EN (GPIO_NUM_48)
/* Display */
#define BSP_LCD_DATA3 (GPIO_NUM_12)
#define BSP_LCD_DATA2 (GPIO_NUM_11)
#define BSP_LCD_DATA1 (GPIO_NUM_13)
#define BSP_LCD_DATA0 (GPIO_NUM_46)
#define BSP_LCD_PCLK (GPIO_NUM_18)
#define BSP_LCD_CS (GPIO_NUM_14)
#define BSP_LCD_DC (GPIO_NUM_45)
#define BSP_LCD_RST (GPIO_NUM_47)
#define BSP_LCD_BACKLIGHT (GPIO_NUM_44)
#define BSP_LCD_TOUCH_INT (GPIO_NUM_10)
/* Power */
#define BSP_POWER_OFF (GPIO_NUM_9)
/* SD card */
#define BSP_SD_D0 (GPIO_NUM_17)
#define BSP_SD_CMD (GPIO_NUM_38)
#define BSP_SD_CLK (GPIO_NUM_16)
/* USB */
#define BSP_USB_DM (GPIO_NUM_19)
#define BSP_USB_DP (GPIO_NUM_20)
/* Others */
#define BSP_UART1_TX (GPIO_NUM_5)
#define BSP_UART1_RX (GPIO_NUM_4)
#define BSP_TOUCH_PAD1 (GPIO_NUM_7)
#define BSP_TOUCH_PAD2 (GPIO_NUM_6)
#define BSP_HEAD_LED (GPIO_NUM_43) // GREEN LED
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @brief BSP display configuration structure
*
*/
typedef struct {
lvgl_port_cfg_t lvgl_port_cfg; /*!< LVGL port configuration */
uint32_t buffer_size; /*!< Size of the buffer for the screen in pixels */
bool double_buffer; /*!< True, if should be allocated two buffers */
struct {
unsigned int buff_dma : 1; /*!< Allocated LVGL buffer will be DMA capable */
unsigned int buff_spiram : 1; /*!< Allocated LVGL buffer will be in PSRAM */
unsigned int default_dummy_draw : 1; /* Use dummy draw to bypass the display driver */
} flags;
} bsp_display_cfg_t;
/**************************************************************************************************
*
* I2C interface
*
* There are multiple devices connected to I2C peripheral:
* - Codec ES8311 (configuration only)
* - ADC ES7210 (configuration only)
* - Encryption chip ATECC608A (NOT populated on most boards)
* - LCD Touch controller
* - Inertial Measurement Unit ICM-42607-P
*
* After initialization of I2C, use BSP_I2C_NUM macro when creating I2C devices drivers ie.:
* \code{.c}
* icm42670_handle_t imu = icm42670_create(BSP_I2C_NUM, ICM42670_I2C_ADDRESS);
* \endcode
**************************************************************************************************/
#define BSP_I2C_NUM CONFIG_BSP_I2C_NUM
/**
* @brief Init I2C driver
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG I2C parameter error
* - ESP_FAIL I2C driver installation error
*
*/
esp_err_t bsp_i2c_init(void);
/**
* @brief Deinit I2C driver and free its resources
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG I2C parameter error
*
*/
esp_err_t bsp_i2c_deinit(void);
/**
* @brief Set I2C driver handle
*
* @param handle I2C handle
*/
void bsp_i2c_set_handle(i2c_master_bus_handle_t handle);
/**
* @brief Get I2C driver handle
*
* @return
* - I2C handle
*/
i2c_master_bus_handle_t bsp_i2c_get_handle(void);
/**************************************************************************************************
*
* LCD interface
*
* ESP-BOX is shipped with 2.4inch ST7789 display controller.
* It features 16-bit colors, 320x240 resolution and capacitive touch controller.
*
* LVGL is used as graphics library. LVGL is NOT thread safe, therefore the user must take LVGL mutex
* by calling bsp_display_lock() before calling and LVGL API (lv_...) and then give the mutex with
* bsp_display_unlock().
*
* Display's backlight must be enabled explicitly by calling bsp_display_backlight_on()
**************************************************************************************************/
#define BSP_LCD_PIXEL_CLOCK_HZ (40 * 1000 * 1000)
#define BSP_LCD_SPI_NUM (SPI2_HOST)
/**
* @brief Initialize display
*
* This function initializes SPI, display controller and starts LVGL handling task.
* LCD backlight must be enabled separately by calling bsp_display_brightness_set()
*
* @return
*/
lv_disp_t *bsp_display_start(void);
/**
* @brief Initialize display
*
* This function initializes SPI, display controller and starts LVGL handling task.
* LCD backlight must be enabled separately by calling bsp_display_brightness_set()
*
* @param cfg display configuration
*
* @return
*/
lv_disp_t *bsp_display_start_with_config(const bsp_display_cfg_t *cfg);
/**
* @brief Get pointer to input device (touch, buttons, ...)
*
* @note The LVGL input device is initialized in bsp_display_start() function.
*
* @return
*/
lv_indev_t *bsp_display_get_input_dev(void);
/**
* @brief Take LVGL mutex
*
* @param timeout_ms Timeout in [ms]. 0 will block indefinitely.
* @return
* @return
*/
bool bsp_display_lock(uint32_t timeout_ms);
/**
* @brief Give LVGL mutex
*
*/
void bsp_display_unlock(void);
/**
* @brief Initialize display brightness
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG I2C parameter error
* - ESP_FAIL I2C driver installation error
*
*/
esp_err_t bsp_display_brightness_init(void);
/**
* @brief Initialize power
*
* @param power_en power enable
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG I2C parameter error
* - ESP_FAIL I2C driver installation error
*
*/
esp_err_t bsp_power_init(bool power_en);
/**************************************************************************************************
*
* SD card
*
* After mounting the SD card, it can be accessed with stdio functions ie.:
* \code{.c}
* FILE* f = fopen(BSP_SD_MOUNT_POINT"/hello.txt", "w");
* fprintf(f, "Hello %s!\n", bsp_sdcard->cid.name);
* fclose(f);
* \endcode
*
* @attention IO2 is also routed to RGB LED and push button
**************************************************************************************************/
#define BSP_SD_MOUNT_POINT CONFIG_BSP_SD_MOUNT_POINT
/**
* @brief BSP SD card configuration structure
*/
typedef struct {
const esp_vfs_fat_sdmmc_mount_config_t *mount;
sdmmc_host_t *host;
union {
const sdmmc_slot_config_t *sdmmc;
} slot;
} bsp_sdcard_cfg_t;
/**
* @brief Mount microSD card to virtual file system
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
* - ESP_ERR_NO_MEM if memory can not be allocated
* - ESP_FAIL if partition can not be mounted
* - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers
*/
esp_err_t bsp_sdcard_mount(void);
/**
* @brief Unmount micorSD card from virtual file system
*
* @return
* - ESP_OK on success
* - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label
* - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount was already called
* - ESP_ERR_NO_MEM if memory can not be allocated
* - ESP_FAIL if partition can not be mounted
* - other error codes from wear levelling library, SPI flash driver, or FATFS drivers
*/
esp_err_t bsp_sdcard_unmount(void);
/**
* @brief Get SD card handle
*
* @return
*/
sdmmc_card_t *bsp_sdcard_get_handle(void);
/**
* @brief Get SD card MMC host config
*
* @param slot SD card slot
* @param config Structure which will be filled
*/
void bsp_sdcard_get_sdmmc_host(const int slot, sdmmc_host_t *config);
/**
* @brief Get SD card MMC slot config
*
* @param slot SD card slot
* @param config Structure which will be filled
*/
void bsp_sdcard_sdmmc_get_slot(const int slot, sdmmc_slot_config_t *config);
/**
* @brief Mount microSD card to virtual file system (MMC mode)
*
* @param cfg SD card configuration
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
* - ESP_ERR_NO_MEM if memory cannot be allocated
* - ESP_FAIL if partition cannot be mounted
* - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers
*/
esp_err_t bsp_sdcard_sdmmc_mount(bsp_sdcard_cfg_t *cfg);
/**
* @brief Get SD card handle
*
* @return
*/
sdmmc_card_t *bsp_sdcard_get_handle(void);
/**
* @brief Set peripheral power
*
* @param on true to turn on, false to turn off
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the parameter is invalid
*/
esp_err_t bsp_set_peripheral_power(bool on);
#ifdef __cplusplus
}
#endif /* __cplusplus */
@@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "bsp/echoear.h"
@@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief BSP Touchscreen
*
* This file offers API for basic touchscreen initialization.
* It is useful for users who want to use the touchscreen without the default Graphical Library LVGL.
*
* For standard LCD initialization with LVGL graphical library, you can call all-in-one function bsp_display_start().
*/
#pragma once
#include "esp_lcd_touch.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief BSP touch configuration structure
*
*/
typedef struct {
void *dummy; /*!< Prepared for future use. */
} bsp_touch_config_t;
/**
* @brief Create new touchscreen
*
* If you want to free resources allocated by this function, you can use esp_lcd_touch API, ie.:
*
* \code{.c}
* esp_lcd_touch_del(tp);
* \endcode
*
* @param[in] config touch configuration
* @param[out] ret_touch esp_lcd_touch touchscreen handle
* @return
* - ESP_OK On success
* - Else esp_lcd_touch failure
*/
esp_err_t bsp_touch_new(const bsp_touch_config_t *config, esp_lcd_touch_handle_t *ret_touch);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_check.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Assert on error, if selected in menuconfig. Otherwise return error code. */
#if CONFIG_BSP_ERROR_CHECK
#define BSP_ERROR_CHECK_RETURN_ERR(x) ESP_ERROR_CHECK(x)
#define BSP_ERROR_CHECK_RETURN_NULL(x) ESP_ERROR_CHECK(x)
#define BSP_ERROR_CHECK(x, ret) ESP_ERROR_CHECK(x)
#define BSP_NULL_CHECK(x, ret) assert(x)
#define BSP_NULL_CHECK_GOTO(x, goto_tag) assert(x)
#else
#define BSP_ERROR_CHECK_RETURN_ERR(x) do { \
esp_err_t err_rc_ = (x); \
if (unlikely(err_rc_ != ESP_OK)) { \
return err_rc_; \
} \
} while(0)
#define BSP_ERROR_CHECK_RETURN_NULL(x) do { \
if (unlikely((x) != ESP_OK)) { \
return NULL; \
} \
} while(0)
#define BSP_NULL_CHECK(x, ret) do { \
if ((x) == NULL) { \
return ret; \
} \
} while(0)
#define BSP_ERROR_CHECK(x, ret) do { \
if (unlikely((x) != ESP_OK)) { \
return ret; \
} \
} while(0)
#define BSP_NULL_CHECK_GOTO(x, goto_tag) do { \
if ((x) == NULL) { \
goto goto_tag; \
} \
} while(0)
#endif
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,4 @@
[codespell]
skip = build,*.yuv,alice.txt,*.rgb
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,afe,muxer,parm
write-changes = true
@@ -0,0 +1,53 @@
---
# FILE: .github/workflows/sync-jira.yml
# This GitHub Actions workflow synchronizes GitHub issues, comments, and pull requests with Jira.
# It triggers on new issues, issue comments, and on a scheduled basis.
# The workflow uses a custom action to perform the synchronization with Jira (espressif/sync-jira-actions).
name: 🔷 Sync to Jira
run-name: >
Sync to Jira -
${{ github.event_name == 'issue_comment' && 'Issue Comment' ||
github.event_name == 'schedule' && 'New Pull Requests' ||
github.event_name == 'issues' && 'New Issue' ||
github.event_name == 'workflow_dispatch' && 'Manual Sync' }}
on:
issues: {types: [opened]}
issue_comment: {types: [created, edited, deleted]}
schedule: [cron: '0 * * * *']
workflow_dispatch:
inputs:
action: {description: 'Action to be performed', required: true, default: 'mirror-issues'}
issue-numbers: {description: 'Issue numbers to sync (comma-separated)', required: true}
jobs:
sync-to-jira:
name: >
Sync to Jira -
${{ github.event_name == 'issue_comment' && 'Issue Comment' ||
github.event_name == 'schedule' && 'New Pull Requests' ||
github.event_name == 'issues' && 'New Issue' ||
github.event_name == 'workflow_dispatch' && 'Manual Sync' }}
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: write
steps:
- name: Check out
uses: actions/checkout@v4
- name: Run synchronization to Jira
uses: espressif/sync-jira-actions@v1
with:
cron_job: ${{ github.event_name == 'schedule' && 'true' || '' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: AUD
JIRA_COMPONENT: GMF_GitHub
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}
@@ -0,0 +1,31 @@
name: Push components to https://components.espressif.com
on:
push:
branches:
- main
jobs:
upload_components:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: "recursive"
- name: Upload components to the component registry
uses: espressif/upload-components-ci-action@v2
with:
components: |
gmf_core:./gmf_core
gmf_audio:./elements/gmf_audio
gmf_io:./elements/gmf_io
gmf_misc:./elements/gmf_misc
gmf_ai_audio:./elements/gmf_ai_audio
gmf_video:./elements/gmf_video
gmf_loader:./packages/gmf_loader
esp_audio_simple_player:./packages/esp_audio_simple_player
esp_capture: ./packages/esp_capture
gmf_app_utils: ./packages/gmf_app_utils
esp_board_manager: ./packages/esp_board_manager
esp_audio_render: ./packages/esp_audio_render
gmf_examples: ./gmf_examples
namespace: "espressif"
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
@@ -0,0 +1,54 @@
.config
*.o
*.pyc
# gtags
GTAGS
GRTAGS
GPATH
# emacs
.dir-locals.el
# emacs temp file suffixes
*~
.#*
\#*#
# MacOS directory files
.DS_Store
# eclipse setting
.settings
# Example project files
**/sdkconfig
**/sdkconfig.old
**/build
**/managed_components
**/dependencies.lock
**/dist
**/gen_bmgr_codes/
# Doc build artifacts
gmf_core/docs/*/_build/
gmf_core/docs/*/doxygen-warning-log.txt
gmf_core/docs/*/sphinx-warning-log.txt
gmf_core/docs/*/sphinx-warning-log-sanitized.txt
gmf_core/docs/*/xml/
gmf_core/docs/*/xml_in/
gmf_core/docs/*/man/
gmf_core/docs/*/doxygen_sqlite3.db
# Downloaded font files
gmf_core/docs/_static/DejaVuSans.ttf
gmf_core/docs/_static/NotoSansSC-Regular.otf
# gcov coverage reports
*.gcda
*.gcno
coverage.info
coverage_report/
.vscode
.cache/
@@ -0,0 +1,33 @@
stages:
- pre_check
- build
- target_test
- deploy
variables:
GIT_STRATEGY: clone
GET_SOURCES_ATTEMPTS: "10"
ARTIFACT_DOWNLOAD_ATTEMPTS: "10"
GIT_SUBMODULE_STRATEGY: none
IDF_SKIP_CHECK_SUBMODULES: 1
GIT_DEPTH: 1
IDF_PATH: "/root/.espressif/esp-idf"
PROJECT_PATH: "${CI_PROJECT_DIR}"
BASE_FRAMEWORK: $IDF_REPOSITORY
BASE_FRAMEWORK_PATH: "${IDF_PATH}"
TARGET_DIR_TYPE: "example"
EXAMPLES_PATH: "${CI_PROJECT_DIR}"
before_script:
- source ${CI_PROJECT_DIR}/tools/ci/utils.sh
- add_gitlab_ssh_keys
include:
- '.gitlab/ci/rules.yml'
- '.gitlab/ci/common.yml'
- '.gitlab/ci/pre_check.yml'
- '.gitlab/ci/build_examples.yml'
- '.gitlab/ci/build_ut.yml'
- '.gitlab/ci/target_ut.yml'
- '.gitlab/ci/target_examples.yml'
- '.gitlab/ci/deploy.yml'
@@ -0,0 +1,19 @@
# The file mainly marks apps with special rules, while other apps are enabled by default
.disable_test_apps: &disable_test_apps
disable:
- if: TARGET_DIR_TYPE == "test_apps"
.disable_example: &disable_example
disable:
- if: TARGET_DIR_TYPE == "example"
.disable_test_apps_esp32: &disable_test_apps_esp32
disable:
- if: TARGET_DIR_TYPE == "test_apps" AND IDF_TARGET == "esp32"
gmf_core/test_apps:
<<: *disable_example
packages/esp_board_manager:
<<: *disable_test_apps_esp32
@@ -0,0 +1,72 @@
.build_cmake_template: &build_cmake_template
stage: build
image: ${IMAGE}
tags:
- multimedia_build
parallel: 2
interruptible: true
dependencies: # set dependencies to null to avoid missing artifacts issue
variables:
DEEP_CLONE: "false"
IDF_FIND_APP_PATH_ARG: "-p"
SDKCFG_DEFAULTS: "sdkconfig.defaults.$IDF_TARGET"
BASE_FRAMEWORK_PATH: "${IDF_PATH}"
BASE_FRAMEWORK: $IDF_REPOSITORY
artifacts:
paths:
- "**/build*/size.json"
- "**/build*/build_log.txt"
- "**/build*/*.bin"
- "**/build*/*.elf"
- "**/build*/flasher_args.json"
- "**/build*/flash_project_args"
- "**/build*/config/sdkconfig.json"
- "**/build*/sdkconfig"
- "**/build*/bootloader/*.bin"
- "**/build*/partition_table/*.bin"
- "**/build*/srmodels/*.bin"
when: always
expire_in: 4 days
extends:
- .build_template
script:
- python $CI_PROJECT_DIR/tools/ci/esp_bmgr_pre_build.py --target $IDF_TARGET --board $AUDIO_BOARD --project-path ${EXAMPLES_PATH[@]} --target-dir-type ${TARGET_DIR_TYPE}
- run_cmd python $CI_PROJECT_DIR/tools/ci/build_apps.py ${EXAMPLES_PATH[@]} \
-t $IDF_TARGET -vv \
--target-dir-type ${TARGET_DIR_TYPE} \
--build-dir ${IDF_VERSION_TAG}/build_@t_@w \
--parallel-count ${parallel##*/} \
--parallel-index ${parallel%%/*}
.matrix_template: &matrix_template
parallel:
matrix:
- IDF_VERSION_TAG: ['v5.4.3']
parallel: [ 1/1 ]
build_examples_esp32_lyrat_mini_v1_1:
extends:
- .rules:build:protected-merge-requests-pipeline
- .build_cmake_template
- .matrix_template
variables:
IDF_TARGET: esp32
AUDIO_BOARD: lyrat_mini_v1_1
.build_examples_esp32s2_kaluga_v1_2:
extends:
- .rules:build:protected-merge-requests-pipeline
- .build_cmake_template
- .matrix_template
variables:
IDF_TARGET: esp32s2
AUDIO_BOARD: ''
build_examples_esp32s3_korvo_v2:
extends:
- .rules:build:protected-merge-requests-pipeline
- .build_cmake_template
- .matrix_template
variables:
IDF_TARGET: esp32s3
AUDIO_BOARD: esp32_s3_korvo2_v3

Some files were not shown because too many files have changed in this diff Show More