From 96e9690869600a03d7b619b6dfe06d59e8436371 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 25 Dec 2023 00:41:07 +0100 Subject: [PATCH 01/41] fixes for esp32 --- targets/esp32/main/EspPlayer.cpp | 139 ++ targets/esp32/main/EspPlayer.h | 41 + targets/esp32/main/Kconfig.projbuild | 25 + targets/esp32/main/main.cpp | 411 ++---- targets/esp32/sdkconfig.defaults | 1948 -------------------------- 5 files changed, 350 insertions(+), 2214 deletions(-) create mode 100644 targets/esp32/main/EspPlayer.cpp create mode 100644 targets/esp32/main/EspPlayer.h delete mode 100644 targets/esp32/sdkconfig.defaults diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp new file mode 100644 index 00000000..90621bc1 --- /dev/null +++ b/targets/esp32/main/EspPlayer.cpp @@ -0,0 +1,139 @@ +#include "EspPlayer.h" + +#include // for uint8_t +#include // for __base +#include // for operator<<, basic_ostream, endl, cout +#include // for shared_ptr, make_shared, make_unique +#include // for scoped_lock +#include // for hash, string_view +#include // for remove_extent_t +#include // for move +#include // for get +#include // for vector + +#include "BellUtils.h" // for BELL_SLEEP_MS +#include "CircularBuffer.h" +#include "Logger.h" +#include "SpircHandler.h" // for SpircHandler, SpircHandler::EventType +#include "StreamInfo.h" // for BitWidth, BitWidth::BW_16 +#include "TrackPlayer.h" // for TrackPlayer + +EspPlayer::EspPlayer(std::unique_ptr sink, + std::shared_ptr handler) + : bell::Task("player", 32 * 1024, 0, 1) { + this->handler = handler; + this->audioSink = std::move(sink); + + this->circularBuffer = + std::make_shared(1024 * 128); + + auto hashFunc = std::hash(); + + this->handler->getTrackPlayer()->setDataCallback( + [this, &hashFunc](uint8_t* data, size_t bytes, std::string_view trackId) { + auto hash = hashFunc(trackId); + this->feedData(data, bytes, hash); + return bytes; + } + ); + + this->isPaused = false; + + this->handler->setEventHandler( + [this, &hashFunc](std::unique_ptr event) { + switch (event->eventType) { + case cspot::SpircHandler::EventType::PLAY_PAUSE: + if (std::get(event->data)) { + this->pauseRequested = true; + } else { + this->isPaused = false; + this->pauseRequested = false; + } + break; + case cspot::SpircHandler::EventType::DISC: + this->circularBuffer->emptyBuffer(); + break; + case cspot::SpircHandler::EventType::FLUSH: + this->circularBuffer->emptyBuffer(); + break; + case cspot::SpircHandler::EventType::SEEK: + this->circularBuffer->emptyBuffer(); + break; + case cspot::SpircHandler::EventType::PLAYBACK_START: + this->isPaused = true; + this->playlistEnd = false; + this->circularBuffer->emptyBuffer(); + break; + case cspot::SpircHandler::EventType::DEPLETED: + this->playlistEnd = true; + break; + case cspot::SpircHandler::EventType::VOLUME: { + int volume = std::get(event->data); + break; + } + default: + break; + } + }); + startTask(); +} + +void EspPlayer::feedData(uint8_t* data, size_t len, size_t trackId) { + size_t toWrite = len; + + while (toWrite > 0) { + this->current_hash = trackId; + size_t written = + this->circularBuffer->write(data + (len - toWrite), toWrite); + if (written == 0) { + BELL_SLEEP_MS(10); + } + + toWrite -= written; + } +} + +void EspPlayer::runTask() { + std::vector outBuf = std::vector(1024); + + std::scoped_lock lock(runningMutex); + + size_t lastHash = 0; + + while (isRunning) { + if (!this->isPaused) { + size_t read = this->circularBuffer->read(outBuf.data(), outBuf.size()); + if (this->pauseRequested) { + this->pauseRequested = false; + std::cout << "Pause requested!" << std::endl; + this->isPaused = true; + } + + //this->audioSink->feedPCMFrames(outBuf.data(), read); + + if (read == 0) { + if (this->playlistEnd) { + this->handler->notifyAudioEnded(); + this->playlistEnd = false; + } + BELL_SLEEP_MS(10); + continue; + } else { + if (lastHash != current_hash) { + std::cout << " Last hash " << lastHash << " new hash " + << current_hash << std::endl; + lastHash = current_hash; + this->handler->notifyAudioReachedPlayback(); + + } + } + } else { + BELL_SLEEP_MS(100); + } + } +} + +void EspPlayer::disconnect() { + isRunning = false; + std::scoped_lock lock(runningMutex); +} diff --git a/targets/esp32/main/EspPlayer.h b/targets/esp32/main/EspPlayer.h new file mode 100644 index 00000000..47189231 --- /dev/null +++ b/targets/esp32/main/EspPlayer.h @@ -0,0 +1,41 @@ +#pragma once + +#include // for size_t +#include // for uint8_t +#include // for atomic +#include // for shared_ptr, unique_ptr +#include // for mutex +#include // for string + +#include "AudioSink.h" // for AudioSink +#include "BellTask.h" // for Task + +namespace bell { +class CircularBuffer; +} // namespace bell +namespace cspot { +class SpircHandler; +} // namespace cspot + +class EspPlayer : public bell::Task { + public: + EspPlayer(std::unique_ptr sink, + std::shared_ptr spircHandler); + void disconnect(); + + private: + std::string currentTrackId; + std::shared_ptr handler; + std::unique_ptr audioSink; + std::shared_ptr circularBuffer; + void feedData(uint8_t* data, size_t len, size_t); + + std::atomic pauseRequested = false; + std::atomic isPaused = true; + std::atomic isRunning = true; + std::mutex runningMutex; + std::atomic playlistEnd = false; + size_t current_hash; + + void runTask() override; +}; diff --git a/targets/esp32/main/Kconfig.projbuild b/targets/esp32/main/Kconfig.projbuild index b0a46638..64e164cb 100644 --- a/targets/esp32/main/Kconfig.projbuild +++ b/targets/esp32/main/Kconfig.projbuild @@ -52,6 +52,31 @@ menu "CSPOT Configuration" config CSPOT_STATUS_LED_TYPE_RMT bool "RMT - Addressable LED" endchoice + choice CSPOT_LOGIN + prompt "Login type" + default CSPOT_LOGIN_ZEROCONF + help + Select login form + + config CSPOT_LOGIN_ZEROCONF + bool "Login with zeroconfServer" + help + login with zeroconf + config CSPOT_LOGIN_PASS + bool "Login with password" + endchoice + + menu "username & password" + visible if CSPOT_LOGIN_PASS + config CSPOT_LOGIN_USERNAME + string "Spotify username" + default "username" + config CSPOT_LOGIN_PASSWORD + string "Spotify password" + default "password" + help + login with username and password + endmenu config CSPOT_STATUS_LED_GPIO int "Status LED GPIO number" diff --git a/targets/esp32/main/main.cpp b/targets/esp32/main/main.cpp index 8e518803..d0ba2ba5 100644 --- a/targets/esp32/main/main.cpp +++ b/targets/esp32/main/main.cpp @@ -7,6 +7,7 @@ #include #include #include "BellHTTPServer.h" +#include "BellLogger.h" // for setDefaultLogger, AbstractLogger #include "BellTask.h" #include "civetweb.h" #include "esp_event.h" @@ -21,6 +22,8 @@ #include "protocol_examples_common.h" #include "sdkconfig.h" +#include "EspPlayer.h" + #include #include #include @@ -30,11 +33,7 @@ #include "CircularBuffer.h" #include "BellUtils.h" -#include "ES8311AudioSink.h" -#include "ESPStatusLed.h" #include "Logger.h" -#include "freertos/ringbuf.h" -#include "freertos/task.h" #define DEVICE_NAME CONFIG_CSPOT_DEVICE_NAME @@ -59,303 +58,182 @@ static const char* TAG = "cspot"; -std::shared_ptr statusLed; -std::string credentialsFileName = "/spiffs/authBlob.json"; -bool createdFromZeroconf = false; extern "C" { -void app_main(void); + void app_main(void); } -class CSpotPlayer : public bell::Task { - private: - std::shared_ptr handler; - std::unique_ptr audioSink; - std::unique_ptr circularBuffer; - std::atomic isPaused; - - public: - CSpotPlayer(std::shared_ptr handler) - : bell::Task("cspot", 8 * 1024, 0, 0) { - this->handler = handler; - this->audioSink = std::make_unique(); - this->audioSink->setParams(44100, 2, 16); - this->audioSink->volumeChanged(160); - - this->circularBuffer = - std::make_unique(1024 * 128 * 8); - - this->handler->getTrackPlayer()->setDataCallback( - [this](uint8_t* data, size_t bytes) { this->feedData(data, bytes); }); - this->isPaused = false; - - this->handler->setEventHandler( - [this](std::unique_ptr event) { - switch (event->eventType) { - case cspot::SpircHandler::EventType::PLAY_PAUSE: - this->isPaused = std::get(event->data); - break; - case cspot::SpircHandler::EventType::FLUSH: - this->circularBuffer->emptyBuffer(); - break; - case cspot::SpircHandler::EventType::SEEK: - this->circularBuffer->emptyBuffer(); - break; - case cspot::SpircHandler::EventType::PLAYBACK_START: - this->circularBuffer->emptyBuffer(); - default: - break; - } - }); - startTask(); - } +class ZeroconfAuthenticator { +public: + ZeroconfAuthenticator() {}; + ~ZeroconfAuthenticator() {}; - void feedData(uint8_t* data, size_t len) { - size_t toWrite = len; + // Authenticator state + int serverPort = 7864; - while (toWrite > 0) { - size_t written = - this->circularBuffer->write(data + (len - toWrite), toWrite); - if (written == 0) { - BELL_SLEEP_MS(10); - } + // Use bell's HTTP server to handle the authentication, although anything can be used + std::unique_ptr server; + std::shared_ptr blob; - toWrite -= written; - } - } + std::function onAuthSuccess; + std::function onClose; - void runTask() { - std::vector outBuf = std::vector(1024); + void registerHandlers() { + this->server = std::make_unique(serverPort); + + server->registerGet("/spotify_info", [this](struct mg_connection* conn) { + return this->server->makeJsonResponse(this->blob->buildZeroconfInfo()); + }); + + + server->registerGet("/close", [this](struct mg_connection* conn) { + this->onClose(); + return this->server->makeEmptyResponse(); + }); + + + server->registerPost("/spotify_info", [this](struct mg_connection* conn) { + nlohmann::json obj; + // Prepare a success response for spotify + obj["status"] = 101; + obj["spotifyError"] = 0; + obj["statusString"] = "ERROR-OK"; + + std::string body = ""; + auto requestInfo = mg_get_request_info(conn); + if (requestInfo->content_length > 0) { + body.resize(requestInfo->content_length); + mg_read(conn, body.data(), requestInfo->content_length); - while (true) { - if (!this->isPaused) { - size_t read = this->circularBuffer->read(outBuf.data(), outBuf.size()); - this->audioSink->feedPCMFrames(outBuf.data(), read); + mg_header hd[10]; + int num = mg_split_form_urlencoded(body.data(), hd, 10); + std::map queryMap; - if (read == 0) { - BELL_SLEEP_MS(100); + // Parse the form data + for (int i = 0; i < num; i++) { + queryMap[hd[i].name] = hd[i].value; } - } else { - BELL_SLEEP_MS(100); + + CSPOT_LOG(info, "Received zeroauth POST data"); + + // Pass user's credentials to the blob + blob->loadZeroconfQuery(queryMap); + + // We have the blob, proceed to login + onAuthSuccess(); } - } + + return server->makeJsonResponse(obj.dump()); + }); + + + // Register mdns service, for spotify to find us + bell::MDNSService::registerService( + blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort, + { {"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"} }); + std::cout << "Waiting for spotify app to connect..." << std::endl; } }; class CSpotTask : public bell::Task { - public: - CSpotTask() : bell::Task("cspot", 32 * 1024, 0, 1) { startTask(); } +private: + std::unique_ptr handler; + std::unique_ptr audioSink; +public: + CSpotTask() : bell::Task("cspot", 8 * 1024, 0, 0) { startTask(); } void runTask() { + mdns_init(); mdns_hostname_set("cspot"); - std::atomic gotBlob = false; - - auto blob = std::make_shared(DEVICE_NAME); - - auto server = std::make_unique(8080); - server->registerGet( - "/spotify_info", [&server, blob](struct mg_connection* conn) { - return server->makeJsonResponse(blob->buildZeroconfInfo()); - }); - server->registerPost( - "/spotify_info", [&server, blob, &gotBlob](struct mg_connection* conn) { - nlohmann::json obj; - obj["status"] = 101; - obj["spotifyError"] = 0; - obj["statusString"] = "ERROR-OK"; - - std::string body = ""; - auto requestInfo = mg_get_request_info(conn); - if (requestInfo->content_length > 0) { - body.resize(requestInfo->content_length); - mg_read(conn, body.data(), requestInfo->content_length); - - mg_header hd[10]; - int num = mg_split_form_urlencoded(body.data(), hd, 10); - std::map queryMap; - - for (int i = 0; i < num; i++) { - queryMap[hd[i].name] = hd[i].value; - } - - blob->loadZeroconfQuery(queryMap); - gotBlob = true; - } - - return server->makeJsonResponse(obj.dump()); - }); +#ifdef CONFIG_CSPOT_SINK_INTERNAL +auto audioSink = std::make_unique(); +#endif +#ifdef CONFIG_CSPOT_SINK_AC101 +auto audioSink = std::make_unique(); +#endif +#ifdef CONFIG_CSPOT_SINK_ES8388 +auto audioSink = std::make_unique(); +#endif +#ifdef CONFIG_CSPOT_SINK_ES9018 +auto audioSink = std::make_unique(); +#endif +#ifdef CONFIG_CSPOT_SINK_PCM5102 +auto audioSink = std::make_unique(); +#endif +#ifdef CONFIG_CSPOT_SINK_TAS5711 +auto audioSink = std::make_unique(); +#endif + audioSink->setParams(44100, 2, 16); + audioSink->volumeChanged(160); - bell::MDNSService::registerService( - blob->getDeviceName(), "_spotify-connect", "_tcp", "", 8080, - {{"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"}}); + auto loggedInSemaphore = std::make_shared(1); - while (!gotBlob) { - BELL_SLEEP_MS(1000); - BELL_LOG(info, "cspot", "Waiting for spotify app to connect..."); - } + auto zeroconfServer = std::make_unique(); + std::atomic isRunning = true; - BELL_LOG(info, "cspot", "Got blob!"); - if (gotBlob) { - auto ctx = cspot::Context::createFromBlob(blob); - CSPOT_LOG(info, "Creating player"); - ctx->session->connectWithRandomAp(); - auto token = ctx->session->authenticate(blob); - - // Auth successful - if (token.size() > 0) { - ctx->session->startTask(); - auto handler = std::make_shared(ctx); - handler->subscribeToMercury(); - auto player = std::make_shared(handler); - - while (true) { - ctx->session->handlePacket(); - } + zeroconfServer->onClose = [&isRunning]() { + isRunning = false; + }; - handler->disconnect(); - // player->disconnect(); + auto loginBlob = std::make_shared(DEVICE_NAME); +#ifdef CONFIG_CSPOT_LOGIN_PASS + loginBlob->loadUserPass(CONFIG_CSPOT_LOGIN_USERNAME, CONFIG_CSPOT_LOGIN_PASSWORD); + loggedInSemaphore->give(); + +#else + zeroconfServer->blob = loginBlob; + zeroconfServer->onAuthSuccess = [loggedInSemaphore]() { + loggedInSemaphore->give(); + }; + zeroconfServer->registerHandlers(); +#endif + loggedInSemaphore->wait(); + auto ctx = cspot::Context::createFromBlob(loginBlob); + ctx->session->connectWithRandomAp(); + ctx->config.authData = ctx->session->authenticate(loginBlob); + if (ctx->config.authData.size() > 0) { + // when credentials file is set, then store reusable credentials + + // Start spirc task + auto handler = std::make_shared(ctx); + + // Start handling mercury messages + ctx->session->startTask(); + + // Create a player, pass the handler + auto player = std::make_shared(std::move(audioSink), std::move(handler)); + + // If we wanted to handle multiple devices, we would halt this loop + // when a new zeroconf login is requested, and reinitialize the session + while (isRunning) { + ctx->session->handlePacket(); } + + // Never happens, but required for above case + handler->disconnect(); + player->disconnect(); + } } }; -static void cspotTask(void* pvParameters) { - - // #ifdef CONFIG_CSPOT_SINK_INTERNAL - // auto audioSink = std::make_shared(); - // #endif - // #ifdef CONFIG_CSPOT_SINK_AC101 - // auto audioSink = std::make_shared(); - // #endif - // #ifdef CONFIG_CSPOT_SINK_ES8388 - // auto audioSink = std::make_shared(); - // #endif - // #ifdef CONFIG_CSPOT_SINK_ES9018 - // auto audioSink = std::make_shared(); - // #endif - // #ifdef CONFIG_CSPOT_SINK_PCM5102 - // auto audioSink = std::make_shared(); - // #endif - // #ifdef CONFIG_CSPOT_SINK_TAS5711 - // auto audioSink = std::make_shared(); - // #endif - - // // Config file - // file = std::make_shared(); - // configMan = std::make_shared("/spiffs/config.json", file); - - // if (!configMan->load()) { - // CSPOT_LOG(error, "Config error"); - // } - - // configMan->deviceName = DEVICE_NAME; - // #ifdef CONFIG_CSPOT_QUALITY_96 - // configMan->format = AudioFormat_OGG_VORBIS_96; - // #endif - // #ifdef CONFIG_CSPOT_QUALITY_160 - // configMan->format = AudioFormat_OGG_VORBIS_160; - // #endif - // #ifdef CONFIG_CSPOT_QUALITY_320 - // configMan->format = AudioFormat_OGG_VORBIS_320; - // #endif - - // auto createPlayerCallback = [audioSink](std::shared_ptr blob) { - - // // heap_trace_start(HEAP_TRACE_LEAKS); - // // esp_dump_per_task_heap_info(); - - // CSPOT_LOG(info, "Creating player"); - // statusLed->setStatus(StatusLed::SPOT_INITIALIZING); - - // auto session = std::make_unique(); - // session->connectWithRandomAp(); - // auto token = session->authenticate(blob); - - // // Auth successful - // if (token.size() > 0) - // { - // if (createdFromZeroconf) { - // file->writeFile(credentialsFileName, blob->toJson()); - // } - - // statusLed->setStatus(StatusLed::SPOT_READY); - - // mercuryManager = std::make_shared(std::move(session)); - // mercuryManager->startTask(); - - // spircController = std::make_shared(mercuryManager, blob->username, audioSink); - - // spircController->setEventHandler([](CSpotEvent& event) { - // switch (event.eventType) { - // case CSpotEventType::TRACK_INFO: - // CSPOT_LOG(info, "Track Info"); - // break; - // case CSpotEventType::PLAY_PAUSE: - // CSPOT_LOG(info, "Track Pause"); - // break; - // case CSpotEventType::SEEK: - // CSPOT_LOG(info, "Track Seek"); - // break; - // case CSpotEventType::DISC: - // CSPOT_LOG(info, "Disconnect"); - // spircController->stopPlayer(); - // mercuryManager->stop(); - // break; - // case CSpotEventType::PREV: - // CSPOT_LOG(info, "Track Previous"); - // break; - // case CSpotEventType::NEXT: - // CSPOT_LOG(info, "Track Next"); - // break; - // default: - // break; - // } - // }); - - // mercuryManager->reconnectedCallback = []() { - // return spircController->subscribe(); - // }; - - // mercuryManager->handleQueue(); - - // mercuryManager.reset(); - // spircController.reset(); - // } - - // BELL_SLEEP_MS(10000); - // // heap_trace_stop(); - // // heap_trace_dump(); - // ESP_LOGI(TAG, "Player exited"); - // auto memUsage = heap_caps_get_free_size(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - // auto memUsage2 = heap_caps_get_free_size(MALLOC_CAP_DMA | MALLOC_CAP_8BIT); - - // BELL_LOG(info, "esp32", "Free RAM %d | %d", memUsage, memUsage2); - // }; - - // createdFromZeroconf = true; - // auto httpServer = std::make_shared(2137); - // auto authenticator = std::make_shared(createPlayerCallback, httpServer); - // authenticator->registerHandlers(); - // httpServer->listen(); - - vTaskSuspend(NULL); -} - void init_spiffs() { - esp_vfs_spiffs_conf_t conf = {.base_path = "/spiffs", + esp_vfs_spiffs_conf_t conf = { .base_path = "/spiffs", .partition_label = NULL, .max_files = 5, - .format_if_mount_failed = true}; + .format_if_mount_failed = true }; esp_err_t ret = esp_vfs_spiffs_register(&conf); if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount or format filesystem"); - } else if (ret == ESP_ERR_NOT_FOUND) { + } + else if (ret == ESP_ERR_NOT_FOUND) { ESP_LOGE(TAG, "Failed to find SPIFFS partition"); - } else { + } + else { ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); } return; @@ -365,8 +243,9 @@ void init_spiffs() { ret = esp_spiffs_info(conf.partition_label, &total, &used); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", - esp_err_to_name(ret)); - } else { + esp_err_to_name(ret)); + } + else { ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); } } @@ -377,7 +256,7 @@ void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || - ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } @@ -398,7 +277,7 @@ void app_main(void) { //auto taskHandle = xTaskCreatePinnedToCore(&cspotTask, "cspot", 12*1024, NULL, 5, NULL, 1); /*auto taskHandle = */ bell::setDefaultLogger(); - + bell::enableTimestampLogging(); auto task = std::make_unique(); vTaskSuspend(NULL); } diff --git a/targets/esp32/sdkconfig.defaults b/targets/esp32/sdkconfig.defaults deleted file mode 100644 index e7db07f6..00000000 --- a/targets/esp32/sdkconfig.defaults +++ /dev/null @@ -1,1948 +0,0 @@ -# -# Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) Project Configuration -# -CONFIG_IDF_CMAKE=y -CONFIG_IDF_TARGET_ARCH_XTENSA=y -CONFIG_IDF_TARGET="esp32s3" -CONFIG_IDF_TARGET_ESP32S3=y -CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 - -# -# SDK tool configuration -# -CONFIG_SDK_TOOLPREFIX="xtensa-esp32s3-elf-" -# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set -# end of SDK tool configuration - -# -# Build type -# -CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y -# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set -CONFIG_APP_BUILD_GENERATE_BINARIES=y -CONFIG_APP_BUILD_BOOTLOADER=y -CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y -# end of Build type - -# -# Application manager -# -CONFIG_APP_COMPILE_TIME_DATE=y -# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set -# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set -# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set -CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 -# end of Application manager - -# -# Bootloader config -# -CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 -CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y -# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set -# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set -# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set -# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set -# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set -# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set -CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y -# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set -# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set -CONFIG_BOOTLOADER_LOG_LEVEL=3 -CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y -# CONFIG_BOOTLOADER_FACTORY_RESET is not set -# CONFIG_BOOTLOADER_APP_TEST is not set -CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y -CONFIG_BOOTLOADER_WDT_ENABLE=y -# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set -CONFIG_BOOTLOADER_WDT_TIME_MS=9000 -# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set -# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set -# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set -# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set -CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 -# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set -CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y -# end of Bootloader config - -# -# Security features -# -CONFIG_SECURE_BOOT_SUPPORTS_RSA=y -CONFIG_SECURE_TARGET_HAS_SECURE_ROM_DL_MODE=y -# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set -# CONFIG_SECURE_BOOT is not set -# CONFIG_SECURE_FLASH_ENC_ENABLED is not set -# end of Security features - -# -# Boot ROM Behavior -# -CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y -# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set -# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set -# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set -# end of Boot ROM Behavior - -# -# Serial flasher config -# -CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 -# CONFIG_ESPTOOLPY_NO_STUB is not set -# CONFIG_ESPTOOLPY_OCT_FLASH is not set -# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set -# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set -CONFIG_ESPTOOLPY_FLASHMODE_DIO=y -# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set -CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y -CONFIG_ESPTOOLPY_FLASHMODE="dio" -# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set -CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set -CONFIG_ESPTOOLPY_FLASHFREQ="80m" -# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y -# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE="8MB" -CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y -CONFIG_ESPTOOLPY_BEFORE_RESET=y -# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set -CONFIG_ESPTOOLPY_BEFORE="default_reset" -CONFIG_ESPTOOLPY_AFTER_RESET=y -# CONFIG_ESPTOOLPY_AFTER_NORESET is not set -CONFIG_ESPTOOLPY_AFTER="hard_reset" -# CONFIG_ESPTOOLPY_MONITOR_BAUD_CONSOLE is not set -# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set -# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set -CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y -# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set -# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set -# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set -# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set -CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 -CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 -# end of Serial flasher config - -# -# Partition Table -# -# CONFIG_PARTITION_TABLE_SINGLE_APP is not set -# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set -# CONFIG_PARTITION_TABLE_TWO_OTA is not set -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_OFFSET=0x8000 -CONFIG_PARTITION_TABLE_MD5=y -# end of Partition Table - -# -# Compiler options -# -CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y -# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set -# CONFIG_COMPILER_OPTIMIZATION_PERF is not set -# CONFIG_COMPILER_OPTIMIZATION_NONE is not set -CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y -# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set -CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 -# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set -CONFIG_COMPILER_HIDE_PATHS_MACROS=y -CONFIG_COMPILER_CXX_EXCEPTIONS=y -CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -# CONFIG_COMPILER_CXX_RTTI is not set -CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y -# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set -# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set -# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set -# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set -# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set -# CONFIG_COMPILER_DUMP_RTL_FILES is not set -# end of Compiler options - -# -# Component config -# - -# -# Application Level Tracing -# -# CONFIG_APPTRACE_DEST_JTAG is not set -CONFIG_APPTRACE_DEST_NONE=y -CONFIG_APPTRACE_LOCK_ENABLE=y -# end of Application Level Tracing - -# -# ESP-ASIO -# -# CONFIG_ASIO_SSL_SUPPORT is not set -# end of ESP-ASIO - -# -# Bluetooth -# -CONFIG_BT_ENABLED=y -CONFIG_BT_SOC_SUPPORT_5_0=y - -# -# Bluetooth controller -# -CONFIG_BT_CTRL_MODE_EFF=1 -CONFIG_BT_CTRL_BLE_MAX_ACT=10 -CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=10 -CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 -CONFIG_BT_CTRL_PINNED_TO_CORE_0=y -# CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set -CONFIG_BT_CTRL_PINNED_TO_CORE=0 -CONFIG_BT_CTRL_HCI_MODE_VHCI=y -# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set -CONFIG_BT_CTRL_HCI_TL=1 -CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30 -# CONFIG_BT_CTRL_HW_CCA is not set -CONFIG_BT_CTRL_HW_CCA_VAL=20 -CONFIG_BT_CTRL_HW_CCA_EFF=0 -CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y -# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set -# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set -CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0 -CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y -# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set -CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0 -CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y -# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set -CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0 -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set -CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3=y -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set -CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=9 -CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y -CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 -CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 -CONFIG_BT_CTRL_BLE_SCAN_DUPL=y -CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE=y -# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA is not set -# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE is not set -CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0 -CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100 -# CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN is not set -# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set -CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y -CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0 - -# -# MODEM SLEEP Options -# -# CONFIG_BT_CTRL_MODEM_SLEEP is not set -# end of MODEM SLEEP Options - -CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 -CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 -CONFIG_BT_CTRL_HCI_TL_EFF=1 -# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set -# end of Bluetooth controller - -CONFIG_BT_BLUEDROID_ENABLED=y -# CONFIG_BT_NIMBLE_ENABLED is not set -# CONFIG_BT_CONTROLLER_ONLY is not set - -# -# Bluedroid Options -# -CONFIG_BT_BTC_TASK_STACK_SIZE=4096 -CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y -# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set -CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 -CONFIG_BT_BTU_TASK_STACK_SIZE=4096 -# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set -CONFIG_BT_BLE_ENABLED=y -CONFIG_BT_GATTS_ENABLE=y -# CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set -# CONFIG_BT_BLE_BLUFI_ENABLE is not set -CONFIG_BT_GATT_MAX_SR_PROFILES=8 -# CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set -CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y -CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 -CONFIG_BT_GATTC_ENABLE=y -# CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set -CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 -CONFIG_BT_BLE_SMP_ENABLE=y -# CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set -# CONFIG_BT_STACK_NO_LOG is not set - -# -# BT DEBUG LOG LEVEL -# -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_HCI_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_HCI_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BTM_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BTM_TRACE_LEVEL=2 -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_L2CAP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL=2 -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_SDP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_SDP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_GAP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_GAP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BNEP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BNEP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_PAN_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_PAN_TRACE_LEVEL=2 -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_A2D_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_A2D_TRACE_LEVEL=2 -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_AVDT_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_AVDT_TRACE_LEVEL=2 -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_AVCT_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_AVCT_TRACE_LEVEL=2 -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_AVRC_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_AVRC_TRACE_LEVEL=2 -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_MCA_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_MCA_TRACE_LEVEL=2 -# CONFIG_BT_LOG_HID_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_HID_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_HID_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_HID_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_HID_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_HID_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_HID_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_HID_TRACE_LEVEL=2 -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_APPL_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_APPL_TRACE_LEVEL=2 -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_GATT_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_GATT_TRACE_LEVEL=2 -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_SMP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_SMP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BTIF_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BTIF_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BTC_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BTC_TRACE_LEVEL=2 -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_OSI_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_OSI_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BLUFI_TRACE_LEVEL=2 -# end of BT DEBUG LOG LEVEL - -CONFIG_BT_ACL_CONNECTIONS=4 -CONFIG_BT_MULTI_CONNECTION_ENBALE=y -# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set -# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set -# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set -CONFIG_BT_SMP_ENABLE=y -CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_MAX_DEVICE_NAME_LEN=32 -CONFIG_BT_BLE_RPA_SUPPORTED=y -CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y -CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -# end of Bluedroid Options -# end of Bluetooth - -# CONFIG_BLE_MESH is not set - -# -# CoAP Configuration -# -CONFIG_COAP_MBEDTLS_PSK=y -# CONFIG_COAP_MBEDTLS_PKI is not set -# CONFIG_COAP_MBEDTLS_DEBUG is not set -CONFIG_COAP_LOG_DEFAULT_LEVEL=0 -# end of CoAP Configuration - -# -# Driver configurations -# - -# -# ADC configuration -# -# CONFIG_ADC_FORCE_XPD_FSM is not set -CONFIG_ADC_DISABLE_DAC=y -# end of ADC configuration - -# -# MCPWM configuration -# -# CONFIG_MCPWM_ISR_IN_IRAM is not set -# end of MCPWM configuration - -# -# SPI configuration -# -# CONFIG_SPI_MASTER_IN_IRAM is not set -CONFIG_SPI_MASTER_ISR_IN_IRAM=y -# CONFIG_SPI_SLAVE_IN_IRAM is not set -CONFIG_SPI_SLAVE_ISR_IN_IRAM=y -# end of SPI configuration - -# -# TWAI configuration -# -# CONFIG_TWAI_ISR_IN_IRAM is not set -# end of TWAI configuration - -# -# UART configuration -# -# CONFIG_UART_ISR_IN_IRAM is not set -# end of UART configuration - -# -# GDMA Configuration -# -# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set -# CONFIG_GDMA_ISR_IRAM_SAFE is not set -# end of GDMA Configuration -# end of Driver configurations - -# -# eFuse Bit Manager -# -# CONFIG_EFUSE_CUSTOM_TABLE is not set -# CONFIG_EFUSE_VIRTUAL is not set -CONFIG_EFUSE_MAX_BLK_LEN=256 -# end of eFuse Bit Manager - -# -# ESP-TLS -# -CONFIG_ESP_TLS_USING_MBEDTLS=y -CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y -# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set -# CONFIG_ESP_TLS_SERVER is not set -# CONFIG_ESP_TLS_PSK_VERIFICATION is not set -CONFIG_ESP_TLS_INSECURE=y -CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y -# end of ESP-TLS - -# -# ESP32S3-Specific -# -# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set -# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160 is not set -CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y -CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 - -# -# Cache config -# -CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y -# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set -CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 -# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set -CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y -CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 -# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set -CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y -CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 -# CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP is not set -# CONFIG_ESP32S3_DATA_CACHE_16KB is not set -CONFIG_ESP32S3_DATA_CACHE_32KB=y -# CONFIG_ESP32S3_DATA_CACHE_64KB is not set -CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 -# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set -CONFIG_ESP32S3_DATA_CACHE_8WAYS=y -CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 -# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set -CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y -# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set -CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 -# CONFIG_ESP32S3_DATA_CACHE_WRAP is not set -# end of Cache config - -CONFIG_ESP32S3_SPIRAM_SUPPORT=y - -# -# SPI RAM config -# -CONFIG_SPIRAM_MODE_QUAD=y -# CONFIG_SPIRAM_MODE_OCT is not set -CONFIG_SPIRAM_TYPE_AUTO=y -# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set -# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set -# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set -CONFIG_SPIRAM_SIZE=-1 - -# -# PSRAM Clock and CS IO for ESP32S3 -# -CONFIG_DEFAULT_PSRAM_CLK_IO=30 -CONFIG_DEFAULT_PSRAM_CS_IO=26 -# end of PSRAM Clock and CS IO for ESP32S3 - -# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set -# CONFIG_SPIRAM_RODATA is not set -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y -# CONFIG_SPIRAM_SPEED_120M is not set -CONFIG_SPIRAM_SPEED_80M=y -# CONFIG_SPIRAM_SPEED_40M is not set -CONFIG_SPIRAM=y -CONFIG_SPIRAM_BOOT_INIT=y -# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set -# CONFIG_SPIRAM_USE_MEMMAP is not set -# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set -CONFIG_SPIRAM_USE_MALLOC=y -CONFIG_SPIRAM_MEMTEST=y -CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 -CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y -CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 -# end of SPI RAM config - -# CONFIG_ESP32S3_TRAX is not set -CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 -# CONFIG_ESP32S3_ULP_COPROC_ENABLED is not set -CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=0 -CONFIG_ESP32S3_DEBUG_OCDAWARE=y -CONFIG_ESP32S3_BROWNOUT_DET=y -CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y -# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set -# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set -# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set -# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set -# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set -# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set -CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 -CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y -# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set -# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set -# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set -CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y -# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set -# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set -# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set -CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 -CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 -# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set -# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set -# end of ESP32S3-Specific - -# -# ADC-Calibration -# -# end of ADC-Calibration - -# -# Common ESP-related -# -CONFIG_ESP_ERR_TO_NAME_LOOKUP=y -# end of Common ESP-related - -# -# Ethernet -# -CONFIG_ETH_ENABLED=y -CONFIG_ETH_USE_SPI_ETHERNET=y -# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set -# CONFIG_ETH_SPI_ETHERNET_W5500 is not set -# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set -# CONFIG_ETH_USE_OPENETH is not set -# end of Ethernet - -# -# Event Loop Library -# -# CONFIG_ESP_EVENT_LOOP_PROFILING is not set -CONFIG_ESP_EVENT_POST_FROM_ISR=y -CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y -# end of Event Loop Library - -# -# GDB Stub -# -# end of GDB Stub - -# -# ESP HTTP client -# -CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y -# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set -CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y -# end of ESP HTTP client - -# -# HTTP Server -# -CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 -CONFIG_HTTPD_MAX_URI_LEN=512 -CONFIG_HTTPD_ERR_RESP_NO_DELAY=y -CONFIG_HTTPD_PURGE_BUF_LEN=32 -# CONFIG_HTTPD_LOG_PURGE_DATA is not set -CONFIG_HTTPD_WS_SUPPORT=y -# end of HTTP Server - -# -# ESP HTTPS OTA -# -# CONFIG_OTA_ALLOW_HTTP is not set -# end of ESP HTTPS OTA - -# -# ESP HTTPS server -# -# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set -# end of ESP HTTPS server - -# -# Hardware Settings -# - -# -# MAC Config -# -CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y -CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y -CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y -CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y -# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set -CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y -CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 -# end of MAC Config - -# -# Sleep Config -# -CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y -CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y -CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y -CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y -CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y -# end of Sleep Config - -# -# RTC Clock Config -# -CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB=y -# end of RTC Clock Config -# end of Hardware Settings - -# -# IPC (Inter-Processor Call) -# -CONFIG_ESP_IPC_TASK_STACK_SIZE=1536 -CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y -CONFIG_ESP_IPC_ISR_ENABLE=y -# end of IPC (Inter-Processor Call) - -# -# LCD and Touch Panel -# - -# -# LCD Peripheral Configuration -# -CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 -# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set -# end of LCD Peripheral Configuration -# end of LCD and Touch Panel - -# -# ESP NETIF Adapter -# -CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 -CONFIG_ESP_NETIF_TCPIP_LWIP=y -# CONFIG_ESP_NETIF_LOOPBACK is not set -CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y -# end of ESP NETIF Adapter - -# -# PHY -# -CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y -# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set -CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 -CONFIG_ESP_PHY_MAX_TX_POWER=20 -CONFIG_ESP_PHY_ENABLE_USB=y -# end of PHY - -# -# Power Management -# -# CONFIG_PM_ENABLE is not set -CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y -CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y -# end of Power Management - -# -# ESP Ringbuf -# -# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set -# CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH is not set -# end of ESP Ringbuf - -# -# ESP System Settings -# -# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set -CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y -# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set -# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set -# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set -CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y -CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y - -# -# Memory protection -# -# end of Memory protection - -CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 -CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 -CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 -CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y -# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set -# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set -CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 -CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 -CONFIG_ESP_CONSOLE_UART_DEFAULT=y -# CONFIG_ESP_CONSOLE_USB_CDC is not set -# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set -# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set -# CONFIG_ESP_CONSOLE_NONE is not set -# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set -CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y -CONFIG_ESP_CONSOLE_UART=y -CONFIG_ESP_CONSOLE_MULTIPLE_UART=y -CONFIG_ESP_CONSOLE_UART_NUM=0 -CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 -CONFIG_ESP_INT_WDT=y -CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 -CONFIG_ESP_INT_WDT_CHECK_CPU1=y -CONFIG_ESP_TASK_WDT=y -# CONFIG_ESP_TASK_WDT_PANIC is not set -CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 -CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y -CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y -# CONFIG_ESP_PANIC_HANDLER_IRAM is not set -# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set -CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y -# end of ESP System Settings - -# -# High resolution timer (esp_timer) -# -# CONFIG_ESP_TIMER_PROFILING is not set -CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y -CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y -CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 -CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 -# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set -CONFIG_ESP_TIMER_IMPL_SYSTIMER=y -# end of High resolution timer (esp_timer) - -# -# Wi-Fi -# -CONFIG_ESP32_WIFI_ENABLED=y -CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=12 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=40 -CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y -CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 -CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=12 -CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32 -# CONFIG_ESP32_WIFI_CSI_ENABLED is not set -# CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED is not set -# CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED is not set -# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set -CONFIG_ESP32_WIFI_NVS_ENABLED=y -CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y -# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set -CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 -CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 -# CONFIG_ESP32_WIFI_IRAM_OPT is not set -# CONFIG_ESP32_WIFI_RX_IRAM_OPT is not set -CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y -# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set -# CONFIG_ESP_WIFI_FTM_ENABLE is not set -# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set -# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set -# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set -CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y -# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set -# end of Wi-Fi - -# -# Core dump -# -# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set -CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y -# end of Core dump - -# -# FAT Filesystem support -# -# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set -CONFIG_FATFS_CODEPAGE_437=y -# CONFIG_FATFS_CODEPAGE_720 is not set -# CONFIG_FATFS_CODEPAGE_737 is not set -# CONFIG_FATFS_CODEPAGE_771 is not set -# CONFIG_FATFS_CODEPAGE_775 is not set -# CONFIG_FATFS_CODEPAGE_850 is not set -# CONFIG_FATFS_CODEPAGE_852 is not set -# CONFIG_FATFS_CODEPAGE_855 is not set -# CONFIG_FATFS_CODEPAGE_857 is not set -# CONFIG_FATFS_CODEPAGE_860 is not set -# CONFIG_FATFS_CODEPAGE_861 is not set -# CONFIG_FATFS_CODEPAGE_862 is not set -# CONFIG_FATFS_CODEPAGE_863 is not set -# CONFIG_FATFS_CODEPAGE_864 is not set -# CONFIG_FATFS_CODEPAGE_865 is not set -# CONFIG_FATFS_CODEPAGE_866 is not set -# CONFIG_FATFS_CODEPAGE_869 is not set -# CONFIG_FATFS_CODEPAGE_932 is not set -# CONFIG_FATFS_CODEPAGE_936 is not set -# CONFIG_FATFS_CODEPAGE_949 is not set -# CONFIG_FATFS_CODEPAGE_950 is not set -CONFIG_FATFS_CODEPAGE=437 -# CONFIG_FATFS_LFN_NONE is not set -CONFIG_FATFS_LFN_HEAP=y -# CONFIG_FATFS_LFN_STACK is not set -CONFIG_FATFS_MAX_LFN=255 -# CONFIG_FATFS_API_ENCODING_ANSI_OEM is not set -# CONFIG_FATFS_API_ENCODING_UTF_16 is not set -CONFIG_FATFS_API_ENCODING_UTF_8=y -CONFIG_FATFS_FS_LOCK=0 -CONFIG_FATFS_TIMEOUT_MS=10000 -CONFIG_FATFS_PER_FILE_CACHE=y -CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y -# CONFIG_FATFS_USE_FASTSEEK is not set -# end of FAT Filesystem support - -# -# Modbus configuration -# -CONFIG_FMB_COMM_MODE_TCP_EN=y -CONFIG_FMB_TCP_PORT_DEFAULT=502 -CONFIG_FMB_TCP_PORT_MAX_CONN=5 -CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 -CONFIG_FMB_COMM_MODE_RTU_EN=y -CONFIG_FMB_COMM_MODE_ASCII_EN=y -CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 -CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 -CONFIG_FMB_QUEUE_LENGTH=20 -CONFIG_FMB_PORT_TASK_STACK_SIZE=4096 -CONFIG_FMB_SERIAL_BUF_SIZE=256 -CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 -CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 -CONFIG_FMB_PORT_TASK_PRIO=10 -# CONFIG_FMB_PORT_TASK_AFFINITY_NO_AFFINITY is not set -CONFIG_FMB_PORT_TASK_AFFINITY_CPU0=y -# CONFIG_FMB_PORT_TASK_AFFINITY_CPU1 is not set -CONFIG_FMB_PORT_TASK_AFFINITY=0x0 -CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y -CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233 -CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 -CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 -CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 -CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 -# CONFIG_FMB_TIMER_PORT_ENABLED is not set -CONFIG_FMB_TIMER_GROUP=0 -CONFIG_FMB_TIMER_INDEX=0 -CONFIG_FMB_MASTER_TIMER_GROUP=0 -CONFIG_FMB_MASTER_TIMER_INDEX=0 -# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set -# end of Modbus configuration - -# -# FreeRTOS -# -# CONFIG_FREERTOS_UNICORE is not set -CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF -CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y -CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y -# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set -CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y -CONFIG_FREERTOS_HZ=100 -CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y -# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set -# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set -CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y -# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set -CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y -CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 -CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y -# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set -# CONFIG_FREERTOS_ASSERT_DISABLE is not set -CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 -CONFIG_FREERTOS_ISR_STACKSIZE=1536 -# CONFIG_FREERTOS_LEGACY_HOOKS is not set -CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 -CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y -# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set -CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 -CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 -CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 -CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 -CONFIG_FREERTOS_USE_TRACE_FACILITY=y -CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y -CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y -CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y -CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y -CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y -CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y -# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set -# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set -CONFIG_FREERTOS_DEBUG_OCDAWARE=y -CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y -# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set -# end of FreeRTOS - -# -# Hardware Abstraction Layer (HAL) and Low Level (LL) -# -CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y -# CONFIG_HAL_ASSERTION_DISABLE is not set -# CONFIG_HAL_ASSERTION_SILIENT is not set -# CONFIG_HAL_ASSERTION_ENABLE is not set -CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 -# end of Hardware Abstraction Layer (HAL) and Low Level (LL) - -# -# Heap memory debugging -# -CONFIG_HEAP_POISONING_DISABLED=y -# CONFIG_HEAP_POISONING_LIGHT is not set -# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set -CONFIG_HEAP_TRACING_OFF=y -# CONFIG_HEAP_TRACING_STANDALONE is not set -# CONFIG_HEAP_TRACING_TOHOST is not set -# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set -# end of Heap memory debugging - -# -# jsmn -# -# CONFIG_JSMN_PARENT_LINKS is not set -# CONFIG_JSMN_STRICT is not set -# end of jsmn - -# -# libsodium -# -# end of libsodium - -# -# Log output -# -# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set -# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set -# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set -CONFIG_LOG_DEFAULT_LEVEL_INFO=y -# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set -# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set -CONFIG_LOG_DEFAULT_LEVEL=3 -CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y -# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set -# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set -CONFIG_LOG_MAXIMUM_LEVEL=3 -CONFIG_LOG_COLORS=y -CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y -# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set -# end of Log output - -# -# LWIP -# -CONFIG_LWIP_LOCAL_HOSTNAME="fuji" -CONFIG_LWIP_NETIF_API=y -# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set -CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y -# CONFIG_LWIP_L2_TO_L3_COPY is not set -# CONFIG_LWIP_IRAM_OPTIMIZATION is not set -CONFIG_LWIP_TIMERS_ONDEMAND=y -CONFIG_LWIP_MAX_SOCKETS=16 -# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set -# CONFIG_LWIP_SO_LINGER is not set -CONFIG_LWIP_SO_REUSE=y -CONFIG_LWIP_SO_REUSE_RXTOALL=y -# CONFIG_LWIP_SO_RCVBUF is not set -# CONFIG_LWIP_NETBUF_RECVINFO is not set -CONFIG_LWIP_IP4_FRAG=y -CONFIG_LWIP_IP6_FRAG=y -# CONFIG_LWIP_IP4_REASSEMBLY is not set -# CONFIG_LWIP_IP6_REASSEMBLY is not set -# CONFIG_LWIP_IP_FORWARD is not set -# CONFIG_LWIP_STATS is not set -# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set -CONFIG_LWIP_ESP_GRATUITOUS_ARP=y -CONFIG_LWIP_GARP_TMR_INTERVAL=60 -CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 -CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y -# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set -CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y -# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set -CONFIG_LWIP_DHCP_OPTIONS_LEN=68 - -# -# DHCP server -# -CONFIG_LWIP_DHCPS=y -CONFIG_LWIP_DHCPS_LEASE_UNIT=60 -CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 -# end of DHCP server - -# CONFIG_LWIP_AUTOIP is not set -CONFIG_LWIP_IPV6=y -# CONFIG_LWIP_IPV6_AUTOCONFIG is not set -CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 -# CONFIG_LWIP_IPV6_FORWARD is not set -# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set -CONFIG_LWIP_NETIF_LOOPBACK=y -CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 - -# -# TCP -# -CONFIG_LWIP_MAX_ACTIVE_TCP=16 -CONFIG_LWIP_MAX_LISTENING_TCP=16 -CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y -CONFIG_LWIP_TCP_MAXRTX=12 -CONFIG_LWIP_TCP_SYNMAXRTX=12 -CONFIG_LWIP_TCP_MSS=1440 -CONFIG_LWIP_TCP_TMR_INTERVAL=250 -CONFIG_LWIP_TCP_MSL=60000 -CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 -CONFIG_LWIP_TCP_WND_DEFAULT=5744 -CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 -CONFIG_LWIP_TCP_QUEUE_OOSEQ=y -# CONFIG_LWIP_TCP_SACK_OUT is not set -# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set -CONFIG_LWIP_TCP_OVERSIZE_MSS=y -# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set -# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set -# CONFIG_LWIP_WND_SCALE is not set -CONFIG_LWIP_TCP_RTO_TIME=1500 -# end of TCP - -# -# UDP -# -CONFIG_LWIP_MAX_UDP_PCBS=16 -CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 -# end of UDP - -# -# Checksums -# -# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set -# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set -CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y -# end of Checksums - -CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 -CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y -# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set -# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set -CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF -# CONFIG_LWIP_PPP_SUPPORT is not set -CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 -CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 -# CONFIG_LWIP_SLIP_SUPPORT is not set - -# -# ICMP -# -CONFIG_LWIP_ICMP=y -# CONFIG_LWIP_MULTICAST_PING is not set -# CONFIG_LWIP_BROADCAST_PING is not set -# end of ICMP - -# -# LWIP RAW API -# -CONFIG_LWIP_MAX_RAW_PCBS=16 -# end of LWIP RAW API - -# -# SNTP -# -CONFIG_LWIP_SNTP_MAX_SERVERS=1 -# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set -CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 -# end of SNTP - -CONFIG_LWIP_ESP_LWIP_ASSERT=y - -# -# Hooks -# -# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set -CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y -# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set -CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y -# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set -# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set -CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y -# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set -# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set -CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y -# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set -# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set -# end of Hooks - -# CONFIG_LWIP_DEBUG is not set -# end of LWIP - -# -# mbedTLS -# -# CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC is not set -CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y -# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set -# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y -CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 -CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 -# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set -CONFIG_MBEDTLS_DEBUG=y -# CONFIG_MBEDTLS_DEBUG_LEVEL_WARN is not set -# CONFIG_MBEDTLS_DEBUG_LEVEL_INFO is not set -# CONFIG_MBEDTLS_DEBUG_LEVEL_DEBUG is not set -CONFIG_MBEDTLS_DEBUG_LEVEL_VERBOSE=y -CONFIG_MBEDTLS_DEBUG_LEVEL=4 - -# -# mbedTLS v2.28.x related -# -# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set -CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT=y -# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set -# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set -CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y -# end of mbedTLS v2.28.x related - -# -# Certificate Bundle -# -CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y -CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y -# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set -# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set -# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set -CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 -# end of Certificate Bundle - -CONFIG_MBEDTLS_ECP_RESTARTABLE=y -CONFIG_MBEDTLS_CMAC_C=y -CONFIG_MBEDTLS_HARDWARE_AES=y -CONFIG_MBEDTLS_AES_USE_INTERRUPT=y -CONFIG_MBEDTLS_HARDWARE_MPI=y -CONFIG_MBEDTLS_HARDWARE_SHA=y -CONFIG_MBEDTLS_ROM_MD5=y -# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set -# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set -CONFIG_MBEDTLS_HAVE_TIME=y -# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set -CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y -CONFIG_MBEDTLS_SHA512_C=y -CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y -# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set -# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set -# CONFIG_MBEDTLS_TLS_DISABLED is not set -CONFIG_MBEDTLS_TLS_SERVER=y -CONFIG_MBEDTLS_TLS_CLIENT=y -CONFIG_MBEDTLS_TLS_ENABLED=y - -# -# TLS Key Exchange Methods -# -CONFIG_MBEDTLS_PSK_MODES=y -# CONFIG_MBEDTLS_KEY_EXCHANGE_PSK is not set -CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y -# end of TLS Key Exchange Methods - -CONFIG_MBEDTLS_SSL_RENEGOTIATION=y -# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set -CONFIG_MBEDTLS_SSL_PROTO_TLS1=y -CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y -CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y -# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set -# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set -CONFIG_MBEDTLS_SSL_ALPN=y -CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y -CONFIG_MBEDTLS_X509_CHECK_KEY_USAGE=y -CONFIG_MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE=y -CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y - -# -# Symmetric Ciphers -# -CONFIG_MBEDTLS_AES_C=y -# CONFIG_MBEDTLS_CAMELLIA_C is not set -# CONFIG_MBEDTLS_DES_C is not set -CONFIG_MBEDTLS_RC4_DISABLED=y -# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set -# CONFIG_MBEDTLS_RC4_ENABLED is not set -# CONFIG_MBEDTLS_BLOWFISH_C is not set -# CONFIG_MBEDTLS_XTEA_C is not set -CONFIG_MBEDTLS_CCM_C=y -CONFIG_MBEDTLS_GCM_C=y -# CONFIG_MBEDTLS_NIST_KW_C is not set -# end of Symmetric Ciphers - -# CONFIG_MBEDTLS_RIPEMD160_C is not set - -# -# Certificates -# -CONFIG_MBEDTLS_PEM_PARSE_C=y -CONFIG_MBEDTLS_PEM_WRITE_C=y -CONFIG_MBEDTLS_X509_CRL_PARSE_C=y -CONFIG_MBEDTLS_X509_CSR_PARSE_C=y -# end of Certificates - -CONFIG_MBEDTLS_ECP_C=y -CONFIG_MBEDTLS_ECDH_C=y -CONFIG_MBEDTLS_ECDSA_C=y -# CONFIG_MBEDTLS_ECJPAKE_C is not set -CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y -CONFIG_MBEDTLS_ECP_NIST_OPTIM=y -# CONFIG_MBEDTLS_POLY1305_C is not set -# CONFIG_MBEDTLS_CHACHA20_C is not set -# CONFIG_MBEDTLS_HKDF_C is not set -# CONFIG_MBEDTLS_THREADING_C is not set -# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set -# CONFIG_MBEDTLS_SECURITY_RISKS is not set -# end of mbedTLS - -# -# mDNS -# -CONFIG_MDNS_MAX_SERVICES=10 -CONFIG_MDNS_TASK_PRIORITY=1 -CONFIG_MDNS_TASK_STACK_SIZE=4096 -# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set -CONFIG_MDNS_TASK_AFFINITY_CPU0=y -# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set -CONFIG_MDNS_TASK_AFFINITY=0x0 -CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 -# CONFIG_MDNS_STRICT_MODE is not set -CONFIG_MDNS_TIMER_PERIOD_MS=100 -# CONFIG_MDNS_NETWORKING_SOCKET is not set -CONFIG_MDNS_MULTIPLE_INSTANCE=y -# end of mDNS - -# -# ESP-MQTT Configurations -# -CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_TRANSPORT_SSL=y -CONFIG_MQTT_TRANSPORT_WEBSOCKET=y -CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y -# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set -# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set -# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set -# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set -# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set -# CONFIG_MQTT_CUSTOM_OUTBOX is not set -# end of ESP-MQTT Configurations - -# -# Newlib -# -CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y -# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set -# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set -# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set -# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set -CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y -# CONFIG_NEWLIB_NANO_FORMAT is not set -# end of Newlib - -# -# NVS -# -# CONFIG_NVS_ASSERT_ERROR_CHECK is not set -# end of NVS - -# -# OpenSSL -# -# CONFIG_OPENSSL_DEBUG is not set -CONFIG_OPENSSL_ERROR_STACK=y -# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set -CONFIG_OPENSSL_ASSERT_EXIT=y -# end of OpenSSL - -# -# OpenThread -# -# CONFIG_OPENTHREAD_ENABLED is not set -# end of OpenThread - -# -# PThreads -# -CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 -CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 -CONFIG_PTHREAD_STACK_MIN=768 -CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y -# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set -# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set -CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 -CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" -# end of PThreads - -# -# SPI Flash driver -# -# CONFIG_SPI_FLASH_VERIFY_WRITE is not set -# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set -CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y -# CONFIG_SPI_FLASH_ROM_IMPL is not set -CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y -# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set -# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set -# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set -# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set -# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set -CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y -CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 -CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 -CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 -# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set -# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set -# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set - -# -# Auto-detect flash chips -# -CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y -CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y -CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y -CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y -CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y -CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y -CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y -# end of Auto-detect flash chips - -CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y -# end of SPI Flash driver - -# -# SPIFFS Configuration -# -CONFIG_SPIFFS_MAX_PARTITIONS=3 - -# -# SPIFFS Cache Configuration -# -CONFIG_SPIFFS_CACHE=y -CONFIG_SPIFFS_CACHE_WR=y -# CONFIG_SPIFFS_CACHE_STATS is not set -# end of SPIFFS Cache Configuration - -CONFIG_SPIFFS_PAGE_CHECK=y -CONFIG_SPIFFS_GC_MAX_RUNS=10 -# CONFIG_SPIFFS_GC_STATS is not set -CONFIG_SPIFFS_PAGE_SIZE=256 -CONFIG_SPIFFS_OBJ_NAME_LEN=32 -# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set -CONFIG_SPIFFS_USE_MAGIC=y -CONFIG_SPIFFS_USE_MAGIC_LENGTH=y -CONFIG_SPIFFS_META_LENGTH=4 -CONFIG_SPIFFS_USE_MTIME=y - -# -# Debug Configuration -# -# CONFIG_SPIFFS_DBG is not set -# CONFIG_SPIFFS_API_DBG is not set -# CONFIG_SPIFFS_GC_DBG is not set -# CONFIG_SPIFFS_CACHE_DBG is not set -# CONFIG_SPIFFS_CHECK_DBG is not set -# CONFIG_SPIFFS_TEST_VISUALISATION is not set -# end of Debug Configuration -# end of SPIFFS Configuration - -# -# TCP Transport -# - -# -# Websocket -# -CONFIG_WS_TRANSPORT=y -CONFIG_WS_BUFFER_SIZE=1024 -# end of Websocket -# end of TCP Transport - -# -# TinyUSB Stack -# -# CONFIG_TINYUSB is not set -# end of TinyUSB Stack - -# -# Unity unit testing library -# -CONFIG_UNITY_ENABLE_FLOAT=y -CONFIG_UNITY_ENABLE_DOUBLE=y -# CONFIG_UNITY_ENABLE_64BIT is not set -# CONFIG_UNITY_ENABLE_COLOR is not set -CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y -# CONFIG_UNITY_ENABLE_FIXTURE is not set -# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set -# end of Unity unit testing library - -# -# USB-OTG -# -CONFIG_USB_OTG_SUPPORTED=y -CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 -CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y -# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set -# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set -# end of USB-OTG - -# -# Virtual file system -# -CONFIG_VFS_SUPPORT_IO=y -CONFIG_VFS_SUPPORT_DIR=y -CONFIG_VFS_SUPPORT_SELECT=y -CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y -CONFIG_VFS_SUPPORT_TERMIOS=y - -# -# Host File System I/O (Semihosting) -# -CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 -# end of Host File System I/O (Semihosting) -# end of Virtual file system - -# -# Wear Levelling -# -# CONFIG_WL_SECTOR_SIZE_512 is not set -CONFIG_WL_SECTOR_SIZE_4096=y -CONFIG_WL_SECTOR_SIZE=4096 -# end of Wear Levelling - -# -# Wi-Fi Provisioning Manager -# -CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 -CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 -CONFIG_WIFI_PROV_BLE_BONDING=y -CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION=y -# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set -# end of Wi-Fi Provisioning Manager - -# -# Supplicant -# -CONFIG_WPA_MBEDTLS_CRYPTO=y -# CONFIG_WPA_WAPI_PSK is not set -# CONFIG_WPA_SUITE_B_192 is not set -# CONFIG_WPA_DEBUG_PRINT is not set -# CONFIG_WPA_TESTING_OPTIONS is not set -# CONFIG_WPA_WPS_STRICT is not set -# CONFIG_WPA_11KV_SUPPORT is not set -# CONFIG_WPA_MBO_SUPPORT is not set -# CONFIG_WPA_DPP_SUPPORT is not set -# end of Supplicant - -# -# LittleFS -# -CONFIG_LITTLEFS_MAX_PARTITIONS=3 -CONFIG_LITTLEFS_PAGE_SIZE=256 -CONFIG_LITTLEFS_OBJ_NAME_LEN=64 -CONFIG_LITTLEFS_READ_SIZE=128 -CONFIG_LITTLEFS_WRITE_SIZE=128 -CONFIG_LITTLEFS_LOOKAHEAD_SIZE=128 -CONFIG_LITTLEFS_CACHE_SIZE=512 -CONFIG_LITTLEFS_BLOCK_CYCLES=512 -CONFIG_LITTLEFS_USE_MTIME=y -# CONFIG_LITTLEFS_USE_ONLY_HASH is not set -# CONFIG_LITTLEFS_HUMAN_READABLE is not set -CONFIG_LITTLEFS_MTIME_USE_SECONDS=y -# CONFIG_LITTLEFS_MTIME_USE_NONCE is not set -# CONFIG_LITTLEFS_SPIFFS_COMPAT is not set -# CONFIG_LITTLEFS_FLUSH_FILE_EVERY_WRITE is not set -# end of LittleFS -# end of Component config - -# -# Compatibility options -# -# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set -# end of Compatibility options - -# Deprecated options for backward compatibility -CONFIG_TOOLPREFIX="xtensa-esp32s3-elf-" -# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set -CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y -# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set -CONFIG_LOG_BOOTLOADER_LEVEL=3 -# CONFIG_APP_ROLLBACK_ENABLE is not set -# CONFIG_FLASH_ENCRYPTION_ENABLED is not set -# CONFIG_FLASHMODE_QIO is not set -# CONFIG_FLASHMODE_QOUT is not set -CONFIG_FLASHMODE_DIO=y -# CONFIG_FLASHMODE_DOUT is not set -# CONFIG_MONITOR_BAUD_9600B is not set -# CONFIG_MONITOR_BAUD_57600B is not set -CONFIG_MONITOR_BAUD_115200B=y -# CONFIG_MONITOR_BAUD_230400B is not set -# CONFIG_MONITOR_BAUD_921600B is not set -# CONFIG_MONITOR_BAUD_2MB is not set -# CONFIG_MONITOR_BAUD_OTHER is not set -CONFIG_MONITOR_BAUD_OTHER_VAL=115200 -CONFIG_MONITOR_BAUD=115200 -CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y -# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set -CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y -# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set -CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 -CONFIG_CXX_EXCEPTIONS=y -CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -CONFIG_STACK_CHECK_NONE=y -# CONFIG_STACK_CHECK_NORM is not set -# CONFIG_STACK_CHECK_STRONG is not set -# CONFIG_STACK_CHECK_ALL is not set -# CONFIG_WARN_WRITE_STRINGS is not set -# CONFIG_DISABLE_GCC8_WARNINGS is not set -# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set -CONFIG_ESP32_APPTRACE_DEST_NONE=y -CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y -CONFIG_BLUEDROID_ENABLED=y -# CONFIG_NIMBLE_ENABLED is not set -CONFIG_BTC_TASK_STACK_SIZE=4096 -CONFIG_BLUEDROID_PINNED_TO_CORE_0=y -# CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set -CONFIG_BLUEDROID_PINNED_TO_CORE=0 -CONFIG_BTU_TASK_STACK_SIZE=4096 -# CONFIG_BLUEDROID_MEM_DEBUG is not set -CONFIG_GATTS_ENABLE=y -# CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set -CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y -CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 -CONFIG_GATTC_ENABLE=y -# CONFIG_GATTC_CACHE_NVS_FLASH is not set -CONFIG_BLE_SMP_ENABLE=y -# CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set -# CONFIG_HCI_TRACE_LEVEL_NONE is not set -# CONFIG_HCI_TRACE_LEVEL_ERROR is not set -CONFIG_HCI_TRACE_LEVEL_WARNING=y -# CONFIG_HCI_TRACE_LEVEL_API is not set -# CONFIG_HCI_TRACE_LEVEL_EVENT is not set -# CONFIG_HCI_TRACE_LEVEL_DEBUG is not set -# CONFIG_HCI_TRACE_LEVEL_VERBOSE is not set -CONFIG_HCI_INITIAL_TRACE_LEVEL=2 -# CONFIG_BTM_TRACE_LEVEL_NONE is not set -# CONFIG_BTM_TRACE_LEVEL_ERROR is not set -CONFIG_BTM_TRACE_LEVEL_WARNING=y -# CONFIG_BTM_TRACE_LEVEL_API is not set -# CONFIG_BTM_TRACE_LEVEL_EVENT is not set -# CONFIG_BTM_TRACE_LEVEL_DEBUG is not set -# CONFIG_BTM_TRACE_LEVEL_VERBOSE is not set -CONFIG_BTM_INITIAL_TRACE_LEVEL=2 -# CONFIG_L2CAP_TRACE_LEVEL_NONE is not set -# CONFIG_L2CAP_TRACE_LEVEL_ERROR is not set -CONFIG_L2CAP_TRACE_LEVEL_WARNING=y -# CONFIG_L2CAP_TRACE_LEVEL_API is not set -# CONFIG_L2CAP_TRACE_LEVEL_EVENT is not set -# CONFIG_L2CAP_TRACE_LEVEL_DEBUG is not set -# CONFIG_L2CAP_TRACE_LEVEL_VERBOSE is not set -CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2 -# CONFIG_RFCOMM_TRACE_LEVEL_NONE is not set -# CONFIG_RFCOMM_TRACE_LEVEL_ERROR is not set -CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y -# CONFIG_RFCOMM_TRACE_LEVEL_API is not set -# CONFIG_RFCOMM_TRACE_LEVEL_EVENT is not set -# CONFIG_RFCOMM_TRACE_LEVEL_DEBUG is not set -# CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE is not set -CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2 -# CONFIG_SDP_TRACE_LEVEL_NONE is not set -# CONFIG_SDP_TRACE_LEVEL_ERROR is not set -CONFIG_SDP_TRACE_LEVEL_WARNING=y -# CONFIG_SDP_TRACE_LEVEL_API is not set -# CONFIG_SDP_TRACE_LEVEL_EVENT is not set -# CONFIG_SDP_TRACE_LEVEL_DEBUG is not set -# CONFIG_SDP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BTH_LOG_SDP_INITIAL_TRACE_LEVEL=2 -# CONFIG_GAP_TRACE_LEVEL_NONE is not set -# CONFIG_GAP_TRACE_LEVEL_ERROR is not set -CONFIG_GAP_TRACE_LEVEL_WARNING=y -# CONFIG_GAP_TRACE_LEVEL_API is not set -# CONFIG_GAP_TRACE_LEVEL_EVENT is not set -# CONFIG_GAP_TRACE_LEVEL_DEBUG is not set -# CONFIG_GAP_TRACE_LEVEL_VERBOSE is not set -CONFIG_GAP_INITIAL_TRACE_LEVEL=2 -CONFIG_BNEP_INITIAL_TRACE_LEVEL=2 -# CONFIG_PAN_TRACE_LEVEL_NONE is not set -# CONFIG_PAN_TRACE_LEVEL_ERROR is not set -CONFIG_PAN_TRACE_LEVEL_WARNING=y -# CONFIG_PAN_TRACE_LEVEL_API is not set -# CONFIG_PAN_TRACE_LEVEL_EVENT is not set -# CONFIG_PAN_TRACE_LEVEL_DEBUG is not set -# CONFIG_PAN_TRACE_LEVEL_VERBOSE is not set -CONFIG_PAN_INITIAL_TRACE_LEVEL=2 -# CONFIG_A2D_TRACE_LEVEL_NONE is not set -# CONFIG_A2D_TRACE_LEVEL_ERROR is not set -CONFIG_A2D_TRACE_LEVEL_WARNING=y -# CONFIG_A2D_TRACE_LEVEL_API is not set -# CONFIG_A2D_TRACE_LEVEL_EVENT is not set -# CONFIG_A2D_TRACE_LEVEL_DEBUG is not set -# CONFIG_A2D_TRACE_LEVEL_VERBOSE is not set -CONFIG_A2D_INITIAL_TRACE_LEVEL=2 -# CONFIG_AVDT_TRACE_LEVEL_NONE is not set -# CONFIG_AVDT_TRACE_LEVEL_ERROR is not set -CONFIG_AVDT_TRACE_LEVEL_WARNING=y -# CONFIG_AVDT_TRACE_LEVEL_API is not set -# CONFIG_AVDT_TRACE_LEVEL_EVENT is not set -# CONFIG_AVDT_TRACE_LEVEL_DEBUG is not set -# CONFIG_AVDT_TRACE_LEVEL_VERBOSE is not set -CONFIG_AVDT_INITIAL_TRACE_LEVEL=2 -# CONFIG_AVCT_TRACE_LEVEL_NONE is not set -# CONFIG_AVCT_TRACE_LEVEL_ERROR is not set -CONFIG_AVCT_TRACE_LEVEL_WARNING=y -# CONFIG_AVCT_TRACE_LEVEL_API is not set -# CONFIG_AVCT_TRACE_LEVEL_EVENT is not set -# CONFIG_AVCT_TRACE_LEVEL_DEBUG is not set -# CONFIG_AVCT_TRACE_LEVEL_VERBOSE is not set -CONFIG_AVCT_INITIAL_TRACE_LEVEL=2 -# CONFIG_AVRC_TRACE_LEVEL_NONE is not set -# CONFIG_AVRC_TRACE_LEVEL_ERROR is not set -CONFIG_AVRC_TRACE_LEVEL_WARNING=y -# CONFIG_AVRC_TRACE_LEVEL_API is not set -# CONFIG_AVRC_TRACE_LEVEL_EVENT is not set -# CONFIG_AVRC_TRACE_LEVEL_DEBUG is not set -# CONFIG_AVRC_TRACE_LEVEL_VERBOSE is not set -CONFIG_AVRC_INITIAL_TRACE_LEVEL=2 -# CONFIG_MCA_TRACE_LEVEL_NONE is not set -# CONFIG_MCA_TRACE_LEVEL_ERROR is not set -CONFIG_MCA_TRACE_LEVEL_WARNING=y -# CONFIG_MCA_TRACE_LEVEL_API is not set -# CONFIG_MCA_TRACE_LEVEL_EVENT is not set -# CONFIG_MCA_TRACE_LEVEL_DEBUG is not set -# CONFIG_MCA_TRACE_LEVEL_VERBOSE is not set -CONFIG_MCA_INITIAL_TRACE_LEVEL=2 -# CONFIG_HID_TRACE_LEVEL_NONE is not set -# CONFIG_HID_TRACE_LEVEL_ERROR is not set -CONFIG_HID_TRACE_LEVEL_WARNING=y -# CONFIG_HID_TRACE_LEVEL_API is not set -# CONFIG_HID_TRACE_LEVEL_EVENT is not set -# CONFIG_HID_TRACE_LEVEL_DEBUG is not set -# CONFIG_HID_TRACE_LEVEL_VERBOSE is not set -CONFIG_HID_INITIAL_TRACE_LEVEL=2 -# CONFIG_APPL_TRACE_LEVEL_NONE is not set -# CONFIG_APPL_TRACE_LEVEL_ERROR is not set -CONFIG_APPL_TRACE_LEVEL_WARNING=y -# CONFIG_APPL_TRACE_LEVEL_API is not set -# CONFIG_APPL_TRACE_LEVEL_EVENT is not set -# CONFIG_APPL_TRACE_LEVEL_DEBUG is not set -# CONFIG_APPL_TRACE_LEVEL_VERBOSE is not set -CONFIG_APPL_INITIAL_TRACE_LEVEL=2 -# CONFIG_GATT_TRACE_LEVEL_NONE is not set -# CONFIG_GATT_TRACE_LEVEL_ERROR is not set -CONFIG_GATT_TRACE_LEVEL_WARNING=y -# CONFIG_GATT_TRACE_LEVEL_API is not set -# CONFIG_GATT_TRACE_LEVEL_EVENT is not set -# CONFIG_GATT_TRACE_LEVEL_DEBUG is not set -# CONFIG_GATT_TRACE_LEVEL_VERBOSE is not set -CONFIG_GATT_INITIAL_TRACE_LEVEL=2 -# CONFIG_SMP_TRACE_LEVEL_NONE is not set -# CONFIG_SMP_TRACE_LEVEL_ERROR is not set -CONFIG_SMP_TRACE_LEVEL_WARNING=y -# CONFIG_SMP_TRACE_LEVEL_API is not set -# CONFIG_SMP_TRACE_LEVEL_EVENT is not set -# CONFIG_SMP_TRACE_LEVEL_DEBUG is not set -# CONFIG_SMP_TRACE_LEVEL_VERBOSE is not set -CONFIG_SMP_INITIAL_TRACE_LEVEL=2 -# CONFIG_BTIF_TRACE_LEVEL_NONE is not set -# CONFIG_BTIF_TRACE_LEVEL_ERROR is not set -CONFIG_BTIF_TRACE_LEVEL_WARNING=y -# CONFIG_BTIF_TRACE_LEVEL_API is not set -# CONFIG_BTIF_TRACE_LEVEL_EVENT is not set -# CONFIG_BTIF_TRACE_LEVEL_DEBUG is not set -# CONFIG_BTIF_TRACE_LEVEL_VERBOSE is not set -CONFIG_BTIF_INITIAL_TRACE_LEVEL=2 -# CONFIG_BTC_TRACE_LEVEL_NONE is not set -# CONFIG_BTC_TRACE_LEVEL_ERROR is not set -CONFIG_BTC_TRACE_LEVEL_WARNING=y -# CONFIG_BTC_TRACE_LEVEL_API is not set -# CONFIG_BTC_TRACE_LEVEL_EVENT is not set -# CONFIG_BTC_TRACE_LEVEL_DEBUG is not set -# CONFIG_BTC_TRACE_LEVEL_VERBOSE is not set -CONFIG_BTC_INITIAL_TRACE_LEVEL=2 -# CONFIG_OSI_TRACE_LEVEL_NONE is not set -# CONFIG_OSI_TRACE_LEVEL_ERROR is not set -CONFIG_OSI_TRACE_LEVEL_WARNING=y -# CONFIG_OSI_TRACE_LEVEL_API is not set -# CONFIG_OSI_TRACE_LEVEL_EVENT is not set -# CONFIG_OSI_TRACE_LEVEL_DEBUG is not set -# CONFIG_OSI_TRACE_LEVEL_VERBOSE is not set -CONFIG_OSI_INITIAL_TRACE_LEVEL=2 -# CONFIG_BLUFI_TRACE_LEVEL_NONE is not set -# CONFIG_BLUFI_TRACE_LEVEL_ERROR is not set -CONFIG_BLUFI_TRACE_LEVEL_WARNING=y -# CONFIG_BLUFI_TRACE_LEVEL_API is not set -# CONFIG_BLUFI_TRACE_LEVEL_EVENT is not set -# CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set -# CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set -CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 -# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set -CONFIG_SMP_ENABLE=y -CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 -CONFIG_ADC2_DISABLE_DAC=y -# CONFIG_EVENT_LOOP_PROFILING is not set -CONFIG_POST_EVENTS_FROM_ISR=y -CONFIG_POST_EVENTS_FROM_IRAM_ISR=y -CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND=y -CONFIG_IPC_TASK_STACK_SIZE=1536 -CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y -# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set -CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 -CONFIG_ESP32_PHY_MAX_TX_POWER=20 -CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y -# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set -CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y -# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set -# CONFIG_ESP32S2_PANIC_GDBSTUB is not set -CONFIG_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP=y -CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 -CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 -CONFIG_MAIN_TASK_STACK_SIZE=3584 -CONFIG_CONSOLE_UART_DEFAULT=y -# CONFIG_CONSOLE_UART_CUSTOM is not set -# CONFIG_ESP_CONSOLE_UART_NONE is not set -CONFIG_CONSOLE_UART=y -CONFIG_CONSOLE_UART_NUM=0 -CONFIG_CONSOLE_UART_BAUDRATE=115200 -CONFIG_INT_WDT=y -CONFIG_INT_WDT_TIMEOUT_MS=300 -CONFIG_INT_WDT_CHECK_CPU1=y -CONFIG_TASK_WDT=y -# CONFIG_TASK_WDT_PANIC is not set -CONFIG_TASK_WDT_TIMEOUT_S=5 -CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y -CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y -# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set -CONFIG_TIMER_TASK_STACK_SIZE=3584 -CONFIG_SW_COEXIST_ENABLE=y -# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set -CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y -CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 -CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 -CONFIG_MB_QUEUE_LENGTH=20 -CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096 -CONFIG_MB_SERIAL_BUF_SIZE=256 -CONFIG_MB_SERIAL_TASK_PRIO=10 -CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y -CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233 -CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 -CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 -CONFIG_MB_CONTROLLER_STACK_SIZE=4096 -CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 -# CONFIG_MB_TIMER_PORT_ENABLED is not set -CONFIG_MB_TIMER_GROUP=0 -CONFIG_MB_TIMER_INDEX=0 -# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set -CONFIG_TIMER_TASK_PRIORITY=1 -CONFIG_TIMER_TASK_STACK_DEPTH=2048 -CONFIG_TIMER_QUEUE_LENGTH=10 -# CONFIG_L2_TO_L3_COPY is not set -# CONFIG_USE_ONLY_LWIP_SELECT is not set -CONFIG_ESP_GRATUITOUS_ARP=y -CONFIG_GARP_TMR_INTERVAL=60 -CONFIG_TCPIP_RECVMBOX_SIZE=32 -CONFIG_TCP_MAXRTX=12 -CONFIG_TCP_SYNMAXRTX=12 -CONFIG_TCP_MSS=1440 -CONFIG_TCP_MSL=60000 -CONFIG_TCP_SND_BUF_DEFAULT=5744 -CONFIG_TCP_WND_DEFAULT=5744 -CONFIG_TCP_RECVMBOX_SIZE=6 -CONFIG_TCP_QUEUE_OOSEQ=y -# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set -CONFIG_TCP_OVERSIZE_MSS=y -# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set -# CONFIG_TCP_OVERSIZE_DISABLE is not set -CONFIG_UDP_RECVMBOX_SIZE=6 -CONFIG_TCPIP_TASK_STACK_SIZE=3072 -CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y -# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set -# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set -CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF -# CONFIG_PPP_SUPPORT is not set -CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 -CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 -CONFIG_ESP32_PTHREAD_STACK_MIN=768 -CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y -# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set -# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set -CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 -CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" -CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y -# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set -# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set -# CONFIG_USB_ENABLED is not set -CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y -CONFIG_SUPPORT_TERMIOS=y -CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 -# End of deprecated options From eb9d20334ef7aad1864f66d26464942be824e3fa Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 25 Dec 2023 00:58:58 +0100 Subject: [PATCH 02/41] fixes for esp32 --- targets/esp32/main/EspPlayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp index 90621bc1..608e3be6 100644 --- a/targets/esp32/main/EspPlayer.cpp +++ b/targets/esp32/main/EspPlayer.cpp @@ -109,7 +109,7 @@ void EspPlayer::runTask() { this->isPaused = true; } - //this->audioSink->feedPCMFrames(outBuf.data(), read); + this->audioSink->feedPCMFrames(outBuf.data(), read); if (read == 0) { if (this->playlistEnd) { From 84e298ae911dfa0aae224956b46bfa6a843ba03c Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 26 Dec 2023 00:12:05 +0100 Subject: [PATCH 03/41] reuploaded sdkconfig.defaults --- targets/esp32/sdkconfig.defaults | 1987 ++++++++++++++++++++++++++++++ 1 file changed, 1987 insertions(+) create mode 100644 targets/esp32/sdkconfig.defaults diff --git a/targets/esp32/sdkconfig.defaults b/targets/esp32/sdkconfig.defaults new file mode 100644 index 00000000..2bd5878a --- /dev/null +++ b/targets/esp32/sdkconfig.defaults @@ -0,0 +1,1987 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_TARGET_ESP32=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_SUPPORTS_RSA=y +CONFIG_SECURE_TARGET_HAS_SECURE_ROM_DL_MODE=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_CONSOLE is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# ESP-ASIO +# +# CONFIG_ASIO_SSL_SUPPORT is not set +# end of ESP-ASIO + +# +# Bluetooth +# +CONFIG_BT_ENABLED=y +CONFIG_BT_SOC_SUPPORT_5_0=y + +# +# Bluetooth controller +# +CONFIG_BT_CTRL_MODE_EFF=1 +CONFIG_BT_CTRL_BLE_MAX_ACT=10 +CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=10 +CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 +CONFIG_BT_CTRL_PINNED_TO_CORE_0=y +# CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set +CONFIG_BT_CTRL_PINNED_TO_CORE=0 +CONFIG_BT_CTRL_HCI_MODE_VHCI=y +# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set +CONFIG_BT_CTRL_HCI_TL=1 +CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30 +# CONFIG_BT_CTRL_HW_CCA is not set +CONFIG_BT_CTRL_HW_CCA_VAL=20 +CONFIG_BT_CTRL_HW_CCA_EFF=0 +CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y +# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set +# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set +CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0 +CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y +# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set +CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0 +CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y +# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set +CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0 +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3=y +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=9 +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 +CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 +CONFIG_BT_CTRL_BLE_SCAN_DUPL=y +CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE=y +# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA is not set +# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE is not set +CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0 +CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100 +# CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN is not set +# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0 + +# +# MODEM SLEEP Options +# +# CONFIG_BT_CTRL_MODEM_SLEEP is not set +# end of MODEM SLEEP Options + +CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 +CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 +CONFIG_BT_CTRL_HCI_TL_EFF=1 +# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set +# end of Bluetooth controller + +CONFIG_BT_BLUEDROID_ENABLED=y +# CONFIG_BT_NIMBLE_ENABLED is not set +# CONFIG_BT_CONTROLLER_ONLY is not set + +# +# Bluedroid Options +# +CONFIG_BT_BTC_TASK_STACK_SIZE=4096 +CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y +# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set +CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BT_BTU_TASK_STACK_SIZE=4096 +# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set +CONFIG_BT_BLE_ENABLED=y +CONFIG_BT_GATTS_ENABLE=y +# CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set +# CONFIG_BT_BLE_BLUFI_ENABLE is not set +CONFIG_BT_GATT_MAX_SR_PROFILES=8 +# CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 +CONFIG_BT_GATTC_ENABLE=y +# CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set +CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 +CONFIG_BT_BLE_SMP_ENABLE=y +# CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set +# CONFIG_BT_STACK_NO_LOG is not set + +# +# BT DEBUG LOG LEVEL +# +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_HCI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_HCI_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTM_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTM_TRACE_LEVEL=2 +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_L2CAP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL=2 +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_SDP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_SDP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_GAP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_GAP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BNEP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BNEP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_PAN_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_PAN_TRACE_LEVEL=2 +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_A2D_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_A2D_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVDT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVDT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVCT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVCT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVRC_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVRC_TRACE_LEVEL=2 +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_MCA_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_MCA_TRACE_LEVEL=2 +# CONFIG_BT_LOG_HID_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_HID_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_HID_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_HID_TRACE_LEVEL=2 +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_APPL_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_APPL_TRACE_LEVEL=2 +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_GATT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_GATT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_SMP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_SMP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTIF_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTIF_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTC_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTC_TRACE_LEVEL=2 +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_OSI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_OSI_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BLUFI_TRACE_LEVEL=2 +# end of BT DEBUG LOG LEVEL + +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_MULTI_CONNECTION_ENBALE=y +# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set +# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set +# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set +CONFIG_BT_SMP_ENABLE=y +CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 +CONFIG_BT_MAX_DEVICE_NAME_LEN=32 +CONFIG_BT_BLE_RPA_SUPPORTED=y +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# end of Bluedroid Options +# end of Bluetooth + +# CONFIG_BLE_MESH is not set + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# MCPWM configuration +# +# CONFIG_MCPWM_ISR_IN_IRAM is not set +# end of MCPWM configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# TWAI configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# end of TWAI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# GDMA Configuration +# +# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +CONFIG_ESP_TLS_INSECURE=y +CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y +# end of ESP-TLS + +# +# ESP32-specific +# +CONFIG_ESP32_REV_MIN_0=y +# CONFIG_ESP32_REV_MIN_1 is not set +# CONFIG_ESP32_REV_MIN_2 is not set +# CONFIG_ESP32_REV_MIN_3 is not set +CONFIG_ESP32_REV_MIN=0 +CONFIG_ESP32_DPORT_WORKAROUND=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_ESP32_SPIRAM_SUPPORT=y + +# +# SPI RAM config +# +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_SIZE=-1 +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +# CONFIG_SPIRAM_USE_MEMMAP is not set +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256 +# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536 +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CACHE_WORKAROUND=y + +# +# SPIRAM cache workaround debugging +# +CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW=y +# CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST is not set +# CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_NOPS is not set +# end of SPIRAM cache workaround debugging + +CONFIG_SPIRAM_BANKSWITCH_ENABLE=y +CONFIG_SPIRAM_BANKSWITCH_RESERVE=8 +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +# CONFIG_SPIRAM_OCCUPY_HSPI_HOST is not set +CONFIG_SPIRAM_OCCUPY_VSPI_HOST=y +# CONFIG_SPIRAM_OCCUPY_NO_HOST is not set + +# +# PSRAM clock and cs IO for ESP32-DOWD +# +CONFIG_D0WD_PSRAM_CLK_IO=17 +CONFIG_D0WD_PSRAM_CS_IO=16 +# end of PSRAM clock and cs IO for ESP32-DOWD + +# +# PSRAM clock and cs IO for ESP32-D2WD +# +CONFIG_D2WD_PSRAM_CLK_IO=9 +CONFIG_D2WD_PSRAM_CS_IO=10 +# end of PSRAM clock and cs IO for ESP32-D2WD + +# +# PSRAM clock and cs IO for ESP32-PICO +# +CONFIG_PICO_PSRAM_CS_IO=10 +# end of PSRAM clock and cs IO for ESP32-PICO + +# CONFIG_SPIRAM_2T_MODE is not set +# end of SPI RAM config + +# CONFIG_ESP32_TRAX is not set +CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32_ULP_COPROC_ENABLED is not set +CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_BROWNOUT_DET=y +CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_ESP32_BROWNOUT_DET_LVL=0 +CONFIG_ESP32_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40=y +# CONFIG_ESP32_XTAL_FREQ_26 is not set +# CONFIG_ESP32_XTAL_FREQ_AUTO is not set +CONFIG_ESP32_XTAL_FREQ=40 +# CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +# CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set +CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 +# end of ESP32-specific + +# +# ADC-Calibration +# +# end of ADC-Calibration + + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_TX_GPIO=1 +CONFIG_ESP_CONSOLE_UART_RX_GPIO=3 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=800 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT_OFFSET=2 +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +CONFIG_HTTPD_WS_SUPPORT=y +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB=y +# end of RTC Clock Config +# end of Hardware Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# LCD and Touch Panel +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# PHY +# +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +CONFIG_ESP_PHY_ENABLE_USB=y +# end of PHY + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_MULTIPLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=12 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=40 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=12 +CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +# CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED is not set +# CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED is not set +# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +# CONFIG_ESP32_WIFI_IRAM_OPT is not set +# CONFIG_ESP32_WIFI_RX_IRAM_OPT is not set +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +# CONFIG_FATFS_LFN_NONE is not set +CONFIG_FATFS_LFN_HEAP=y +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_MAX_LFN=255 +# CONFIG_FATFS_API_ENCODING_ANSI_OEM is not set +# CONFIG_FATFS_API_ENCODING_UTF_16 is not set +CONFIG_FATFS_API_ENCODING_UTF_8=y +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y +# CONFIG_FATFS_USE_FASTSEEK is not set +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_TCP_EN=y +CONFIG_FMB_TCP_PORT_DEFAULT=502 +CONFIG_FMB_TCP_PORT_MAX_CONN=5 +CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_PORT_TASK_STACK_SIZE=4096 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_PORT_TASK_PRIO=10 +# CONFIG_FMB_PORT_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_FMB_PORT_TASK_AFFINITY_CPU0=y +# CONFIG_FMB_PORT_TASK_AFFINITY_CPU1 is not set +CONFIG_FMB_PORT_TASK_AFFINITY=0x0 +CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_FMB_TIMER_PORT_ENABLED is not set +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +CONFIG_FMB_MASTER_TIMER_GROUP=0 +CONFIG_FMB_MASTER_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration + +# +# FreeRTOS +# +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="fuji" +CONFIG_LWIP_NETIF_API=y +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=16 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +# CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC is not set +CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +CONFIG_MBEDTLS_DEBUG=y +# CONFIG_MBEDTLS_DEBUG_LEVEL_WARN is not set +# CONFIG_MBEDTLS_DEBUG_LEVEL_INFO is not set +# CONFIG_MBEDTLS_DEBUG_LEVEL_DEBUG is not set +CONFIG_MBEDTLS_DEBUG_LEVEL_VERBOSE=y +CONFIG_MBEDTLS_DEBUG_LEVEL=4 + +# +# mbedTLS v2.28.x related +# +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT=y +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# end of mbedTLS v2.28.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +CONFIG_MBEDTLS_ECP_RESTARTABLE=y +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +CONFIG_MBEDTLS_PSK_MODES=y +# CONFIG_MBEDTLS_KEY_EXCHANGE_PSK is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_X509_CHECK_KEY_USAGE=y +CONFIG_MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +# CONFIG_MDNS_STRICT_MODE is not set +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ERROR_STACK=y +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set +# end of OpenThread + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# end of Websocket +# end of TCP Transport + +# +# TinyUSB Stack +# +# CONFIG_TINYUSB is not set +# end of TinyUSB Stack + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_OTG_SUPPORTED=y +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_BLE_BONDING=y +CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION=y +# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# end of Supplicant + +# +# LittleFS +# +CONFIG_LITTLEFS_MAX_PARTITIONS=3 +CONFIG_LITTLEFS_PAGE_SIZE=256 +CONFIG_LITTLEFS_OBJ_NAME_LEN=64 +CONFIG_LITTLEFS_READ_SIZE=128 +CONFIG_LITTLEFS_WRITE_SIZE=128 +CONFIG_LITTLEFS_LOOKAHEAD_SIZE=128 +CONFIG_LITTLEFS_CACHE_SIZE=512 +CONFIG_LITTLEFS_BLOCK_CYCLES=512 +CONFIG_LITTLEFS_USE_MTIME=y +# CONFIG_LITTLEFS_USE_ONLY_HASH is not set +# CONFIG_LITTLEFS_HUMAN_READABLE is not set +CONFIG_LITTLEFS_MTIME_USE_SECONDS=y +# CONFIG_LITTLEFS_MTIME_USE_NONCE is not set +# CONFIG_LITTLEFS_SPIFFS_COMPAT is not set +# CONFIG_LITTLEFS_FLUSH_FILE_EVERY_WRITE is not set +# end of LittleFS +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32s3-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +CONFIG_CXX_EXCEPTIONS=y +CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_BLUEDROID_ENABLED=y +# CONFIG_NIMBLE_ENABLED is not set +CONFIG_BTC_TASK_STACK_SIZE=4096 +CONFIG_BLUEDROID_PINNED_TO_CORE_0=y +# CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set +CONFIG_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BTU_TASK_STACK_SIZE=4096 +# CONFIG_BLUEDROID_MEM_DEBUG is not set +CONFIG_GATTS_ENABLE=y +# CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set +CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 +CONFIG_GATTC_ENABLE=y +# CONFIG_GATTC_CACHE_NVS_FLASH is not set +CONFIG_BLE_SMP_ENABLE=y +# CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set +# CONFIG_HCI_TRACE_LEVEL_NONE is not set +# CONFIG_HCI_TRACE_LEVEL_ERROR is not set +CONFIG_HCI_TRACE_LEVEL_WARNING=y +# CONFIG_HCI_TRACE_LEVEL_API is not set +# CONFIG_HCI_TRACE_LEVEL_EVENT is not set +# CONFIG_HCI_TRACE_LEVEL_DEBUG is not set +# CONFIG_HCI_TRACE_LEVEL_VERBOSE is not set +CONFIG_HCI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTM_TRACE_LEVEL_NONE is not set +# CONFIG_BTM_TRACE_LEVEL_ERROR is not set +CONFIG_BTM_TRACE_LEVEL_WARNING=y +# CONFIG_BTM_TRACE_LEVEL_API is not set +# CONFIG_BTM_TRACE_LEVEL_EVENT is not set +# CONFIG_BTM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTM_INITIAL_TRACE_LEVEL=2 +# CONFIG_L2CAP_TRACE_LEVEL_NONE is not set +# CONFIG_L2CAP_TRACE_LEVEL_ERROR is not set +CONFIG_L2CAP_TRACE_LEVEL_WARNING=y +# CONFIG_L2CAP_TRACE_LEVEL_API is not set +# CONFIG_L2CAP_TRACE_LEVEL_EVENT is not set +# CONFIG_L2CAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_L2CAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2 +# CONFIG_RFCOMM_TRACE_LEVEL_NONE is not set +# CONFIG_RFCOMM_TRACE_LEVEL_ERROR is not set +CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y +# CONFIG_RFCOMM_TRACE_LEVEL_API is not set +# CONFIG_RFCOMM_TRACE_LEVEL_EVENT is not set +# CONFIG_RFCOMM_TRACE_LEVEL_DEBUG is not set +# CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE is not set +CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2 +# CONFIG_SDP_TRACE_LEVEL_NONE is not set +# CONFIG_SDP_TRACE_LEVEL_ERROR is not set +CONFIG_SDP_TRACE_LEVEL_WARNING=y +# CONFIG_SDP_TRACE_LEVEL_API is not set +# CONFIG_SDP_TRACE_LEVEL_EVENT is not set +# CONFIG_SDP_TRACE_LEVEL_DEBUG is not set +# CONFIG_SDP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTH_LOG_SDP_INITIAL_TRACE_LEVEL=2 +# CONFIG_GAP_TRACE_LEVEL_NONE is not set +# CONFIG_GAP_TRACE_LEVEL_ERROR is not set +CONFIG_GAP_TRACE_LEVEL_WARNING=y +# CONFIG_GAP_TRACE_LEVEL_API is not set +# CONFIG_GAP_TRACE_LEVEL_EVENT is not set +# CONFIG_GAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_GAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_GAP_INITIAL_TRACE_LEVEL=2 +CONFIG_BNEP_INITIAL_TRACE_LEVEL=2 +# CONFIG_PAN_TRACE_LEVEL_NONE is not set +# CONFIG_PAN_TRACE_LEVEL_ERROR is not set +CONFIG_PAN_TRACE_LEVEL_WARNING=y +# CONFIG_PAN_TRACE_LEVEL_API is not set +# CONFIG_PAN_TRACE_LEVEL_EVENT is not set +# CONFIG_PAN_TRACE_LEVEL_DEBUG is not set +# CONFIG_PAN_TRACE_LEVEL_VERBOSE is not set +CONFIG_PAN_INITIAL_TRACE_LEVEL=2 +# CONFIG_A2D_TRACE_LEVEL_NONE is not set +# CONFIG_A2D_TRACE_LEVEL_ERROR is not set +CONFIG_A2D_TRACE_LEVEL_WARNING=y +# CONFIG_A2D_TRACE_LEVEL_API is not set +# CONFIG_A2D_TRACE_LEVEL_EVENT is not set +# CONFIG_A2D_TRACE_LEVEL_DEBUG is not set +# CONFIG_A2D_TRACE_LEVEL_VERBOSE is not set +CONFIG_A2D_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVDT_TRACE_LEVEL_NONE is not set +# CONFIG_AVDT_TRACE_LEVEL_ERROR is not set +CONFIG_AVDT_TRACE_LEVEL_WARNING=y +# CONFIG_AVDT_TRACE_LEVEL_API is not set +# CONFIG_AVDT_TRACE_LEVEL_EVENT is not set +# CONFIG_AVDT_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVDT_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVDT_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVCT_TRACE_LEVEL_NONE is not set +# CONFIG_AVCT_TRACE_LEVEL_ERROR is not set +CONFIG_AVCT_TRACE_LEVEL_WARNING=y +# CONFIG_AVCT_TRACE_LEVEL_API is not set +# CONFIG_AVCT_TRACE_LEVEL_EVENT is not set +# CONFIG_AVCT_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVCT_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVCT_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVRC_TRACE_LEVEL_NONE is not set +# CONFIG_AVRC_TRACE_LEVEL_ERROR is not set +CONFIG_AVRC_TRACE_LEVEL_WARNING=y +# CONFIG_AVRC_TRACE_LEVEL_API is not set +# CONFIG_AVRC_TRACE_LEVEL_EVENT is not set +# CONFIG_AVRC_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVRC_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVRC_INITIAL_TRACE_LEVEL=2 +# CONFIG_MCA_TRACE_LEVEL_NONE is not set +# CONFIG_MCA_TRACE_LEVEL_ERROR is not set +CONFIG_MCA_TRACE_LEVEL_WARNING=y +# CONFIG_MCA_TRACE_LEVEL_API is not set +# CONFIG_MCA_TRACE_LEVEL_EVENT is not set +# CONFIG_MCA_TRACE_LEVEL_DEBUG is not set +# CONFIG_MCA_TRACE_LEVEL_VERBOSE is not set +CONFIG_MCA_INITIAL_TRACE_LEVEL=2 +# CONFIG_HID_TRACE_LEVEL_NONE is not set +# CONFIG_HID_TRACE_LEVEL_ERROR is not set +CONFIG_HID_TRACE_LEVEL_WARNING=y +# CONFIG_HID_TRACE_LEVEL_API is not set +# CONFIG_HID_TRACE_LEVEL_EVENT is not set +# CONFIG_HID_TRACE_LEVEL_DEBUG is not set +# CONFIG_HID_TRACE_LEVEL_VERBOSE is not set +CONFIG_HID_INITIAL_TRACE_LEVEL=2 +# CONFIG_APPL_TRACE_LEVEL_NONE is not set +# CONFIG_APPL_TRACE_LEVEL_ERROR is not set +CONFIG_APPL_TRACE_LEVEL_WARNING=y +# CONFIG_APPL_TRACE_LEVEL_API is not set +# CONFIG_APPL_TRACE_LEVEL_EVENT is not set +# CONFIG_APPL_TRACE_LEVEL_DEBUG is not set +# CONFIG_APPL_TRACE_LEVEL_VERBOSE is not set +CONFIG_APPL_INITIAL_TRACE_LEVEL=2 +# CONFIG_GATT_TRACE_LEVEL_NONE is not set +# CONFIG_GATT_TRACE_LEVEL_ERROR is not set +CONFIG_GATT_TRACE_LEVEL_WARNING=y +# CONFIG_GATT_TRACE_LEVEL_API is not set +# CONFIG_GATT_TRACE_LEVEL_EVENT is not set +# CONFIG_GATT_TRACE_LEVEL_DEBUG is not set +# CONFIG_GATT_TRACE_LEVEL_VERBOSE is not set +CONFIG_GATT_INITIAL_TRACE_LEVEL=2 +# CONFIG_SMP_TRACE_LEVEL_NONE is not set +# CONFIG_SMP_TRACE_LEVEL_ERROR is not set +CONFIG_SMP_TRACE_LEVEL_WARNING=y +# CONFIG_SMP_TRACE_LEVEL_API is not set +# CONFIG_SMP_TRACE_LEVEL_EVENT is not set +# CONFIG_SMP_TRACE_LEVEL_DEBUG is not set +# CONFIG_SMP_TRACE_LEVEL_VERBOSE is not set +CONFIG_SMP_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTIF_TRACE_LEVEL_NONE is not set +# CONFIG_BTIF_TRACE_LEVEL_ERROR is not set +CONFIG_BTIF_TRACE_LEVEL_WARNING=y +# CONFIG_BTIF_TRACE_LEVEL_API is not set +# CONFIG_BTIF_TRACE_LEVEL_EVENT is not set +# CONFIG_BTIF_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTIF_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTIF_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTC_TRACE_LEVEL_NONE is not set +# CONFIG_BTC_TRACE_LEVEL_ERROR is not set +CONFIG_BTC_TRACE_LEVEL_WARNING=y +# CONFIG_BTC_TRACE_LEVEL_API is not set +# CONFIG_BTC_TRACE_LEVEL_EVENT is not set +# CONFIG_BTC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTC_INITIAL_TRACE_LEVEL=2 +# CONFIG_OSI_TRACE_LEVEL_NONE is not set +# CONFIG_OSI_TRACE_LEVEL_ERROR is not set +CONFIG_OSI_TRACE_LEVEL_WARNING=y +# CONFIG_OSI_TRACE_LEVEL_API is not set +# CONFIG_OSI_TRACE_LEVEL_EVENT is not set +# CONFIG_OSI_TRACE_LEVEL_DEBUG is not set +# CONFIG_OSI_TRACE_LEVEL_VERBOSE is not set +CONFIG_OSI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BLUFI_TRACE_LEVEL_NONE is not set +# CONFIG_BLUFI_TRACE_LEVEL_ERROR is not set +CONFIG_BLUFI_TRACE_LEVEL_WARNING=y +# CONFIG_BLUFI_TRACE_LEVEL_API is not set +# CONFIG_BLUFI_TRACE_LEVEL_EVENT is not set +# CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set +CONFIG_SMP_ENABLE=y +CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_SW_COEXIST_ENABLE=y +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_MB_TIMER_PORT_ENABLED is not set +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +# CONFIG_USB_ENABLED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options From 1354a287575b88c466c95f9b745af5e2a286cce4 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Wed, 10 Jul 2024 13:31:46 +0200 Subject: [PATCH 04/41] added gzip compatible mercury decoder (failed if message were trucated) - updated from main-branch --- cspot/bell | 2 +- cspot/include/MercurySession.h | 8 ++-- cspot/protobuf/mercury.options | 3 ++ cspot/protobuf/mercury.proto | 8 ++++ cspot/src/MercurySession.cpp | 81 +++++++++++++++++++++------------- 5 files changed, 65 insertions(+), 37 deletions(-) diff --git a/cspot/bell b/cspot/bell index e8373736..33612f42 160000 --- a/cspot/bell +++ b/cspot/bell @@ -1 +1 @@ -Subproject commit e83737367a08b5a5a1f652a7ecb97a0d926929dd +Subproject commit 33612f425489c552a71fddb175581049e4a75af1 diff --git a/cspot/include/MercurySession.h b/cspot/include/MercurySession.h index 91f05f58..5296c11f 100644 --- a/cspot/include/MercurySession.h +++ b/cspot/include/MercurySession.h @@ -26,12 +26,9 @@ class MercurySession : public bell::Task, public cspot::Session { struct Response { Header mercuryHeader; - uint8_t flags; DataParts parts; - uint64_t sequenceId; bool fail; }; - typedef std::function ResponseCallback; typedef std::function&)> AudioKeyCallback; @@ -111,7 +108,8 @@ class MercurySession : public bell::Task, public cspot::Session { void runTask() override; void reconnect(); - std::unordered_map callbacks; + std::unordered_map callbacks; + std::unordered_map partials; std::unordered_map subscriptions; std::unordered_map audioKeyCallbacks; @@ -129,6 +127,6 @@ class MercurySession : public bell::Task, public cspot::Session { void failAllPending(); - Response decodeResponse(const std::vector& data); + std::pair decodeResponse(const std::vector& data); }; } // namespace cspot diff --git a/cspot/protobuf/mercury.options b/cspot/protobuf/mercury.options index e7c7718b..d0fb231b 100644 --- a/cspot/protobuf/mercury.options +++ b/cspot/protobuf/mercury.options @@ -1,2 +1,5 @@ Header.uri max_size:256, fixed_length:false Header.method max_size:64, fixed_length:false +UserField.key type:FT_POINTER +UserField.value type:FT_POINTER +Header.user_fields max_count:64, fixed_count:false \ No newline at end of file diff --git a/cspot/protobuf/mercury.proto b/cspot/protobuf/mercury.proto index 72138948..cd754d2d 100644 --- a/cspot/protobuf/mercury.proto +++ b/cspot/protobuf/mercury.proto @@ -1,4 +1,12 @@ message Header { optional string uri = 0x01; + optional string content_type = 0x02; optional string method = 0x03; + optional int32 status_code = 0x04; + repeated UserField user_fields = 0x06; } + +message UserField { + optional string key = 0x01; + optional string value = 0x02; +} \ No newline at end of file diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index 7aafbb76..d28ecce0 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -174,19 +174,25 @@ void MercurySession::handlePacket() { CSPOT_LOG(debug, "Received mercury packet"); auto response = this->decodeResponse(packet.data); - if (this->callbacks.count(response.sequenceId) > 0) { - auto seqId = response.sequenceId; - this->callbacks[response.sequenceId](response); - this->callbacks.erase(this->callbacks.find(seqId)); + if(response.first == 1){ + auto partial = this->partials.find(response.second); + if(this->callbacks.count(response.second)){ + this->callbacks[response.second](partial->second); + this->callbacks.erase(this->callbacks.find(response.second)); + } + this->partials.erase(partial); } break; } case RequestType::SUBRES: { auto response = decodeResponse(packet.data); - auto uri = std::string(response.mercuryHeader.uri); - if (this->subscriptions.count(uri) > 0) { - this->subscriptions[uri](response); + if(response.first){ + auto partial = this->partials.find(response.second); + auto uri = std::string(partial->second.mercuryHeader.uri); + if (this->subscriptions.count(uri) > 0) { + this->subscriptions[uri](partial->second); + } } break; } @@ -214,33 +220,46 @@ void MercurySession::failAllPending() { this->callbacks = {}; } -MercurySession::Response MercurySession::decodeResponse( +std::pair MercurySession::decodeResponse( const std::vector& data) { - Response response = {}; - response.parts = {}; - - auto sequenceLength = ntohs(extract(data, 0)); - response.sequenceId = hton64(extract(data, 2)); - - auto partsNumber = ntohs(extract(data, 11)); - - auto headerSize = ntohs(extract(data, 13)); - auto headerBytes = - std::vector(data.begin() + 15, data.begin() + 15 + headerSize); - - auto pos = 15 + headerSize; - while (pos < data.size()) { + auto sequenceLength = ntohs(extract(data, 0)); + int64_t sequenceId; uint8_t flag; + if(sequenceLength == 2) sequenceId = ntohs(extract(data, 2)); + else if(sequenceLength == 4) sequenceId = ntohl(extract(data, 2)); + else if(sequenceLength == 8) sequenceId = hton64(extract(data, 2)); + else return std::make_pair(0,0); + size_t pos = 2 + sequenceLength; + flag = (uint8_t)data[pos]; + pos++; + auto parts = ntohs(extract(data, pos)); + pos+= 2; + auto partial = partials.find(sequenceId); + if (partial==partials.end()) { + CSPOT_LOG(debug, "Creating new Mercury Response, seq: %lld, flags: %i, parts: %i\n", sequenceId, flag, parts); + partial = this->partials.insert({sequenceId,Response()}).first; + partial->second.parts = {}; + partial->second.fail = false; + } else CSPOT_LOG(debug, "Adding to Mercury Response, seq: %lld, flags: %i, parts: %i\n", sequenceId, flag, parts); + uint8_t index = 0; + while(parts){ + if(data.size() <= pos || partial->second.fail) break; auto partSize = ntohs(extract(data, pos)); - - response.parts.push_back(std::vector( - data.begin() + pos + 2, data.begin() + pos + 2 + partSize)); - pos += 2 + partSize; + pos += 2; + if(!partial->second.mercuryHeader.has_uri){ + partial->second.fail = false; + auto headerBytes = + std::vector(data.begin() + pos, data.begin() + pos + partSize); + pbDecode(partial->second.mercuryHeader, Header_fields, headerBytes); + } + else{ + if( index >= partial->second.parts.size() ) partial->second.parts.push_back(std::vector{}); + partial->second.parts[index].insert(partial->second.parts[index].end(),data.begin() + pos, data.begin() + pos + partSize); + index++; + } + pos += partSize; + parts--; } - - pbDecode(response.mercuryHeader, Header_fields, headerBytes); - response.fail = false; - - return response; + return std::make_pair(flag, sequenceId); } uint64_t MercurySession::executeSubscription(RequestType method, From 5edbb8d18564e189578dfc614bf01ad4783d46e4 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Thu, 11 Jul 2024 09:44:43 +0200 Subject: [PATCH 05/41] reporting trough event-manager, so the played songs will pop up in the listening history --- cspot/include/CSpotContext.h | 3 + cspot/include/SpircHandler.h | 7 +-- cspot/include/TrackPlayer.h | 22 ++++++- cspot/include/TrackQueue.h | 5 +- cspot/src/PlaybackState.cpp | 6 ++ cspot/src/SpircHandler.cpp | 6 +- cspot/src/TrackPlayer.cpp | 107 +++++++++++++++++++++++++++++++---- 7 files changed, 138 insertions(+), 18 deletions(-) diff --git a/cspot/include/CSpotContext.h b/cspot/include/CSpotContext.h index d4fdde84..be20940d 100644 --- a/cspot/include/CSpotContext.h +++ b/cspot/include/CSpotContext.h @@ -4,6 +4,7 @@ #include #include "Crypto.h" +#include "EventManager.h" #include "LoginBlob.h" #include "MercurySession.h" #include "TimeProvider.h" @@ -35,6 +36,7 @@ struct Context { std::shared_ptr timeProvider; std::shared_ptr session; + std::shared_ptr playbackMetrics; std::string getCredentialsJson() { #ifdef BELL_ONLY_CJSON cJSON* json_obj = cJSON_CreateObject(); @@ -68,6 +70,7 @@ struct Context { ctx->timeProvider = std::make_shared(); ctx->session = std::make_shared(ctx->timeProvider); + ctx->playbackMetrics = std::make_shared(ctx); ctx->config.deviceId = blob->getDeviceId(); ctx->config.deviceName = blob->getDeviceName(); ctx->config.authData = blob->authData; diff --git a/cspot/include/SpircHandler.h b/cspot/include/SpircHandler.h index 7d558cd8..3464450f 100644 --- a/cspot/include/SpircHandler.h +++ b/cspot/include/SpircHandler.h @@ -58,18 +58,17 @@ class SpircHandler { void setRemoteVolume(int volume); void loadTrackFromURI(const std::string& uri); std::shared_ptr getTrackQueue() { return trackQueue; } + std::shared_ptr trackPlayer; + std::shared_ptr trackQueue; + std::shared_ptr playbackState; void disconnect(); private: std::shared_ptr ctx; - std::shared_ptr trackPlayer; - std::shared_ptr trackQueue; EventHandler eventHandler = nullptr; - std::shared_ptr playbackState; - void sendCmd(MessageType typ); void sendEvent(EventType type); diff --git a/cspot/include/TrackPlayer.h b/cspot/include/TrackPlayer.h index 1577c476..ccc3eb1d 100644 --- a/cspot/include/TrackPlayer.h +++ b/cspot/include/TrackPlayer.h @@ -17,11 +17,13 @@ namespace bell { class WrappedSemaphore; } // namespace bell +#ifndef CONFIG_BELL_NOCODEC #ifdef BELL_VORBIS_FLOAT #include "vorbis/vorbisfile.h" #else #include "ivorbisfile.h" // for OggVorbis_File, ov_callbacks #endif +#endif namespace cspot { class TrackProvider; @@ -34,9 +36,16 @@ class TrackPlayer : bell::Task { // Callback types typedef std::function, bool)> TrackLoadedCallback; - typedef std::function + typedef std::function DataCallback; typedef std::function EOFCallback; + typedef std::function SeekableCallback; + TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, @@ -45,17 +54,19 @@ class TrackPlayer : bell::Task { void loadTrackFromRef(TrackReference& ref, size_t playbackMs, bool startAutomatically); - void setDataCallback(DataCallback callback); + void setDataCallback(DataCallback callback, SeekableCallback seekable_callback = nullptr, SeekableCallback spaces_available = nullptr); // CDNTrackStream::TrackInfo getCurrentTrackInfo(); void seekMs(size_t ms); void resetState(bool paused = false); +#ifndef CONFIG_BELL_NOCODEC // Vorbis codec callbacks size_t _vorbisRead(void* ptr, size_t size, size_t nmemb); size_t _vorbisClose(); int _vorbisSeek(int64_t offset, int whence); long _vorbisTell(); +#endif void stop(); void start(); @@ -70,16 +81,23 @@ class TrackPlayer : bell::Task { TrackLoadedCallback trackLoaded; DataCallback dataCallback = nullptr; EOFCallback eofCallback; +#ifdef CONFIG_BELL_NOCODEC + SeekableCallback spaces_available = nullptr; + SeekableCallback seekable_callback; + size_t seekable_offset; +#endif // Playback control std::atomic currentSongPlaying; std::mutex playbackMutex; std::mutex dataOutMutex; +#ifndef CONFIG_BELL_NOCODEC // Vorbis related OggVorbis_File vorbisFile; ov_callbacks vorbisCallbacks; int currentSection; +#endif std::vector pcmBuffer = std::vector(1024); diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 8e2f0c37..ca95d553 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -8,6 +8,7 @@ #include "BellTask.h" #include "PlaybackState.h" +#include "EventManager.h" // for TrackMetrics #include "TrackReference.h" #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode @@ -53,9 +54,11 @@ class QueuedTrack { TrackInfo trackInfo; // Full track information fetched from spotify, name etc uint32_t requestedPosition; + uint64_t written_bytes = 0; std::string identifier; bool loading = false; - + std::shared_ptr trackMetrics; + // Will return nullptr if the track is not ready std::shared_ptr getAudioFile(); diff --git a/cspot/src/PlaybackState.cpp b/cspot/src/PlaybackState.cpp index 72697c2f..cfc9636b 100644 --- a/cspot/src/PlaybackState.cpp +++ b/cspot/src/PlaybackState.cpp @@ -118,6 +118,12 @@ void PlaybackState::syncWithRemote() { innerFrame.state.has_playing_track_index = true; innerFrame.state.playing_track_index = remoteFrame.state.playing_track_index; + innerFrame.state.has_shuffle = remoteFrame.state.has_shuffle;; + innerFrame.state.shuffle = remoteFrame.state.shuffle; + innerFrame.state.has_repeat = remoteFrame.state.has_repeat; + innerFrame.state.repeat = remoteFrame.state.repeat; + innerFrame.state.has_index = true; + innerFrame.state.index = remoteFrame.state.index; } bool PlaybackState::isActive() { diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index 8d8add6a..f12134d5 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -127,6 +127,7 @@ void SpircHandler::handleFrame(std::vector& data) { // Decode received spirc frame playbackState->decodeRemoteFrame(data); + std::string influence = "unknown"; switch (playbackState->remoteFrame.typ) { case MessageType_kMessageTypeNotify: { CSPOT_LOG(debug, "Notify frame"); @@ -136,7 +137,8 @@ void SpircHandler::handleFrame(std::vector& data) { playbackState->remoteFrame.device_state.is_active) { CSPOT_LOG(debug, "Another player took control, pausing playback"); playbackState->setActive(false); - + ctx->playbackMetrics->end_reason = PlaybackMetrics::REMOTE; + ctx->playbackMetrics->end_source = influence; this->trackPlayer->stop(); sendEvent(EventType::DISC); } @@ -166,11 +168,13 @@ void SpircHandler::handleFrame(std::vector& data) { case MessageType_kMessageTypeNext: if (nextSong()) { sendEvent(EventType::NEXT); + ctx->playbackMetrics->end_reason = PlaybackMetrics::FORWARD_BTN; } break; case MessageType_kMessageTypePrev: if (previousSong()) { sendEvent(EventType::PREV); + ctx->playbackMetrics->end_reason = PlaybackMetrics::BACKWARD_BTN; } break; case MessageType_kMessageTypeLoad: { diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index c96f2ec7..eeb7ec9e 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -11,7 +11,9 @@ #include "Packet.h" // for cspot #include "TrackQueue.h" // for CDNTrackStream, CDNTrackStream::TrackInfo #include "WrappedSemaphore.h" // for WrappedSemaphore +#include "CSpotContext.h" +#ifndef CONFIG_BELL_NOCODEC #ifdef BELL_VORBIS_FLOAT #define VORBIS_SEEK(file, position) \ (ov_time_seek(file, (double)position / 1000)) @@ -22,14 +24,17 @@ #define VORBIS_READ(file, buffer, bufferSize, section) \ (ov_read(file, buffer, bufferSize, section)) #endif +#endif namespace cspot { struct Context; struct TrackReference; +class PlaybackMetrics; } // namespace cspot using namespace cspot; +#ifndef CONFIG_BELL_NOCODEC static size_t vorbisReadCb(void* ptr, size_t size, size_t nmemb, TrackPlayer* self) { return self->_vorbisRead(ptr, size, nmemb); @@ -47,6 +52,7 @@ static int vorbisSeekCb(TrackPlayer* self, int64_t offset, int whence) { static long vorbisTellCb(TrackPlayer* self) { return self->_vorbisTell(); } +#endif TrackPlayer::TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, @@ -58,6 +64,7 @@ TrackPlayer::TrackPlayer(std::shared_ptr ctx, this->trackQueue = trackQueue; this->playbackSemaphore = std::make_unique(5); +#ifndef CONFIG_BELL_NOCODEC // Initialize vorbis callbacks vorbisFile = {}; vorbisCallbacks = { @@ -66,6 +73,7 @@ TrackPlayer::TrackPlayer(std::shared_ptr ctx, (decltype(ov_callbacks::close_func))&vorbisCloseCb, (decltype(ov_callbacks::tell_func))&vorbisTellCb, }; +#endif } TrackPlayer::~TrackPlayer() { @@ -78,7 +86,10 @@ void TrackPlayer::start() { if (!isRunning) { isRunning = true; startTask(); + this->ctx->playbackMetrics->start_reason = PlaybackMetrics::REMOTE; + this->ctx->playbackMetrics->start_source = "unknown"; } + else this->ctx->playbackMetrics->end_reason = PlaybackMetrics::END_PLAY; } void TrackPlayer::stop() { @@ -99,10 +110,12 @@ void TrackPlayer::resetState(bool paused) { } void TrackPlayer::seekMs(size_t ms) { +#ifndef CONFIG_BELL_NOCODEC if (inFuture) { // We're in the middle of the next track, so we need to reset the player in order to seek resetState(); } +#endif CSPOT_LOG(info, "Seeking..."); this->pendingSeekPositionMs = ms; @@ -111,7 +124,7 @@ void TrackPlayer::seekMs(size_t ms) { void TrackPlayer::runTask() { std::scoped_lock lock(runningMutex); - std::shared_ptr track, newTrack = nullptr; + std::shared_ptr track= nullptr, newTrack = nullptr; int trackOffset = 0; bool eof = false; @@ -155,6 +168,8 @@ void TrackPlayer::runTask() { } track = newTrack; + track->trackMetrics = std::make_shared(this->ctx); + this->ctx->playbackMetrics->trackMetrics = track->trackMetrics; inFuture = trackOffset > 0; @@ -174,9 +189,12 @@ void TrackPlayer::runTask() { { std::scoped_lock lock(playbackMutex); + bool skipped = 0; currentTrackStream = track->getAudioFile(); + track->trackMetrics->startTrackDecoding(); + // Open the stream currentTrackStream->openStream(); @@ -184,6 +202,7 @@ void TrackPlayer::runTask() { continue; } +#ifndef CONFIG_BELL_NOCODEC if (trackOffset == 0 && pendingSeekPositionMs == 0) { this->trackLoaded(track, startPaused); startPaused = false; @@ -191,17 +210,52 @@ void TrackPlayer::runTask() { int32_t r = ov_open_callbacks(this, &vorbisFile, NULL, 0, vorbisCallbacks); - +#else + size_t start_offset = 0; + size_t write_offset = 0; + while (!start_offset) { + size_t ret = this->currentTrackStream->readBytes(&pcmBuffer[0], pcmBuffer.size()); + size_t written = 0; + size_t toWrite = ret; + while (toWrite) { + written = dataCallback(pcmBuffer.data() + (ret - toWrite), + toWrite, track->identifier, 0); + if (written == 0) { + BELL_SLEEP_MS(1000); + } + toWrite -= written; + } + track->written_bytes += ret; + start_offset = seekable_callback(track->identifier); + if(this->spaces_available(track->identifier)trackMetrics->track_size = currentTrackStream->getSize(); + float duration_lambda = 1.0 * (currentTrackStream->getSize() - start_offset) / track->trackInfo.duration; +#endif if (pendingSeekPositionMs > 0) { track->requestedPosition = pendingSeekPositionMs; +#ifdef CONFIG_BELL_NOCODEC + pendingSeekPositionMs = 0; +#endif } if (track->requestedPosition > 0) { +#ifndef CONFIG_BELL_NOCODEC VORBIS_SEEK(&vorbisFile, track->requestedPosition); +#else + size_t seekPosition = track->requestedPosition * duration_lambda + start_offset; + currentTrackStream->seek(seekPosition); + skipped = true; +#endif } eof = false; track->loading = true; + track->trackMetrics->startTrack(track->requestedPosition); CSPOT_LOG(info, "Playing"); @@ -210,15 +264,28 @@ void TrackPlayer::runTask() { if (pendingSeekPositionMs > 0) { uint32_t seekPosition = pendingSeekPositionMs; - // Reset the pending seek position - pendingSeekPositionMs = 0; - // Seek to the new position +#ifndef CONFIG_BELL_NOCODEC VORBIS_SEEK(&vorbisFile, seekPosition); +#else + seekPosition = seekPosition * duration_lambda + start_offset; + currentTrackStream->seek(seekPosition); + track->trackMetrics->newPosition(pendingSeekPositionMs); + skipped = true; +#endif + + // Reset the pending seek position + pendingSeekPositionMs = 0; } - long ret = VORBIS_READ(&vorbisFile, (char*)&pcmBuffer[0], - pcmBuffer.size(), ¤tSection); + + long ret = +#ifdef CONFIG_BELL_NOCODEC + this->currentTrackStream->readBytes(&pcmBuffer[0], pcmBuffer.size()); +#else + VORBIS_READ(&vorbisFile, (char*)&pcmBuffer[0], + pcmBuffer.size(), ¤tSection); +#endif if (ret == 0) { CSPOT_LOG(info, "EOF"); @@ -238,25 +305,39 @@ void TrackPlayer::runTask() { // If reset happened during playback, return if (!currentSongPlaying || pendingReset) break; - +#ifdef CONFIG_BELL_NOCODEC + if (skipped) { + // Reset the pending seek position + skipped = 0; + } +#endif written = dataCallback(pcmBuffer.data() + (ret - toWrite), - toWrite, track->identifier); + toWrite, track->identifier + #ifdef CONFIG_BELL_NOCODEC + ,skipped + #endif + ); } if (written == 0) { BELL_SLEEP_MS(50); } toWrite -= written; } + track->written_bytes += ret; } } } +#ifndef CONFIG_BELL_NOCODEC ov_clear(&vorbisFile); +#endif CSPOT_LOG(info, "Playing done"); // always move back to LOADING (ensure proper seeking after last track has been loaded) currentTrackStream = nullptr; track->loading = false; + track->trackMetrics->endTrack(); + std::vector result = this->ctx->playbackMetrics->sendEvent(track); } if (eof) { @@ -269,6 +350,7 @@ void TrackPlayer::runTask() { } } +#ifndef CONFIG_BELL_NOCODEC size_t TrackPlayer::_vorbisRead(void* ptr, size_t size, size_t nmemb) { if (this->currentTrackStream == nullptr) { return 0; @@ -307,7 +389,12 @@ long TrackPlayer::_vorbisTell() { } return this->currentTrackStream->getPosition(); } +#endif -void TrackPlayer::setDataCallback(DataCallback callback) { +void TrackPlayer::setDataCallback(DataCallback callback, SeekableCallback seekable_callback, SeekableCallback spaces_available ) { this->dataCallback = callback; + #ifdef CONFIG_BELL_NOCODEC + this->seekable_callback = seekable_callback; + this->spaces_available = spaces_available; + #endif } From a450f3be4bf4ba850fe09d84568c5ae7e19760d1 Mon Sep 17 00:00:00 2001 From: Filip Date: Fri, 12 Jul 2024 13:56:03 +0200 Subject: [PATCH 06/41] fix: clang-format --- cspot/src/MercurySession.cpp | 60 ++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index d28ecce0..1976dc60 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -174,9 +174,9 @@ void MercurySession::handlePacket() { CSPOT_LOG(debug, "Received mercury packet"); auto response = this->decodeResponse(packet.data); - if(response.first == 1){ + if (response.first == 1) { auto partial = this->partials.find(response.second); - if(this->callbacks.count(response.second)){ + if (this->callbacks.count(response.second)) { this->callbacks[response.second](partial->second); this->callbacks.erase(this->callbacks.find(response.second)); } @@ -187,7 +187,7 @@ void MercurySession::handlePacket() { case RequestType::SUBRES: { auto response = decodeResponse(packet.data); - if(response.first){ + if (response.first) { auto partial = this->partials.find(response.second); auto uri = std::string(partial->second.mercuryHeader.uri); if (this->subscriptions.count(uri) > 0) { @@ -222,38 +222,52 @@ void MercurySession::failAllPending() { std::pair MercurySession::decodeResponse( const std::vector& data) { - auto sequenceLength = ntohs(extract(data, 0)); - int64_t sequenceId; uint8_t flag; - if(sequenceLength == 2) sequenceId = ntohs(extract(data, 2)); - else if(sequenceLength == 4) sequenceId = ntohl(extract(data, 2)); - else if(sequenceLength == 8) sequenceId = hton64(extract(data, 2)); - else return std::make_pair(0,0); + auto sequenceLength = ntohs(extract(data, 0)); + int64_t sequenceId; + uint8_t flag; + if (sequenceLength == 2) + sequenceId = ntohs(extract(data, 2)); + else if (sequenceLength == 4) + sequenceId = ntohl(extract(data, 2)); + else if (sequenceLength == 8) + sequenceId = hton64(extract(data, 2)); + else + return std::make_pair(0, 0); size_t pos = 2 + sequenceLength; flag = (uint8_t)data[pos]; pos++; auto parts = ntohs(extract(data, pos)); - pos+= 2; + pos += 2; auto partial = partials.find(sequenceId); - if (partial==partials.end()) { - CSPOT_LOG(debug, "Creating new Mercury Response, seq: %lld, flags: %i, parts: %i\n", sequenceId, flag, parts); - partial = this->partials.insert({sequenceId,Response()}).first; + if (partial == partials.end()) { + CSPOT_LOG( + debug, + "Creating new Mercury Response, seq: %lld, flags: %i, parts: %i\n", + sequenceId, flag, parts); + partial = this->partials.insert({sequenceId, Response()}).first; partial->second.parts = {}; partial->second.fail = false; - } else CSPOT_LOG(debug, "Adding to Mercury Response, seq: %lld, flags: %i, parts: %i\n", sequenceId, flag, parts); + } else + CSPOT_LOG(debug, + "Adding to Mercury Response, seq: %lld, flags: %i, parts: %i\n", + sequenceId, flag, parts); uint8_t index = 0; - while(parts){ - if(data.size() <= pos || partial->second.fail) break; + while (parts) { + if (data.size() <= pos || partial->second.fail) + break; auto partSize = ntohs(extract(data, pos)); pos += 2; - if(!partial->second.mercuryHeader.has_uri){ + if (!partial->second.mercuryHeader.has_uri) { partial->second.fail = false; - auto headerBytes = - std::vector(data.begin() + pos, data.begin() + pos + partSize); + auto headerBytes = std::vector(data.begin() + pos, + data.begin() + pos + partSize); pbDecode(partial->second.mercuryHeader, Header_fields, headerBytes); - } - else{ - if( index >= partial->second.parts.size() ) partial->second.parts.push_back(std::vector{}); - partial->second.parts[index].insert(partial->second.parts[index].end(),data.begin() + pos, data.begin() + pos + partSize); + } else { + if (index >= partial->second.parts.size()) + partial->second.parts.push_back(std::vector{}); + partial->second.parts[index].insert(partial->second.parts[index].end(), + data.begin() + pos, + data.begin() + pos + partSize); index++; } pos += partSize; From aca2a2c8a39ab059d502b3ac030f4b65ca190bf6 Mon Sep 17 00:00:00 2001 From: Filip Date: Fri, 12 Jul 2024 14:17:57 +0200 Subject: [PATCH 07/41] fix: Minor style fixes --- cspot/include/MercurySession.h | 5 ++ cspot/src/MercurySession.cpp | 20 ++--- targets/cli/CliPlayer.cpp | 2 - targets/esp32/main/EspPlayer.cpp | 145 +++++++++++++++---------------- 4 files changed, 85 insertions(+), 87 deletions(-) diff --git a/cspot/include/MercurySession.h b/cspot/include/MercurySession.h index 5296c11f..de53dd2a 100644 --- a/cspot/include/MercurySession.h +++ b/cspot/include/MercurySession.h @@ -51,6 +51,11 @@ class MercurySession : public bell::Task, public cspot::Session { COUNTRY_CODE_RESPONSE = 0x1B, }; + enum class ResponseFlag : uint8_t { + FINAL = 0x01, + PARTIAL = 0x02, + }; + std::unordered_map RequestTypeMap = { {RequestType::GET, "GET"}, {RequestType::SEND, "SEND"}, diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index 1976dc60..ddcc466d 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -174,7 +174,7 @@ void MercurySession::handlePacket() { CSPOT_LOG(debug, "Received mercury packet"); auto response = this->decodeResponse(packet.data); - if (response.first == 1) { + if (response.first == static_cast(ResponseFlag::FINAL)) { auto partial = this->partials.find(response.second); if (this->callbacks.count(response.second)) { this->callbacks[response.second](partial->second); @@ -223,16 +223,17 @@ void MercurySession::failAllPending() { std::pair MercurySession::decodeResponse( const std::vector& data) { auto sequenceLength = ntohs(extract(data, 0)); - int64_t sequenceId; + uint64_t sequenceId; uint8_t flag; if (sequenceLength == 2) - sequenceId = ntohs(extract(data, 2)); + sequenceId = ntohs(extract(data, 2)); else if (sequenceLength == 4) - sequenceId = ntohl(extract(data, 2)); + sequenceId = ntohl(extract(data, 2)); else if (sequenceLength == 8) - sequenceId = hton64(extract(data, 2)); + sequenceId = hton64(extract(data, 2)); else return std::make_pair(0, 0); + size_t pos = 2 + sequenceLength; flag = (uint8_t)data[pos]; pos++; @@ -240,16 +241,15 @@ std::pair MercurySession::decodeResponse( pos += 2; auto partial = partials.find(sequenceId); if (partial == partials.end()) { - CSPOT_LOG( - debug, - "Creating new Mercury Response, seq: %lld, flags: %i, parts: %i\n", - sequenceId, flag, parts); + CSPOT_LOG(debug, + "Creating new Mercury Response, seq: %llu, flags: %i, parts: %i", + sequenceId, flag, parts); partial = this->partials.insert({sequenceId, Response()}).first; partial->second.parts = {}; partial->second.fail = false; } else CSPOT_LOG(debug, - "Adding to Mercury Response, seq: %lld, flags: %i, parts: %i\n", + "Adding to Mercury Response, seq: %llu, flags: %i, parts: %i", sequenceId, flag, parts); uint8_t index = 0; while (parts) { diff --git a/targets/cli/CliPlayer.cpp b/targets/cli/CliPlayer.cpp index 1642c4ec..69cbfba7 100644 --- a/targets/cli/CliPlayer.cpp +++ b/targets/cli/CliPlayer.cpp @@ -118,8 +118,6 @@ void CliPlayer::runTask() { continue; } else { if (lastHash != chunk->trackHash) { - std::cout << " Last hash " << lastHash << " new hash " - << chunk->trackHash << std::endl; lastHash = chunk->trackHash; this->handler->notifyAudioReachedPlayback(); } diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp index 608e3be6..0d7ed823 100644 --- a/targets/esp32/main/EspPlayer.cpp +++ b/targets/esp32/main/EspPlayer.cpp @@ -11,7 +11,7 @@ #include // for get #include // for vector -#include "BellUtils.h" // for BELL_SLEEP_MS +#include "BellUtils.h" // for BELL_SLEEP_MS #include "CircularBuffer.h" #include "Logger.h" #include "SpircHandler.h" // for SpircHandler, SpircHandler::EventType @@ -24,73 +24,71 @@ EspPlayer::EspPlayer(std::unique_ptr sink, this->handler = handler; this->audioSink = std::move(sink); - this->circularBuffer = - std::make_shared(1024 * 128); + this->circularBuffer = std::make_shared(1024 * 128); auto hashFunc = std::hash(); - this->handler->getTrackPlayer()->setDataCallback( + this->handler->getTrackPlayer()->setDataCallback( [this, &hashFunc](uint8_t* data, size_t bytes, std::string_view trackId) { auto hash = hashFunc(trackId); this->feedData(data, bytes, hash); return bytes; - } - ); - + }); + this->isPaused = false; this->handler->setEventHandler( - [this, &hashFunc](std::unique_ptr event) { + [this, &hashFunc](std::unique_ptr event) { switch (event->eventType) { - case cspot::SpircHandler::EventType::PLAY_PAUSE: - if (std::get(event->data)) { - this->pauseRequested = true; - } else { - this->isPaused = false; - this->pauseRequested = false; - } - break; - case cspot::SpircHandler::EventType::DISC: - this->circularBuffer->emptyBuffer(); - break; - case cspot::SpircHandler::EventType::FLUSH: - this->circularBuffer->emptyBuffer(); - break; - case cspot::SpircHandler::EventType::SEEK: - this->circularBuffer->emptyBuffer(); - break; - case cspot::SpircHandler::EventType::PLAYBACK_START: - this->isPaused = true; - this->playlistEnd = false; - this->circularBuffer->emptyBuffer(); - break; - case cspot::SpircHandler::EventType::DEPLETED: - this->playlistEnd = true; - break; - case cspot::SpircHandler::EventType::VOLUME: { - int volume = std::get(event->data); - break; + case cspot::SpircHandler::EventType::PLAY_PAUSE: + if (std::get(event->data)) { + this->pauseRequested = true; + } else { + this->isPaused = false; + this->pauseRequested = false; } - default: - break; - } - }); + break; + case cspot::SpircHandler::EventType::DISC: + this->circularBuffer->emptyBuffer(); + break; + case cspot::SpircHandler::EventType::FLUSH: + this->circularBuffer->emptyBuffer(); + break; + case cspot::SpircHandler::EventType::SEEK: + this->circularBuffer->emptyBuffer(); + break; + case cspot::SpircHandler::EventType::PLAYBACK_START: + this->isPaused = true; + this->playlistEnd = false; + this->circularBuffer->emptyBuffer(); + break; + case cspot::SpircHandler::EventType::DEPLETED: + this->playlistEnd = true; + break; + case cspot::SpircHandler::EventType::VOLUME: { + int volume = std::get(event->data); + break; + } + default: + break; + } + }); startTask(); } void EspPlayer::feedData(uint8_t* data, size_t len, size_t trackId) { - size_t toWrite = len; - - while (toWrite > 0) { - this->current_hash = trackId; - size_t written = - this->circularBuffer->write(data + (len - toWrite), toWrite); - if (written == 0) { - BELL_SLEEP_MS(10); - } - - toWrite -= written; + size_t toWrite = len; + + while (toWrite > 0) { + this->current_hash = trackId; + size_t written = + this->circularBuffer->write(data + (len - toWrite), toWrite); + if (written == 0) { + BELL_SLEEP_MS(10); } + + toWrite -= written; + } } void EspPlayer::runTask() { @@ -101,36 +99,33 @@ void EspPlayer::runTask() { size_t lastHash = 0; while (isRunning) { - if (!this->isPaused) { - size_t read = this->circularBuffer->read(outBuf.data(), outBuf.size()); - if (this->pauseRequested) { - this->pauseRequested = false; - std::cout << "Pause requested!" << std::endl; - this->isPaused = true; - } - - this->audioSink->feedPCMFrames(outBuf.data(), read); + if (!this->isPaused) { + size_t read = this->circularBuffer->read(outBuf.data(), outBuf.size()); + if (this->pauseRequested) { + this->pauseRequested = false; + std::cout << "Pause requested!" << std::endl; + this->isPaused = true; + } - if (read == 0) { - if (this->playlistEnd) { - this->handler->notifyAudioEnded(); - this->playlistEnd = false; - } - BELL_SLEEP_MS(10); - continue; - } else { - if (lastHash != current_hash) { - std::cout << " Last hash " << lastHash << " new hash " - << current_hash << std::endl; - lastHash = current_hash; - this->handler->notifyAudioReachedPlayback(); + this->audioSink->feedPCMFrames(outBuf.data(), read); - } + if (read == 0) { + if (this->playlistEnd) { + this->handler->notifyAudioEnded(); + this->playlistEnd = false; } + BELL_SLEEP_MS(10); + continue; } else { - BELL_SLEEP_MS(100); + if (lastHash != current_hash) { + lastHash = current_hash; + this->handler->notifyAudioReachedPlayback(); + } } + } else { + BELL_SLEEP_MS(100); } + } } void EspPlayer::disconnect() { From 7a61b09ae3728b7b85a47bc5b8447ed2c57fa1a3 Mon Sep 17 00:00:00 2001 From: Filip Date: Fri, 12 Jul 2024 14:27:05 +0200 Subject: [PATCH 08/41] fix: clear partials on sub res and reconnect --- cspot/src/MercurySession.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index ddcc466d..4863472a 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -68,6 +68,7 @@ void MercurySession::reconnect() { try { this->conn = nullptr; this->shanConn = nullptr; + this->partials.clear(); this->connectWithRandomAp(); this->authenticate(this->authBlob); @@ -187,12 +188,13 @@ void MercurySession::handlePacket() { case RequestType::SUBRES: { auto response = decodeResponse(packet.data); - if (response.first) { + if (response.first == static_cast(ResponseFlag::FINAL)) { auto partial = this->partials.find(response.second); auto uri = std::string(partial->second.mercuryHeader.uri); if (this->subscriptions.count(uri) > 0) { this->subscriptions[uri](partial->second); } + this->partials.erase(partial); } break; } From 1ea97b4d5931d8207f1f6bfcf95c0128fd3ff91e Mon Sep 17 00:00:00 2001 From: Filip Date: Fri, 12 Jul 2024 14:32:22 +0200 Subject: [PATCH 09/41] fix: Restore bell version --- cspot/bell | 2 +- flake.nix | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/cspot/bell b/cspot/bell index 33612f42..40abf30b 160000 --- a/cspot/bell +++ b/cspot/bell @@ -1 +1 @@ -Subproject commit 33612f425489c552a71fddb175581049e4a75af1 +Subproject commit 40abf30bcd739fc3ad10caa8e2eec7c9b31642f3 diff --git a/flake.nix b/flake.nix index 9c07fb73..59955e12 100644 --- a/flake.nix +++ b/flake.nix @@ -30,15 +30,7 @@ clang-tools = pkgs.clang-tools.override {llvmPackages = llvm;}; - apps = { - }; - - packages = { - target-cli = llvm.stdenv.mkDerivation { - name = "cspotcli"; - src = ./.; - cmakeFlags = ["-DCSPOT_TARGET_CLI=ON"]; - nativeBuildInputs = with pkgs; [ + cspot-pkgs = with pkgs; [ avahi avahi-compat cmake @@ -50,6 +42,16 @@ portaudio protobuf ]; + + apps = { + }; + + packages = { + target-cli = llvm.stdenv.mkDerivation { + name = "cspotcli"; + src = ./.; + cmakeFlags = ["-DCSPOT_TARGET_CLI=ON"]; + nativeBuildInputs = cspot-pkgs; # Patch nanopb shebangs to refer to provided python postPatch = '' patchShebangs cspot/bell/external/nanopb/generator/* @@ -60,7 +62,7 @@ devShells = { default = pkgs.mkShell { - packages = with pkgs; [cmake unstable.mbedtls ninja python3] ++ [clang-tools llvm.clang]; + packages = cspot-pkgs; }; }; in { From 5771aa27cd3f6ec26db71b035107c2e5cf94212a Mon Sep 17 00:00:00 2001 From: Filip Date: Fri, 12 Jul 2024 14:33:43 +0200 Subject: [PATCH 10/41] fix: Update bell --- cspot/bell | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cspot/bell b/cspot/bell index 40abf30b..e8373736 160000 --- a/cspot/bell +++ b/cspot/bell @@ -1 +1 @@ -Subproject commit 40abf30bcd739fc3ad10caa8e2eec7c9b31642f3 +Subproject commit e83737367a08b5a5a1f652a7ecb97a0d926929dd From 34bf9e1a77b69892282e0c639962827aa0ef0ec3 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Thu, 11 Jul 2024 09:44:43 +0200 Subject: [PATCH 11/41] reporting trough event-manager, so the played songs will pop up in the listening history --- cspot/include/CSpotContext.h | 3 + cspot/include/EventManager.h | 126 ++++++++++++++++++++++++++ cspot/include/SpircHandler.h | 7 +- cspot/include/TrackPlayer.h | 22 ++++- cspot/include/TrackQueue.h | 5 +- cspot/src/EventManager.cpp | 168 +++++++++++++++++++++++++++++++++++ cspot/src/PlaybackState.cpp | 6 ++ cspot/src/SpircHandler.cpp | 6 +- cspot/src/TrackPlayer.cpp | 107 +++++++++++++++++++--- 9 files changed, 432 insertions(+), 18 deletions(-) create mode 100644 cspot/include/EventManager.h create mode 100644 cspot/src/EventManager.cpp diff --git a/cspot/include/CSpotContext.h b/cspot/include/CSpotContext.h index d4fdde84..be20940d 100644 --- a/cspot/include/CSpotContext.h +++ b/cspot/include/CSpotContext.h @@ -4,6 +4,7 @@ #include #include "Crypto.h" +#include "EventManager.h" #include "LoginBlob.h" #include "MercurySession.h" #include "TimeProvider.h" @@ -35,6 +36,7 @@ struct Context { std::shared_ptr timeProvider; std::shared_ptr session; + std::shared_ptr playbackMetrics; std::string getCredentialsJson() { #ifdef BELL_ONLY_CJSON cJSON* json_obj = cJSON_CreateObject(); @@ -68,6 +70,7 @@ struct Context { ctx->timeProvider = std::make_shared(); ctx->session = std::make_shared(ctx->timeProvider); + ctx->playbackMetrics = std::make_shared(ctx); ctx->config.deviceId = blob->getDeviceId(); ctx->config.deviceName = blob->getDeviceName(); ctx->config.authData = blob->authData; diff --git a/cspot/include/EventManager.h b/cspot/include/EventManager.h new file mode 100644 index 00000000..14422e16 --- /dev/null +++ b/cspot/include/EventManager.h @@ -0,0 +1,126 @@ +#pragma once + +#include // for uint8_t, uint32_t +#include // for shared_ptr +#include //for sort +#include // for string +#include // for vector + + +namespace cspot { + struct Context; + class QueuedTrack; + + struct TrackInterval { + uint64_t start; + uint64_t end; + uint64_t position; + uint64_t length; + + TrackInterval(); + TrackInterval(uint64_t start, uint64_t position) { + this->start = start; + this->position = position; + } + }; + + struct skip { + uint8_t count = 0; + uint64_t amount = 0; + + void add(uint64_t amount) { + this->amount += amount; + count++; + } + }; + + class TrackMetrics { + public: + + TrackMetrics(std::shared_ptr ctx, uint64_t pos = 0); + + std::shared_ptr currentInterval; + uint64_t longestInterval = 0, totalAmountOfPlayTime = 0, totalMsOfPlayedTrack = 0, + totalAmountPlayed = 0, audioKeyTime = 0, trackHeaderTime = 0, + written_bytes = 0, track_size = 0, timestamp = 0; + std::vector > intervals; + skip skipped_backward, skipped_forward; + + void newPosition(uint64_t pos); + void endInterval(uint64_t pos); + void endTrack(); + void startTrackDecoding(); + void startTrack(uint64_t pos); + uint64_t getPosition(); + + private: + + std::shared_ptr ctx; + std::vector> addInterval(std::vector>& intervals, std::pair newInterval) { + // Add the new interval to the list of intervals + intervals.push_back(newInterval); + + // Sort intervals by starting time + std::sort(intervals.begin(), intervals.end()); + + // Result vector to hold merged intervals + std::vector> merged; + + // Iterate over intervals to merge overlapping ones + for (const auto& interval : intervals) { + // If merged is empty or current interval does not overlap with the previous one + if (merged.empty() || merged.back().second < interval.first) { + merged.push_back(interval); + } + else { + // If it overlaps, merge the intervals + merged.back().second = std::max(merged.back().second, interval.second); + } + } + + return merged; + } + + + }; + class PlaybackMetrics { + private: + + std::shared_ptr ctx; + uint32_t seqNum = 0; + size_t timestamp; + + std::string get_source_from_context(); + std::string get_end_source(); + + void append(std::vector* data, std::string to_do) { + data->insert(data->end(), to_do.begin(), to_do.end()); + data->push_back(9); + } + + public: + + PlaybackMetrics(std::shared_ptr ctx) { + this->ctx = ctx; + } + enum reason { + TRACK_DONE, + TRACK_ERROR, + FORWARD_BTN, + BACKWARD_BTN, + END_PLAY, + PLAY_BTN, + CLICK_ROW, + LOGOUT, + APP_LOAD, + REMOTE, + UNKNOWN + }end_reason = UNKNOWN, start_reason = UNKNOWN, nested_reason = UNKNOWN; + + std::string context_uri, correlation_id, start_source, end_source; + std::shared_ptr trackMetrics; + + std::vector sendEvent(std::shared_ptr track); + + }; +} \ No newline at end of file diff --git a/cspot/include/SpircHandler.h b/cspot/include/SpircHandler.h index 7d558cd8..3464450f 100644 --- a/cspot/include/SpircHandler.h +++ b/cspot/include/SpircHandler.h @@ -58,18 +58,17 @@ class SpircHandler { void setRemoteVolume(int volume); void loadTrackFromURI(const std::string& uri); std::shared_ptr getTrackQueue() { return trackQueue; } + std::shared_ptr trackPlayer; + std::shared_ptr trackQueue; + std::shared_ptr playbackState; void disconnect(); private: std::shared_ptr ctx; - std::shared_ptr trackPlayer; - std::shared_ptr trackQueue; EventHandler eventHandler = nullptr; - std::shared_ptr playbackState; - void sendCmd(MessageType typ); void sendEvent(EventType type); diff --git a/cspot/include/TrackPlayer.h b/cspot/include/TrackPlayer.h index 1577c476..ccc3eb1d 100644 --- a/cspot/include/TrackPlayer.h +++ b/cspot/include/TrackPlayer.h @@ -17,11 +17,13 @@ namespace bell { class WrappedSemaphore; } // namespace bell +#ifndef CONFIG_BELL_NOCODEC #ifdef BELL_VORBIS_FLOAT #include "vorbis/vorbisfile.h" #else #include "ivorbisfile.h" // for OggVorbis_File, ov_callbacks #endif +#endif namespace cspot { class TrackProvider; @@ -34,9 +36,16 @@ class TrackPlayer : bell::Task { // Callback types typedef std::function, bool)> TrackLoadedCallback; - typedef std::function + typedef std::function DataCallback; typedef std::function EOFCallback; + typedef std::function SeekableCallback; + TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, @@ -45,17 +54,19 @@ class TrackPlayer : bell::Task { void loadTrackFromRef(TrackReference& ref, size_t playbackMs, bool startAutomatically); - void setDataCallback(DataCallback callback); + void setDataCallback(DataCallback callback, SeekableCallback seekable_callback = nullptr, SeekableCallback spaces_available = nullptr); // CDNTrackStream::TrackInfo getCurrentTrackInfo(); void seekMs(size_t ms); void resetState(bool paused = false); +#ifndef CONFIG_BELL_NOCODEC // Vorbis codec callbacks size_t _vorbisRead(void* ptr, size_t size, size_t nmemb); size_t _vorbisClose(); int _vorbisSeek(int64_t offset, int whence); long _vorbisTell(); +#endif void stop(); void start(); @@ -70,16 +81,23 @@ class TrackPlayer : bell::Task { TrackLoadedCallback trackLoaded; DataCallback dataCallback = nullptr; EOFCallback eofCallback; +#ifdef CONFIG_BELL_NOCODEC + SeekableCallback spaces_available = nullptr; + SeekableCallback seekable_callback; + size_t seekable_offset; +#endif // Playback control std::atomic currentSongPlaying; std::mutex playbackMutex; std::mutex dataOutMutex; +#ifndef CONFIG_BELL_NOCODEC // Vorbis related OggVorbis_File vorbisFile; ov_callbacks vorbisCallbacks; int currentSection; +#endif std::vector pcmBuffer = std::vector(1024); diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 8e2f0c37..ca95d553 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -8,6 +8,7 @@ #include "BellTask.h" #include "PlaybackState.h" +#include "EventManager.h" // for TrackMetrics #include "TrackReference.h" #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode @@ -53,9 +54,11 @@ class QueuedTrack { TrackInfo trackInfo; // Full track information fetched from spotify, name etc uint32_t requestedPosition; + uint64_t written_bytes = 0; std::string identifier; bool loading = false; - + std::shared_ptr trackMetrics; + // Will return nullptr if the track is not ready std::shared_ptr getAudioFile(); diff --git a/cspot/src/EventManager.cpp b/cspot/src/EventManager.cpp new file mode 100644 index 00000000..52e64686 --- /dev/null +++ b/cspot/src/EventManager.cpp @@ -0,0 +1,168 @@ +#include "EventManager.h" +#include "CSpotContext.h" // for Context::ConfigState, Context (ptr o... +#include "TrackQueue.h" // for Context::ConfigState, Context (ptr o... +#include "Logger.h" // for CSPOT_LOG + +using namespace cspot; + +static std::string reason_text[11] = { + "trackdone", + "trackerror", + "fwdbtn", + "backbtn", + "endplay", + "playbtn", + "clickrow", + "logout", + "appload", + "remote", + "" +}; + +TrackMetrics::TrackMetrics(std::shared_ptr ctx, uint64_t pos) { + this->ctx = ctx; + timestamp = ctx->timeProvider->getSyncedTimestamp(); + currentInterval = std::make_shared(timestamp, pos); +} + +void TrackMetrics::endInterval(uint64_t pos) { + // end Interval + currentInterval->length = this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start; + currentInterval->end = currentInterval->position + currentInterval->length; + totalAmountPlayed += currentInterval->length; + // add skipped time + if (pos != 0) { + if (pos > currentInterval->position + currentInterval->length) + skipped_forward.add(pos - (currentInterval->position + currentInterval->length)); + else skipped_backward.add((currentInterval->position + currentInterval->length) - pos); + } + if (currentInterval->length > longestInterval) longestInterval = currentInterval->length; + intervals = addInterval(intervals, { currentInterval->position, currentInterval->end }); +} + +uint64_t TrackMetrics::getPosition() { + return (currentInterval->position + (this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start)); +} + + +void TrackMetrics::startTrackDecoding() { + trackHeaderTime = this->ctx->timeProvider->getSyncedTimestamp(); + audioKeyTime = trackHeaderTime - timestamp; +} + +void TrackMetrics::startTrack(uint64_t pos) { + audioKeyTime = this->ctx->timeProvider->getSyncedTimestamp() - audioKeyTime; + currentInterval = std::make_shared(this->ctx->timeProvider->getSyncedTimestamp(), pos); +} + +void TrackMetrics::endTrack() { + endInterval(0); + for (const auto& interval : intervals) totalMsOfPlayedTrack += interval.second - interval.first; + totalAmountOfPlayTime = this->ctx->timeProvider->getSyncedTimestamp() - timestamp; +} + +void TrackMetrics::newPosition(uint64_t pos) { + if (pos == currentInterval->position + currentInterval->length) return; + endInterval(pos); + currentInterval = std::make_shared(this->ctx->timeProvider->getSyncedTimestamp(), pos); +} + +std::string PlaybackMetrics::get_source_from_context() { + if (context_uri != "") { + if (context_uri.find("playlist") != std::string::npos) return "playlist"; + else if (context_uri.find("collection") != std::string::npos) return "your_library"; + else if (context_uri.find("artist") != std::string::npos) return "artist"; + else if (context_uri.find("album") != std::string::npos) return "album"; + else if (context_uri.find("track") != std::string::npos) return "track"; + } + return ""; +} +std::string PlaybackMetrics::get_end_source() { + end_source = get_source_from_context(); + return end_source; +} +std::vector PlaybackMetrics::sendEvent(std::shared_ptr track) { + std::string data; + std::vector msg; + CSPOT_LOG(debug, "Sending playbackend event"); + std::string requestUrl = "hm://event-service/v1/events"; + + append(&msg, "12"); + append(&msg, "45"); + append(&msg, std::to_string(seqNum++)); + append(&msg, this->ctx->config.deviceId); + append(&msg, track->identifier); //PLAYBACKiD + append(&msg, "00000000000000000000000000000000"); //parent_playback_id + append(&msg, start_source); + append(&msg, reason_text[(uint8_t)start_reason]); //remote when taken over by anyone + append(&msg, end_source == "" ? get_end_source() : end_source); //free-tier-artist / playlist / your_library .com.spotify.gaia / artist + append(&msg, reason_text[(uint8_t)end_reason]); //remote when taken over of anyone + append(&msg, std::to_string(track->written_bytes)); //@librespot usually the same size as track->size, if shifted forward, usually shorter, if shifted backward, usually bigger + append(&msg, std::to_string(track->trackMetrics->track_size)); //in bytes + append(&msg, std::to_string(track->trackMetrics->totalAmountOfPlayTime)); //total millis from start to end (sometimes a little longer than millis_played) pause has no influence + append(&msg, std::to_string(track->trackMetrics->totalAmountPlayed)); //total millis played + append(&msg, std::to_string(track->trackInfo.duration)); //track duration in millis + append(&msg, std::to_string(track->trackMetrics->trackHeaderTime));//total time of decrypting? often 3 or 4 when nothing played -1 + append(&msg, "0");// fadeoverlapp? usually 0, but fading is set on + append(&msg, "0");// librespot says, could bee that the first value shows if it is the first played song, usually 0 + append(&msg, "0");//?? usually 0 + append(&msg, "0");//?? usually 0 + append(&msg, std::to_string(track->trackMetrics->skipped_backward.count));//total times skipped backward + append(&msg, std::to_string(track->trackMetrics->skipped_backward.amount));//total amount of time skipped backward + append(&msg, std::to_string(track->trackMetrics->skipped_forward.count));//total times skipped forward + append(&msg, std::to_string(track->trackMetrics->skipped_forward.amount));//total amount of time skipped forward + append(&msg, "15"); //randomNumber; biggest value so far 260, usually biggert than 1 //spotify says play latencie + append(&msg, "-1"); // usually -1, if paused positive, probablly in seconds + append(&msg, "context"); + append(&msg, std::to_string(track->trackMetrics->audioKeyTime));//time to get the audiokey? usually -1 + append(&msg, "0"); // usually 0 + append(&msg, "1");// @librespot audioKey preloaded? usually positive (1) + append(&msg, "0");//?? usually 0 + append(&msg, "0");//?? usually bigger than 0, if startup(not playing) or takenover "0" + append(&msg, "1"); // usually 1 , if taken over 0, if player took over not from the start 0 + append(&msg, std::to_string(track->trackMetrics->longestInterval)); //length longest interval + append(&msg, std::to_string(track->trackMetrics->totalMsOfPlayedTrack)); //total time since start total millis of song played + append(&msg, "0");//?? usually 0 + append(&msg, "320000");//CONFIG_CSPOT_AUDIO_FORMAT ? CONFIG_CSPOT_AUDIO_FORMAT == 2 ? "320000" : "160000" : "96000"); // bitrate + append(&msg, context_uri); + append(&msg, "vorbis"); + append(&msg, track->trackInfo.trackId); // sometimes, when commands come from outside, or else, this value is something else and the following one is the gid + append(&msg, ""); + append(&msg, "0");//?? usually 0 + append(&msg, std::to_string(track->trackMetrics->timestamp)); // unix timestamp when track started + append(&msg, "0");//?? usually 0 + append(&msg, track->ref.context == "radio" ? "autoplay" : "context"); + append(&msg, (end_source == "playlist" || end_source == "your_library") ? "your_library" : "search");//std::to_string(this->ctx->referrerIdentifier));//your_library:lybrary_header / autoplay:afterplaylist / search:found in search / find /home:found in home + append(&msg, "xpui_2024-05-31_1717155884878_"); //xpui_2024-05-31_1717155884878_ xpui_ + date of version(update) + _ + unix_timestamp probably of update //empty if autoplay + append(&msg, "com.spotify"); + append(&msg, "none"); //"transition" : gapless if song ended beforehand inside player + append(&msg, "none"); + append(&msg, "local"); // @librespot lastCommandSentByDeviceId , usually"local", if orderd from outside last command ident last comment ident from frame.state + append(&msg, "na"); + append(&msg, "none"); + append(&msg, ""); // 3067b220-9721-4489-93b4-118dd3a59b7b //page-instance-id // changing , if radio / autoplay empty + append(&msg, ""); // 054dfc5a-0108-4971-b8de-1fd95070e416 //interaction_id // stays still , if radio / autoplay capped + append(&msg, ""); + append(&msg, "5003900000000146"); + append(&msg, ""); + append(&msg, track->ref.context == "radio" ? correlation_id : ""); //ssp~061a6236e23e1a9847bd9b6ad4cd942eac8d //allways the same , only when radio? / autoplay + append(&msg, ""); + append(&msg, "0");//?? usually 0 + append(&msg, "0");//?? usually 0 + + if (end_reason == END_PLAY) start_reason = nested_reason; + else start_reason = end_reason; + start_source = end_source; + +#ifndef CONFIG_HIDDEN + auto responseLambda = [=](MercurySession::Response& res) { + }; + + auto parts = MercurySession::DataParts({ msg }); + // Execute the request + ctx->session->execute(MercurySession::RequestType::SEND, + requestUrl, + responseLambda, parts); +#endif + return msg; +} \ No newline at end of file diff --git a/cspot/src/PlaybackState.cpp b/cspot/src/PlaybackState.cpp index 72697c2f..cfc9636b 100644 --- a/cspot/src/PlaybackState.cpp +++ b/cspot/src/PlaybackState.cpp @@ -118,6 +118,12 @@ void PlaybackState::syncWithRemote() { innerFrame.state.has_playing_track_index = true; innerFrame.state.playing_track_index = remoteFrame.state.playing_track_index; + innerFrame.state.has_shuffle = remoteFrame.state.has_shuffle;; + innerFrame.state.shuffle = remoteFrame.state.shuffle; + innerFrame.state.has_repeat = remoteFrame.state.has_repeat; + innerFrame.state.repeat = remoteFrame.state.repeat; + innerFrame.state.has_index = true; + innerFrame.state.index = remoteFrame.state.index; } bool PlaybackState::isActive() { diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index 8d8add6a..f12134d5 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -127,6 +127,7 @@ void SpircHandler::handleFrame(std::vector& data) { // Decode received spirc frame playbackState->decodeRemoteFrame(data); + std::string influence = "unknown"; switch (playbackState->remoteFrame.typ) { case MessageType_kMessageTypeNotify: { CSPOT_LOG(debug, "Notify frame"); @@ -136,7 +137,8 @@ void SpircHandler::handleFrame(std::vector& data) { playbackState->remoteFrame.device_state.is_active) { CSPOT_LOG(debug, "Another player took control, pausing playback"); playbackState->setActive(false); - + ctx->playbackMetrics->end_reason = PlaybackMetrics::REMOTE; + ctx->playbackMetrics->end_source = influence; this->trackPlayer->stop(); sendEvent(EventType::DISC); } @@ -166,11 +168,13 @@ void SpircHandler::handleFrame(std::vector& data) { case MessageType_kMessageTypeNext: if (nextSong()) { sendEvent(EventType::NEXT); + ctx->playbackMetrics->end_reason = PlaybackMetrics::FORWARD_BTN; } break; case MessageType_kMessageTypePrev: if (previousSong()) { sendEvent(EventType::PREV); + ctx->playbackMetrics->end_reason = PlaybackMetrics::BACKWARD_BTN; } break; case MessageType_kMessageTypeLoad: { diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index c96f2ec7..eeb7ec9e 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -11,7 +11,9 @@ #include "Packet.h" // for cspot #include "TrackQueue.h" // for CDNTrackStream, CDNTrackStream::TrackInfo #include "WrappedSemaphore.h" // for WrappedSemaphore +#include "CSpotContext.h" +#ifndef CONFIG_BELL_NOCODEC #ifdef BELL_VORBIS_FLOAT #define VORBIS_SEEK(file, position) \ (ov_time_seek(file, (double)position / 1000)) @@ -22,14 +24,17 @@ #define VORBIS_READ(file, buffer, bufferSize, section) \ (ov_read(file, buffer, bufferSize, section)) #endif +#endif namespace cspot { struct Context; struct TrackReference; +class PlaybackMetrics; } // namespace cspot using namespace cspot; +#ifndef CONFIG_BELL_NOCODEC static size_t vorbisReadCb(void* ptr, size_t size, size_t nmemb, TrackPlayer* self) { return self->_vorbisRead(ptr, size, nmemb); @@ -47,6 +52,7 @@ static int vorbisSeekCb(TrackPlayer* self, int64_t offset, int whence) { static long vorbisTellCb(TrackPlayer* self) { return self->_vorbisTell(); } +#endif TrackPlayer::TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, @@ -58,6 +64,7 @@ TrackPlayer::TrackPlayer(std::shared_ptr ctx, this->trackQueue = trackQueue; this->playbackSemaphore = std::make_unique(5); +#ifndef CONFIG_BELL_NOCODEC // Initialize vorbis callbacks vorbisFile = {}; vorbisCallbacks = { @@ -66,6 +73,7 @@ TrackPlayer::TrackPlayer(std::shared_ptr ctx, (decltype(ov_callbacks::close_func))&vorbisCloseCb, (decltype(ov_callbacks::tell_func))&vorbisTellCb, }; +#endif } TrackPlayer::~TrackPlayer() { @@ -78,7 +86,10 @@ void TrackPlayer::start() { if (!isRunning) { isRunning = true; startTask(); + this->ctx->playbackMetrics->start_reason = PlaybackMetrics::REMOTE; + this->ctx->playbackMetrics->start_source = "unknown"; } + else this->ctx->playbackMetrics->end_reason = PlaybackMetrics::END_PLAY; } void TrackPlayer::stop() { @@ -99,10 +110,12 @@ void TrackPlayer::resetState(bool paused) { } void TrackPlayer::seekMs(size_t ms) { +#ifndef CONFIG_BELL_NOCODEC if (inFuture) { // We're in the middle of the next track, so we need to reset the player in order to seek resetState(); } +#endif CSPOT_LOG(info, "Seeking..."); this->pendingSeekPositionMs = ms; @@ -111,7 +124,7 @@ void TrackPlayer::seekMs(size_t ms) { void TrackPlayer::runTask() { std::scoped_lock lock(runningMutex); - std::shared_ptr track, newTrack = nullptr; + std::shared_ptr track= nullptr, newTrack = nullptr; int trackOffset = 0; bool eof = false; @@ -155,6 +168,8 @@ void TrackPlayer::runTask() { } track = newTrack; + track->trackMetrics = std::make_shared(this->ctx); + this->ctx->playbackMetrics->trackMetrics = track->trackMetrics; inFuture = trackOffset > 0; @@ -174,9 +189,12 @@ void TrackPlayer::runTask() { { std::scoped_lock lock(playbackMutex); + bool skipped = 0; currentTrackStream = track->getAudioFile(); + track->trackMetrics->startTrackDecoding(); + // Open the stream currentTrackStream->openStream(); @@ -184,6 +202,7 @@ void TrackPlayer::runTask() { continue; } +#ifndef CONFIG_BELL_NOCODEC if (trackOffset == 0 && pendingSeekPositionMs == 0) { this->trackLoaded(track, startPaused); startPaused = false; @@ -191,17 +210,52 @@ void TrackPlayer::runTask() { int32_t r = ov_open_callbacks(this, &vorbisFile, NULL, 0, vorbisCallbacks); - +#else + size_t start_offset = 0; + size_t write_offset = 0; + while (!start_offset) { + size_t ret = this->currentTrackStream->readBytes(&pcmBuffer[0], pcmBuffer.size()); + size_t written = 0; + size_t toWrite = ret; + while (toWrite) { + written = dataCallback(pcmBuffer.data() + (ret - toWrite), + toWrite, track->identifier, 0); + if (written == 0) { + BELL_SLEEP_MS(1000); + } + toWrite -= written; + } + track->written_bytes += ret; + start_offset = seekable_callback(track->identifier); + if(this->spaces_available(track->identifier)trackMetrics->track_size = currentTrackStream->getSize(); + float duration_lambda = 1.0 * (currentTrackStream->getSize() - start_offset) / track->trackInfo.duration; +#endif if (pendingSeekPositionMs > 0) { track->requestedPosition = pendingSeekPositionMs; +#ifdef CONFIG_BELL_NOCODEC + pendingSeekPositionMs = 0; +#endif } if (track->requestedPosition > 0) { +#ifndef CONFIG_BELL_NOCODEC VORBIS_SEEK(&vorbisFile, track->requestedPosition); +#else + size_t seekPosition = track->requestedPosition * duration_lambda + start_offset; + currentTrackStream->seek(seekPosition); + skipped = true; +#endif } eof = false; track->loading = true; + track->trackMetrics->startTrack(track->requestedPosition); CSPOT_LOG(info, "Playing"); @@ -210,15 +264,28 @@ void TrackPlayer::runTask() { if (pendingSeekPositionMs > 0) { uint32_t seekPosition = pendingSeekPositionMs; - // Reset the pending seek position - pendingSeekPositionMs = 0; - // Seek to the new position +#ifndef CONFIG_BELL_NOCODEC VORBIS_SEEK(&vorbisFile, seekPosition); +#else + seekPosition = seekPosition * duration_lambda + start_offset; + currentTrackStream->seek(seekPosition); + track->trackMetrics->newPosition(pendingSeekPositionMs); + skipped = true; +#endif + + // Reset the pending seek position + pendingSeekPositionMs = 0; } - long ret = VORBIS_READ(&vorbisFile, (char*)&pcmBuffer[0], - pcmBuffer.size(), ¤tSection); + + long ret = +#ifdef CONFIG_BELL_NOCODEC + this->currentTrackStream->readBytes(&pcmBuffer[0], pcmBuffer.size()); +#else + VORBIS_READ(&vorbisFile, (char*)&pcmBuffer[0], + pcmBuffer.size(), ¤tSection); +#endif if (ret == 0) { CSPOT_LOG(info, "EOF"); @@ -238,25 +305,39 @@ void TrackPlayer::runTask() { // If reset happened during playback, return if (!currentSongPlaying || pendingReset) break; - +#ifdef CONFIG_BELL_NOCODEC + if (skipped) { + // Reset the pending seek position + skipped = 0; + } +#endif written = dataCallback(pcmBuffer.data() + (ret - toWrite), - toWrite, track->identifier); + toWrite, track->identifier + #ifdef CONFIG_BELL_NOCODEC + ,skipped + #endif + ); } if (written == 0) { BELL_SLEEP_MS(50); } toWrite -= written; } + track->written_bytes += ret; } } } +#ifndef CONFIG_BELL_NOCODEC ov_clear(&vorbisFile); +#endif CSPOT_LOG(info, "Playing done"); // always move back to LOADING (ensure proper seeking after last track has been loaded) currentTrackStream = nullptr; track->loading = false; + track->trackMetrics->endTrack(); + std::vector result = this->ctx->playbackMetrics->sendEvent(track); } if (eof) { @@ -269,6 +350,7 @@ void TrackPlayer::runTask() { } } +#ifndef CONFIG_BELL_NOCODEC size_t TrackPlayer::_vorbisRead(void* ptr, size_t size, size_t nmemb) { if (this->currentTrackStream == nullptr) { return 0; @@ -307,7 +389,12 @@ long TrackPlayer::_vorbisTell() { } return this->currentTrackStream->getPosition(); } +#endif -void TrackPlayer::setDataCallback(DataCallback callback) { +void TrackPlayer::setDataCallback(DataCallback callback, SeekableCallback seekable_callback, SeekableCallback spaces_available ) { this->dataCallback = callback; + #ifdef CONFIG_BELL_NOCODEC + this->seekable_callback = seekable_callback; + this->spaces_available = spaces_available; + #endif } From b41251cc33f780ad6e0579ea3bf0e310f820846b Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Thu, 11 Jul 2024 09:44:43 +0200 Subject: [PATCH 12/41] reporting trough event-manager, so the played songs will pop up in the listening history --- cspot/include/CSpotContext.h | 3 + cspot/include/EventManager.h | 126 ++++++++++++++++++++++++++ cspot/include/SpircHandler.h | 7 +- cspot/include/TrackPlayer.h | 22 ++++- cspot/include/TrackQueue.h | 5 +- cspot/src/EventManager.cpp | 168 +++++++++++++++++++++++++++++++++++ cspot/src/MercurySession.cpp | 64 ++++++++----- cspot/src/PlaybackState.cpp | 6 ++ cspot/src/SpircHandler.cpp | 6 +- cspot/src/TrackPlayer.cpp | 107 +++++++++++++++++++--- 10 files changed, 472 insertions(+), 42 deletions(-) create mode 100644 cspot/include/EventManager.h create mode 100644 cspot/src/EventManager.cpp diff --git a/cspot/include/CSpotContext.h b/cspot/include/CSpotContext.h index d4fdde84..be20940d 100644 --- a/cspot/include/CSpotContext.h +++ b/cspot/include/CSpotContext.h @@ -4,6 +4,7 @@ #include #include "Crypto.h" +#include "EventManager.h" #include "LoginBlob.h" #include "MercurySession.h" #include "TimeProvider.h" @@ -35,6 +36,7 @@ struct Context { std::shared_ptr timeProvider; std::shared_ptr session; + std::shared_ptr playbackMetrics; std::string getCredentialsJson() { #ifdef BELL_ONLY_CJSON cJSON* json_obj = cJSON_CreateObject(); @@ -68,6 +70,7 @@ struct Context { ctx->timeProvider = std::make_shared(); ctx->session = std::make_shared(ctx->timeProvider); + ctx->playbackMetrics = std::make_shared(ctx); ctx->config.deviceId = blob->getDeviceId(); ctx->config.deviceName = blob->getDeviceName(); ctx->config.authData = blob->authData; diff --git a/cspot/include/EventManager.h b/cspot/include/EventManager.h new file mode 100644 index 00000000..14422e16 --- /dev/null +++ b/cspot/include/EventManager.h @@ -0,0 +1,126 @@ +#pragma once + +#include // for uint8_t, uint32_t +#include // for shared_ptr +#include //for sort +#include // for string +#include // for vector + + +namespace cspot { + struct Context; + class QueuedTrack; + + struct TrackInterval { + uint64_t start; + uint64_t end; + uint64_t position; + uint64_t length; + + TrackInterval(); + TrackInterval(uint64_t start, uint64_t position) { + this->start = start; + this->position = position; + } + }; + + struct skip { + uint8_t count = 0; + uint64_t amount = 0; + + void add(uint64_t amount) { + this->amount += amount; + count++; + } + }; + + class TrackMetrics { + public: + + TrackMetrics(std::shared_ptr ctx, uint64_t pos = 0); + + std::shared_ptr currentInterval; + uint64_t longestInterval = 0, totalAmountOfPlayTime = 0, totalMsOfPlayedTrack = 0, + totalAmountPlayed = 0, audioKeyTime = 0, trackHeaderTime = 0, + written_bytes = 0, track_size = 0, timestamp = 0; + std::vector > intervals; + skip skipped_backward, skipped_forward; + + void newPosition(uint64_t pos); + void endInterval(uint64_t pos); + void endTrack(); + void startTrackDecoding(); + void startTrack(uint64_t pos); + uint64_t getPosition(); + + private: + + std::shared_ptr ctx; + std::vector> addInterval(std::vector>& intervals, std::pair newInterval) { + // Add the new interval to the list of intervals + intervals.push_back(newInterval); + + // Sort intervals by starting time + std::sort(intervals.begin(), intervals.end()); + + // Result vector to hold merged intervals + std::vector> merged; + + // Iterate over intervals to merge overlapping ones + for (const auto& interval : intervals) { + // If merged is empty or current interval does not overlap with the previous one + if (merged.empty() || merged.back().second < interval.first) { + merged.push_back(interval); + } + else { + // If it overlaps, merge the intervals + merged.back().second = std::max(merged.back().second, interval.second); + } + } + + return merged; + } + + + }; + class PlaybackMetrics { + private: + + std::shared_ptr ctx; + uint32_t seqNum = 0; + size_t timestamp; + + std::string get_source_from_context(); + std::string get_end_source(); + + void append(std::vector* data, std::string to_do) { + data->insert(data->end(), to_do.begin(), to_do.end()); + data->push_back(9); + } + + public: + + PlaybackMetrics(std::shared_ptr ctx) { + this->ctx = ctx; + } + enum reason { + TRACK_DONE, + TRACK_ERROR, + FORWARD_BTN, + BACKWARD_BTN, + END_PLAY, + PLAY_BTN, + CLICK_ROW, + LOGOUT, + APP_LOAD, + REMOTE, + UNKNOWN + }end_reason = UNKNOWN, start_reason = UNKNOWN, nested_reason = UNKNOWN; + + std::string context_uri, correlation_id, start_source, end_source; + std::shared_ptr trackMetrics; + + std::vector sendEvent(std::shared_ptr track); + + }; +} \ No newline at end of file diff --git a/cspot/include/SpircHandler.h b/cspot/include/SpircHandler.h index 7d558cd8..3464450f 100644 --- a/cspot/include/SpircHandler.h +++ b/cspot/include/SpircHandler.h @@ -58,18 +58,17 @@ class SpircHandler { void setRemoteVolume(int volume); void loadTrackFromURI(const std::string& uri); std::shared_ptr getTrackQueue() { return trackQueue; } + std::shared_ptr trackPlayer; + std::shared_ptr trackQueue; + std::shared_ptr playbackState; void disconnect(); private: std::shared_ptr ctx; - std::shared_ptr trackPlayer; - std::shared_ptr trackQueue; EventHandler eventHandler = nullptr; - std::shared_ptr playbackState; - void sendCmd(MessageType typ); void sendEvent(EventType type); diff --git a/cspot/include/TrackPlayer.h b/cspot/include/TrackPlayer.h index 1577c476..ccc3eb1d 100644 --- a/cspot/include/TrackPlayer.h +++ b/cspot/include/TrackPlayer.h @@ -17,11 +17,13 @@ namespace bell { class WrappedSemaphore; } // namespace bell +#ifndef CONFIG_BELL_NOCODEC #ifdef BELL_VORBIS_FLOAT #include "vorbis/vorbisfile.h" #else #include "ivorbisfile.h" // for OggVorbis_File, ov_callbacks #endif +#endif namespace cspot { class TrackProvider; @@ -34,9 +36,16 @@ class TrackPlayer : bell::Task { // Callback types typedef std::function, bool)> TrackLoadedCallback; - typedef std::function + typedef std::function DataCallback; typedef std::function EOFCallback; + typedef std::function SeekableCallback; + TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, @@ -45,17 +54,19 @@ class TrackPlayer : bell::Task { void loadTrackFromRef(TrackReference& ref, size_t playbackMs, bool startAutomatically); - void setDataCallback(DataCallback callback); + void setDataCallback(DataCallback callback, SeekableCallback seekable_callback = nullptr, SeekableCallback spaces_available = nullptr); // CDNTrackStream::TrackInfo getCurrentTrackInfo(); void seekMs(size_t ms); void resetState(bool paused = false); +#ifndef CONFIG_BELL_NOCODEC // Vorbis codec callbacks size_t _vorbisRead(void* ptr, size_t size, size_t nmemb); size_t _vorbisClose(); int _vorbisSeek(int64_t offset, int whence); long _vorbisTell(); +#endif void stop(); void start(); @@ -70,16 +81,23 @@ class TrackPlayer : bell::Task { TrackLoadedCallback trackLoaded; DataCallback dataCallback = nullptr; EOFCallback eofCallback; +#ifdef CONFIG_BELL_NOCODEC + SeekableCallback spaces_available = nullptr; + SeekableCallback seekable_callback; + size_t seekable_offset; +#endif // Playback control std::atomic currentSongPlaying; std::mutex playbackMutex; std::mutex dataOutMutex; +#ifndef CONFIG_BELL_NOCODEC // Vorbis related OggVorbis_File vorbisFile; ov_callbacks vorbisCallbacks; int currentSection; +#endif std::vector pcmBuffer = std::vector(1024); diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 8e2f0c37..ca95d553 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -8,6 +8,7 @@ #include "BellTask.h" #include "PlaybackState.h" +#include "EventManager.h" // for TrackMetrics #include "TrackReference.h" #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode @@ -53,9 +54,11 @@ class QueuedTrack { TrackInfo trackInfo; // Full track information fetched from spotify, name etc uint32_t requestedPosition; + uint64_t written_bytes = 0; std::string identifier; bool loading = false; - + std::shared_ptr trackMetrics; + // Will return nullptr if the track is not ready std::shared_ptr getAudioFile(); diff --git a/cspot/src/EventManager.cpp b/cspot/src/EventManager.cpp new file mode 100644 index 00000000..52e64686 --- /dev/null +++ b/cspot/src/EventManager.cpp @@ -0,0 +1,168 @@ +#include "EventManager.h" +#include "CSpotContext.h" // for Context::ConfigState, Context (ptr o... +#include "TrackQueue.h" // for Context::ConfigState, Context (ptr o... +#include "Logger.h" // for CSPOT_LOG + +using namespace cspot; + +static std::string reason_text[11] = { + "trackdone", + "trackerror", + "fwdbtn", + "backbtn", + "endplay", + "playbtn", + "clickrow", + "logout", + "appload", + "remote", + "" +}; + +TrackMetrics::TrackMetrics(std::shared_ptr ctx, uint64_t pos) { + this->ctx = ctx; + timestamp = ctx->timeProvider->getSyncedTimestamp(); + currentInterval = std::make_shared(timestamp, pos); +} + +void TrackMetrics::endInterval(uint64_t pos) { + // end Interval + currentInterval->length = this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start; + currentInterval->end = currentInterval->position + currentInterval->length; + totalAmountPlayed += currentInterval->length; + // add skipped time + if (pos != 0) { + if (pos > currentInterval->position + currentInterval->length) + skipped_forward.add(pos - (currentInterval->position + currentInterval->length)); + else skipped_backward.add((currentInterval->position + currentInterval->length) - pos); + } + if (currentInterval->length > longestInterval) longestInterval = currentInterval->length; + intervals = addInterval(intervals, { currentInterval->position, currentInterval->end }); +} + +uint64_t TrackMetrics::getPosition() { + return (currentInterval->position + (this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start)); +} + + +void TrackMetrics::startTrackDecoding() { + trackHeaderTime = this->ctx->timeProvider->getSyncedTimestamp(); + audioKeyTime = trackHeaderTime - timestamp; +} + +void TrackMetrics::startTrack(uint64_t pos) { + audioKeyTime = this->ctx->timeProvider->getSyncedTimestamp() - audioKeyTime; + currentInterval = std::make_shared(this->ctx->timeProvider->getSyncedTimestamp(), pos); +} + +void TrackMetrics::endTrack() { + endInterval(0); + for (const auto& interval : intervals) totalMsOfPlayedTrack += interval.second - interval.first; + totalAmountOfPlayTime = this->ctx->timeProvider->getSyncedTimestamp() - timestamp; +} + +void TrackMetrics::newPosition(uint64_t pos) { + if (pos == currentInterval->position + currentInterval->length) return; + endInterval(pos); + currentInterval = std::make_shared(this->ctx->timeProvider->getSyncedTimestamp(), pos); +} + +std::string PlaybackMetrics::get_source_from_context() { + if (context_uri != "") { + if (context_uri.find("playlist") != std::string::npos) return "playlist"; + else if (context_uri.find("collection") != std::string::npos) return "your_library"; + else if (context_uri.find("artist") != std::string::npos) return "artist"; + else if (context_uri.find("album") != std::string::npos) return "album"; + else if (context_uri.find("track") != std::string::npos) return "track"; + } + return ""; +} +std::string PlaybackMetrics::get_end_source() { + end_source = get_source_from_context(); + return end_source; +} +std::vector PlaybackMetrics::sendEvent(std::shared_ptr track) { + std::string data; + std::vector msg; + CSPOT_LOG(debug, "Sending playbackend event"); + std::string requestUrl = "hm://event-service/v1/events"; + + append(&msg, "12"); + append(&msg, "45"); + append(&msg, std::to_string(seqNum++)); + append(&msg, this->ctx->config.deviceId); + append(&msg, track->identifier); //PLAYBACKiD + append(&msg, "00000000000000000000000000000000"); //parent_playback_id + append(&msg, start_source); + append(&msg, reason_text[(uint8_t)start_reason]); //remote when taken over by anyone + append(&msg, end_source == "" ? get_end_source() : end_source); //free-tier-artist / playlist / your_library .com.spotify.gaia / artist + append(&msg, reason_text[(uint8_t)end_reason]); //remote when taken over of anyone + append(&msg, std::to_string(track->written_bytes)); //@librespot usually the same size as track->size, if shifted forward, usually shorter, if shifted backward, usually bigger + append(&msg, std::to_string(track->trackMetrics->track_size)); //in bytes + append(&msg, std::to_string(track->trackMetrics->totalAmountOfPlayTime)); //total millis from start to end (sometimes a little longer than millis_played) pause has no influence + append(&msg, std::to_string(track->trackMetrics->totalAmountPlayed)); //total millis played + append(&msg, std::to_string(track->trackInfo.duration)); //track duration in millis + append(&msg, std::to_string(track->trackMetrics->trackHeaderTime));//total time of decrypting? often 3 or 4 when nothing played -1 + append(&msg, "0");// fadeoverlapp? usually 0, but fading is set on + append(&msg, "0");// librespot says, could bee that the first value shows if it is the first played song, usually 0 + append(&msg, "0");//?? usually 0 + append(&msg, "0");//?? usually 0 + append(&msg, std::to_string(track->trackMetrics->skipped_backward.count));//total times skipped backward + append(&msg, std::to_string(track->trackMetrics->skipped_backward.amount));//total amount of time skipped backward + append(&msg, std::to_string(track->trackMetrics->skipped_forward.count));//total times skipped forward + append(&msg, std::to_string(track->trackMetrics->skipped_forward.amount));//total amount of time skipped forward + append(&msg, "15"); //randomNumber; biggest value so far 260, usually biggert than 1 //spotify says play latencie + append(&msg, "-1"); // usually -1, if paused positive, probablly in seconds + append(&msg, "context"); + append(&msg, std::to_string(track->trackMetrics->audioKeyTime));//time to get the audiokey? usually -1 + append(&msg, "0"); // usually 0 + append(&msg, "1");// @librespot audioKey preloaded? usually positive (1) + append(&msg, "0");//?? usually 0 + append(&msg, "0");//?? usually bigger than 0, if startup(not playing) or takenover "0" + append(&msg, "1"); // usually 1 , if taken over 0, if player took over not from the start 0 + append(&msg, std::to_string(track->trackMetrics->longestInterval)); //length longest interval + append(&msg, std::to_string(track->trackMetrics->totalMsOfPlayedTrack)); //total time since start total millis of song played + append(&msg, "0");//?? usually 0 + append(&msg, "320000");//CONFIG_CSPOT_AUDIO_FORMAT ? CONFIG_CSPOT_AUDIO_FORMAT == 2 ? "320000" : "160000" : "96000"); // bitrate + append(&msg, context_uri); + append(&msg, "vorbis"); + append(&msg, track->trackInfo.trackId); // sometimes, when commands come from outside, or else, this value is something else and the following one is the gid + append(&msg, ""); + append(&msg, "0");//?? usually 0 + append(&msg, std::to_string(track->trackMetrics->timestamp)); // unix timestamp when track started + append(&msg, "0");//?? usually 0 + append(&msg, track->ref.context == "radio" ? "autoplay" : "context"); + append(&msg, (end_source == "playlist" || end_source == "your_library") ? "your_library" : "search");//std::to_string(this->ctx->referrerIdentifier));//your_library:lybrary_header / autoplay:afterplaylist / search:found in search / find /home:found in home + append(&msg, "xpui_2024-05-31_1717155884878_"); //xpui_2024-05-31_1717155884878_ xpui_ + date of version(update) + _ + unix_timestamp probably of update //empty if autoplay + append(&msg, "com.spotify"); + append(&msg, "none"); //"transition" : gapless if song ended beforehand inside player + append(&msg, "none"); + append(&msg, "local"); // @librespot lastCommandSentByDeviceId , usually"local", if orderd from outside last command ident last comment ident from frame.state + append(&msg, "na"); + append(&msg, "none"); + append(&msg, ""); // 3067b220-9721-4489-93b4-118dd3a59b7b //page-instance-id // changing , if radio / autoplay empty + append(&msg, ""); // 054dfc5a-0108-4971-b8de-1fd95070e416 //interaction_id // stays still , if radio / autoplay capped + append(&msg, ""); + append(&msg, "5003900000000146"); + append(&msg, ""); + append(&msg, track->ref.context == "radio" ? correlation_id : ""); //ssp~061a6236e23e1a9847bd9b6ad4cd942eac8d //allways the same , only when radio? / autoplay + append(&msg, ""); + append(&msg, "0");//?? usually 0 + append(&msg, "0");//?? usually 0 + + if (end_reason == END_PLAY) start_reason = nested_reason; + else start_reason = end_reason; + start_source = end_source; + +#ifndef CONFIG_HIDDEN + auto responseLambda = [=](MercurySession::Response& res) { + }; + + auto parts = MercurySession::DataParts({ msg }); + // Execute the request + ctx->session->execute(MercurySession::RequestType::SEND, + requestUrl, + responseLambda, parts); +#endif + return msg; +} \ No newline at end of file diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index d28ecce0..7d880ea1 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -68,6 +68,7 @@ void MercurySession::reconnect() { try { this->conn = nullptr; this->shanConn = nullptr; + this->partials.clear(); this->connectWithRandomAp(); this->authenticate(this->authBlob); @@ -174,9 +175,9 @@ void MercurySession::handlePacket() { CSPOT_LOG(debug, "Received mercury packet"); auto response = this->decodeResponse(packet.data); - if(response.first == 1){ + if (response.first == static_cast(ResponseFlag::FINAL)) { auto partial = this->partials.find(response.second); - if(this->callbacks.count(response.second)){ + if (this->callbacks.count(response.second)) { this->callbacks[response.second](partial->second); this->callbacks.erase(this->callbacks.find(response.second)); } @@ -187,12 +188,13 @@ void MercurySession::handlePacket() { case RequestType::SUBRES: { auto response = decodeResponse(packet.data); - if(response.first){ + if (response.first == static_cast(ResponseFlag::FINAL)) { auto partial = this->partials.find(response.second); auto uri = std::string(partial->second.mercuryHeader.uri); if (this->subscriptions.count(uri) > 0) { this->subscriptions[uri](partial->second); } + this->partials.erase(partial); } break; } @@ -222,38 +224,52 @@ void MercurySession::failAllPending() { std::pair MercurySession::decodeResponse( const std::vector& data) { - auto sequenceLength = ntohs(extract(data, 0)); - int64_t sequenceId; uint8_t flag; - if(sequenceLength == 2) sequenceId = ntohs(extract(data, 2)); - else if(sequenceLength == 4) sequenceId = ntohl(extract(data, 2)); - else if(sequenceLength == 8) sequenceId = hton64(extract(data, 2)); - else return std::make_pair(0,0); + auto sequenceLength = ntohs(extract(data, 0)); + uint64_t sequenceId; + uint8_t flag; + if (sequenceLength == 2) + sequenceId = ntohs(extract(data, 2)); + else if (sequenceLength == 4) + sequenceId = ntohl(extract(data, 2)); + else if (sequenceLength == 8) + sequenceId = hton64(extract(data, 2)); + else + return std::make_pair(0, 0); + size_t pos = 2 + sequenceLength; flag = (uint8_t)data[pos]; pos++; auto parts = ntohs(extract(data, pos)); - pos+= 2; + pos += 2; auto partial = partials.find(sequenceId); - if (partial==partials.end()) { - CSPOT_LOG(debug, "Creating new Mercury Response, seq: %lld, flags: %i, parts: %i\n", sequenceId, flag, parts); - partial = this->partials.insert({sequenceId,Response()}).first; + if (partial == partials.end()) { + CSPOT_LOG(debug, + "Creating new Mercury Response, seq: %llu, flags: %i, parts: %i", + sequenceId, flag, parts); + partial = this->partials.insert({sequenceId, Response()}).first; partial->second.parts = {}; partial->second.fail = false; - } else CSPOT_LOG(debug, "Adding to Mercury Response, seq: %lld, flags: %i, parts: %i\n", sequenceId, flag, parts); + } else + CSPOT_LOG(debug, + "Adding to Mercury Response, seq: %llu, flags: %i, parts: %i", + sequenceId, flag, parts); uint8_t index = 0; - while(parts){ - if(data.size() <= pos || partial->second.fail) break; + while (parts) { + if (data.size() <= pos || partial->second.fail) + break; auto partSize = ntohs(extract(data, pos)); pos += 2; - if(!partial->second.mercuryHeader.has_uri){ + if (!partial->second.mercuryHeader.has_uri) { partial->second.fail = false; - auto headerBytes = - std::vector(data.begin() + pos, data.begin() + pos + partSize); + auto headerBytes = std::vector(data.begin() + pos, + data.begin() + pos + partSize); pbDecode(partial->second.mercuryHeader, Header_fields, headerBytes); - } - else{ - if( index >= partial->second.parts.size() ) partial->second.parts.push_back(std::vector{}); - partial->second.parts[index].insert(partial->second.parts[index].end(),data.begin() + pos, data.begin() + pos + partSize); + } else { + if (index >= partial->second.parts.size()) + partial->second.parts.push_back(std::vector{}); + partial->second.parts[index].insert(partial->second.parts[index].end(), + data.begin() + pos, + data.begin() + pos + partSize); index++; } pos += partSize; @@ -363,4 +379,4 @@ uint32_t MercurySession::requestAudioKey(const std::vector& trackId, // @TODO: Handle disconnect } return audioKeySequence - 1; -} +} \ No newline at end of file diff --git a/cspot/src/PlaybackState.cpp b/cspot/src/PlaybackState.cpp index 72697c2f..cfc9636b 100644 --- a/cspot/src/PlaybackState.cpp +++ b/cspot/src/PlaybackState.cpp @@ -118,6 +118,12 @@ void PlaybackState::syncWithRemote() { innerFrame.state.has_playing_track_index = true; innerFrame.state.playing_track_index = remoteFrame.state.playing_track_index; + innerFrame.state.has_shuffle = remoteFrame.state.has_shuffle;; + innerFrame.state.shuffle = remoteFrame.state.shuffle; + innerFrame.state.has_repeat = remoteFrame.state.has_repeat; + innerFrame.state.repeat = remoteFrame.state.repeat; + innerFrame.state.has_index = true; + innerFrame.state.index = remoteFrame.state.index; } bool PlaybackState::isActive() { diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index 8d8add6a..f12134d5 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -127,6 +127,7 @@ void SpircHandler::handleFrame(std::vector& data) { // Decode received spirc frame playbackState->decodeRemoteFrame(data); + std::string influence = "unknown"; switch (playbackState->remoteFrame.typ) { case MessageType_kMessageTypeNotify: { CSPOT_LOG(debug, "Notify frame"); @@ -136,7 +137,8 @@ void SpircHandler::handleFrame(std::vector& data) { playbackState->remoteFrame.device_state.is_active) { CSPOT_LOG(debug, "Another player took control, pausing playback"); playbackState->setActive(false); - + ctx->playbackMetrics->end_reason = PlaybackMetrics::REMOTE; + ctx->playbackMetrics->end_source = influence; this->trackPlayer->stop(); sendEvent(EventType::DISC); } @@ -166,11 +168,13 @@ void SpircHandler::handleFrame(std::vector& data) { case MessageType_kMessageTypeNext: if (nextSong()) { sendEvent(EventType::NEXT); + ctx->playbackMetrics->end_reason = PlaybackMetrics::FORWARD_BTN; } break; case MessageType_kMessageTypePrev: if (previousSong()) { sendEvent(EventType::PREV); + ctx->playbackMetrics->end_reason = PlaybackMetrics::BACKWARD_BTN; } break; case MessageType_kMessageTypeLoad: { diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index c96f2ec7..eeb7ec9e 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -11,7 +11,9 @@ #include "Packet.h" // for cspot #include "TrackQueue.h" // for CDNTrackStream, CDNTrackStream::TrackInfo #include "WrappedSemaphore.h" // for WrappedSemaphore +#include "CSpotContext.h" +#ifndef CONFIG_BELL_NOCODEC #ifdef BELL_VORBIS_FLOAT #define VORBIS_SEEK(file, position) \ (ov_time_seek(file, (double)position / 1000)) @@ -22,14 +24,17 @@ #define VORBIS_READ(file, buffer, bufferSize, section) \ (ov_read(file, buffer, bufferSize, section)) #endif +#endif namespace cspot { struct Context; struct TrackReference; +class PlaybackMetrics; } // namespace cspot using namespace cspot; +#ifndef CONFIG_BELL_NOCODEC static size_t vorbisReadCb(void* ptr, size_t size, size_t nmemb, TrackPlayer* self) { return self->_vorbisRead(ptr, size, nmemb); @@ -47,6 +52,7 @@ static int vorbisSeekCb(TrackPlayer* self, int64_t offset, int whence) { static long vorbisTellCb(TrackPlayer* self) { return self->_vorbisTell(); } +#endif TrackPlayer::TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, @@ -58,6 +64,7 @@ TrackPlayer::TrackPlayer(std::shared_ptr ctx, this->trackQueue = trackQueue; this->playbackSemaphore = std::make_unique(5); +#ifndef CONFIG_BELL_NOCODEC // Initialize vorbis callbacks vorbisFile = {}; vorbisCallbacks = { @@ -66,6 +73,7 @@ TrackPlayer::TrackPlayer(std::shared_ptr ctx, (decltype(ov_callbacks::close_func))&vorbisCloseCb, (decltype(ov_callbacks::tell_func))&vorbisTellCb, }; +#endif } TrackPlayer::~TrackPlayer() { @@ -78,7 +86,10 @@ void TrackPlayer::start() { if (!isRunning) { isRunning = true; startTask(); + this->ctx->playbackMetrics->start_reason = PlaybackMetrics::REMOTE; + this->ctx->playbackMetrics->start_source = "unknown"; } + else this->ctx->playbackMetrics->end_reason = PlaybackMetrics::END_PLAY; } void TrackPlayer::stop() { @@ -99,10 +110,12 @@ void TrackPlayer::resetState(bool paused) { } void TrackPlayer::seekMs(size_t ms) { +#ifndef CONFIG_BELL_NOCODEC if (inFuture) { // We're in the middle of the next track, so we need to reset the player in order to seek resetState(); } +#endif CSPOT_LOG(info, "Seeking..."); this->pendingSeekPositionMs = ms; @@ -111,7 +124,7 @@ void TrackPlayer::seekMs(size_t ms) { void TrackPlayer::runTask() { std::scoped_lock lock(runningMutex); - std::shared_ptr track, newTrack = nullptr; + std::shared_ptr track= nullptr, newTrack = nullptr; int trackOffset = 0; bool eof = false; @@ -155,6 +168,8 @@ void TrackPlayer::runTask() { } track = newTrack; + track->trackMetrics = std::make_shared(this->ctx); + this->ctx->playbackMetrics->trackMetrics = track->trackMetrics; inFuture = trackOffset > 0; @@ -174,9 +189,12 @@ void TrackPlayer::runTask() { { std::scoped_lock lock(playbackMutex); + bool skipped = 0; currentTrackStream = track->getAudioFile(); + track->trackMetrics->startTrackDecoding(); + // Open the stream currentTrackStream->openStream(); @@ -184,6 +202,7 @@ void TrackPlayer::runTask() { continue; } +#ifndef CONFIG_BELL_NOCODEC if (trackOffset == 0 && pendingSeekPositionMs == 0) { this->trackLoaded(track, startPaused); startPaused = false; @@ -191,17 +210,52 @@ void TrackPlayer::runTask() { int32_t r = ov_open_callbacks(this, &vorbisFile, NULL, 0, vorbisCallbacks); - +#else + size_t start_offset = 0; + size_t write_offset = 0; + while (!start_offset) { + size_t ret = this->currentTrackStream->readBytes(&pcmBuffer[0], pcmBuffer.size()); + size_t written = 0; + size_t toWrite = ret; + while (toWrite) { + written = dataCallback(pcmBuffer.data() + (ret - toWrite), + toWrite, track->identifier, 0); + if (written == 0) { + BELL_SLEEP_MS(1000); + } + toWrite -= written; + } + track->written_bytes += ret; + start_offset = seekable_callback(track->identifier); + if(this->spaces_available(track->identifier)trackMetrics->track_size = currentTrackStream->getSize(); + float duration_lambda = 1.0 * (currentTrackStream->getSize() - start_offset) / track->trackInfo.duration; +#endif if (pendingSeekPositionMs > 0) { track->requestedPosition = pendingSeekPositionMs; +#ifdef CONFIG_BELL_NOCODEC + pendingSeekPositionMs = 0; +#endif } if (track->requestedPosition > 0) { +#ifndef CONFIG_BELL_NOCODEC VORBIS_SEEK(&vorbisFile, track->requestedPosition); +#else + size_t seekPosition = track->requestedPosition * duration_lambda + start_offset; + currentTrackStream->seek(seekPosition); + skipped = true; +#endif } eof = false; track->loading = true; + track->trackMetrics->startTrack(track->requestedPosition); CSPOT_LOG(info, "Playing"); @@ -210,15 +264,28 @@ void TrackPlayer::runTask() { if (pendingSeekPositionMs > 0) { uint32_t seekPosition = pendingSeekPositionMs; - // Reset the pending seek position - pendingSeekPositionMs = 0; - // Seek to the new position +#ifndef CONFIG_BELL_NOCODEC VORBIS_SEEK(&vorbisFile, seekPosition); +#else + seekPosition = seekPosition * duration_lambda + start_offset; + currentTrackStream->seek(seekPosition); + track->trackMetrics->newPosition(pendingSeekPositionMs); + skipped = true; +#endif + + // Reset the pending seek position + pendingSeekPositionMs = 0; } - long ret = VORBIS_READ(&vorbisFile, (char*)&pcmBuffer[0], - pcmBuffer.size(), ¤tSection); + + long ret = +#ifdef CONFIG_BELL_NOCODEC + this->currentTrackStream->readBytes(&pcmBuffer[0], pcmBuffer.size()); +#else + VORBIS_READ(&vorbisFile, (char*)&pcmBuffer[0], + pcmBuffer.size(), ¤tSection); +#endif if (ret == 0) { CSPOT_LOG(info, "EOF"); @@ -238,25 +305,39 @@ void TrackPlayer::runTask() { // If reset happened during playback, return if (!currentSongPlaying || pendingReset) break; - +#ifdef CONFIG_BELL_NOCODEC + if (skipped) { + // Reset the pending seek position + skipped = 0; + } +#endif written = dataCallback(pcmBuffer.data() + (ret - toWrite), - toWrite, track->identifier); + toWrite, track->identifier + #ifdef CONFIG_BELL_NOCODEC + ,skipped + #endif + ); } if (written == 0) { BELL_SLEEP_MS(50); } toWrite -= written; } + track->written_bytes += ret; } } } +#ifndef CONFIG_BELL_NOCODEC ov_clear(&vorbisFile); +#endif CSPOT_LOG(info, "Playing done"); // always move back to LOADING (ensure proper seeking after last track has been loaded) currentTrackStream = nullptr; track->loading = false; + track->trackMetrics->endTrack(); + std::vector result = this->ctx->playbackMetrics->sendEvent(track); } if (eof) { @@ -269,6 +350,7 @@ void TrackPlayer::runTask() { } } +#ifndef CONFIG_BELL_NOCODEC size_t TrackPlayer::_vorbisRead(void* ptr, size_t size, size_t nmemb) { if (this->currentTrackStream == nullptr) { return 0; @@ -307,7 +389,12 @@ long TrackPlayer::_vorbisTell() { } return this->currentTrackStream->getPosition(); } +#endif -void TrackPlayer::setDataCallback(DataCallback callback) { +void TrackPlayer::setDataCallback(DataCallback callback, SeekableCallback seekable_callback, SeekableCallback spaces_available ) { this->dataCallback = callback; + #ifdef CONFIG_BELL_NOCODEC + this->seekable_callback = seekable_callback; + this->spaces_available = spaces_available; + #endif } From e041d9a10144216558b247eb3b075318bc770429 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 15 Jul 2024 15:06:20 +0200 Subject: [PATCH 13/41] added repeat and shuffle support, a context-resolver and a radio function --- cspot/include/TrackPlayer.h | 4 +- cspot/include/TrackQueue.h | 23 ++- cspot/include/TrackReference.h | 18 ++- cspot/include/Utils.h | 8 + cspot/src/PlaybackState.cpp | 3 + cspot/src/SpircHandler.cpp | 20 +-- cspot/src/TrackPlayer.cpp | 17 ++- cspot/src/TrackQueue.cpp | 244 ++++++++++++++++++++++++++++--- cspot/src/TrackReference.cpp | 16 +- cspot/src/Utils.cpp | 16 ++ targets/cli/CliPlayer.cpp | 7 +- targets/esp32/main/EspPlayer.cpp | 10 +- 12 files changed, 317 insertions(+), 69 deletions(-) diff --git a/cspot/include/TrackPlayer.h b/cspot/include/TrackPlayer.h index ccc3eb1d..6d29d1b6 100644 --- a/cspot/include/TrackPlayer.h +++ b/cspot/include/TrackPlayer.h @@ -36,7 +36,7 @@ class TrackPlayer : bell::Task { // Callback types typedef std::function, bool)> TrackLoadedCallback; - typedef std::function DataCallback; typedef std::function EOFCallback; - typedef std::function SeekableCallback; + typedef std::function SeekableCallback; TrackPlayer(std::shared_ptr ctx, diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index ca95d553..34f98117 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -5,6 +5,7 @@ #include #include #include +#include //for random_device and default_random_engine #include "BellTask.h" #include "PlaybackState.h" @@ -13,6 +14,11 @@ #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode +#define inner_tracks_treshhold 10 +#define SEND_OLD_TRACKS 2 +#define SEND_FUTURE_TRACKS 2 +#define GET_RADIO_TRACKS 10 + namespace bell { class WrappedSemaphore; }; @@ -96,11 +102,15 @@ class TrackQueue : public bell::Task { enum class SkipDirection { NEXT, PREV }; std::shared_ptr playableSemaphore; + std::shared_ptr playbackState; std::atomic notifyPending = false; void runTask() override; void stopTask(); + void prepareRepeat(); + void shuffle_tracks(bool shuffleTracks); + void update_ghost_tracks(int16_t offset = 0); bool hasTracks(); bool isFinished(); bool skipTrack(SkipDirection dir, bool expectNotify = true); @@ -113,12 +123,13 @@ class TrackQueue : public bell::Task { static const int MAX_TRACKS_PRELOAD = 3; std::shared_ptr accessKeyFetcher; - std::shared_ptr playbackState; std::shared_ptr ctx; std::shared_ptr processSemaphore; std::deque> preloadedTracks; + std::vectoralt_index; std::vector currentTracks; + std::vector ghostTracks; std::mutex tracksMutex, runningMutex; // PB data @@ -126,12 +137,22 @@ class TrackQueue : public bell::Task { Episode pbEpisode; std::string accessKey; + uint32_t radio_offset = 0; int16_t currentTracksIndex = -1; + int16_t currentTracksSize = 0; bool isRunning = false; + bool context_resolved = false; + bool continue_with_radio = true; + + std::random_device rd; + std::default_random_engine rng; + void resolveAutoplay(); + void resolveContext(); void processTrack(std::shared_ptr track); bool queueNextTrack(int offset = 0, uint32_t positionMs = 0); + void loadRadio(std::string req); }; } // namespace cspot diff --git a/cspot/include/TrackReference.h b/cspot/include/TrackReference.h index 8b986349..5d0d5b43 100644 --- a/cspot/include/TrackReference.h +++ b/cspot/include/TrackReference.h @@ -5,12 +5,28 @@ #include #include #include "NanoPBHelper.h" +#include "Utils.h" //for base62decode #include "pb_decode.h" #include "protobuf/spirc.pb.h" namespace cspot { struct TrackReference { - TrackReference(); + TrackReference(); + TrackReference(std::string uri, std::string context) : type(Type::TRACK) { + this->gid = base62Decode(uri); + //this->uri=uri; + this->context=context; + } + TrackReference(std::string uri) : type(Type::TRACK) { + gid = base62Decode(uri); + + if (uri.find("episode:") != std::string::npos) { + type = Type::EPISODE; + } + if (uri.find("track:") == std::string::npos) { + this->uri = uri; + } + } // Resolved track GID std::vector gid; diff --git a/cspot/include/Utils.h b/cspot/include/Utils.h index a52be4ea..a657e5b6 100644 --- a/cspot/include/Utils.h +++ b/cspot/include/Utils.h @@ -55,6 +55,14 @@ std::vector bigNumAdd(std::vector num, int n); unsigned char h2int(char c); +/** + * @brief Extracts the spotify id from a spotify uri and decodes its base62-format + * + * @param uri spotify uri/spotify id(base62) string + * @return std::vector gid + */ +std::vector base62Decode(std::string uri); + std::string urlDecode(std::string str); /** diff --git a/cspot/src/PlaybackState.cpp b/cspot/src/PlaybackState.cpp index cfc9636b..cdc9596d 100644 --- a/cspot/src/PlaybackState.cpp +++ b/cspot/src/PlaybackState.cpp @@ -173,6 +173,9 @@ std::vector PlaybackState::encodeCurrentFrame(MessageType typ) { innerFrame.has_device_state = true; innerFrame.has_typ = true; innerFrame.has_state_update_id = true; + innerFrame.state.playing_track_index = innerFrame.state.index; + innerFrame.state.has_playing_track_index = true; + innerFrame.state.has_index = true; this->seqNum += 1; diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index f12134d5..75482465 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -82,7 +82,9 @@ void SpircHandler::loadTrackFromURI(const std::string& uri) {} void SpircHandler::notifyAudioEnded() { playbackState->updatePositionMs(0); notify(); +#ifndef CONFIG_BELL_NOCODEC trackPlayer->resetState(true); +#endif } void SpircHandler::notifyAudioReachedPlayback() { @@ -91,18 +93,8 @@ void SpircHandler::notifyAudioReachedPlayback() { // get HEAD track auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - // Do not execute when meta is already updated - if (trackQueue->notifyPending) { - trackQueue->notifyPending = false; - - playbackState->updatePositionMs(currentTrack->requestedPosition); - - // Reset position in queued track - currentTrack->requestedPosition = 0; - } else { - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); - playbackState->updatePositionMs(0); - + if (!playbackState->innerFrame.state.repeat) { + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT); // we moved to next track, re-acquire currentTrack again currentTrack = trackQueue->consumeTrack(nullptr, offset); } @@ -227,11 +219,15 @@ void SpircHandler::handleFrame(std::vector& data) { } case MessageType_kMessageTypeShuffle: { CSPOT_LOG(debug, "Got shuffle frame"); + playbackState->innerFrame.state.shuffle = playbackState->remoteFrame.state.shuffle; + trackQueue->shuffle_tracks(playbackState->remoteFrame.state.shuffle); this->notify(); break; } case MessageType_kMessageTypeRepeat: { CSPOT_LOG(debug, "Got repeat frame"); + playbackState->innerFrame.state.repeat = playbackState->remoteFrame.state.repeat; + trackQueue->prepareRepeat(); this->notify(); break; } diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index eeb7ec9e..e736d9a2 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -127,6 +127,7 @@ void TrackPlayer::runTask() { std::shared_ptr track= nullptr, newTrack = nullptr; int trackOffset = 0; + size_t tracksPlayed = 0; bool eof = false; bool endOfQueueReached = false; @@ -156,6 +157,7 @@ void TrackPlayer::runTask() { } newTrack = trackQueue->consumeTrack(track, trackOffset); + this->trackQueue->update_ghost_tracks(trackOffset); if (newTrack == nullptr) { if (trackOffset == -1) { @@ -208,6 +210,7 @@ void TrackPlayer::runTask() { startPaused = false; } + track->trackMetrics->track_size = currentTrackStream->getSize(); int32_t r = ov_open_callbacks(this, &vorbisFile, NULL, 0, vorbisCallbacks); #else @@ -219,21 +222,19 @@ void TrackPlayer::runTask() { size_t toWrite = ret; while (toWrite) { written = dataCallback(pcmBuffer.data() + (ret - toWrite), - toWrite, track->identifier, 0); + toWrite, tracksPlayed, 0); if (written == 0) { BELL_SLEEP_MS(1000); } toWrite -= written; } track->written_bytes += ret; - start_offset = seekable_callback(track->identifier); - if(this->spaces_available(track->identifier)spaces_available(tracksPlayed)trackMetrics->track_size = currentTrackStream->getSize(); float duration_lambda = 1.0 * (currentTrackStream->getSize() - start_offset) / track->trackInfo.duration; #endif if (pendingSeekPositionMs > 0) { @@ -242,6 +243,7 @@ void TrackPlayer::runTask() { pendingSeekPositionMs = 0; #endif } + ctx->playbackMetrics->end_reason = PlaybackMetrics::REMOTE; if (track->requestedPosition > 0) { #ifndef CONFIG_BELL_NOCODEC @@ -256,6 +258,8 @@ void TrackPlayer::runTask() { eof = false; track->loading = true; track->trackMetrics->startTrack(track->requestedPosition); + //in case of a repeatedtrack, set requested position to 0 + track->requestedPosition = 0; CSPOT_LOG(info, "Playing"); @@ -312,7 +316,7 @@ void TrackPlayer::runTask() { } #endif written = dataCallback(pcmBuffer.data() + (ret - toWrite), - toWrite, track->identifier + toWrite, tracksPlayed #ifdef CONFIG_BELL_NOCODEC ,skipped #endif @@ -327,6 +331,7 @@ void TrackPlayer::runTask() { } } } + tracksPlayed++; #ifndef CONFIG_BELL_NOCODEC ov_clear(&vorbisFile); #endif diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 26ec0a27..bfc8d239 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -23,6 +24,11 @@ #include "protobuf/metadata.pb.h" using namespace cspot; + +static void randomizeIndex(std::vector &index, uint16_t offset, std::default_random_engine rng){ + std::shuffle(index.begin() + offset, index.end(),rng); +} + namespace TrackDataUtils { bool countryListContains(char* countryList, const char* country) { uint16_t countryList_length = strlen(countryList); @@ -375,7 +381,7 @@ TrackQueue::TrackQueue(std::shared_ptr ctx, // Assign encode callback to track list playbackState->innerFrame.state.track.funcs.encode = &TrackReference::pbEncodeTrackList; - playbackState->innerFrame.state.track.arg = ¤tTracks; + playbackState->innerFrame.state.track.arg = &ghostTracks; pbTrack = Track_init_zero; pbEpisode = Episode_init_zero; @@ -449,7 +455,7 @@ std::shared_ptr TrackQueue::consumeTrack( } // No previous track, return head - if (prevTrack == nullptr) { + if (prevTrack == nullptr || playbackState->innerFrame.state.repeat) { offset = 0; return preloadedTracks[0]; @@ -481,6 +487,154 @@ std::shared_ptr TrackQueue::consumeTrack( return preloadedTracks[offset]; } +void TrackQueue::update_ghost_tracks(int16_t offset){ + if(currentTracksIndex + offset >= SEND_OLD_TRACKS) this->playbackState->innerFrame.state.index = SEND_OLD_TRACKS; + else this->playbackState->innerFrame.state.index = currentTracksIndex + offset; + ghostTracks.clear(); + uint16_t index = currentTracksIndex + offset > SEND_OLD_TRACKS ? currentTracksIndex + offset - SEND_OLD_TRACKS : 0; + uint16_t end = currentTracksIndex + offset + SEND_FUTURE_TRACKS + 1; + if(end >= currentTracks.size())end = currentTracks.size(); + for (uint16_t i = 0; i < end - index; i++){ + ghostTracks.push_back(currentTracks[(index + i) >= currentTracksSize ? index + i : alt_index[ index + i]]); + } +} + +void TrackQueue::loadRadio(std::string req){ + size_t keepTracks = currentTracks.size() - currentTracksIndex; + keepTracks = keepTracks < inner_tracks_treshhold ? keepTracks : inner_tracks_treshhold; + if (keepTracks < inner_tracks_treshhold && continue_with_radio && currentTracks.size()) { + + //if currentTrack is over the treshhold, remove some tracks from the front + if (currentTracks.size() > inner_tracks_treshhold * 3){ + uint32_t int_offset = currentTracks.size() - inner_tracks_treshhold; + currentTracks.erase(currentTracks.begin(), currentTracks.begin() + int_offset); + currentTracksIndex -= int_offset; + } + + std::string requestUrl = string_format( + "hm://radio-apollo/v3/stations/%s?autoplay=true&offset=%i", + &req[0],radio_offset); + + auto responseHandler = [this](MercurySession::Response& res) { + std::scoped_lock lock(tracksMutex); + CSPOT_LOG(info, "Fetched new radio tracks"); + + if (res.parts[0].size() == 0) return; + auto jsonResult = nlohmann::json::parse(res.parts[0]); + radio_offset += jsonResult["tracks"].size(); + std::string uri; + for (int i = 0; i < jsonResult["tracks"].size(); i++) { + currentTracks.push_back( + TrackReference(jsonResult["tracks"][i]["original_gid"], "radio") + ); + } + this->ctx->playbackMetrics->correlation_id = jsonResult["correlation_id"]; + if(preloadedTracks.size() < MAX_TRACKS_PRELOAD){ + queueNextTrack(preloadedTracks.size()); + } + }; + // Execute the request + ctx->session->execute( + MercurySession::RequestType::GET, requestUrl, responseHandler); + } +} + +void TrackQueue::resolveAutoplay() { + if(!this->playbackState->innerFrame.state.context_uri) return; + std::string requestUrl = string_format( + "hm://autoplay-enabled/query?uri=%s", + this->playbackState->innerFrame.state.context_uri); + auto responseHandler = [this](MercurySession::Response& res) { + if(res.parts.size()){ + loadRadio(std::string(res.parts[0].begin(), res.parts[0].end())); + } + }; + // Execute the request + ctx->session->execute( + MercurySession::RequestType::GET, requestUrl, responseHandler); +} + +void TrackQueue::resolveContext() { + std::scoped_lock lock(tracksMutex); + std::string requestUrl = string_format( + "hm://context-resolve/v1/%s", + this->playbackState->innerFrame.state.context_uri); + auto responseHandler = [this](MercurySession::Response& res) { + std::scoped_lock lock(tracksMutex); + auto jsonResult = nlohmann::json::parse(res.parts[0]); + //do nothing if last track is the same as last track in currentTracks + for(auto pages_itr:jsonResult["pages"]) { + TrackReference _ref; + int32_t front = 0; + if(pages_itr.find("tracks")==pages_itr.end())continue; + if(this->playbackState->innerFrame.state.shuffle) { + std::vector new_alt_index; + std::vector alt_tracks; + for(int i = 0; i < pages_itr["tracks"].size(); i++) + new_alt_index.push_back(i); + //not written yet + for(auto itr:pages_itr["tracks"]) { + _ref = TrackReference(itr["uri"]); + auto currentTracksIter = + std::find(currentTracks.begin(), currentTracks.end(), _ref); + if(currentTracksIter != currentTracks.end()) { + int32_t old_index = std::distance(currentTracks.begin(), currentTracksIter); + new_alt_index[front] = new_alt_index[alt_index[old_index]]; + new_alt_index[alt_index[old_index]] = front; + alt_index[old_index] = -1; + } + alt_tracks.push_back(_ref); + front++; + } + // in case of smartshuffle, we currently just put the few already recieved "smart-tracks" in order and reshuffle the whole playlist + for(size_t i = 0; i < alt_index.size(); i++ ) { + if(alt_index[i] >= 0) { + new_alt_index.push_back(new_alt_index[alt_index[i]]); + new_alt_index[alt_index[i]] = alt_tracks.size(); + alt_tracks.push_back(currentTracks[alt_index[i]]); + } + } + randomizeIndex(new_alt_index,currentTracks.size(),rng); + alt_index = new_alt_index; + currentTracks = alt_tracks; + } else { + auto altref = currentTracks.front().gid; + uint8_t loop_pointer = 0; + for(auto itr:pages_itr["tracks"]){ + _ref = TrackReference(itr["uri"]); + switch(loop_pointer){ + case 0 : + if(_ref.gid==altref) { + loop_pointer++; + altref = currentTracks.back().gid; + if(altref == base62Decode(pages_itr["tracks"].back()["uri"])) goto exit_loop; + } else { + //for completion of the trasklist in case of shuffle, add missing item too the front + currentTracks.insert(currentTracks.begin() + front, _ref); + front++; + } + break; + case 1 : + if(_ref.gid == altref) loop_pointer++; + break; + case 2 : + //add missing tracks to the back + currentTracks.push_back(_ref); + break; + default: + break; + + } + } exit_loop: ; + currentTracksIndex += front; + CSPOT_LOG(info, "Resolved context, new currentTracks-size = %i", currentTracks.size()); + } + } + }; + ctx->session->execute( + MercurySession::RequestType::GET, requestUrl, responseHandler); +} + void TrackQueue::processTrack(std::shared_ptr track) { switch (track->state) { case QueuedTrack::State::QUEUED: @@ -493,7 +647,14 @@ void TrackQueue::processTrack(std::shared_ptr track) { case QueuedTrack::State::CDN_REQUIRED: track->stepLoadCDNUrl(accessKey); - if (track->state == QueuedTrack::State::READY) { + if (track->state == QueuedTrack::State::READY) { + if(!context_resolved) { + resolveContext(); + context_resolved = true; + } + if(continue_with_radio) + if(preloadedTracks.size() + currentTracksIndex >= currentTracks.size()) + resolveAutoplay(); if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { // Queue a new track to preload queueNextTrack(preloadedTracks.size()); @@ -507,7 +668,8 @@ void TrackQueue::processTrack(std::shared_ptr track) { } bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { - const int requestedRefIndex = offset + currentTracksIndex; + int requestedRefIndex = offset + currentTracksIndex; + if(playbackState->innerFrame.state.shuffle && requestedRefIndex < alt_index.size()) requestedRefIndex = alt_index[requestedRefIndex]; if (requestedRefIndex < 0 || requestedRefIndex >= currentTracks.size()) { return false; @@ -530,6 +692,12 @@ bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { return true; } +void TrackQueue::prepareRepeat() { + if(currentTracksIndex)currentTracksIndex--; + preloadedTracks.push_front(std::make_shared( + currentTracks[currentTracksIndex], ctx, 0)); +} + bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { bool skipped = true; std::scoped_lock lock(tracksMutex); @@ -591,15 +759,38 @@ bool TrackQueue::isFinished() { return currentTracksIndex >= currentTracks.size() - 1; } +void TrackQueue::shuffle_tracks(bool shuffleTracks) { + if(!shuffleTracks)currentTracksIndex = alt_index[currentTracksIndex]; + alt_index.clear(); + for(int i = 0; i < currentTracksSize; i++) alt_index.push_back(i); + if(shuffleTracks) { + alt_index[currentTracksIndex] = 0; + alt_index[0] = currentTracksIndex; + randomizeIndex(alt_index,1, rng); + currentTracksIndex = 0; + } + update_ghost_tracks(); + preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); + // Push a song on the preloaded queue + queueNextTrack(1, 0); +} + bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { std::scoped_lock lock(tracksMutex); bool cleared = true; - // Copy requested track list - currentTracks = playbackState->remoteTracks; - currentTracksIndex = playbackState->innerFrame.state.playing_track_index; - if (initial) { + // initialize new random_engine + rng = std::default_random_engine { rd() }; + // Copy requested track list + currentTracks = playbackState->remoteTracks; + currentTracksIndex = playbackState->innerFrame.state.playing_track_index; + currentTracksSize = currentTracks.size(); + + // Revert the alternative Index to it's inital Index structure + alt_index.clear(); + for(int i = 0; i < playbackState->remoteTracks.size(); i++) alt_index.push_back(i); + // Clear preloaded tracks preloadedTracks.clear(); @@ -610,27 +801,36 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { // We already updated track meta, mark it notifyPending = true; + radio_offset = 0; playableSemaphore->give(); - } else if (preloadedTracks[0]->loading) { - // try to not re-load track if we are still loading it + } else { + auto prevTrackIter = currentTracks.begin() + alt_index.size(); + alt_index.insert(alt_index.begin() + currentTracksIndex + 1, alt_index.size()); + + currentTracks.insert(prevTrackIter, playbackState->remoteTracks[playbackState->innerFrame.state.index + 1]); - // remove everything except first track - preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); + if (preloadedTracks[0]->loading) { + // try to not re-load track if we are still loading it - // Push a song on the preloaded queue - CSPOT_LOG(info, "Keeping current track %d", currentTracksIndex); - queueNextTrack(1); + // remove everything except first track + preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); - cleared = false; - } else { - // Clear preloaded tracks - preloadedTracks.clear(); + // Push a song on the preloaded queue + CSPOT_LOG(info, "Keeping current track %d", currentTracksIndex); + queueNextTrack(1); + + cleared = false; + } else { + // Clear preloaded tracks + preloadedTracks.clear(); - // Push a song on the preloaded queue - CSPOT_LOG(info, "Re-loading current track"); - queueNextTrack(0, requestedPosition); + // Push a song on the preloaded queue + CSPOT_LOG(info, "Re-loading current track"); + queueNextTrack(0, requestedPosition); + } } + update_ghost_tracks(); return cleared; } diff --git a/cspot/src/TrackReference.cpp b/cspot/src/TrackReference.cpp index 3b3b7031..2affd801 100644 --- a/cspot/src/TrackReference.cpp +++ b/cspot/src/TrackReference.cpp @@ -1,28 +1,18 @@ #include "TrackReference.h" #include "NanoPBExtensions.h" -#include "Utils.h" #include "protobuf/spirc.pb.h" using namespace cspot; -static constexpr auto base62Alphabet = - "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static std::string empty_string =""; TrackReference::TrackReference() : type(Type::TRACK) {} void TrackReference::decodeURI() { if (gid.size() == 0) { // Episode GID is being fetched via base62 encoded URI - auto idString = uri.substr(uri.find_last_of(":") + 1, uri.size()); - gid = {0}; - - std::string_view alphabet(base62Alphabet); - for (int x = 0; x < idString.size(); x++) { - size_t d = alphabet.find(idString[x]); - gid = bigNumMultiply(gid, 62); - gid = bigNumAdd(gid, d); - } + gid = base62Decode(uri); if (uri.find("episode:") != std::string::npos) { type = Type::EPISODE; @@ -53,7 +43,7 @@ bool TrackReference::pbEncodeTrackList(pb_ostream_t* stream, msg.gid.arg = &trackRef.gid; msg.uri.arg = &trackRef.uri; - msg.context.arg = &trackRef.context; + msg.context.arg = &empty_string;//&trackRef.context; msg.queued.arg = &trackRef.queued; if (!pb_encode_submessage(stream, TrackRef_fields, &msg)) { diff --git a/cspot/src/Utils.cpp b/cspot/src/Utils.cpp index fa5a3d95..0453e6b5 100644 --- a/cspot/src/Utils.cpp +++ b/cspot/src/Utils.cpp @@ -11,6 +11,8 @@ #include #endif +static std::string alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + unsigned long long getCurrentTimestamp() { return std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) @@ -151,4 +153,18 @@ std::string urlDecode(std::string str) { } return encodedString; +} + +std::vector base62Decode(std::string uri) { + std::vector n = std::vector({0}); + auto it = uri.begin(); + if(uri.find(":")!=std::string::npos) it += uri.rfind(":") + 1; + while(it!=uri.end()) { + size_t d = alphabet.find(*it); + n = bigNumMultiply(n, 62); + n = bigNumAdd(n, d); + it++; + } + + return n; } \ No newline at end of file diff --git a/targets/cli/CliPlayer.cpp b/targets/cli/CliPlayer.cpp index 69cbfba7..15492850 100644 --- a/targets/cli/CliPlayer.cpp +++ b/targets/cli/CliPlayer.cpp @@ -32,13 +32,10 @@ CliPlayer::CliPlayer(std::unique_ptr sink, this->dsp = std::make_shared(this->centralAudioBuffer); #endif - auto hashFunc = std::hash(); - this->handler->getTrackPlayer()->setDataCallback( - [this, &hashFunc](uint8_t* data, size_t bytes, std::string_view trackId) { - auto hash = hashFunc(trackId); + [this](uint8_t* data, size_t bytes, std::string_view trackId) { - return this->centralAudioBuffer->writePCM(data, bytes, hash); + return this->centralAudioBuffer->writePCM(data, bytes, trackId); }); this->isPaused = false; diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp index 0d7ed823..4fed7df6 100644 --- a/targets/esp32/main/EspPlayer.cpp +++ b/targets/esp32/main/EspPlayer.cpp @@ -26,19 +26,16 @@ EspPlayer::EspPlayer(std::unique_ptr sink, this->circularBuffer = std::make_shared(1024 * 128); - auto hashFunc = std::hash(); - this->handler->getTrackPlayer()->setDataCallback( - [this, &hashFunc](uint8_t* data, size_t bytes, std::string_view trackId) { - auto hash = hashFunc(trackId); - this->feedData(data, bytes, hash); + [this](uint8_t* data, size_t bytes, size_t trackId) { + this->feedData(data, bytes, trackId); return bytes; }); this->isPaused = false; this->handler->setEventHandler( - [this, &hashFunc](std::unique_ptr event) { + [this](std::unique_ptr event) { switch (event->eventType) { case cspot::SpircHandler::EventType::PLAY_PAUSE: if (std::get(event->data)) { @@ -103,7 +100,6 @@ void EspPlayer::runTask() { size_t read = this->circularBuffer->read(outBuf.data(), outBuf.size()); if (this->pauseRequested) { this->pauseRequested = false; - std::cout << "Pause requested!" << std::endl; this->isPaused = true; } From 5539d29a26584ca3a693770a2ed488efef750035 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 15 Jul 2024 15:17:28 +0200 Subject: [PATCH 14/41] missing change in CliPlayer.cpp --- targets/cli/CliPlayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/cli/CliPlayer.cpp b/targets/cli/CliPlayer.cpp index 15492850..0dc469ef 100644 --- a/targets/cli/CliPlayer.cpp +++ b/targets/cli/CliPlayer.cpp @@ -33,7 +33,7 @@ CliPlayer::CliPlayer(std::unique_ptr sink, #endif this->handler->getTrackPlayer()->setDataCallback( - [this](uint8_t* data, size_t bytes, std::string_view trackId) { + [this](uint8_t* data, size_t bytes, size_t trackId) { return this->centralAudioBuffer->writePCM(data, bytes, trackId); }); From 8f412a625031c03f0ac0baf51fb0d487d3bf7457 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 15 Jul 2024 17:12:23 +0200 Subject: [PATCH 15/41] Minor style fixes --- cspot/include/EventManager.h | 229 ++++++++++++++++---------------- cspot/include/TrackQueue.h | 8 +- cspot/src/EventManager.cpp | 250 +++++++++++++++++++++++------------ cspot/src/MercurySession.cpp | 15 ++- cspot/src/SpircHandler.cpp | 6 +- cspot/src/TrackPlayer.cpp | 62 +++++---- cspot/src/TrackQueue.cpp | 193 +++++++++++++++------------ cspot/src/TrackReference.cpp | 4 +- cspot/src/Utils.cpp | 24 ++-- 9 files changed, 452 insertions(+), 339 deletions(-) diff --git a/cspot/include/EventManager.h b/cspot/include/EventManager.h index 14422e16..63006599 100644 --- a/cspot/include/EventManager.h +++ b/cspot/include/EventManager.h @@ -1,126 +1,119 @@ #pragma once -#include // for uint8_t, uint32_t -#include // for shared_ptr +#include // for uint8_t, uint32_t #include //for sort -#include // for string -#include // for vector - +#include // for shared_ptr +#include // for string +#include // for vector namespace cspot { - struct Context; - class QueuedTrack; - - struct TrackInterval { - uint64_t start; - uint64_t end; - uint64_t position; - uint64_t length; - - TrackInterval(); - TrackInterval(uint64_t start, uint64_t position) { - this->start = start; - this->position = position; - } - }; - - struct skip { - uint8_t count = 0; - uint64_t amount = 0; - - void add(uint64_t amount) { - this->amount += amount; - count++; - } - }; - - class TrackMetrics { - public: - - TrackMetrics(std::shared_ptr ctx, uint64_t pos = 0); - - std::shared_ptr currentInterval; - uint64_t longestInterval = 0, totalAmountOfPlayTime = 0, totalMsOfPlayedTrack = 0, - totalAmountPlayed = 0, audioKeyTime = 0, trackHeaderTime = 0, - written_bytes = 0, track_size = 0, timestamp = 0; - std::vector > intervals; - skip skipped_backward, skipped_forward; - - void newPosition(uint64_t pos); - void endInterval(uint64_t pos); - void endTrack(); - void startTrackDecoding(); - void startTrack(uint64_t pos); - uint64_t getPosition(); - - private: - - std::shared_ptr ctx; - std::vector> addInterval(std::vector>& intervals, std::pair newInterval) { - // Add the new interval to the list of intervals - intervals.push_back(newInterval); - - // Sort intervals by starting time - std::sort(intervals.begin(), intervals.end()); - - // Result vector to hold merged intervals - std::vector> merged; - - // Iterate over intervals to merge overlapping ones - for (const auto& interval : intervals) { - // If merged is empty or current interval does not overlap with the previous one - if (merged.empty() || merged.back().second < interval.first) { - merged.push_back(interval); - } - else { - // If it overlaps, merge the intervals - merged.back().second = std::max(merged.back().second, interval.second); - } +struct Context; +class QueuedTrack; + +struct TrackInterval { + uint64_t start; + uint64_t end; + uint64_t position; + uint64_t length; + + TrackInterval(); + TrackInterval(uint64_t start, uint64_t position) { + this->start = start; + this->position = position; + } +}; + +struct skip { + uint8_t count = 0; + uint64_t amount = 0; + + void add(uint64_t amount) { + this->amount += amount; + count++; + } +}; + +class TrackMetrics { + public: + TrackMetrics(std::shared_ptr ctx, uint64_t pos = 0); + + std::shared_ptr currentInterval; + uint64_t longestInterval = 0, totalAmountOfPlayTime = 0, + totalMsOfPlayedTrack = 0, totalAmountPlayed = 0, audioKeyTime = 0, + trackHeaderTime = 0, written_bytes = 0, track_size = 0, + timestamp = 0; + std::vector> intervals; + skip skipped_backward, skipped_forward; + + void newPosition(uint64_t pos); + void endInterval(uint64_t pos); + void endTrack(); + void startTrackDecoding(); + void startTrack(uint64_t pos); + uint64_t getPosition(); + + private: + std::shared_ptr ctx; + std::vector> addInterval( + std::vector>& intervals, + std::pair newInterval) { + // Add the new interval to the list of intervals + intervals.push_back(newInterval); + + // Sort intervals by starting time + std::sort(intervals.begin(), intervals.end()); + + // Result vector to hold merged intervals + std::vector> merged; + + // Iterate over intervals to merge overlapping ones + for (const auto& interval : intervals) { + // If merged is empty or current interval does not overlap with the previous one + if (merged.empty() || merged.back().second < interval.first) { + merged.push_back(interval); + } else { + // If it overlaps, merge the intervals + merged.back().second = std::max(merged.back().second, interval.second); } - - return merged; - } - - - }; - class PlaybackMetrics { - private: - - std::shared_ptr ctx; - uint32_t seqNum = 0; - size_t timestamp; - - std::string get_source_from_context(); - std::string get_end_source(); - - void append(std::vector* data, std::string to_do) { - data->insert(data->end(), to_do.begin(), to_do.end()); - data->push_back(9); } - public: - - PlaybackMetrics(std::shared_ptr ctx) { - this->ctx = ctx; - } - enum reason { - TRACK_DONE, - TRACK_ERROR, - FORWARD_BTN, - BACKWARD_BTN, - END_PLAY, - PLAY_BTN, - CLICK_ROW, - LOGOUT, - APP_LOAD, - REMOTE, - UNKNOWN - }end_reason = UNKNOWN, start_reason = UNKNOWN, nested_reason = UNKNOWN; - - std::string context_uri, correlation_id, start_source, end_source; - std::shared_ptr trackMetrics; - - std::vector sendEvent(std::shared_ptr track); - - }; -} \ No newline at end of file + return merged; + } +}; +class PlaybackMetrics { + private: + std::shared_ptr ctx; + uint32_t seqNum = 0; + size_t timestamp; + + std::string get_source_from_context(); + std::string get_end_source(); + + void append(std::vector* data, std::string to_do) { + data->insert(data->end(), to_do.begin(), to_do.end()); + data->push_back(9); + } + + public: + PlaybackMetrics(std::shared_ptr ctx) { this->ctx = ctx; } + enum reason { + TRACK_DONE, + TRACK_ERROR, + FORWARD_BTN, + BACKWARD_BTN, + END_PLAY, + PLAY_BTN, + CLICK_ROW, + LOGOUT, + APP_LOAD, + REMOTE, + UNKNOWN + } end_reason = UNKNOWN, + start_reason = UNKNOWN, nested_reason = UNKNOWN; + + std::string context_uri, correlation_id, start_source, end_source; + std::shared_ptr trackMetrics; + + std::vector sendEvent(std::shared_ptr track); +}; +} // namespace cspot \ No newline at end of file diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 34f98117..da320f96 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -5,11 +5,11 @@ #include #include #include -#include //for random_device and default_random_engine +#include //for random_device and default_random_engine #include "BellTask.h" +#include "EventManager.h" // for TrackMetrics #include "PlaybackState.h" -#include "EventManager.h" // for TrackMetrics #include "TrackReference.h" #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode @@ -64,7 +64,7 @@ class QueuedTrack { std::string identifier; bool loading = false; std::shared_ptr trackMetrics; - + // Will return nullptr if the track is not ready std::shared_ptr getAudioFile(); @@ -127,7 +127,7 @@ class TrackQueue : public bell::Task { std::shared_ptr processSemaphore; std::deque> preloadedTracks; - std::vectoralt_index; + std::vector alt_index; std::vector currentTracks; std::vector ghostTracks; std::mutex tracksMutex, runningMutex; diff --git a/cspot/src/EventManager.cpp b/cspot/src/EventManager.cpp index 52e64686..ca079371 100644 --- a/cspot/src/EventManager.cpp +++ b/cspot/src/EventManager.cpp @@ -1,23 +1,13 @@ #include "EventManager.h" -#include "CSpotContext.h" // for Context::ConfigState, Context (ptr o... -#include "TrackQueue.h" // for Context::ConfigState, Context (ptr o... -#include "Logger.h" // for CSPOT_LOG +#include "CSpotContext.h" // for Context::ConfigState, Context (ptr o... +#include "Logger.h" // for CSPOT_LOG +#include "TrackQueue.h" using namespace cspot; static std::string reason_text[11] = { - "trackdone", - "trackerror", - "fwdbtn", - "backbtn", - "endplay", - "playbtn", - "clickrow", - "logout", - "appload", - "remote", - "" -}; + "trackdone", "trackerror", "fwdbtn", "backbtn", "endplay", "playbtn", + "clickrow", "logout", "appload", "remote", ""}; TrackMetrics::TrackMetrics(std::shared_ptr ctx, uint64_t pos) { this->ctx = ctx; @@ -26,25 +16,32 @@ TrackMetrics::TrackMetrics(std::shared_ptr ctx, uint64_t pos) { } void TrackMetrics::endInterval(uint64_t pos) { - // end Interval - currentInterval->length = this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start; + // end Interval + currentInterval->length = + this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start; currentInterval->end = currentInterval->position + currentInterval->length; totalAmountPlayed += currentInterval->length; - // add skipped time + // add skipped time if (pos != 0) { if (pos > currentInterval->position + currentInterval->length) - skipped_forward.add(pos - (currentInterval->position + currentInterval->length)); - else skipped_backward.add((currentInterval->position + currentInterval->length) - pos); + skipped_forward.add( + pos - (currentInterval->position + currentInterval->length)); + else + skipped_backward.add( + (currentInterval->position + currentInterval->length) - pos); } - if (currentInterval->length > longestInterval) longestInterval = currentInterval->length; - intervals = addInterval(intervals, { currentInterval->position, currentInterval->end }); + if (currentInterval->length > longestInterval) + longestInterval = currentInterval->length; + intervals = + addInterval(intervals, {currentInterval->position, currentInterval->end}); } uint64_t TrackMetrics::getPosition() { - return (currentInterval->position + (this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start)); + return ( + currentInterval->position + + (this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start)); } - void TrackMetrics::startTrackDecoding() { trackHeaderTime = this->ctx->timeProvider->getSyncedTimestamp(); audioKeyTime = trackHeaderTime - timestamp; @@ -52,28 +49,38 @@ void TrackMetrics::startTrackDecoding() { void TrackMetrics::startTrack(uint64_t pos) { audioKeyTime = this->ctx->timeProvider->getSyncedTimestamp() - audioKeyTime; - currentInterval = std::make_shared(this->ctx->timeProvider->getSyncedTimestamp(), pos); + currentInterval = std::make_shared( + this->ctx->timeProvider->getSyncedTimestamp(), pos); } void TrackMetrics::endTrack() { endInterval(0); - for (const auto& interval : intervals) totalMsOfPlayedTrack += interval.second - interval.first; - totalAmountOfPlayTime = this->ctx->timeProvider->getSyncedTimestamp() - timestamp; + for (const auto& interval : intervals) + totalMsOfPlayedTrack += interval.second - interval.first; + totalAmountOfPlayTime = + this->ctx->timeProvider->getSyncedTimestamp() - timestamp; } void TrackMetrics::newPosition(uint64_t pos) { - if (pos == currentInterval->position + currentInterval->length) return; + if (pos == currentInterval->position + currentInterval->length) + return; endInterval(pos); - currentInterval = std::make_shared(this->ctx->timeProvider->getSyncedTimestamp(), pos); + currentInterval = std::make_shared( + this->ctx->timeProvider->getSyncedTimestamp(), pos); } std::string PlaybackMetrics::get_source_from_context() { if (context_uri != "") { - if (context_uri.find("playlist") != std::string::npos) return "playlist"; - else if (context_uri.find("collection") != std::string::npos) return "your_library"; - else if (context_uri.find("artist") != std::string::npos) return "artist"; - else if (context_uri.find("album") != std::string::npos) return "album"; - else if (context_uri.find("track") != std::string::npos) return "track"; + if (context_uri.find("playlist") != std::string::npos) + return "playlist"; + else if (context_uri.find("collection") != std::string::npos) + return "your_library"; + else if (context_uri.find("artist") != std::string::npos) + return "artist"; + else if (context_uri.find("album") != std::string::npos) + return "album"; + else if (context_uri.find("track") != std::string::npos) + return "track"; } return ""; } @@ -81,7 +88,8 @@ std::string PlaybackMetrics::get_end_source() { end_source = get_source_from_context(); return end_source; } -std::vector PlaybackMetrics::sendEvent(std::shared_ptr track) { +std::vector PlaybackMetrics::sendEvent( + std::shared_ptr track) { std::string data; std::vector msg; CSPOT_LOG(debug, "Sending playbackend event"); @@ -91,78 +99,148 @@ std::vector PlaybackMetrics::sendEvent(std::shared_ptrctx->config.deviceId); - append(&msg, track->identifier); //PLAYBACKiD - append(&msg, "00000000000000000000000000000000"); //parent_playback_id + append(&msg, track->identifier); //PLAYBACKiD + append(&msg, "00000000000000000000000000000000"); //parent_playback_id append(&msg, start_source); - append(&msg, reason_text[(uint8_t)start_reason]); //remote when taken over by anyone - append(&msg, end_source == "" ? get_end_source() : end_source); //free-tier-artist / playlist / your_library .com.spotify.gaia / artist - append(&msg, reason_text[(uint8_t)end_reason]); //remote when taken over of anyone - append(&msg, std::to_string(track->written_bytes)); //@librespot usually the same size as track->size, if shifted forward, usually shorter, if shifted backward, usually bigger - append(&msg, std::to_string(track->trackMetrics->track_size)); //in bytes - append(&msg, std::to_string(track->trackMetrics->totalAmountOfPlayTime)); //total millis from start to end (sometimes a little longer than millis_played) pause has no influence - append(&msg, std::to_string(track->trackMetrics->totalAmountPlayed)); //total millis played - append(&msg, std::to_string(track->trackInfo.duration)); //track duration in millis - append(&msg, std::to_string(track->trackMetrics->trackHeaderTime));//total time of decrypting? often 3 or 4 when nothing played -1 - append(&msg, "0");// fadeoverlapp? usually 0, but fading is set on - append(&msg, "0");// librespot says, could bee that the first value shows if it is the first played song, usually 0 - append(&msg, "0");//?? usually 0 - append(&msg, "0");//?? usually 0 - append(&msg, std::to_string(track->trackMetrics->skipped_backward.count));//total times skipped backward - append(&msg, std::to_string(track->trackMetrics->skipped_backward.amount));//total amount of time skipped backward - append(&msg, std::to_string(track->trackMetrics->skipped_forward.count));//total times skipped forward - append(&msg, std::to_string(track->trackMetrics->skipped_forward.amount));//total amount of time skipped forward - append(&msg, "15"); //randomNumber; biggest value so far 260, usually biggert than 1 //spotify says play latencie - append(&msg, "-1"); // usually -1, if paused positive, probablly in seconds + append( + &msg, + reason_text[(uint8_t)start_reason]); //remote when taken over by anyone + append( + &msg, + end_source == "" + ? get_end_source() + : end_source); //free-tier-artist / playlist / your_library .com.spotify.gaia / artist + append(&msg, + reason_text[(uint8_t)end_reason]); //remote when taken over of anyone + append( + &msg, + std::to_string( + track + ->written_bytes)); //@librespot usually the same size as track->size, if shifted forward, usually shorter, if shifted backward, usually bigger + append(&msg, std::to_string(track->trackMetrics->track_size)); //in bytes + append( + &msg, + std::to_string( + track->trackMetrics + ->totalAmountOfPlayTime)); //total millis from start to end (sometimes a little longer than millis_played) pause has no influence + append(&msg, + std::to_string( + track->trackMetrics->totalAmountPlayed)); //total millis played + append(&msg, + std::to_string(track->trackInfo.duration)); //track duration in millis + append( + &msg, + std::to_string( + track->trackMetrics + ->trackHeaderTime)); //total time of decrypting? often 3 or 4 when nothing played -1 + append(&msg, "0"); // fadeoverlapp? usually 0, but fading is set on + append( + &msg, + "0"); // librespot says, could bee that the first value shows if it is the first played song, usually 0 + append(&msg, "0"); //?? usually 0 + append(&msg, "0"); //?? usually 0 + append(&msg, std::to_string(track->trackMetrics->skipped_backward + .count)); //total times skipped backward + append(&msg, + std::to_string(track->trackMetrics->skipped_backward + .amount)); //total amount of time skipped backward + append(&msg, std::to_string(track->trackMetrics->skipped_forward + .count)); //total times skipped forward + append(&msg, + std::to_string(track->trackMetrics->skipped_forward + .amount)); //total amount of time skipped forward + append( + &msg, + "15"); //randomNumber; biggest value so far 260, usually biggert than 1 //spotify says play latencie + append(&msg, "-1"); // usually -1, if paused positive, probablly in seconds append(&msg, "context"); - append(&msg, std::to_string(track->trackMetrics->audioKeyTime));//time to get the audiokey? usually -1 - append(&msg, "0"); // usually 0 - append(&msg, "1");// @librespot audioKey preloaded? usually positive (1) - append(&msg, "0");//?? usually 0 - append(&msg, "0");//?? usually bigger than 0, if startup(not playing) or takenover "0" - append(&msg, "1"); // usually 1 , if taken over 0, if player took over not from the start 0 - append(&msg, std::to_string(track->trackMetrics->longestInterval)); //length longest interval - append(&msg, std::to_string(track->trackMetrics->totalMsOfPlayedTrack)); //total time since start total millis of song played - append(&msg, "0");//?? usually 0 - append(&msg, "320000");//CONFIG_CSPOT_AUDIO_FORMAT ? CONFIG_CSPOT_AUDIO_FORMAT == 2 ? "320000" : "160000" : "96000"); // bitrate + append(&msg, std::to_string( + track->trackMetrics + ->audioKeyTime)); //time to get the audiokey? usually -1 + append(&msg, "0"); // usually 0 + append(&msg, "1"); // @librespot audioKey preloaded? usually positive (1) + append(&msg, "0"); //?? usually 0 + append( + &msg, + "0"); //?? usually bigger than 0, if startup(not playing) or takenover "0" + append( + &msg, + "1"); // usually 1 , if taken over 0, if player took over not from the start 0 + append(&msg, + std::to_string( + track->trackMetrics->longestInterval)); //length longest interval + append( + &msg, + std::to_string( + track->trackMetrics + ->totalMsOfPlayedTrack)); //total time since start total millis of song played + append(&msg, "0"); //?? usually 0 + append( + &msg, + "320000"); //CONFIG_CSPOT_AUDIO_FORMAT ? CONFIG_CSPOT_AUDIO_FORMAT == 2 ? "320000" : "160000" : "96000"); // bitrate append(&msg, context_uri); append(&msg, "vorbis"); - append(&msg, track->trackInfo.trackId); // sometimes, when commands come from outside, or else, this value is something else and the following one is the gid + append( + &msg, + track->trackInfo + .trackId); // sometimes, when commands come from outside, or else, this value is something else and the following one is the gid append(&msg, ""); - append(&msg, "0");//?? usually 0 - append(&msg, std::to_string(track->trackMetrics->timestamp)); // unix timestamp when track started - append(&msg, "0");//?? usually 0 + append(&msg, "0"); //?? usually 0 + append(&msg, + std::to_string(track->trackMetrics + ->timestamp)); // unix timestamp when track started + append(&msg, "0"); //?? usually 0 append(&msg, track->ref.context == "radio" ? "autoplay" : "context"); - append(&msg, (end_source == "playlist" || end_source == "your_library") ? "your_library" : "search");//std::to_string(this->ctx->referrerIdentifier));//your_library:lybrary_header / autoplay:afterplaylist / search:found in search / find /home:found in home - append(&msg, "xpui_2024-05-31_1717155884878_"); //xpui_2024-05-31_1717155884878_ xpui_ + date of version(update) + _ + unix_timestamp probably of update //empty if autoplay + append( + &msg, + (end_source == "playlist" || end_source == "your_library") + ? "your_library" + : "search"); //std::to_string(this->ctx->referrerIdentifier));//your_library:lybrary_header / autoplay:afterplaylist / search:found in search / find /home:found in home + append( + &msg, + "xpui_2024-05-31_1717155884878_"); //xpui_2024-05-31_1717155884878_ xpui_ + date of version(update) + _ + unix_timestamp probably of update //empty if autoplay append(&msg, "com.spotify"); - append(&msg, "none"); //"transition" : gapless if song ended beforehand inside player + append( + &msg, + "none"); //"transition" : gapless if song ended beforehand inside player append(&msg, "none"); - append(&msg, "local"); // @librespot lastCommandSentByDeviceId , usually"local", if orderd from outside last command ident last comment ident from frame.state + append( + &msg, + "local"); // @librespot lastCommandSentByDeviceId , usually"local", if orderd from outside last command ident last comment ident from frame.state append(&msg, "na"); append(&msg, "none"); - append(&msg, ""); // 3067b220-9721-4489-93b4-118dd3a59b7b //page-instance-id // changing , if radio / autoplay empty - append(&msg, ""); // 054dfc5a-0108-4971-b8de-1fd95070e416 //interaction_id // stays still , if radio / autoplay capped + append( + &msg, + ""); // 3067b220-9721-4489-93b4-118dd3a59b7b //page-instance-id // changing , if radio / autoplay empty + append( + &msg, + ""); // 054dfc5a-0108-4971-b8de-1fd95070e416 //interaction_id // stays still , if radio / autoplay capped append(&msg, ""); append(&msg, "5003900000000146"); append(&msg, ""); - append(&msg, track->ref.context == "radio" ? correlation_id : ""); //ssp~061a6236e23e1a9847bd9b6ad4cd942eac8d //allways the same , only when radio? / autoplay + append( + &msg, + track->ref.context == "radio" + ? correlation_id + : ""); //ssp~061a6236e23e1a9847bd9b6ad4cd942eac8d //allways the same , only when radio? / autoplay append(&msg, ""); - append(&msg, "0");//?? usually 0 - append(&msg, "0");//?? usually 0 + append(&msg, "0"); //?? usually 0 + append(&msg, "0"); //?? usually 0 - if (end_reason == END_PLAY) start_reason = nested_reason; - else start_reason = end_reason; + if (end_reason == END_PLAY) + start_reason = nested_reason; + else + start_reason = end_reason; start_source = end_source; #ifndef CONFIG_HIDDEN auto responseLambda = [=](MercurySession::Response& res) { - }; + }; - auto parts = MercurySession::DataParts({ msg }); + auto parts = MercurySession::DataParts({msg}); // Execute the request - ctx->session->execute(MercurySession::RequestType::SEND, - requestUrl, - responseLambda, parts); + ctx->session->execute(MercurySession::RequestType::SEND, requestUrl, + responseLambda, parts); #endif return msg; } \ No newline at end of file diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index 7d880ea1..e925e288 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -177,9 +177,12 @@ void MercurySession::handlePacket() { auto response = this->decodeResponse(packet.data); if (response.first == static_cast(ResponseFlag::FINAL)) { auto partial = this->partials.find(response.second); - if (this->callbacks.count(response.second)) { - this->callbacks[response.second](partial->second); - this->callbacks.erase(this->callbacks.find(response.second)); + //if the event-id is negative, they got sent without any request + if (response.first >= 0) { + if (this->callbacks.count(response.second)) { + this->callbacks[response.second](partial->second); + this->callbacks.erase(this->callbacks.find(response.second)); + } } this->partials.erase(partial); } @@ -228,11 +231,11 @@ std::pair MercurySession::decodeResponse( uint64_t sequenceId; uint8_t flag; if (sequenceLength == 2) - sequenceId = ntohs(extract(data, 2)); + sequenceId = ntohs(extract(data, 2)); else if (sequenceLength == 4) - sequenceId = ntohl(extract(data, 2)); + sequenceId = ntohl(extract(data, 2)); else if (sequenceLength == 8) - sequenceId = hton64(extract(data, 2)); + sequenceId = hton64(extract(data, 2)); else return std::make_pair(0, 0); diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index 75482465..dbf09877 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -219,14 +219,16 @@ void SpircHandler::handleFrame(std::vector& data) { } case MessageType_kMessageTypeShuffle: { CSPOT_LOG(debug, "Got shuffle frame"); - playbackState->innerFrame.state.shuffle = playbackState->remoteFrame.state.shuffle; + playbackState->innerFrame.state.shuffle = + playbackState->remoteFrame.state.shuffle; trackQueue->shuffle_tracks(playbackState->remoteFrame.state.shuffle); this->notify(); break; } case MessageType_kMessageTypeRepeat: { CSPOT_LOG(debug, "Got repeat frame"); - playbackState->innerFrame.state.repeat = playbackState->remoteFrame.state.repeat; + playbackState->innerFrame.state.repeat = + playbackState->remoteFrame.state.repeat; trackQueue->prepareRepeat(); this->notify(); break; diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index e736d9a2..b65f3cc7 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -5,13 +5,13 @@ #include // for remove_extent_t #include // for vector, vector<>::value_type -#include "BellLogger.h" // for AbstractLogger -#include "BellUtils.h" // for BELL_SLEEP_MS +#include "BellLogger.h" // for AbstractLogger +#include "BellUtils.h" // for BELL_SLEEP_MS +#include "CSpotContext.h" #include "Logger.h" // for CSPOT_LOG #include "Packet.h" // for cspot #include "TrackQueue.h" // for CDNTrackStream, CDNTrackStream::TrackInfo #include "WrappedSemaphore.h" // for WrappedSemaphore -#include "CSpotContext.h" #ifndef CONFIG_BELL_NOCODEC #ifdef BELL_VORBIS_FLOAT @@ -88,8 +88,8 @@ void TrackPlayer::start() { startTask(); this->ctx->playbackMetrics->start_reason = PlaybackMetrics::REMOTE; this->ctx->playbackMetrics->start_source = "unknown"; - } - else this->ctx->playbackMetrics->end_reason = PlaybackMetrics::END_PLAY; + } else + this->ctx->playbackMetrics->end_reason = PlaybackMetrics::END_PLAY; } void TrackPlayer::stop() { @@ -124,7 +124,7 @@ void TrackPlayer::seekMs(size_t ms) { void TrackPlayer::runTask() { std::scoped_lock lock(runningMutex); - std::shared_ptr track= nullptr, newTrack = nullptr; + std::shared_ptr track = nullptr, newTrack = nullptr; int trackOffset = 0; size_t tracksPlayed = 0; @@ -217,25 +217,28 @@ void TrackPlayer::runTask() { size_t start_offset = 0; size_t write_offset = 0; while (!start_offset) { - size_t ret = this->currentTrackStream->readBytes(&pcmBuffer[0], pcmBuffer.size()); + size_t ret = this->currentTrackStream->readBytes(&pcmBuffer[0], + pcmBuffer.size()); size_t written = 0; size_t toWrite = ret; while (toWrite) { - written = dataCallback(pcmBuffer.data() + (ret - toWrite), - toWrite, tracksPlayed, 0); + written = dataCallback(pcmBuffer.data() + (ret - toWrite), toWrite, + tracksPlayed, 0); if (written == 0) { BELL_SLEEP_MS(1000); } toWrite -= written; } track->written_bytes += ret; - start_offset = seekable_callback(tracksPlayed); - if(this->spaces_available(tracksPlayed)spaces_available(tracksPlayed) < pcmBuffer.size()) { + BELL_SLEEP_MS(50); continue; } } - float duration_lambda = 1.0 * (currentTrackStream->getSize() - start_offset) / track->trackInfo.duration; + float duration_lambda = 1.0 * + (currentTrackStream->getSize() - start_offset) / + track->trackInfo.duration; #endif if (pendingSeekPositionMs > 0) { track->requestedPosition = pendingSeekPositionMs; @@ -249,7 +252,8 @@ void TrackPlayer::runTask() { #ifndef CONFIG_BELL_NOCODEC VORBIS_SEEK(&vorbisFile, track->requestedPosition); #else - size_t seekPosition = track->requestedPosition * duration_lambda + start_offset; + size_t seekPosition = + track->requestedPosition * duration_lambda + start_offset; currentTrackStream->seek(seekPosition); skipped = true; #endif @@ -274,7 +278,7 @@ void TrackPlayer::runTask() { #else seekPosition = seekPosition * duration_lambda + start_offset; currentTrackStream->seek(seekPosition); - track->trackMetrics->newPosition(pendingSeekPositionMs); + track->trackMetrics->newPosition(pendingSeekPositionMs); skipped = true; #endif @@ -282,13 +286,13 @@ void TrackPlayer::runTask() { pendingSeekPositionMs = 0; } - long ret = #ifdef CONFIG_BELL_NOCODEC - this->currentTrackStream->readBytes(&pcmBuffer[0], pcmBuffer.size()); + this->currentTrackStream->readBytes(&pcmBuffer[0], + pcmBuffer.size()); #else - VORBIS_READ(&vorbisFile, (char*)&pcmBuffer[0], - pcmBuffer.size(), ¤tSection); + VORBIS_READ(&vorbisFile, (char*)&pcmBuffer[0], pcmBuffer.size(), + ¤tSection); #endif if (ret == 0) { @@ -317,10 +321,11 @@ void TrackPlayer::runTask() { #endif written = dataCallback(pcmBuffer.data() + (ret - toWrite), toWrite, tracksPlayed - #ifdef CONFIG_BELL_NOCODEC - ,skipped - #endif - ); +#ifdef CONFIG_BELL_NOCODEC + , + skipped +#endif + ); } if (written == 0) { BELL_SLEEP_MS(50); @@ -342,7 +347,8 @@ void TrackPlayer::runTask() { currentTrackStream = nullptr; track->loading = false; track->trackMetrics->endTrack(); - std::vector result = this->ctx->playbackMetrics->sendEvent(track); + std::vector result = + this->ctx->playbackMetrics->sendEvent(track); } if (eof) { @@ -396,10 +402,12 @@ long TrackPlayer::_vorbisTell() { } #endif -void TrackPlayer::setDataCallback(DataCallback callback, SeekableCallback seekable_callback, SeekableCallback spaces_available ) { +void TrackPlayer::setDataCallback(DataCallback callback, + SeekableCallback seekable_callback, + SeekableCallback spaces_available) { this->dataCallback = callback; - #ifdef CONFIG_BELL_NOCODEC +#ifdef CONFIG_BELL_NOCODEC this->seekable_callback = seekable_callback; this->spaces_available = spaces_available; - #endif +#endif } diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index bfc8d239..727adfc7 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -2,10 +2,10 @@ #include #include -#include #include #include #include +#include #include "AccessKeyFetcher.h" #include "BellTask.h" @@ -25,8 +25,9 @@ using namespace cspot; -static void randomizeIndex(std::vector &index, uint16_t offset, std::default_random_engine rng){ - std::shuffle(index.begin() + offset, index.end(),rng); +static void randomizeIndex(std::vector& index, uint16_t offset, + std::default_random_engine rng) { + std::shuffle(index.begin() + offset, index.end(), rng); } namespace TrackDataUtils { @@ -487,98 +488,111 @@ std::shared_ptr TrackQueue::consumeTrack( return preloadedTracks[offset]; } -void TrackQueue::update_ghost_tracks(int16_t offset){ - if(currentTracksIndex + offset >= SEND_OLD_TRACKS) this->playbackState->innerFrame.state.index = SEND_OLD_TRACKS; - else this->playbackState->innerFrame.state.index = currentTracksIndex + offset; +void TrackQueue::update_ghost_tracks(int16_t offset) { + if (currentTracksIndex + offset >= SEND_OLD_TRACKS) + this->playbackState->innerFrame.state.index = SEND_OLD_TRACKS; + else + this->playbackState->innerFrame.state.index = currentTracksIndex + offset; ghostTracks.clear(); - uint16_t index = currentTracksIndex + offset > SEND_OLD_TRACKS ? currentTracksIndex + offset - SEND_OLD_TRACKS : 0; + uint16_t index = currentTracksIndex + offset > SEND_OLD_TRACKS + ? currentTracksIndex + offset - SEND_OLD_TRACKS + : 0; uint16_t end = currentTracksIndex + offset + SEND_FUTURE_TRACKS + 1; - if(end >= currentTracks.size())end = currentTracks.size(); - for (uint16_t i = 0; i < end - index; i++){ - ghostTracks.push_back(currentTracks[(index + i) >= currentTracksSize ? index + i : alt_index[ index + i]]); + if (end >= currentTracks.size()) + end = currentTracks.size(); + for (uint16_t i = 0; i < end - index; i++) { + ghostTracks.push_back( + currentTracks[(index + i) >= currentTracksSize ? index + i + : alt_index[index + i]]); } } -void TrackQueue::loadRadio(std::string req){ +void TrackQueue::loadRadio(std::string req) { size_t keepTracks = currentTracks.size() - currentTracksIndex; - keepTracks = keepTracks < inner_tracks_treshhold ? keepTracks : inner_tracks_treshhold; - if (keepTracks < inner_tracks_treshhold && continue_with_radio && currentTracks.size()) { + keepTracks = + keepTracks < inner_tracks_treshhold ? keepTracks : inner_tracks_treshhold; + if (keepTracks < inner_tracks_treshhold && continue_with_radio && + currentTracks.size()) { //if currentTrack is over the treshhold, remove some tracks from the front - if (currentTracks.size() > inner_tracks_treshhold * 3){ + if (currentTracks.size() > inner_tracks_treshhold * 3) { uint32_t int_offset = currentTracks.size() - inner_tracks_treshhold; - currentTracks.erase(currentTracks.begin(), currentTracks.begin() + int_offset); + currentTracks.erase(currentTracks.begin(), + currentTracks.begin() + int_offset); currentTracksIndex -= int_offset; } std::string requestUrl = string_format( - "hm://radio-apollo/v3/stations/%s?autoplay=true&offset=%i", - &req[0],radio_offset); + "hm://radio-apollo/v3/stations/%s?autoplay=true&offset=%i", &req[0], + radio_offset); auto responseHandler = [this](MercurySession::Response& res) { std::scoped_lock lock(tracksMutex); CSPOT_LOG(info, "Fetched new radio tracks"); - if (res.parts[0].size() == 0) return; + if (res.parts[0].size() == 0) + return; auto jsonResult = nlohmann::json::parse(res.parts[0]); radio_offset += jsonResult["tracks"].size(); std::string uri; for (int i = 0; i < jsonResult["tracks"].size(); i++) { currentTracks.push_back( - TrackReference(jsonResult["tracks"][i]["original_gid"], "radio") - ); + TrackReference(jsonResult["tracks"][i]["original_gid"], "radio")); } this->ctx->playbackMetrics->correlation_id = jsonResult["correlation_id"]; - if(preloadedTracks.size() < MAX_TRACKS_PRELOAD){ + if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { queueNextTrack(preloadedTracks.size()); } - }; + }; // Execute the request - ctx->session->execute( - MercurySession::RequestType::GET, requestUrl, responseHandler); + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); } } void TrackQueue::resolveAutoplay() { - if(!this->playbackState->innerFrame.state.context_uri) return; - std::string requestUrl = string_format( - "hm://autoplay-enabled/query?uri=%s", - this->playbackState->innerFrame.state.context_uri); + if (!this->playbackState->innerFrame.state.context_uri) + return; + std::string requestUrl = + string_format("hm://autoplay-enabled/query?uri=%s", + this->playbackState->innerFrame.state.context_uri); auto responseHandler = [this](MercurySession::Response& res) { - if(res.parts.size()){ - loadRadio(std::string(res.parts[0].begin(), res.parts[0].end())); + if (res.parts.size()) { + loadRadio(std::string(res.parts[0].begin(), res.parts[0].end())); } }; // Execute the request - ctx->session->execute( - MercurySession::RequestType::GET, requestUrl, responseHandler); + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); } -void TrackQueue::resolveContext() { - std::scoped_lock lock(tracksMutex); - std::string requestUrl = string_format( - "hm://context-resolve/v1/%s", - this->playbackState->innerFrame.state.context_uri); - auto responseHandler = [this](MercurySession::Response& res) { +void TrackQueue::resolveContext() { + std::scoped_lock lock(tracksMutex); + std::string requestUrl = + string_format("hm://context-resolve/v1/%s", + this->playbackState->innerFrame.state.context_uri); + auto responseHandler = [this](MercurySession::Response& res) { std::scoped_lock lock(tracksMutex); auto jsonResult = nlohmann::json::parse(res.parts[0]); //do nothing if last track is the same as last track in currentTracks - for(auto pages_itr:jsonResult["pages"]) { + for (auto pages_itr : jsonResult["pages"]) { TrackReference _ref; int32_t front = 0; - if(pages_itr.find("tracks")==pages_itr.end())continue; - if(this->playbackState->innerFrame.state.shuffle) { + if (pages_itr.find("tracks") == pages_itr.end()) + continue; + if (this->playbackState->innerFrame.state.shuffle) { std::vector new_alt_index; std::vector alt_tracks; - for(int i = 0; i < pages_itr["tracks"].size(); i++) + for (int i = 0; i < pages_itr["tracks"].size(); i++) new_alt_index.push_back(i); //not written yet - for(auto itr:pages_itr["tracks"]) { + for (auto itr : pages_itr["tracks"]) { _ref = TrackReference(itr["uri"]); auto currentTracksIter = - std::find(currentTracks.begin(), currentTracks.end(), _ref); - if(currentTracksIter != currentTracks.end()) { - int32_t old_index = std::distance(currentTracks.begin(), currentTracksIter); + std::find(currentTracks.begin(), currentTracks.end(), _ref); + if (currentTracksIter != currentTracks.end()) { + int32_t old_index = + std::distance(currentTracks.begin(), currentTracksIter); new_alt_index[front] = new_alt_index[alt_index[old_index]]; new_alt_index[alt_index[old_index]] = front; alt_index[old_index] = -1; @@ -587,52 +601,55 @@ void TrackQueue::resolveContext() { front++; } // in case of smartshuffle, we currently just put the few already recieved "smart-tracks" in order and reshuffle the whole playlist - for(size_t i = 0; i < alt_index.size(); i++ ) { - if(alt_index[i] >= 0) { + for (size_t i = 0; i < alt_index.size(); i++) { + if (alt_index[i] >= 0) { new_alt_index.push_back(new_alt_index[alt_index[i]]); new_alt_index[alt_index[i]] = alt_tracks.size(); alt_tracks.push_back(currentTracks[alt_index[i]]); } } - randomizeIndex(new_alt_index,currentTracks.size(),rng); + randomizeIndex(new_alt_index, currentTracks.size(), rng); alt_index = new_alt_index; currentTracks = alt_tracks; } else { auto altref = currentTracks.front().gid; uint8_t loop_pointer = 0; - for(auto itr:pages_itr["tracks"]){ + for (auto itr : pages_itr["tracks"]) { _ref = TrackReference(itr["uri"]); - switch(loop_pointer){ - case 0 : - if(_ref.gid==altref) { + switch (loop_pointer) { + case 0: + if (_ref.gid == altref) { loop_pointer++; altref = currentTracks.back().gid; - if(altref == base62Decode(pages_itr["tracks"].back()["uri"])) goto exit_loop; + if (altref == base62Decode(pages_itr["tracks"].back()["uri"])) + goto exit_loop; } else { - //for completion of the trasklist in case of shuffle, add missing item too the front - currentTracks.insert(currentTracks.begin() + front, _ref); - front++; + //for completion of the trasklist in case of shuffle, add missing item too the front + currentTracks.insert(currentTracks.begin() + front, _ref); + front++; } break; - case 1 : - if(_ref.gid == altref) loop_pointer++; + case 1: + if (_ref.gid == altref) + loop_pointer++; break; - case 2 : + case 2: //add missing tracks to the back currentTracks.push_back(_ref); break; default: break; - } - } exit_loop: ; + } + exit_loop:; currentTracksIndex += front; - CSPOT_LOG(info, "Resolved context, new currentTracks-size = %i", currentTracks.size()); + CSPOT_LOG(info, "Resolved context, new currentTracks-size = %i", + currentTracks.size()); } } }; - ctx->session->execute( - MercurySession::RequestType::GET, requestUrl, responseHandler); + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); } void TrackQueue::processTrack(std::shared_ptr track) { @@ -647,14 +664,15 @@ void TrackQueue::processTrack(std::shared_ptr track) { case QueuedTrack::State::CDN_REQUIRED: track->stepLoadCDNUrl(accessKey); - if (track->state == QueuedTrack::State::READY) { - if(!context_resolved) { + if (track->state == QueuedTrack::State::READY) { + if (!context_resolved) { resolveContext(); context_resolved = true; } - if(continue_with_radio) - if(preloadedTracks.size() + currentTracksIndex >= currentTracks.size()) - resolveAutoplay(); + if (continue_with_radio) + if (preloadedTracks.size() + currentTracksIndex >= + currentTracks.size()) + resolveAutoplay(); if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { // Queue a new track to preload queueNextTrack(preloadedTracks.size()); @@ -669,7 +687,9 @@ void TrackQueue::processTrack(std::shared_ptr track) { bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { int requestedRefIndex = offset + currentTracksIndex; - if(playbackState->innerFrame.state.shuffle && requestedRefIndex < alt_index.size()) requestedRefIndex = alt_index[requestedRefIndex]; + if (playbackState->innerFrame.state.shuffle && + requestedRefIndex < alt_index.size()) + requestedRefIndex = alt_index[requestedRefIndex]; if (requestedRefIndex < 0 || requestedRefIndex >= currentTracks.size()) { return false; @@ -693,9 +713,10 @@ bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { } void TrackQueue::prepareRepeat() { - if(currentTracksIndex)currentTracksIndex--; - preloadedTracks.push_front(std::make_shared( - currentTracks[currentTracksIndex], ctx, 0)); + if (currentTracksIndex) + currentTracksIndex--; + preloadedTracks.push_front( + std::make_shared(currentTracks[currentTracksIndex], ctx, 0)); } bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { @@ -760,13 +781,15 @@ bool TrackQueue::isFinished() { } void TrackQueue::shuffle_tracks(bool shuffleTracks) { - if(!shuffleTracks)currentTracksIndex = alt_index[currentTracksIndex]; + if (!shuffleTracks) + currentTracksIndex = alt_index[currentTracksIndex]; alt_index.clear(); - for(int i = 0; i < currentTracksSize; i++) alt_index.push_back(i); - if(shuffleTracks) { + for (int i = 0; i < currentTracksSize; i++) + alt_index.push_back(i); + if (shuffleTracks) { alt_index[currentTracksIndex] = 0; alt_index[0] = currentTracksIndex; - randomizeIndex(alt_index,1, rng); + randomizeIndex(alt_index, 1, rng); currentTracksIndex = 0; } update_ghost_tracks(); @@ -781,7 +804,7 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { if (initial) { // initialize new random_engine - rng = std::default_random_engine { rd() }; + rng = std::default_random_engine{rd()}; // Copy requested track list currentTracks = playbackState->remoteTracks; currentTracksIndex = playbackState->innerFrame.state.playing_track_index; @@ -789,7 +812,8 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { // Revert the alternative Index to it's inital Index structure alt_index.clear(); - for(int i = 0; i < playbackState->remoteTracks.size(); i++) alt_index.push_back(i); + for (int i = 0; i < playbackState->remoteTracks.size(); i++) + alt_index.push_back(i); // Clear preloaded tracks preloadedTracks.clear(); @@ -806,9 +830,12 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { playableSemaphore->give(); } else { auto prevTrackIter = currentTracks.begin() + alt_index.size(); - alt_index.insert(alt_index.begin() + currentTracksIndex + 1, alt_index.size()); - - currentTracks.insert(prevTrackIter, playbackState->remoteTracks[playbackState->innerFrame.state.index + 1]); + alt_index.insert(alt_index.begin() + currentTracksIndex + 1, + alt_index.size()); + + currentTracks.insert( + prevTrackIter, + playbackState->remoteTracks[playbackState->innerFrame.state.index + 1]); if (preloadedTracks[0]->loading) { // try to not re-load track if we are still loading it diff --git a/cspot/src/TrackReference.cpp b/cspot/src/TrackReference.cpp index 2affd801..e978d9f3 100644 --- a/cspot/src/TrackReference.cpp +++ b/cspot/src/TrackReference.cpp @@ -5,7 +5,7 @@ using namespace cspot; -static std::string empty_string =""; +static std::string empty_string = ""; TrackReference::TrackReference() : type(Type::TRACK) {} @@ -43,7 +43,7 @@ bool TrackReference::pbEncodeTrackList(pb_ostream_t* stream, msg.gid.arg = &trackRef.gid; msg.uri.arg = &trackRef.uri; - msg.context.arg = &empty_string;//&trackRef.context; + msg.context.arg = &empty_string; //&trackRef.context; msg.queued.arg = &trackRef.queued; if (!pb_encode_submessage(stream, TrackRef_fields, &msg)) { diff --git a/cspot/src/Utils.cpp b/cspot/src/Utils.cpp index 0453e6b5..74c0c0d7 100644 --- a/cspot/src/Utils.cpp +++ b/cspot/src/Utils.cpp @@ -11,7 +11,8 @@ #include #endif -static std::string alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static std::string alphabet = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; unsigned long long getCurrentTimestamp() { return std::chrono::duration_cast( @@ -156,15 +157,16 @@ std::string urlDecode(std::string str) { } std::vector base62Decode(std::string uri) { - std::vector n = std::vector({0}); - auto it = uri.begin(); - if(uri.find(":")!=std::string::npos) it += uri.rfind(":") + 1; - while(it!=uri.end()) { - size_t d = alphabet.find(*it); - n = bigNumMultiply(n, 62); - n = bigNumAdd(n, d); - it++; - } + std::vector n = std::vector({0}); + auto it = uri.begin(); + if (uri.find(":") != std::string::npos) + it += uri.rfind(":") + 1; + while (it != uri.end()) { + size_t d = alphabet.find(*it); + n = bigNumMultiply(n, 62); + n = bigNumAdd(n, d); + it++; + } - return n; + return n; } \ No newline at end of file From a53083ae884c095e473db4b54f0d10e91153b76c Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 15 Jul 2024 17:21:07 +0200 Subject: [PATCH 16/41] Minor style fixes --- cspot/include/TrackPlayer.h | 12 +++++++----- cspot/include/TrackReference.h | 6 +++--- cspot/src/PlaybackState.cpp | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cspot/include/TrackPlayer.h b/cspot/include/TrackPlayer.h index 6d29d1b6..8dbeacd8 100644 --- a/cspot/include/TrackPlayer.h +++ b/cspot/include/TrackPlayer.h @@ -36,17 +36,17 @@ class TrackPlayer : bell::Task { // Callback types typedef std::function, bool)> TrackLoadedCallback; - typedef std::function + )> DataCallback; typedef std::function EOFCallback; typedef std::function SeekableCallback; - TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, EOFCallback eofCallback, TrackLoadedCallback loadedCallback); @@ -54,7 +54,9 @@ class TrackPlayer : bell::Task { void loadTrackFromRef(TrackReference& ref, size_t playbackMs, bool startAutomatically); - void setDataCallback(DataCallback callback, SeekableCallback seekable_callback = nullptr, SeekableCallback spaces_available = nullptr); + void setDataCallback(DataCallback callback, + SeekableCallback seekable_callback = nullptr, + SeekableCallback spaces_available = nullptr); // CDNTrackStream::TrackInfo getCurrentTrackInfo(); void seekMs(size_t ms); diff --git a/cspot/include/TrackReference.h b/cspot/include/TrackReference.h index 5d0d5b43..d303224b 100644 --- a/cspot/include/TrackReference.h +++ b/cspot/include/TrackReference.h @@ -5,17 +5,17 @@ #include #include #include "NanoPBHelper.h" -#include "Utils.h" //for base62decode +#include "Utils.h" //for base62decode #include "pb_decode.h" #include "protobuf/spirc.pb.h" namespace cspot { struct TrackReference { - TrackReference(); + TrackReference(); TrackReference(std::string uri, std::string context) : type(Type::TRACK) { this->gid = base62Decode(uri); //this->uri=uri; - this->context=context; + this->context = context; } TrackReference(std::string uri) : type(Type::TRACK) { gid = base62Decode(uri); diff --git a/cspot/src/PlaybackState.cpp b/cspot/src/PlaybackState.cpp index cdc9596d..56cca32e 100644 --- a/cspot/src/PlaybackState.cpp +++ b/cspot/src/PlaybackState.cpp @@ -118,7 +118,7 @@ void PlaybackState::syncWithRemote() { innerFrame.state.has_playing_track_index = true; innerFrame.state.playing_track_index = remoteFrame.state.playing_track_index; - innerFrame.state.has_shuffle = remoteFrame.state.has_shuffle;; + innerFrame.state.has_shuffle = remoteFrame.state.has_shuffle; innerFrame.state.shuffle = remoteFrame.state.shuffle; innerFrame.state.has_repeat = remoteFrame.state.has_repeat; innerFrame.state.repeat = remoteFrame.state.repeat; From a87f828439aaf095ff7285bcbea63630e80c3ef8 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 15 Jul 2024 18:03:57 +0200 Subject: [PATCH 17/41] Minor fixes --- cspot/src/TrackPlayer.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index 465c5c46..bbc21bd5 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -89,13 +89,8 @@ void TrackPlayer::start() { startTask(); this->ctx->playbackMetrics->start_reason = PlaybackMetrics::REMOTE; this->ctx->playbackMetrics->start_source = "unknown"; -<<<<<<< HEAD - } - else this->ctx->playbackMetrics->end_reason = PlaybackMetrics::END_PLAY; -======= } else this->ctx->playbackMetrics->end_reason = PlaybackMetrics::END_PLAY; ->>>>>>> master } void TrackPlayer::stop() { @@ -130,11 +125,7 @@ void TrackPlayer::seekMs(size_t ms) { void TrackPlayer::runTask() { std::scoped_lock lock(runningMutex); -<<<<<<< HEAD - std::shared_ptr track= nullptr, newTrack = nullptr; -======= std::shared_ptr track = nullptr, newTrack = nullptr; ->>>>>>> master int trackOffset = 0; size_t tracksPlayed = 0; From 2e7df5e5c5c795fde1e5e10259bd24e8f0146133 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 15 Jul 2024 18:10:38 +0200 Subject: [PATCH 18/41] fixing formating mistakes --- cspot/include/TrackQueue.h | 1 - cspot/src/EventManager.cpp | 2 +- cspot/src/TrackPlayer.cpp | 24 ------------------------ 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 30562770..2686077c 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -10,7 +10,6 @@ #include "BellTask.h" #include "EventManager.h" // for TrackMetrics #include "PlaybackState.h" -#include "EventManager.h" // for TrackMetrics #include "TrackReference.h" #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode diff --git a/cspot/src/EventManager.cpp b/cspot/src/EventManager.cpp index ca079371..f4faa1d5 100644 --- a/cspot/src/EventManager.cpp +++ b/cspot/src/EventManager.cpp @@ -1,7 +1,7 @@ #include "EventManager.h" #include "CSpotContext.h" // for Context::ConfigState, Context (ptr o... #include "Logger.h" // for CSPOT_LOG -#include "TrackQueue.h" +#include "TrackQueue.h" using namespace cspot; diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index bbc21bd5..243ccf7a 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -321,20 +321,12 @@ void TrackPlayer::runTask() { } #endif written = dataCallback(pcmBuffer.data() + (ret - toWrite), -<<<<<<< HEAD - toWrite, track->identifier - #ifdef CONFIG_BELL_NOCODEC - ,skipped - #endif - ); -======= toWrite, tracksPlayed #ifdef CONFIG_BELL_NOCODEC , skipped #endif ); ->>>>>>> master } if (written == 0) { BELL_SLEEP_MS(50); @@ -345,10 +337,7 @@ void TrackPlayer::runTask() { } } } -<<<<<<< HEAD -======= tracksPlayed++; ->>>>>>> master #ifndef CONFIG_BELL_NOCODEC ov_clear(&vorbisFile); #endif @@ -359,12 +348,8 @@ void TrackPlayer::runTask() { currentTrackStream = nullptr; track->loading = false; track->trackMetrics->endTrack(); -<<<<<<< HEAD - std::vector result = this->ctx->playbackMetrics->sendEvent(track); -======= std::vector result = this->ctx->playbackMetrics->sendEvent(track); ->>>>>>> master } if (eof) { @@ -418,14 +403,6 @@ long TrackPlayer::_vorbisTell() { } #endif -<<<<<<< HEAD -void TrackPlayer::setDataCallback(DataCallback callback, SeekableCallback seekable_callback, SeekableCallback spaces_available ) { - this->dataCallback = callback; - #ifdef CONFIG_BELL_NOCODEC - this->seekable_callback = seekable_callback; - this->spaces_available = spaces_available; - #endif -======= void TrackPlayer::setDataCallback(DataCallback callback, SeekableCallback seekable_callback, SeekableCallback spaces_available) { @@ -434,5 +411,4 @@ void TrackPlayer::setDataCallback(DataCallback callback, this->seekable_callback = seekable_callback; this->spaces_available = spaces_available; #endif ->>>>>>> master } From 24f7f3e9742714612275f11959ed8cb0ed69d71f Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 15 Jul 2024 18:14:19 +0200 Subject: [PATCH 19/41] fixing formating mistakes --- cspot/src/TrackPlayer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index 243ccf7a..b65f3cc7 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -12,7 +12,6 @@ #include "Packet.h" // for cspot #include "TrackQueue.h" // for CDNTrackStream, CDNTrackStream::TrackInfo #include "WrappedSemaphore.h" // for WrappedSemaphore -#include "CSpotContext.h" #ifndef CONFIG_BELL_NOCODEC #ifdef BELL_VORBIS_FLOAT From cb9f489666c8e8089ea4f4209528d2e39b1c467d Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 15 Jul 2024 20:24:21 +0200 Subject: [PATCH 20/41] Update currentTracksSize in the resolveContext function --- cspot/src/TrackQueue.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 727adfc7..557c89e6 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -502,8 +502,8 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { end = currentTracks.size(); for (uint16_t i = 0; i < end - index; i++) { ghostTracks.push_back( - currentTracks[(index + i) >= currentTracksSize ? index + i - : alt_index[index + i]]); + currentTracks[(index + i) >= alt_index.size() ? index + i + : alt_index[index + i]]); } } @@ -611,6 +611,7 @@ void TrackQueue::resolveContext() { randomizeIndex(new_alt_index, currentTracks.size(), rng); alt_index = new_alt_index; currentTracks = alt_tracks; + currentTracksSize = currentTracks.size(); } else { auto altref = currentTracks.front().gid; uint8_t loop_pointer = 0; @@ -846,7 +847,6 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { // Push a song on the preloaded queue CSPOT_LOG(info, "Keeping current track %d", currentTracksIndex); queueNextTrack(1); - cleared = false; } else { // Clear preloaded tracks From cd72ee67d5acf72736a8847d1216715e1a0363e4 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 16 Jul 2024 12:05:23 +0200 Subject: [PATCH 21/41] Solved problems with resolveContext in case of smart shuffle --- cspot/src/TrackQueue.cpp | 56 +++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 557c89e6..5621b279 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -581,37 +581,31 @@ void TrackQueue::resolveContext() { if (pages_itr.find("tracks") == pages_itr.end()) continue; if (this->playbackState->innerFrame.state.shuffle) { - std::vector new_alt_index; - std::vector alt_tracks; - for (int i = 0; i < pages_itr["tracks"].size(); i++) - new_alt_index.push_back(i); - //not written yet - for (auto itr : pages_itr["tracks"]) { - _ref = TrackReference(itr["uri"]); + std::vector new_index = {}; + std::vector new_tracks = {}; + for (const auto& track : pages_itr["tracks"]) { + new_tracks.push_back(TrackReference(track["uri"])); + } + for (const auto& itr : currentTracks) { auto currentTracksIter = - std::find(currentTracks.begin(), currentTracks.end(), _ref); - if (currentTracksIter != currentTracks.end()) { + std::find(new_tracks.begin(), new_tracks.end(), itr); + if (currentTracksIter != new_tracks.end()) { int32_t old_index = - std::distance(currentTracks.begin(), currentTracksIter); - new_alt_index[front] = new_alt_index[alt_index[old_index]]; - new_alt_index[alt_index[old_index]] = front; - alt_index[old_index] = -1; - } - alt_tracks.push_back(_ref); - front++; - } - // in case of smartshuffle, we currently just put the few already recieved "smart-tracks" in order and reshuffle the whole playlist - for (size_t i = 0; i < alt_index.size(); i++) { - if (alt_index[i] >= 0) { - new_alt_index.push_back(new_alt_index[alt_index[i]]); - new_alt_index[alt_index[i]] = alt_tracks.size(); - alt_tracks.push_back(currentTracks[alt_index[i]]); + std::distance(new_tracks.begin(), currentTracksIter); + new_index.push_back(old_index); + } else { + int newIndex = new_tracks.size(); + new_tracks.push_back(itr); + new_index.push_back(newIndex); } } - randomizeIndex(new_alt_index, currentTracks.size(), rng); - alt_index = new_alt_index; - currentTracks = alt_tracks; - currentTracksSize = currentTracks.size(); + for (uint32_t i = 0; i < new_index.size(); i++) + if (std::find(new_index.begin(), new_index.end(), i) == + new_index.end()) + new_index.push_back(i); + randomizeIndex(new_index, currentTracks.size(), rng); + alt_index = new_index; + currentTracks = new_tracks; } else { auto altref = currentTracks.front().gid; uint8_t loop_pointer = 0; @@ -644,9 +638,13 @@ void TrackQueue::resolveContext() { } exit_loop:; currentTracksIndex += front; - CSPOT_LOG(info, "Resolved context, new currentTracks-size = %i", - currentTracks.size()); + alt_index.clear(); + for (int32_t i = 0; i < currentTracks.size(); i++) + alt_index.push_back(i); } + currentTracksSize = currentTracks.size(); + CSPOT_LOG(info, "Resolved context, new currentTracks-size = %i", + currentTracksSize); } }; ctx->session->execute(MercurySession::RequestType::GET, requestUrl, From a7426ec6ba1cd60972624fe3d74e36942001ee3a Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 16 Jul 2024 23:29:48 +0200 Subject: [PATCH 22/41] currentTracksIndex is pointing to the currentlyPlaying song, VS1053 support --- cspot/include/SpircHandler.h | 1 + cspot/src/SpircHandler.cpp | 23 +- cspot/src/TrackPlayer.cpp | 13 +- targets/cli/CliPlayer.cpp | 7 +- .../esp32/components/VS1053/CMakeLists.txt | 4 + targets/esp32/components/VS1053/Kconfig | 69 ++ targets/esp32/components/VS1053/component.mk | 0 .../esp32/components/VS1053/include/VS1053.h | 239 +++++ .../components/VS1053/include/patches_dsd.h | 983 ++++++++++++++++++ .../components/VS1053/include/patches_flac.h | 961 +++++++++++++++++ .../VS1053/include/patches_flac_latm.h | 980 +++++++++++++++++ .../components/VS1053/include/patches_latm.h | 644 ++++++++++++ .../components/VS1053/include/patches_pitch.h | 688 ++++++++++++ .../VS1053/include/spectrum_analyzer.h | 124 +++ .../components/VS1053/include/vs10xx_uc.h | 561 ++++++++++ .../esp32/components/VS1053/src/VS1053.cpp | 666 ++++++++++++ targets/esp32/main/EspPlayer.cpp | 36 +- targets/esp32/main/Kconfig.projbuild | 25 +- targets/esp32/main/VSPlayer.cpp | 100 ++ targets/esp32/main/VSPlayer.h | 36 + targets/esp32/main/VSinit.h | 30 + targets/esp32/main/main.cpp | 110 +- 22 files changed, 6215 insertions(+), 85 deletions(-) create mode 100644 targets/esp32/components/VS1053/CMakeLists.txt create mode 100644 targets/esp32/components/VS1053/Kconfig create mode 100644 targets/esp32/components/VS1053/component.mk create mode 100644 targets/esp32/components/VS1053/include/VS1053.h create mode 100644 targets/esp32/components/VS1053/include/patches_dsd.h create mode 100644 targets/esp32/components/VS1053/include/patches_flac.h create mode 100644 targets/esp32/components/VS1053/include/patches_flac_latm.h create mode 100644 targets/esp32/components/VS1053/include/patches_latm.h create mode 100644 targets/esp32/components/VS1053/include/patches_pitch.h create mode 100644 targets/esp32/components/VS1053/include/spectrum_analyzer.h create mode 100644 targets/esp32/components/VS1053/include/vs10xx_uc.h create mode 100644 targets/esp32/components/VS1053/src/VS1053.cpp create mode 100644 targets/esp32/main/VSPlayer.cpp create mode 100644 targets/esp32/main/VSPlayer.h create mode 100644 targets/esp32/main/VSinit.h diff --git a/cspot/include/SpircHandler.h b/cspot/include/SpircHandler.h index 3464450f..9baa7658 100644 --- a/cspot/include/SpircHandler.h +++ b/cspot/include/SpircHandler.h @@ -52,6 +52,7 @@ class SpircHandler { bool nextSong(); + void notifyAudioReachedPlaybackEnd(); void notifyAudioReachedPlayback(); void notifyAudioEnded(); void updatePositionMs(uint32_t position); diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index dbf09877..894809e0 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -82,23 +82,34 @@ void SpircHandler::loadTrackFromURI(const std::string& uri) {} void SpircHandler::notifyAudioEnded() { playbackState->updatePositionMs(0); notify(); -#ifndef CONFIG_BELL_NOCODEC trackPlayer->resetState(true); -#endif } - -void SpircHandler::notifyAudioReachedPlayback() { +void SpircHandler::notifyAudioReachedPlaybackEnd() { int offset = 0; // get HEAD track auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - if (!playbackState->innerFrame.state.repeat) { - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT); + if (trackQueue->notifyPending) { + trackQueue->notifyPending = false; + + playbackState->updatePositionMs(currentTrack->requestedPosition); + + // Reset position in queued track + currentTrack->requestedPosition = 0; + } else if (!playbackState->innerFrame.state.repeat) { + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); // we moved to next track, re-acquire currentTrack again currentTrack = trackQueue->consumeTrack(nullptr, offset); } + playbackState->updatePositionMs(0); +} +void SpircHandler::notifyAudioReachedPlayback() { + int offset = 0; + + // get HEAD track + auto currentTrack = trackQueue->consumeTrack(nullptr, offset); this->notify(); sendEvent(EventType::TRACK_INFO, currentTrack->trackInfo); diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index b65f3cc7..ff7a4b6f 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -127,7 +127,7 @@ void TrackPlayer::runTask() { std::shared_ptr track = nullptr, newTrack = nullptr; int trackOffset = 0; - size_t tracksPlayed = 0; + size_t tracksPlayed = 1; bool eof = false; bool endOfQueueReached = false; @@ -295,14 +295,15 @@ void TrackPlayer::runTask() { ¤tSection); #endif - if (ret == 0) { - CSPOT_LOG(info, "EOF"); - // and done :) - eof = true; - } else if (ret < 0) { + if (ret < 0) { CSPOT_LOG(error, "An error has occured in the stream %d", ret); currentSongPlaying = false; } else { + if (ret == 0) { + CSPOT_LOG(info, "EOF"); + // and done :) + eof = true; + } if (this->dataCallback != nullptr) { auto toWrite = ret; diff --git a/targets/cli/CliPlayer.cpp b/targets/cli/CliPlayer.cpp index 0dc469ef..766574cf 100644 --- a/targets/cli/CliPlayer.cpp +++ b/targets/cli/CliPlayer.cpp @@ -34,7 +34,8 @@ CliPlayer::CliPlayer(std::unique_ptr sink, this->handler->getTrackPlayer()->setDataCallback( [this](uint8_t* data, size_t bytes, size_t trackId) { - + if (!bytes) + this->handler->notifyAudioReachedPlaybackEnd(); return this->centralAudioBuffer->writePCM(data, bytes, trackId); }); @@ -108,8 +109,8 @@ void CliPlayer::runTask() { if (!chunk || chunk->pcmSize == 0) { if (this->playlistEnd) { - this->handler->notifyAudioEnded(); - this->playlistEnd = false; + this->handler->notifyAudioEnded(); + this->playlistEnd = false; } BELL_SLEEP_MS(10); continue; diff --git a/targets/esp32/components/VS1053/CMakeLists.txt b/targets/esp32/components/VS1053/CMakeLists.txt new file mode 100644 index 00000000..2d42d503 --- /dev/null +++ b/targets/esp32/components/VS1053/CMakeLists.txt @@ -0,0 +1,4 @@ +set(CMAKE_CXX_STANDARD 17) + idf_component_register(SRCS "src/VS1053.cpp" INCLUDE_DIRS + "include" + "src" PRIV_REQUIRES fatfs) diff --git a/targets/esp32/components/VS1053/Kconfig b/targets/esp32/components/VS1053/Kconfig new file mode 100644 index 00000000..9b45b46c --- /dev/null +++ b/targets/esp32/components/VS1053/Kconfig @@ -0,0 +1,69 @@ +menu "VS1053 Configuration" + + menu "VS1053 PIN Configuration" + + config GPIO_MISO + int "GPIO pin MISO" + range -1 39 + default 19 + + config GPIO_MOSI + int "GPIO pin MOSI" + range -1 39 + default 23 + + config GPIO_CLK + int "GPIO pin CLK" + range -1 39 + default 18 + + config GPIO_VS_CS + int "GPIO pin VS CS" + range -1 39 + default 4 + + config GPIO_VS_DCS + int "GPIO pin VS DCS" + range -1 39 + default 21 + + config GPIO_VS_RESET + int "GPIO pin VS RESET" + range -1 39 + default 0 + + config GPIO_VS_DREQ + int "GPIO pin VS DREQ" + range -1 39 + default 22 + + config GPIO_SD_CS + int "GPIO pin SD CS" + range -1 39 + default 5 + endmenu + +choice VS_PLUGIN + prompt "VS1053 plugin" + default VS_FLAC + help + you have to choose between special audio compability or a spectrum analyzer + config VS_DSD64 + bool "with dsd patch" + config VS_FLAC + bool "with flac patch" + config VS_FLAC_LATM + bool "with flac & latm/loas patch" + config VS_LATM + bool "with latm/loas patch" + config VS_PITCH + bool "with pitch plugin" + config VS_SPECTRUM_ANALYZER + bool "with spectrum analyzer plugin" +endchoice + + +config REPORT_ON_SCREEN + bool "REPORT_ON_SCREEN" + +endmenu diff --git a/targets/esp32/components/VS1053/component.mk b/targets/esp32/components/VS1053/component.mk new file mode 100644 index 00000000..e69de29b diff --git a/targets/esp32/components/VS1053/include/VS1053.h b/targets/esp32/components/VS1053/include/VS1053.h new file mode 100644 index 00000000..35bcbc71 --- /dev/null +++ b/targets/esp32/components/VS1053/include/VS1053.h @@ -0,0 +1,239 @@ +#ifndef VS1053_H +#define VS1053_H + +#include //for memset +#include //for dequeue +#include //for function +#include +#include + +#include "esp_err.h" + +#include +#include + +#include "freertos/semphr.h" +#include "freertos/stream_buffer.h" +#include "freertos/task.h" + +#include "vs10xx_uc.h" +#ifdef CONFIG_VS_DSD64 +#include "patches_dsd.h" +#endif +#ifdef CONFIG_VS_FLAC +#include "patches_flac.h" +#endif +#ifdef CONFIG_VS_FLAC_LATM +#include "patches_flac_latm.h" +#endif +#ifdef CONFIG_VS_LATM +#include "patches_latm.h" +#endif +#ifdef CONFIG_VS_PITCH +#include "patches_pitch.h" +#endif +#ifdef CONFIG_VS_SPECTRUM_ANALYZER +#include "spectrum_analyzer.h" +#endif + +#define VERSION 1 +#define VS1053_CHUNK_SIZE 16 // chunck size +#define VS1053_PACKET_SIZE 8 +#define BUF_SIZE_CMD 1028 +#define BUF_SIZE_FEED 4096 * 4 + +#define SDI_END_FILL_BYTES_FLAC 12288 +#define SDI_END_FILL_BYTES 2050 + +#define REPORT_INTERVAL 4096 +#define REPORT_INTERVAL_MIDI 512 +/** + * + * callback for the command_pipeline + * + */ +class VS1053_SINK; +class VS1053_TRACK { + public: + VS1053_TRACK(VS1053_SINK* vsSink, size_t track_id = 0, + size_t buffer_size = BUF_SIZE_FEED); + ~VS1053_TRACK(); + /** + * feed data to dataBuffer + * @param data pointer to byte array + * @param len length of the byte array + * @warning always call data_request, before feeding data, + * to get available space in dataBuffer + */ + size_t feed_data(uint8_t* data, size_t len, bool STORAGE_VOLATILE = 0); + void empty_feed(); + void run_track(size_t FILL_BUFFER_BEFORE_PLAYSTART = 0); + VS1053_SINK* audioSink; + TaskHandle_t track_handle = NULL; + enum VS_TRACK_STATE { + tsPlaybackStart = 0, + tsPlayback = 1, + tsPlaybackSeekable = 2, + tsPlaybackPaused = 3, + tsSoftCancel = 4, + tsCancel = 5, + tsCancelAwait = 6, + tsStopped = 7 + } track_state = tsStopped; + size_t header_size = 0; + size_t track_id; + StreamBufferHandle_t dataBuffer; + + private: +}; +class VS1053_SINK { + public: + /** + * `CONSTRUCTOR` + * + * PULLS CS and DCS HIGH. + * If RESET >= 0, VS1053 gets hardreset. + * For sharing the SPI_BUS with a SD-Card, the CS-pins + * of the other devices are needed to be pulled high + * before mounting the SD-card. + * After mounting the SD-card, you can add the other devices + * + * @param RESET GPIO_PIN_NUM, if + */ + VS1053_SINK(); + + /** + * DECONSTRUCTOR + */ + ~VS1053_SINK(); + typedef std::function command_callback; + //typedef std::function command_callback; + /** + * `init feed` + * add the VS 1053 to the SPI_BUS, test the device and + * add vs_loop to freertosTask + * + * @param SPI pointer to the used SPI peripheral + * @param SPI_semaphore semaphore for the SPI_BUS, NULL if uninitiallized + * + * @return `ESP_OK` if setup worked. + * @return `ESP_ERR_INVALID_RESPONSE` if the register response is wrong. + * @return `ESP_ERR_NOT_SUPPORTED` if the chip is not a VS1053. + * @return `ESP_ERR_NOT_FOUND` if the chipNumber is not recognized. + */ + esp_err_t init(spi_host_device_t SPI, + SemaphoreHandle_t* SPI_semaphore = NULL); + /** + * stops data feed imeaditly + */ + void stop_feed(); + /** + * stops data feed if dataBuffer contains no more + */ + void soft_stop_feed(); + /** + * feed data to commandBuffer + * @param command_callback callback function + * + */ + uint8_t feed_command(command_callback commandCallback); + void set_volume_logarithmic(size_t vol); + /** + * set volume through cmd_pipeline, sets left and right volume to vol + * @param vol 0...100, gets capped if bigger + */ + void set_volume(uint8_t vol); + /** + * set volume through cmd_pipeline, sets separate volume for left and right channel + * @param left 0...100, gets capped if bigger + * @param right 0...100, gets capped if bigger + */ + void set_volume(uint8_t left, uint8_t right); + /** + * get available Space in dataBuffer + * @return free space available in dataBuffer + */ + size_t data_request(); + /** + * loads Usercode(PATCH) + * @param plugin uint8_t * to plugin array + * @param sizeofpatch length of the array + */ + void load_user_code(const unsigned short* plugin, uint16_t sizeofpatch); + /** + * test SPI communication and if the board is a VS1053 + * @return `ESP_OK` if setup worked. + * @return `ESP_ERR_INVALID_RESPONSE` if the register response is wrong. + * @return `ESP_ERR_NOT_SUPPORTED` if the chip is not a VS1053. + * @return `ESP_ERR_NOT_FOUND` if the chipNumber is not recognized. + */ + esp_err_t test_comm(const char* header); + std::function state_callback = nullptr; + enum Audio_Format { + afUnknown, + afRiff, + afOggVorbis, + afMp1, + afMp2, + afMp3, + afAacMp4, + afAacAdts, + afAacAdif, + afFlac, + afWma, + afMidi, + afDsd64, + afLatm + } audioFormat = afUnknown; + void get_audio_format(Audio_Format* audioFormat, size_t* endFillBytes); + void control_mode_on(); + void control_mode_off(); + void data_mode_on(); + void data_mode_off(); + uint16_t read_register(uint8_t _reg); + bool write_register(uint8_t _reg, uint16_t _value); + uint32_t read_mem32(uint16_t addr); + uint32_t read_mem32_counter(uint16_t addr); + uint16_t read_mem(uint16_t addr); + void write_mem(uint16_t addr, uint16_t data); + void write_mem32(uint16_t addr, uint32_t data); + bool sdi_send_buffer(uint8_t* data, size_t len); + void remove_track(std::shared_ptr track) { + if (this->track->track_id == track->track_id) + this->track = nullptr; + }; + void start_track(std::shared_ptr, size_t); + bool is_seekable(VS1053_TRACK::VS_TRACK_STATE* state); + size_t track_seekable(size_t); + void cancel_track(VS1053_TRACK::VS_TRACK_STATE* state); + bool is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state); + size_t get_track_info(size_t); + void new_state(VS1053_TRACK::VS_TRACK_STATE); + void new_track(std::shared_ptr track); + VS1053_TRACK newTrack(size_t track_id, size_t buffer_size = BUF_SIZE_FEED); + + void delete_track(void); + size_t spaces_available(size_t); + std::shared_ptr track = nullptr; + std::shared_ptr future_track = nullptr; + size_t command_pointer = 0, command_reader = 0; + std::deque command_callbacks; + + private: + spi_device_handle_t SPIHandleLow; + spi_device_handle_t SPIHandleFast; + uint8_t curvol; // Current volume setting 0..100% + uint8_t endFillByte = 0; // Byte to send when stopping song + size_t endFillBytes = SDI_END_FILL_BYTES; + int playMode = 0; + uint8_t chipVersion; // Version of hardware + SemaphoreHandle_t* SPI_semaphore = NULL; + TaskHandle_t VS_TASK; + void await_data_request(); + bool sdi_send_fillers(size_t len); + void wram_write(uint16_t address, uint16_t data); + uint16_t wram_read(uint16_t address); + size_t (*data_callback)(uint8_t*, size_t) = NULL; +}; + +#endif \ No newline at end of file diff --git a/targets/esp32/components/VS1053/include/patches_dsd.h b/targets/esp32/components/VS1053/include/patches_dsd.h new file mode 100644 index 00000000..d9ac29d9 --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_dsd.h @@ -0,0 +1,983 @@ + +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x001e, /*copy 30*/ + 0x2a00, 0xc000, 0x3e12, 0xb817, 0x3e14, 0xf812, 0x3e01, 0xb811, 0x0007, + 0x9717, 0x0020, 0xffd2, 0x0030, 0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, + 0x3b81, 0x8024, 0x3101, 0x8024, 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, + 0x4800, 0x36f1, 0x9811, 0x0007, 0x0001, /*copy 1*/ + 0x8060, 0x0006, 0x053e, /*copy 1342*/ + 0xf400, 0x4095, 0x0000, 0x02c2, 0x6124, 0x0024, 0x0000, 0x0024, 0x2800, + 0x1ac5, 0x4192, 0x4542, 0x0000, 0x0041, 0x2000, 0x0015, 0x0030, 0x0317, + 0x2000, 0x0000, 0x3f00, 0x4024, 0x2000, 0x0000, 0x0000, 0x0000, 0x3e12, + 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, 0x8257, 0x3700, 0x984c, + 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, 0x2910, 0x0181, 0x0000, + 0x1bc8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, 0x0195, 0x0000, 0x1bc8, + 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2945, 0x3e13, 0x780e, 0x3e11, + 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, 0xb808, 0x003f, 0xe004, + 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, 0x48be, 0x4497, 0x4090, + 0x1c46, 0xf06c, 0x0024, 0x2400, 0x2580, 0x6090, 0x41c3, 0x6628, 0x1c47, + 0x0000, 0x0024, 0x2800, 0x2449, 0xf07e, 0x0024, 0xf400, 0x4182, 0x673a, + 0x1c46, 0x0000, 0x0024, 0x2800, 0x2589, 0xf06c, 0x0024, 0xf400, 0x41c3, + 0x0000, 0x0024, 0x4224, 0x3442, 0x2903, 0xdc80, 0x4336, 0x37c3, 0x0000, + 0x1805, 0x2903, 0xdc80, 0x4508, 0x40c2, 0x450a, 0x9808, 0x0000, 0x0207, + 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, 0x3d01, 0x5bc1, 0x36f3, + 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, 0x580e, 0x0007, 0x8257, + 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, 0xd428, 0x3c02, 0x0006, + 0xc717, 0x2800, 0x2d05, 0x4284, 0x0024, 0x3613, 0x3c02, 0x0006, 0xc357, + 0x2901, 0x6a00, 0x3e11, 0x5c05, 0x4284, 0x1bc5, 0x0007, 0x8257, 0x2800, + 0x3285, 0x0002, 0x0001, 0x3701, 0x0024, 0x0006, 0xc357, 0xb412, 0x9c02, + 0x002e, 0xe001, 0x2800, 0x3005, 0x6212, 0x0024, 0x0000, 0x0024, 0x2800, + 0x3295, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, 0x0024, 0x3613, 0x0024, + 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, 0x2900, 0x4b40, 0x0006, + 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, 0x8257, 0x3700, 0x8024, + 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x3491, 0x3600, 0x9844, 0x2900, + 0x3a40, 0x0000, 0x3508, 0x2911, 0xf140, 0x0000, 0x0024, 0x0030, 0x0057, + 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, 0xa024, 0x164c, 0x8000, + 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, 0x6d82, 0xd024, 0x44c0, + 0x0006, 0xa402, 0x2800, 0x3955, 0xd024, 0x0024, 0x0000, 0x0000, 0x2800, + 0x3955, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, 0x8024, 0x36f2, 0x1800, + 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, 0x3e13, 0xb80d, 0x3e13, + 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0xf801, + 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, 0xbf8e, 0x9c42, 0x3e01, + 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, 0x8250, 0x0fff, 0xfd85, + 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, 0x2800, 0x4091, 0xf25a, + 0x104c, 0x34f3, 0x0024, 0x2800, 0x4091, 0x0000, 0x0024, 0x3413, 0x084c, + 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, 0x2400, 0x42c0, 0x4efa, + 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, 0x4d64, 0x48b2, 0xa201, + 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, 0x36f4, 0xd801, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0xd80a, 0x36f3, 0x980d, + 0x2000, 0x0000, 0x36f4, 0x5810, 0x36f3, 0x0024, 0x3009, 0x3848, 0x3e14, + 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, + 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, 0x9e40, 0x3604, 0x1811, 0x3613, + 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, + 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x36f4, 0x1811, 0x3009, + 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e13, 0x7801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, + 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, 0x34e5, 0xc024, 0x3524, + 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, 0x4a0c, 0x3d44, 0x8024, + 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, 0x6010, 0x3400, 0x3710, + 0x8024, 0x2800, 0x5704, 0x3af0, 0x8024, 0x3df0, 0x0024, 0x3591, 0x4024, + 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, 0x4020, 0x1753, 0xbf8e, + 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, 0x550e, 0xfe6d, 0x2819, + 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, 0xad56, 0x904c, 0xaf5e, + 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, 0x2046, 0x3cf4, 0x0024, + 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, 0x2800, 0x4f95, 0x3c00, + 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0x5801, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x0000, 0x0200, + 0xb386, 0x3803, 0xad06, 0x0024, 0x2000, 0x0000, 0xc320, 0x1bc3, 0x2814, + 0x9c91, 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, 0x3e12, 0xb817, + 0x3e12, 0x7808, 0x3e11, 0xb811, 0x3e15, 0x7810, 0x3e18, 0xb823, 0x3e18, + 0x3821, 0x3e10, 0x3801, 0x48b2, 0x0024, 0x3e10, 0x3801, 0x3e11, 0x3802, + 0x3009, 0x3814, 0x0030, 0x0717, 0x3f05, 0xc024, 0x0030, 0x0351, 0x3100, + 0x0024, 0x4080, 0x0024, 0x0030, 0x10d1, 0x2800, 0x6885, 0x0001, 0x800a, + 0x0006, 0x6514, 0x3111, 0x8024, 0x6894, 0x13c1, 0x6618, 0x0024, 0xfe44, + 0x1000, 0x4cb2, 0x0406, 0x3c10, 0x0024, 0x3c50, 0x4024, 0x34f0, 0x4024, + 0x661c, 0x1040, 0xfe64, 0x0024, 0x4cb2, 0x0024, 0x3cf0, 0x4024, 0xbc82, + 0x3080, 0x0030, 0x0351, 0x3100, 0x8024, 0xfea8, 0x0024, 0x5ca2, 0x0024, + 0x0000, 0x0182, 0xac22, 0x0024, 0xf7c8, 0x0024, 0x48b2, 0x0024, 0xac22, + 0x0024, 0x2800, 0x6c00, 0xf7cc, 0x1002, 0x0030, 0x0394, 0x3400, 0x4024, + 0x3100, 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, 0x6410, 0x4088, + 0x1001, 0x0030, 0x1111, 0x3100, 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, + 0x0006, 0x6550, 0x0006, 0x6694, 0x408c, 0x1002, 0xf224, 0x0024, 0x0006, + 0xa017, 0x2800, 0x7015, 0x0000, 0x0024, 0x2808, 0x3f41, 0x0006, 0x6410, + 0x3050, 0x0024, 0x3000, 0x4024, 0x6014, 0x0024, 0x0000, 0x0024, 0x2800, + 0x6f59, 0x0000, 0x0024, 0xf400, 0x4040, 0x38b0, 0x0024, 0x2808, 0x3f40, + 0x3800, 0x0024, 0x2800, 0x7201, 0xf224, 0x0024, 0x0000, 0x0024, 0x2808, + 0x3f45, 0x4684, 0x4106, 0xf12c, 0x0024, 0xf148, 0x0024, 0x846c, 0x0024, + 0x2808, 0x3f40, 0xf400, 0x4184, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0xa090, 0x2912, + 0x0d00, 0x3e14, 0xc024, 0x4088, 0x8000, 0x4080, 0x0024, 0x0007, 0x90d1, + 0x2800, 0x7845, 0x0000, 0x0024, 0x0007, 0x9051, 0x3100, 0x4024, 0x4100, + 0x0024, 0x3900, 0x0024, 0x0007, 0x90d1, 0x0004, 0x0000, 0x31f0, 0x4024, + 0x6014, 0x0400, 0x0000, 0x0024, 0x2800, 0x7c91, 0x4080, 0x0024, 0x0000, + 0x0000, 0x2800, 0x7c05, 0x0000, 0x0024, 0x0007, 0x9053, 0x3300, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0000, 0x2800, 0x7c98, 0x0000, 0x0024, 0x0007, + 0x9051, 0x3900, 0x0024, 0x3200, 0x504c, 0x6410, 0x0024, 0x3cf0, 0x0000, + 0x4080, 0x0024, 0x0006, 0xc691, 0x2800, 0x9545, 0x3009, 0x0400, 0x0000, + 0x1001, 0x0007, 0x9051, 0x3100, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, + 0x2800, 0x8989, 0x003f, 0xe000, 0x0006, 0xc693, 0x3900, 0x0c00, 0x3009, + 0x0001, 0x6014, 0x0024, 0x0007, 0x1ad0, 0x2800, 0x8995, 0x3009, 0x0000, + 0x4080, 0x0024, 0x0000, 0x0301, 0x2800, 0x8385, 0x4090, 0x0024, 0x0000, + 0x0024, 0x2800, 0x8495, 0x0000, 0x0024, 0x3009, 0x0000, 0xc012, 0x0024, + 0x2800, 0x8980, 0x3009, 0x2001, 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, + 0x0341, 0x2800, 0x8695, 0x0000, 0x0024, 0x6190, 0x0024, 0x2800, 0x8980, + 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, 0x0381, 0x2800, 0x8855, 0x0000, + 0x0024, 0x6190, 0x0024, 0x2800, 0x8980, 0x3009, 0x2000, 0x6012, 0x0024, + 0x0000, 0x00c0, 0x2800, 0x8995, 0x0000, 0x0024, 0x3009, 0x2000, 0x0006, + 0xa090, 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0081, 0x2800, 0x8e55, + 0x0007, 0x8c13, 0x3300, 0x104c, 0xb010, 0x0024, 0x0002, 0x8001, 0x2800, + 0x90c5, 0x34f0, 0x0024, 0x2800, 0x8e40, 0x0000, 0x0024, 0x0006, 0xc351, + 0x3009, 0x0000, 0x6090, 0x0024, 0x3009, 0x2000, 0x2900, 0x0b80, 0x3009, + 0x0405, 0x0006, 0xc6d1, 0x0006, 0xc690, 0x3009, 0x0000, 0x3009, 0x0401, + 0x6014, 0x0024, 0x0006, 0xa093, 0x2800, 0x8cd1, 0xb880, 0x0024, 0x2800, + 0x9e00, 0x3009, 0x2c00, 0x4040, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, + 0x2800, 0x9e18, 0x0000, 0x0024, 0x0006, 0xc693, 0x3009, 0x0c00, 0x3009, + 0x0001, 0x6014, 0x0024, 0x0006, 0xc350, 0x2800, 0x9e01, 0x0000, 0x0024, + 0x6090, 0x0024, 0x3009, 0x2c00, 0x3009, 0x0005, 0x2900, 0x0b80, 0x0000, + 0x9e08, 0x3009, 0x0400, 0x4080, 0x0024, 0x0003, 0x8000, 0x2800, 0x9e05, + 0x0000, 0x0024, 0x6400, 0x0024, 0x0000, 0x0081, 0x2800, 0x9e09, 0x0000, + 0x0024, 0x0007, 0x8c13, 0x3300, 0x0024, 0xb010, 0x0024, 0x0006, 0xc650, + 0x2800, 0x9e15, 0x0000, 0x0024, 0x0001, 0x0002, 0x3413, 0x0000, 0x3009, + 0x0401, 0x4010, 0x8406, 0x0000, 0x0281, 0xa010, 0x13c1, 0x4122, 0x0024, + 0x0000, 0x03c2, 0x6122, 0x8002, 0x462c, 0x0024, 0x469c, 0x0024, 0xfee2, + 0x0024, 0x48be, 0x0024, 0x6066, 0x8400, 0x0006, 0xc350, 0x2800, 0x9e01, + 0x0000, 0x0024, 0x4090, 0x0024, 0x3009, 0x2400, 0x2900, 0x0b80, 0x3009, + 0x0005, 0x0007, 0x1b50, 0x2912, 0x0d00, 0x3613, 0x0024, 0x3a00, 0x0380, + 0x4080, 0x0024, 0x0000, 0x00c1, 0x2800, 0xa6c5, 0x3009, 0x0000, 0xb010, + 0x008c, 0x4192, 0x0024, 0x6012, 0x0024, 0x0006, 0xf051, 0x2800, 0xa4d8, + 0x3009, 0x0400, 0x0007, 0x1fd1, 0x30e3, 0x0400, 0x4080, 0x0024, 0x0000, + 0x0301, 0x2800, 0xa6c5, 0x3009, 0x0000, 0xb010, 0x0024, 0x0000, 0x0101, + 0x6012, 0x0024, 0x0006, 0xf051, 0x2800, 0xa6d5, 0x0000, 0x0024, 0x3023, + 0x0400, 0xf200, 0x184c, 0xb880, 0xa400, 0x3009, 0x2000, 0x3009, 0x0441, + 0x3e10, 0x4402, 0x2909, 0xa9c0, 0x3e10, 0x8024, 0x36e3, 0x0024, 0x36f4, + 0xc024, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e14, 0x3811, 0x3e14, 0x92cc, 0x3400, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0590, 0x2800, 0xb058, 0x0000, 0x0024, 0x6800, 0x9bcc, 0x3c20, + 0x0024, 0x34e4, 0x4024, 0x3410, 0x860c, 0x3100, 0x0024, 0xff20, 0x1012, + 0x48b6, 0x084c, 0x4280, 0x1110, 0x6898, 0x0024, 0x2900, 0xb480, 0x0000, + 0x0085, 0x34b3, 0x184c, 0x3410, 0x0024, 0x3e10, 0x0024, 0x3410, 0x0024, + 0x3e10, 0x0024, 0x3430, 0x0024, 0x2920, 0x1340, 0x3e00, 0x0024, 0x36d3, + 0x0024, 0x36f4, 0x8024, 0x36f4, 0x1811, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, + 0x9817, 0x4090, 0x184c, 0x3e14, 0xf811, 0x3e13, 0xf80e, 0x2800, 0xb6c4, + 0x3e03, 0x4024, 0x2400, 0xb680, 0x2b11, 0x1153, 0x3280, 0x0024, 0x3880, + 0x0024, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x36f4, 0xd811, + 0x4090, 0x184c, 0x3e14, 0xf811, 0x3e13, 0xf80e, 0x2800, 0xbac4, 0x4498, + 0x380d, 0x459a, 0x0024, 0x2400, 0xba80, 0x2b11, 0x1153, 0x3210, 0x0024, + 0x3810, 0x0024, 0x3280, 0x0024, 0x3880, 0x0024, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x2000, 0x0000, 0x36f4, 0xd811, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0xb880, 0x1854, 0x3405, 0x9014, 0x36e3, 0x0024, 0x2000, + 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, + 0x3615, 0x0024, 0x3405, 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, + 0x9815, 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x191c, /*copy 6428*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x69d7, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x5c8e, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x4d86, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdd55, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xdc0e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x10c8, 0x0039, + 0x324f, 0x0001, 0x3dce, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x0014, 0x1b01, 0x0015, 0x59c0, + 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, 0xe795, 0x0000, 0x0024, 0x290c, + 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, 0x4086, 0x184c, 0x0000, 0x18c2, + 0x6234, 0x0024, 0x0000, 0x1d02, 0x2800, 0xe395, 0x6234, 0x0024, 0x0030, + 0x0317, 0x2800, 0xe780, 0x3f00, 0x0024, 0x0000, 0x1d82, 0x2800, 0xe615, + 0x6234, 0x0024, 0x2912, 0x0d00, 0x4084, 0x184c, 0xf200, 0x0024, 0x6200, + 0x0024, 0x0006, 0x0017, 0x2800, 0xe300, 0xb080, 0x3c40, 0x0000, 0x0202, + 0x2800, 0xe795, 0xa024, 0x0024, 0xc020, 0x0024, 0x2800, 0xe300, 0x0030, + 0x02d7, 0x0011, 0x14c1, 0x0011, 0x0800, 0x6fc2, 0x0024, 0x0011, 0x9481, + 0x2800, 0xea05, 0x0013, 0x4e00, 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, + 0xea95, 0x0000, 0x0024, 0x2801, 0x8ec0, 0x000a, 0xcac8, 0x000a, 0x8c8f, + 0x0000, 0xebce, 0x000c, 0x0981, 0x280a, 0x71c0, 0x002c, 0x9d40, 0x000a, + 0x708f, 0x0000, 0xd7ce, 0x280a, 0xc0d5, 0x0012, 0x5182, 0x6fd6, 0x0024, + 0x003f, 0xfd81, 0x280a, 0x8e45, 0xb710, 0x0024, 0xb710, 0x0024, 0x003f, + 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x0795, 0xffd2, 0x0024, + 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x190d, 0x2801, 0x0795, 0x0030, + 0x0250, 0xb880, 0x104c, 0x3cf0, 0x0024, 0x0010, 0x5500, 0xb880, 0x23c0, + 0xb882, 0x2000, 0x0007, 0x8590, 0x2914, 0xbec0, 0x0000, 0x0440, 0x0007, + 0x8b50, 0xb880, 0x0024, 0x2920, 0x0100, 0x3800, 0x0024, 0x2920, 0x0000, + 0x0006, 0x8a91, 0x0000, 0x0800, 0xb880, 0xa440, 0x003f, 0xfd81, 0xb710, + 0xa7c0, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x10d5, + 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, + 0x0024, 0x2801, 0x10d5, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, + 0x4080, 0x0024, 0x0006, 0x8a90, 0x2801, 0x10d5, 0x0000, 0x01c2, 0xb886, + 0x8040, 0x3613, 0x03c1, 0xbcd2, 0x0024, 0x0030, 0x0011, 0x2800, 0xfd55, + 0x003f, 0xff42, 0xb886, 0x8040, 0x3009, 0x03c1, 0x0000, 0x0020, 0xac22, + 0x0024, 0x0000, 0x0102, 0x6cd2, 0x0024, 0x3e10, 0x0024, 0x2909, 0x8c80, + 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3e11, 0x8024, 0x3e01, 0xc024, 0x2901, + 0x3480, 0x0000, 0x0201, 0xf400, 0x4512, 0x2900, 0x0c80, 0x3213, 0x1b8c, + 0x3100, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, 0x10d5, 0x0000, + 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2920, 0x0200, 0x3633, 0x0024, + 0x2920, 0x0280, 0x0000, 0x0401, 0x408e, 0x0024, 0x2920, 0x0280, 0x0000, + 0x0401, 0x003f, 0xfd81, 0xb710, 0x4006, 0x003f, 0xfc01, 0x6012, 0x0024, + 0x0000, 0x0101, 0x2801, 0x10d5, 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, + 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x10d5, 0x0000, 0x0024, + 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0000, 0x01c2, 0x2800, + 0xf945, 0x0006, 0x8a90, 0x2a01, 0x10c0, 0x2920, 0x0100, 0x0000, 0x0401, + 0x0000, 0x0180, 0x2920, 0x0200, 0x3613, 0x0024, 0x2920, 0x0280, 0x3613, + 0x0024, 0x0000, 0x0401, 0x2920, 0x0280, 0x4084, 0x984c, 0x0019, 0x9d01, + 0x6212, 0x0024, 0x001e, 0x5c01, 0x2801, 0x0c15, 0x6012, 0x0024, 0x0000, + 0x0024, 0x2801, 0x0e05, 0x0000, 0x0024, 0x001b, 0x5bc1, 0x6212, 0x0024, + 0x001b, 0xdd81, 0x2801, 0x11d5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, + 0x11d5, 0x0000, 0x0024, 0x0000, 0x004d, 0x000a, 0xbf4f, 0x280a, 0xb880, + 0x0001, 0x0f0e, 0x0020, 0xfb4f, 0x0000, 0x190d, 0x0001, 0x160e, 0x2920, + 0xf440, 0x3009, 0x2bc1, 0x291a, 0x8a40, 0x36e3, 0x0024, 0x0000, 0x190d, + 0x000a, 0x708f, 0x280a, 0xcac0, 0x0000, 0xd7ce, 0x0030, 0x0017, 0x3700, + 0x4024, 0x0000, 0x0200, 0xb102, 0x0024, 0x0000, 0x00c0, 0x2801, 0x1505, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0000, 0x190d, 0x000a, 0x708f, + 0x280a, 0xc0c0, 0x0000, 0xd7ce, 0x0000, 0x004d, 0x0020, 0xfe0f, 0x2820, + 0xfb40, 0x0001, 0x170e, 0x2801, 0x18d5, 0x3009, 0x1000, 0x6012, 0x93cc, + 0x0000, 0x0024, 0x2801, 0x3385, 0x0000, 0x0024, 0x3413, 0x0024, 0x34b0, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, 0x1bd5, 0xb882, 0x0024, + 0x3453, 0x0024, 0x3009, 0x13c0, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, + 0x3385, 0x0000, 0x0024, 0xb882, 0x130c, 0x0000, 0x004d, 0x0021, 0x058f, + 0x2821, 0x0340, 0x0001, 0x1cce, 0x2801, 0x2d15, 0x6012, 0x0024, 0x0000, + 0x0024, 0x2801, 0x2d15, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3e13, 0xb80f, + 0xf400, 0x4500, 0x0026, 0x9dcf, 0x0001, 0x20ce, 0x0000, 0xfa0d, 0x2926, + 0x8e80, 0x3e10, 0x110c, 0x36f3, 0x0024, 0x2801, 0x2d00, 0x36f3, 0x980f, + 0x001c, 0xdd00, 0x001c, 0xd901, 0x6ec2, 0x0024, 0x001c, 0xdd00, 0x2801, + 0x23d5, 0x0018, 0xdbc1, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0xc640, + 0x3e00, 0x13cc, 0x2801, 0x2ac0, 0x36f3, 0x0024, 0x6ec2, 0x0024, 0x003f, + 0xc000, 0x2801, 0x2655, 0x002a, 0x4001, 0x3413, 0x184c, 0xf400, 0x4500, + 0x2926, 0xafc0, 0x3e00, 0x13cc, 0x2801, 0x2ac0, 0x36f3, 0x0024, 0xb400, + 0x0024, 0xd100, 0x0024, 0x0000, 0x0024, 0x2801, 0x2ac5, 0x0000, 0x0024, + 0x3613, 0x0024, 0x3e11, 0x4024, 0x2926, 0x8540, 0x3e01, 0x0024, 0x4080, + 0x1b8c, 0x0000, 0x0024, 0x2801, 0x2ac5, 0x0000, 0x0024, 0x3413, 0x184c, + 0xf400, 0x4500, 0x2926, 0x8e80, 0x3e10, 0x13cc, 0x36f3, 0x0024, 0x3110, + 0x8024, 0x31f0, 0xc024, 0x0000, 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, + 0x3110, 0x8024, 0x2826, 0xa8c4, 0x31f0, 0xc024, 0x2a26, 0xad00, 0x34c3, + 0x184c, 0x3410, 0x8024, 0x3430, 0xc024, 0x0000, 0x4000, 0x0000, 0x0021, + 0x6d06, 0x0024, 0x0000, 0x0024, 0x2801, 0x3394, 0x4d06, 0x0024, 0x0000, + 0x0200, 0x2922, 0x1885, 0x0001, 0x3208, 0x0000, 0x0200, 0x3e10, 0x8024, + 0x2921, 0xca80, 0x3e00, 0xc024, 0x291a, 0x8a40, 0x0000, 0x0024, 0x2922, + 0x1880, 0x36f3, 0x0024, 0x0000, 0x004d, 0x0021, 0x0ecf, 0x2821, 0x0bc0, + 0x0001, 0x330e, 0x2801, 0x1600, 0x3c30, 0x4024, 0x0000, 0x190d, 0x0000, + 0x458e, 0x2821, 0x0f80, 0x0027, 0x9e0f, 0x0020, 0xcd4f, 0x2820, 0xc780, + 0x0001, 0x354e, 0x0006, 0xf017, 0x0000, 0x0015, 0xb070, 0xbc15, 0x0000, + 0x458e, 0x0027, 0x9e0f, 0x2820, 0xcd80, 0x0000, 0x190d, 0x3613, 0x0024, + 0x3e10, 0xb803, 0x3e14, 0x3811, 0x3e11, 0x3805, 0x3e00, 0x3801, 0x0007, + 0xc390, 0x0006, 0xa011, 0x3010, 0x0444, 0x3050, 0x4405, 0x6458, 0x0302, + 0xff94, 0x4081, 0x0003, 0xffc5, 0x48b6, 0x0024, 0xff82, 0x0024, 0x42b2, + 0x0042, 0xb458, 0x0003, 0x4cd6, 0x9801, 0xf248, 0x1bc0, 0xb58a, 0x0024, + 0x6de6, 0x1804, 0x0006, 0x0010, 0x3810, 0x9bc5, 0x3800, 0xc024, 0x36f4, + 0x1811, 0x36f0, 0x9803, 0x283e, 0x2d80, 0x0fff, 0xffc3, 0x2801, 0x4b80, + 0x0000, 0x0024, 0x3413, 0x0024, 0x2801, 0x3f85, 0xf400, 0x4517, 0x2801, + 0x4380, 0x6894, 0x13cc, 0x37b0, 0x184c, 0x6090, 0x1d51, 0x0000, 0x0910, + 0x3f00, 0x060c, 0x3100, 0x4024, 0x6016, 0xb812, 0x000c, 0x8012, 0x2801, + 0x4211, 0xb884, 0x0024, 0x6894, 0x3002, 0x0000, 0x028d, 0x003a, 0x5e0f, + 0x0001, 0x538e, 0x2939, 0xb0c0, 0x3e10, 0x93cc, 0x4084, 0x9bd2, 0x4282, + 0x0024, 0x0000, 0x0040, 0x2801, 0x4585, 0x4292, 0x130c, 0x3443, 0x0024, + 0x2801, 0x46c5, 0x000c, 0x8390, 0x2a01, 0x4a40, 0x3444, 0x0024, 0x3073, + 0x0024, 0xc090, 0x014c, 0x2801, 0x4a40, 0x3800, 0x0024, 0x000c, 0x4113, + 0xb880, 0x2380, 0x3304, 0x4024, 0x3800, 0x05cc, 0xcc92, 0x05cc, 0x3910, + 0x0024, 0x3910, 0x4024, 0x000c, 0x8110, 0x3910, 0x0024, 0x39f0, 0x4024, + 0x3810, 0x0024, 0x38d0, 0x4024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x34c3, + 0x0024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x3613, + 0x0024, 0x2801, 0x4d85, 0x6898, 0xb804, 0x0000, 0x0084, 0x293b, 0x1cc0, + 0x3613, 0x0024, 0x000c, 0x8117, 0x3711, 0x0024, 0x37d1, 0x4024, 0x4e8a, + 0x0024, 0x0000, 0x0015, 0x2801, 0x5045, 0xce9a, 0x0024, 0x3f11, 0x0024, + 0x3f01, 0x4024, 0x000c, 0x8197, 0x408a, 0x9bc4, 0x3f15, 0x4024, 0x2801, + 0x5285, 0x4284, 0x3c15, 0x6590, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, + 0x4284, 0x0024, 0x0000, 0x0024, 0x2801, 0x3e58, 0x458a, 0x0024, 0x2a39, + 0x53c0, 0x003e, 0x2d4f, 0x283a, 0x5ed5, 0x0001, 0x370e, 0x000c, 0x4653, + 0x0000, 0x0246, 0xffac, 0x0c01, 0x48be, 0x0024, 0x4162, 0x4546, 0x6642, + 0x4055, 0x3501, 0x8024, 0x0000, 0x0087, 0x667c, 0x4057, 0x000c, 0x41d5, + 0x283a, 0x62d5, 0x3501, 0x8024, 0x667c, 0x1c47, 0x3701, 0x8024, 0x283a, + 0x62d5, 0xc67c, 0x0024, 0x0000, 0x0024, 0x283a, 0x62c5, 0x0000, 0x0024, + 0x2a3a, 0x5ec0, 0x3009, 0x3851, 0x3e14, 0xf812, 0x3e12, 0xb817, 0x3e11, + 0x8024, 0x0006, 0x0293, 0x3301, 0x8024, 0x468c, 0x3804, 0x0006, 0xa057, + 0x2801, 0x5f84, 0x0006, 0x0011, 0x469c, 0x0024, 0x3be1, 0x8024, 0x2801, + 0x5f95, 0x0006, 0xc392, 0x3311, 0x0024, 0x33f1, 0x2844, 0x3009, 0x2bc4, + 0x0030, 0x04d2, 0x3311, 0x0024, 0x3a11, 0x0024, 0x3201, 0x8024, 0x003f, + 0xfc04, 0xb64c, 0x0fc4, 0xc648, 0x0024, 0x3a01, 0x0024, 0x3111, 0x1fd3, + 0x6498, 0x07c6, 0x868c, 0x2444, 0x0023, 0xffd2, 0x3901, 0x8e06, 0x0030, + 0x0551, 0x3911, 0x8e06, 0x3961, 0x9c44, 0xf400, 0x44c6, 0xd46c, 0x1bc4, + 0x36f1, 0xbc13, 0x2801, 0x6915, 0x36f2, 0x9817, 0x002b, 0xffd2, 0x3383, + 0x188c, 0x3e01, 0x8c06, 0x0006, 0xa097, 0x3009, 0x1c12, 0x3213, 0x0024, + 0x468c, 0xbc12, 0x002b, 0xffd2, 0xf400, 0x4197, 0x2801, 0x6604, 0x3713, + 0x0024, 0x2801, 0x6645, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x3383, 0x0024, + 0x3009, 0x0c06, 0x468c, 0x4197, 0x0006, 0xa052, 0x2801, 0x6844, 0x3713, + 0x2813, 0x2801, 0x6885, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x36f1, 0x8024, + 0x36f2, 0x9817, 0x36f4, 0xd812, 0x2100, 0x0000, 0x3904, 0x5bd1, 0x2a01, + 0x594e, 0x3e11, 0x7804, 0x0030, 0x0257, 0x3701, 0x0024, 0x0013, 0x4d05, + 0xd45b, 0xe0e1, 0x0007, 0xc795, 0x2801, 0x7095, 0x0fff, 0xff45, 0x3511, + 0x184c, 0x4488, 0xb808, 0x0006, 0x8a97, 0x2801, 0x7045, 0x3009, 0x1c40, + 0x3511, 0x1fc1, 0x0000, 0x0020, 0xac52, 0x1405, 0x6ce2, 0x0024, 0x0000, + 0x0024, 0x2801, 0x7041, 0x68c2, 0x0024, 0x291a, 0x8a40, 0x3e10, 0x0024, + 0x2921, 0xca80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3009, 0x1bc8, 0x36f0, + 0x1801, 0x3601, 0x5804, 0x3e13, 0x780f, 0x3e13, 0xb808, 0x0008, 0x9b0f, + 0x0001, 0x734e, 0x2908, 0x9300, 0x0000, 0x004d, 0x36f3, 0x9808, 0x2000, + 0x0000, 0x36f3, 0x580f, 0x0007, 0x81d7, 0x3711, 0x8024, 0x3711, 0xc024, + 0x3700, 0x0024, 0x0000, 0x2001, 0xb012, 0x0024, 0x0034, 0x0000, 0x2801, + 0x78c5, 0x0000, 0x01c1, 0x3700, 0x0024, 0x0002, 0x0001, 0xb012, 0x0024, + 0x002e, 0xe001, 0x2801, 0x77c5, 0x6512, 0x0024, 0x0034, 0x0000, 0x2801, + 0x78d5, 0x0000, 0x01c1, 0x0030, 0x0117, 0x3f00, 0x0024, 0x0014, 0xc000, + 0x0000, 0x01c1, 0x4fce, 0x0024, 0xffea, 0x0024, 0x48b6, 0x0024, 0x4384, + 0x4097, 0xb886, 0x45c6, 0xfede, 0x0024, 0x4db6, 0x0024, 0x466c, 0x0024, + 0x0006, 0xc610, 0x8dd6, 0x8007, 0x0000, 0x00c6, 0xff6e, 0x0024, 0x48b2, + 0x0024, 0x0034, 0x2406, 0xffee, 0x0024, 0x2914, 0xaa80, 0x40b2, 0x0024, + 0xf1c6, 0x0024, 0xf1d6, 0x0024, 0x0000, 0x0201, 0x8d86, 0x0024, 0x61de, + 0x0024, 0x0006, 0xc612, 0x2801, 0x7f41, 0x0006, 0xc713, 0x4c86, 0x0024, + 0x2912, 0x1180, 0x0006, 0xc351, 0x0006, 0x0210, 0x2912, 0x0d00, 0x3810, + 0x984c, 0xf200, 0x2043, 0x2808, 0xa000, 0x3800, 0x0024, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x7802, 0x3e04, 0x3811, 0x34a3, 0x0024, 0x3470, 0x0024, + 0x2801, 0x88c0, 0x3cf0, 0x0024, 0x0000, 0xfa01, 0x3e10, 0x0024, 0x3410, + 0x0024, 0x3e10, 0x0024, 0x3410, 0x0024, 0x3e10, 0x0024, 0x3430, 0x0024, + 0x2920, 0x0600, 0x3e00, 0x0024, 0x36c3, 0x128c, 0xf400, 0x4510, 0x3420, + 0x0024, 0x6012, 0x4511, 0x3800, 0x4024, 0x0000, 0x7d01, 0x3440, 0x0024, + 0x4012, 0x0024, 0x3900, 0x4024, 0x0000, 0xfa00, 0x34a3, 0x184c, 0x3410, + 0x4024, 0x6014, 0x0024, 0x0000, 0x0024, 0x2801, 0x8451, 0x0000, 0x0024, + 0x3e10, 0x4024, 0x3410, 0x0024, 0x3e10, 0x0024, 0x3410, 0x0024, 0x3e10, + 0x0024, 0x3430, 0x0024, 0x2920, 0x0600, 0x3e00, 0x0024, 0x36c3, 0x104c, + 0x34f0, 0x1811, 0x36f4, 0x0024, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x0000, 0x0081, 0x3e10, 0xb804, 0x3e14, 0x3811, + 0x0006, 0x9f90, 0x3e04, 0xb813, 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, + 0x0000, 0x6104, 0xa001, 0x0000, 0x0940, 0x2801, 0x94c1, 0xb882, 0x0024, + 0x0001, 0x0001, 0x3009, 0x0000, 0x4012, 0x0024, 0x0000, 0x0940, 0xb882, + 0xa001, 0x0000, 0xa992, 0x0007, 0xc051, 0x2914, 0xbec0, 0x0007, 0xc010, + 0x0001, 0x8150, 0x003f, 0xffc0, 0x001f, 0xffc1, 0x3944, 0x0024, 0x0007, + 0xd010, 0x3974, 0x8024, 0x0030, 0x0252, 0x4890, 0x2780, 0x3910, 0x0024, + 0x39d0, 0x4024, 0x3910, 0x0024, 0x2902, 0x0600, 0x39f0, 0x4024, 0x3800, + 0x0024, 0x0011, 0x14c0, 0x3a00, 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0024, 0x2801, 0x9d85, 0x0000, 0x0024, 0x3413, 0x184c, 0x2b50, + 0x4013, 0x3e11, 0x0c8c, 0x0007, 0xc004, 0x3e11, 0x13cc, 0x3e00, 0x0024, + 0x3302, 0x0024, 0x2000, 0x0000, 0x0001, 0x9d48, 0x36d3, 0x0024, 0x36f4, + 0x9813, 0x36f4, 0x1811, 0x36f0, 0x9804, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb813, 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, + 0x3e11, 0x7806, 0x3e11, 0xf80d, 0x3e13, 0xf80e, 0xf400, 0x4455, 0x6804, + 0x1444, 0xf400, 0x4417, 0x2801, 0xb458, 0x4094, 0x1453, 0x0000, 0x0051, + 0x0fff, 0xff01, 0x2401, 0xb402, 0x3700, 0x8024, 0x003f, 0xc007, 0xb274, + 0x0024, 0xc428, 0x3812, 0x0020, 0x07d2, 0x0003, 0xffc7, 0xb47c, 0x0e0c, + 0x0008, 0x0003, 0x4360, 0x0024, 0xa41c, 0x4010, 0xb67c, 0x0002, 0x4360, + 0x2e02, 0x0000, 0x0206, 0xb58a, 0x1c04, 0xae6a, 0x4010, 0xc548, 0x0002, + 0xb47c, 0x2e02, 0x4360, 0x148c, 0xa41c, 0x4010, 0xb67c, 0x0002, 0x4360, + 0x2e02, 0xf400, 0x4010, 0x3711, 0x3813, 0x0000, 0x3fc6, 0xb468, 0x0000, + 0xb78e, 0x1786, 0x0028, 0x07d2, 0x4ffe, 0x0024, 0x4ffe, 0x1490, 0xbd87, + 0xb80d, 0xfe51, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, + 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, + 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, + 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, + 0x380d, 0x505f, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, + 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, + 0x3005, 0x5056, 0x1812, 0x4db6, 0x9813, 0x0fff, 0xff40, 0xad06, 0x0024, + 0x4fde, 0x0024, 0xf1fe, 0x1c02, 0xf1fe, 0x0024, 0xf6fe, 0x3786, 0x3009, + 0x2847, 0x35f3, 0x0024, 0x3df4, 0xc024, 0x3d01, 0x1bcc, 0x36f3, 0xd80e, + 0x36f1, 0xd80d, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x2000, + 0x0000, 0x36f2, 0x9813, 0x3613, 0x0024, 0x3e12, 0xb813, 0x0000, 0x800a, + 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7806, 0x3e11, 0xf80d, 0x3e13, + 0xf80e, 0x3009, 0x3854, 0xf400, 0x4455, 0x6804, 0x1444, 0xf400, 0x4417, + 0x2801, 0xcc18, 0x4094, 0x1453, 0x0fff, 0xff01, 0x0000, 0x0051, 0x2401, + 0xcbc2, 0x3700, 0x8024, 0x0fff, 0xfe07, 0xa274, 0x3812, 0x0000, 0x3fc7, + 0xb274, 0x0024, 0x0020, 0x07d2, 0xc428, 0x0e0c, 0xa41c, 0x0024, 0x0003, + 0xffc7, 0xb67c, 0x0024, 0x0008, 0x0003, 0x4360, 0x0024, 0xf400, 0x4010, + 0xb47c, 0x0002, 0x4360, 0x2e02, 0x3701, 0x0024, 0xa41c, 0x4010, 0x3000, + 0x8024, 0xb67c, 0x2e02, 0x4360, 0x948c, 0xf400, 0x4010, 0xb47c, 0x0002, + 0x4360, 0x2e02, 0xf400, 0x4010, 0x3711, 0x3813, 0x0000, 0x0206, 0xa468, + 0x0000, 0xb78e, 0x1786, 0x0028, 0x07d2, 0x4ffe, 0x0024, 0x4ffe, 0x1490, + 0xbd87, 0xb80d, 0xfe51, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, + 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, + 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x505f, 0x380d, 0x505f, + 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, + 0x505f, 0x380d, 0x505f, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, + 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, + 0x5057, 0x3005, 0x5056, 0x1812, 0x4db6, 0x9813, 0x0fff, 0xff40, 0xad06, + 0x0024, 0x4fde, 0x0024, 0xf1fe, 0x1c02, 0xf1fe, 0x0024, 0xf6fe, 0x3786, + 0x3009, 0x2847, 0x35f3, 0x0024, 0x3df4, 0xdbcc, 0x3d01, 0x1bd4, 0x36f3, + 0xd80e, 0x36f1, 0xd80d, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, + 0x2000, 0x0000, 0x36f2, 0x9813, 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, + 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7806, 0x3e11, 0xf813, + 0x3e13, 0xf80e, 0x3e03, 0x7814, 0xf400, 0x4497, 0x6804, 0x044c, 0x0000, + 0x0024, 0x2801, 0xdb18, 0x4094, 0x0024, 0xf224, 0x0024, 0x2401, 0xdac2, + 0x0000, 0x0055, 0x0028, 0x07d3, 0x3114, 0x8024, 0x31f5, 0x0024, 0x3283, + 0x0040, 0x3a80, 0x0040, 0x3a00, 0x0024, 0xbe8a, 0x2412, 0x0020, 0x07d3, + 0xbd87, 0x2849, 0xfe11, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x501b, 0x2849, 0x501b, 0x2849, + 0x501b, 0x2849, 0x501b, 0x2849, 0x501b, 0x2849, 0x501b, 0x2849, 0x501b, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5016, 0x0024, + 0x4db6, 0x0024, 0x0fff, 0xff40, 0xad06, 0x0024, 0x4eda, 0x0024, 0xf7ea, + 0x0024, 0x3f11, 0x4024, 0x3f18, 0x8024, 0x36f3, 0x5814, 0x36f3, 0xd80e, + 0x36f1, 0xd813, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x2000, + 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, 0xb814, 0x0000, 0x800a, + 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7806, 0x3e11, 0xf813, 0x3e13, + 0xf80e, 0x3e03, 0x4024, 0x6804, 0x044c, 0x0000, 0x0024, 0x2801, 0xf758, + 0x4094, 0x4497, 0xf224, 0x0024, 0x2401, 0xf702, 0x0000, 0x0095, 0x0028, + 0x7fd3, 0xbe8a, 0x0452, 0x31f5, 0x0a0c, 0x3010, 0x0024, 0x3010, 0x4024, + 0x3a80, 0x4024, 0x3a80, 0x0024, 0x3010, 0x0024, 0x3010, 0x4024, 0x3a80, + 0x4024, 0x3a00, 0x3812, 0x0010, 0x41d3, 0xbd87, 0x2849, 0xfe11, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2041, 0x3223, + 0x104c, 0x501b, 0x2041, 0x32e3, 0x13cc, 0x3283, 0x120c, 0x501b, 0x2849, + 0x501b, 0x2849, 0x501b, 0x2849, 0x501b, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5016, 0x9812, 0x4db6, 0x2452, 0x0fff, 0xff40, 0xad06, 0x07d4, + 0x4dee, 0x084c, 0x3f11, 0x8024, 0x3f31, 0xc024, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x36f1, 0xd813, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, + 0x2000, 0x0000, 0x36f2, 0x9814, 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x780d, 0x6840, 0xb80e, + 0x0000, 0x0024, 0x2801, 0xfe18, 0x4490, 0x380f, 0xf200, 0x0024, 0x003f, + 0xc001, 0x2401, 0xfdc0, 0x0000, 0x0200, 0xb386, 0x0445, 0xb51a, 0x0442, + 0xad06, 0x0024, 0xc356, 0x0024, 0x3810, 0xc024, 0x36f3, 0xd80e, 0x36f1, + 0x580d, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x2000, 0x0000, 0x36f2, 0x9815, + 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, + 0xb805, 0x3e13, 0xf80e, 0x3e03, 0x4024, 0x6840, 0x0024, 0x0000, 0x0024, + 0x2802, 0x0498, 0x4490, 0x0024, 0x0000, 0x0201, 0xf200, 0x0024, 0x2402, + 0x0440, 0x0000, 0x3fc2, 0x3110, 0x0024, 0xa010, 0x0445, 0xb52a, 0x0024, + 0xc050, 0x0024, 0x3810, 0x0024, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f0, + 0x9805, 0x36f0, 0x1801, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x3e10, + 0x7810, 0x0003, 0xf410, 0xb882, 0x3811, 0x0002, 0x0611, 0x3009, 0x3812, + 0x0002, 0x0d12, 0x2914, 0xbec0, 0x0000, 0x0700, 0x0003, 0xf410, 0x0000, + 0x4140, 0x3810, 0x0024, 0x0003, 0xf400, 0x3824, 0x4024, 0x0002, 0x70d1, + 0x38f4, 0x9812, 0x3804, 0x4024, 0x36f4, 0x4024, 0x36f0, 0x5810, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x0000, 0x0200, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3655, + 0x0024, 0x0000, 0x800a, 0x3e10, 0xb804, 0x3e11, 0x7810, 0x3e14, 0x504c, + 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x130c, 0x3430, + 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, + 0x0002, 0x1408, 0x0000, 0x0201, 0x6012, 0x9b4c, 0x3413, 0x0024, 0x2802, + 0x1601, 0xf400, 0x4511, 0x34f3, 0x1bcc, 0x2802, 0x1880, 0xbc82, 0x0024, + 0x2900, 0x5b40, 0x3100, 0x93cc, 0xb182, 0x184c, 0x3113, 0x3840, 0x2900, + 0x5b40, 0x3100, 0x8024, 0x4088, 0x9bc0, 0xf400, 0x4105, 0x0000, 0x0004, + 0xcce2, 0x0024, 0x36f4, 0x4024, 0x36f1, 0x5810, 0x36f0, 0x9804, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x0000, 0x0200, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3655, 0x0024, 0x0000, 0x800a, 0x3e11, 0x3805, 0x3e14, 0x3811, + 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, + 0x130c, 0x3430, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, + 0x2000, 0x0000, 0x0002, 0x1f88, 0x0000, 0x0201, 0x6012, 0x9b0c, 0x3443, + 0x0024, 0x2802, 0x2141, 0xf400, 0x4511, 0x2802, 0x2280, 0xbc82, 0x130c, + 0x31f0, 0x130c, 0xb182, 0x0404, 0xf400, 0x4105, 0x0000, 0x0004, 0xcce2, + 0x0024, 0x36f4, 0x1811, 0x36f1, 0x1805, 0x3405, 0x9014, 0x36f3, 0x0024, + 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x0000, 0x0100, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, + 0x0000, 0x800a, 0x3e10, 0xb804, 0x3e11, 0x7810, 0x3e14, 0x504c, 0xb880, + 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x130c, 0x3430, 0x0024, + 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, 0x0002, + 0x2948, 0x0000, 0x0101, 0x6012, 0x9b4c, 0x3413, 0x0024, 0x2802, 0x2b41, + 0xf400, 0x4511, 0x34f3, 0x1bcc, 0x2802, 0x2dc0, 0xbc82, 0x0024, 0x2900, + 0x5b40, 0x3100, 0x93cc, 0xb182, 0x184c, 0x3113, 0x3840, 0x2900, 0x5b40, + 0x3100, 0x8024, 0x4088, 0x9bc0, 0xf400, 0x4105, 0x0000, 0x0004, 0xcce2, + 0x0024, 0x36f4, 0x4024, 0x36f1, 0x5810, 0x36f0, 0x9804, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x0000, + 0x0100, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3635, 0x0024, 0x0000, 0x800a, 0x3e11, 0x3805, 0x3e14, 0x3811, 0x3e10, + 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x130c, + 0x3430, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, + 0x0000, 0x0002, 0x34c8, 0x0000, 0x0101, 0x6012, 0x9b0c, 0x3423, 0x0024, + 0x2802, 0x3681, 0xf400, 0x4511, 0x2802, 0x37c0, 0xbc82, 0x138c, 0x31f0, + 0x138c, 0xb182, 0x0404, 0xf400, 0x4105, 0x0000, 0x0004, 0xcce2, 0x0024, + 0x36f4, 0x1811, 0x36f1, 0x1805, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x0000, 0x0080, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, + 0x800a, 0x3e14, 0x3811, 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, + 0xf400, 0x4500, 0x3e10, 0x130c, 0x3430, 0x0024, 0xf400, 0x4010, 0x3e00, + 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, 0x0002, 0x3e48, 0x0000, 0x0081, + 0x6012, 0x1b0c, 0x0000, 0x0024, 0x2802, 0x4001, 0xb182, 0x104c, 0x2802, + 0x4040, 0xbc82, 0x13cc, 0x34f0, 0x0024, 0x36f4, 0x1811, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3645, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb804, 0x3e11, 0x7806, 0x3e11, 0xf810, 0x3e14, + 0x780d, 0x3e03, 0xf80e, 0x0003, 0xffce, 0xb880, 0x108c, 0x3c10, 0x0024, + 0x3ce0, 0x0024, 0x2402, 0x6e0e, 0x3cf0, 0x0024, 0x0006, 0x18d0, 0xbe8a, + 0x104c, 0x6892, 0x13c0, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, + 0x2802, 0x4885, 0xfe02, 0x0024, 0x2802, 0x48c0, 0x4eba, 0x0024, 0x6eba, + 0x0024, 0x0000, 0x0081, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0024, 0x2802, 0x4b45, 0x4192, 0x0000, 0xfe02, 0x0024, 0x2802, + 0x4bc0, 0x4eba, 0x0024, 0xfe02, 0x0024, 0x6eba, 0x0024, 0x0000, 0x0101, + 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, + 0x0024, 0x2802, 0x4e45, 0xfe02, 0x0024, 0x2802, 0x4e80, 0x4eba, 0x0024, + 0x6eba, 0x0024, 0x0000, 0x0201, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, 0x5105, 0xfe02, 0x0024, + 0x2802, 0x5140, 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0000, 0x0401, 0x3413, + 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, + 0x2802, 0x53c5, 0xfe02, 0x0024, 0x2802, 0x5400, 0x4eba, 0x0024, 0x6eba, + 0x0024, 0x0000, 0x0801, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, 0x5685, 0xfe02, 0x0024, 0x2802, + 0x56c0, 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0000, 0x1001, 0x3413, 0x004c, + 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, + 0x5945, 0xfe02, 0x0024, 0x2802, 0x5980, 0x4eba, 0x0024, 0x6eba, 0x0024, + 0x0000, 0x2001, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, + 0x0041, 0x3000, 0x0024, 0x2802, 0x5c05, 0xfe02, 0x0024, 0x2802, 0x5c40, + 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0000, 0x4001, 0x3413, 0x004c, 0x34f0, + 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, 0x5ec5, + 0xfe02, 0x0024, 0x2802, 0x5f00, 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0000, + 0x8001, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, + 0x3000, 0x0024, 0x2802, 0x6185, 0xfe02, 0x0024, 0x2802, 0x61c0, 0x4eba, + 0x0024, 0x6eba, 0x0024, 0x0001, 0x0001, 0x3413, 0x004c, 0x34f0, 0x0024, + 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, 0x6445, 0xfe02, + 0x0024, 0x2802, 0x6480, 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0002, 0x0001, + 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, + 0x0024, 0x2802, 0x6705, 0xfe02, 0x0024, 0x2802, 0x6740, 0x4eba, 0x0024, + 0x6eba, 0x0024, 0xf1ea, 0x104c, 0x4e82, 0x1042, 0x0008, 0x0001, 0x4122, + 0x0024, 0xf400, 0x4055, 0x0000, 0x0041, 0x3d00, 0x0024, 0x3410, 0x0024, + 0xfe02, 0x0024, 0x48b2, 0x0024, 0x6cee, 0x1380, 0x0000, 0x0041, 0x2802, + 0x6bc9, 0xfe02, 0x4511, 0x3413, 0x0024, 0x3c11, 0x0024, 0x34e0, 0x0024, + 0xfe02, 0x4511, 0x48b2, 0x0024, 0x6cee, 0x1080, 0x0000, 0x0024, 0x2802, + 0x6dd8, 0x0000, 0x0024, 0x3ce1, 0x0024, 0xf400, 0x4511, 0x3420, 0x0024, + 0x6090, 0x934c, 0x3900, 0x0024, 0x36f3, 0xd80e, 0x36f4, 0x580d, 0x36f1, + 0xd810, 0x36f1, 0x5806, 0x36f0, 0x9804, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x0000, 0x0657, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3685, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7806, 0x3e11, + 0xf810, 0x3e14, 0x7812, 0x3e04, 0xd34c, 0x2902, 0x41c0, 0x6898, 0x10d2, + 0xf400, 0x4490, 0x34c3, 0x010c, 0x34f0, 0x184c, 0x3800, 0x0024, 0x3460, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0100, 0x2802, 0x7805, 0x0000, 0x0024, + 0x0006, 0x0580, 0x3009, 0x128c, 0x3464, 0x4024, 0x3900, 0x0024, 0x0000, + 0x0100, 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, + 0x3440, 0x0024, 0xf400, 0x4011, 0x3e00, 0x044c, 0x3102, 0x0024, 0x2000, + 0x0000, 0x0002, 0x7a88, 0x0000, 0x0101, 0x6012, 0x9b0c, 0x0012, 0x5101, + 0x2802, 0x7c41, 0x3413, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x13cc, 0xf400, + 0x4510, 0x34f0, 0x004c, 0x6012, 0x0000, 0x003f, 0xc001, 0x2802, 0x9515, + 0xb010, 0x0024, 0x000c, 0xc001, 0x6012, 0x0024, 0x0000, 0x0024, 0x2802, + 0x9515, 0x0000, 0x0024, 0xb880, 0x110c, 0x3cd0, 0x184c, 0x0000, 0x0080, + 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, 0x3440, + 0x0024, 0x3e00, 0x0024, 0x3102, 0x0024, 0x2000, 0x0000, 0x0002, 0x8208, + 0x0000, 0x0100, 0x36d3, 0x104c, 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, + 0x4500, 0x3e10, 0x12cc, 0x3440, 0x0024, 0x3e00, 0x0024, 0x3102, 0x0024, + 0x2000, 0x0000, 0x0002, 0x84c8, 0x001f, 0xc001, 0x0000, 0x1fc2, 0x3123, + 0x108c, 0xf400, 0x4510, 0x34e0, 0x1b0c, 0xb010, 0x0081, 0xf200, 0x0024, + 0xb122, 0x0024, 0x4010, 0x0024, 0x3800, 0x0024, 0x31f0, 0x0024, 0x4080, + 0x0024, 0x3100, 0x0024, 0x2802, 0x8c85, 0x4080, 0x0024, 0x0000, 0x0043, + 0x34c3, 0x184c, 0x6890, 0x844c, 0x3e10, 0x0024, 0x3000, 0x8024, 0xfe26, + 0x0024, 0x48b6, 0x0024, 0x3e10, 0x8024, 0x3e10, 0xc024, 0x3440, 0x0024, + 0x3e00, 0x0024, 0x3102, 0x0024, 0x2000, 0x0000, 0x0002, 0x8c08, 0x2802, + 0x9040, 0x36c3, 0x0024, 0x0000, 0x0024, 0x2802, 0x9045, 0x0000, 0x0024, + 0x0000, 0x0041, 0x3000, 0x184c, 0xfe02, 0x930c, 0x48b2, 0x0024, 0x3e10, + 0x0024, 0x3e10, 0x4024, 0x3440, 0xc024, 0x3e00, 0xc024, 0x3102, 0x0024, + 0x2000, 0x0000, 0x0002, 0x9008, 0x36d3, 0x0024, 0x0000, 0x0100, 0x3613, + 0x104c, 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, + 0x3440, 0x0024, 0xf400, 0x4011, 0x3e00, 0x044c, 0x3102, 0x0024, 0x2000, + 0x0000, 0x0002, 0x9348, 0x0000, 0x0101, 0x6012, 0x1b0c, 0x0000, 0x0024, + 0x2802, 0x9501, 0x0000, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x0024, 0x0011, + 0x9481, 0x3413, 0x0024, 0xf400, 0x4510, 0x34f0, 0x004c, 0x6012, 0x0000, + 0x0013, 0x4e01, 0x2803, 0x1fd5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2803, + 0x1fd5, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3470, 0x8024, 0x2902, 0x1a80, + 0x3e00, 0x8024, 0x3c10, 0x0024, 0x0000, 0x0100, 0x3cd0, 0x4024, 0xb880, + 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x13cc, 0x3e00, 0x8024, + 0x3102, 0x0024, 0x2000, 0x0000, 0x0002, 0x9b88, 0x0000, 0x0101, 0x6012, + 0x9b0c, 0x0011, 0x14c1, 0x2802, 0x9d41, 0x3413, 0x0024, 0x2803, 0xd9c0, + 0x4480, 0x13cc, 0xf400, 0x4510, 0x34f0, 0x004c, 0x6012, 0x0000, 0x0011, + 0x0801, 0x2803, 0x1fd5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2803, 0x1fd5, + 0x0000, 0x0024, 0xb880, 0x11cc, 0xb882, 0x3040, 0x002b, 0x1100, 0xb888, + 0x3040, 0x3c90, 0x4024, 0x3493, 0x0024, 0x3450, 0x0024, 0x4080, 0x0024, + 0x0006, 0x0a40, 0x2803, 0x1b45, 0x0000, 0x0024, 0x34b3, 0x0024, 0x3454, + 0x0024, 0x2803, 0x1b40, 0x3800, 0x0024, 0xb880, 0x3840, 0x3e10, 0x0024, + 0xf400, 0x4500, 0x3e10, 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, + 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, 0x0002, 0xa5c8, 0x0000, 0x0101, + 0x6012, 0x130c, 0x3440, 0x9b4c, 0x2802, 0xa781, 0xf400, 0x4100, 0x2803, + 0xd9c0, 0x3009, 0x1bcc, 0x2902, 0x1a80, 0x3e00, 0x8024, 0x36f3, 0x114c, + 0x3c10, 0x0024, 0x3cb0, 0x4024, 0xf400, 0x4511, 0x0014, 0x1481, 0x34f0, + 0x0024, 0x6012, 0x0024, 0x0013, 0xd401, 0x2803, 0x1715, 0x0000, 0x0024, + 0x3113, 0x0024, 0x3100, 0x0024, 0x6012, 0x0024, 0x0000, 0x0024, 0x2803, + 0x1715, 0x0000, 0x0024, 0x3613, 0x0024, 0x2902, 0x2440, 0x3e00, 0x8024, + 0x36f3, 0x11cc, 0x3433, 0x0024, 0x3c10, 0x0024, 0x3c90, 0x4024, 0x2803, + 0x1000, 0x34c3, 0x0024, 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, + 0x3e10, 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0002, 0xb0c8, 0x0000, 0x0101, 0x6012, 0x130c, + 0x3440, 0x9b4c, 0x2802, 0xb281, 0xf400, 0x4100, 0x2803, 0xd9c0, 0x3009, + 0x1bcc, 0x2902, 0x1a80, 0x3e00, 0x8024, 0x36f3, 0x11cc, 0x3453, 0x0024, + 0x3c10, 0x0024, 0x0000, 0x0300, 0xb882, 0x33c1, 0x3411, 0x8024, 0x3491, + 0xc024, 0x6cf2, 0x13cc, 0xf400, 0x4511, 0x3110, 0x92cc, 0x31f0, 0xc024, + 0x6dc2, 0x0024, 0x3910, 0x0024, 0x39b0, 0x4024, 0x0011, 0x94c1, 0x3110, + 0x0024, 0x6012, 0x0400, 0x0008, 0x0801, 0x2802, 0xbd95, 0x6012, 0x0024, + 0x0000, 0x0024, 0x2802, 0xbd95, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3440, + 0x8024, 0x2902, 0x2fc0, 0x3e00, 0x8024, 0x0000, 0x0102, 0x36f3, 0x11cc, + 0xb886, 0x104c, 0x3c10, 0x0024, 0x3c90, 0x4024, 0x34e3, 0x0024, 0xf400, + 0x4511, 0x3173, 0x0024, 0x3153, 0x0024, 0x3110, 0x0024, 0x31f0, 0x4024, + 0x6cd6, 0x0024, 0x3910, 0x8024, 0x2803, 0x0b80, 0x39f0, 0xc024, 0x0010, + 0xd201, 0x3413, 0x0024, 0xf400, 0x4511, 0x34f0, 0x044c, 0x6012, 0x0400, + 0x0013, 0x9301, 0x2802, 0xc455, 0x6012, 0x0024, 0x0000, 0x0024, 0x2802, + 0xc455, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3440, 0x8024, 0x2902, 0x3980, + 0x3e00, 0x8024, 0x36f3, 0x11cc, 0xb882, 0x3240, 0xf400, 0x4511, 0x0000, + 0x0080, 0x3173, 0x0024, 0x3153, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, + 0x6dc2, 0x0024, 0x3910, 0x0024, 0x2803, 0x0b80, 0x39f0, 0x4024, 0x0011, + 0x14c1, 0x3413, 0x0024, 0xf400, 0x4511, 0x34f0, 0x0024, 0x6012, 0x0024, + 0x0011, 0x0801, 0x2803, 0x0b95, 0x0000, 0x0024, 0x3113, 0x0024, 0x3100, + 0x0024, 0x6012, 0x0024, 0x0000, 0x0024, 0x2803, 0x0b95, 0x0000, 0x0024, + 0x003f, 0xfe82, 0x0000, 0x04d1, 0x3473, 0x020c, 0x3413, 0x04cc, 0x3410, + 0x0024, 0x34e0, 0x4024, 0xac22, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, + 0x0000, 0x0081, 0x3490, 0x0024, 0x34c3, 0x0024, 0x3474, 0x0024, 0x3083, + 0x110c, 0x3800, 0x0024, 0x3490, 0x0024, 0x6012, 0x130c, 0x3444, 0x0024, + 0x2802, 0xcf85, 0x3043, 0x0024, 0x34b3, 0x0024, 0x3450, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0184, 0x2802, 0xcf05, 0x0006, 0x0b00, 0x34b3, 0x0024, + 0x3454, 0x0024, 0x3800, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x0024, 0x30f0, + 0x0024, 0x4080, 0x0024, 0x3000, 0x0024, 0x2803, 0x01c5, 0x4080, 0x0024, + 0x0000, 0x0024, 0x2803, 0x01c5, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3440, + 0x8024, 0xf400, 0x4090, 0x3e00, 0x810c, 0x3002, 0x0024, 0x2000, 0x0000, + 0x0002, 0xd348, 0xf400, 0x4491, 0x0000, 0x0610, 0x3473, 0x060c, 0x3910, + 0x114c, 0x3910, 0x5bcc, 0x3410, 0x0024, 0x3490, 0x4024, 0x3910, 0x128c, + 0x2803, 0x01c0, 0x39f0, 0x4024, 0x3053, 0x0024, 0x3090, 0x0024, 0x6012, + 0x038c, 0x3000, 0x0024, 0x2802, 0xecc5, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2802, 0xecc5, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3444, 0x0024, 0x3073, + 0x0024, 0x3053, 0x0024, 0x3070, 0x0024, 0x4080, 0x00cc, 0x0000, 0x0024, + 0x2802, 0xe095, 0x0000, 0x0024, 0x0000, 0x0610, 0xb880, 0x4491, 0x3e10, + 0x060c, 0x3110, 0x930c, 0x31f0, 0xc024, 0x3e10, 0x8024, 0x3e10, 0xc024, + 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x00cc, 0x3002, 0x0024, 0x2000, + 0x0000, 0x0002, 0xdd88, 0x3473, 0x048c, 0x3110, 0x114c, 0x31f0, 0x41cc, + 0x0000, 0x0411, 0x3c10, 0x010c, 0x3c90, 0x5b0c, 0xbc82, 0x124c, 0x3810, + 0x134c, 0x38f0, 0x4024, 0x3444, 0x0024, 0x2802, 0xeb00, 0x3083, 0x0024, + 0xb78e, 0x4511, 0x3090, 0x3804, 0x30d3, 0x130c, 0x3021, 0x8024, 0x3010, + 0x8024, 0x3050, 0xc024, 0x6fde, 0x0042, 0xfeae, 0x03c3, 0x0000, 0x03d0, + 0x3e00, 0xc60c, 0x48ba, 0x0024, 0xffe6, 0x0024, 0x5daa, 0x0024, 0x0000, + 0x00c2, 0x44be, 0x9804, 0xaf2e, 0x0024, 0xfff0, 0x4007, 0x48b2, 0x0024, + 0xffee, 0x0024, 0x40b2, 0x0024, 0x6890, 0x2440, 0x39f0, 0x4024, 0x3e10, + 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x3e10, 0x8024, 0x3e10, 0xc024, + 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x00cc, 0x3002, 0x0024, 0x2000, + 0x0000, 0x0002, 0xe8c8, 0xf400, 0x4513, 0x3073, 0x0dcc, 0x3353, 0x008c, + 0x3310, 0x1b0c, 0x33f0, 0x4024, 0x6cd6, 0x0024, 0xb182, 0x2c42, 0x3bf0, + 0xc024, 0x3020, 0x0024, 0x3810, 0x130c, 0x003f, 0xffc0, 0x38f0, 0x4024, + 0x3444, 0x0024, 0x3073, 0x0024, 0x3053, 0x0024, 0x3800, 0x0024, 0x0004, + 0x0000, 0x3613, 0x130c, 0xb880, 0x3840, 0x3e10, 0x0024, 0x000d, 0x0000, + 0x3e10, 0x0024, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0002, 0xefc8, 0x0004, 0x0001, 0x6012, 0x1b0c, + 0x0004, 0x0000, 0x2803, 0x0b91, 0x0004, 0x0010, 0xb882, 0x4511, 0x3173, + 0x184c, 0x3153, 0x3804, 0x3110, 0x8024, 0x31f0, 0xc024, 0x6dc2, 0x0024, + 0x3910, 0x0024, 0x39f0, 0x4024, 0x000d, 0x0011, 0x2901, 0xf940, 0x0002, + 0x0004, 0x0005, 0x0010, 0x000d, 0x0011, 0x0000, 0x4001, 0x2901, 0xff80, + 0x0002, 0x0004, 0x0004, 0x0010, 0x0001, 0x0000, 0x0006, 0x8091, 0x3009, + 0x1804, 0x3009, 0x3812, 0x2901, 0xb6c0, 0x0008, 0x0012, 0x0001, 0x0000, + 0x0006, 0x8311, 0x0008, 0x0010, 0x2901, 0xce80, 0x000d, 0x0012, 0x0000, + 0x8000, 0x000d, 0x0010, 0x0006, 0x8591, 0x2901, 0xdd00, 0x0002, 0x0012, + 0x0005, 0x0010, 0x0001, 0x0000, 0x0006, 0x81d1, 0x2901, 0xb6c0, 0x0008, + 0x0012, 0x0001, 0x0000, 0x0006, 0x8451, 0x0008, 0x0010, 0x2901, 0xce80, + 0x000d, 0x0012, 0x0000, 0x8000, 0x000d, 0x0010, 0x0006, 0x86d1, 0x2901, + 0xdd00, 0x0002, 0x0092, 0x0006, 0x8010, 0x3000, 0x9812, 0x6122, 0x930c, + 0x6810, 0x0024, 0x3e10, 0x0024, 0x0002, 0x0000, 0x4020, 0x0024, 0x4020, + 0x0024, 0x4020, 0x0024, 0x4020, 0x0024, 0x3e10, 0x0024, 0x3440, 0x0024, + 0xf400, 0x4011, 0x3e00, 0x054c, 0x3102, 0x0024, 0x2000, 0x0000, 0x0003, + 0x0148, 0xb880, 0x9b4c, 0x3800, 0x0024, 0x0004, 0x0000, 0xb882, 0x11cc, + 0x3453, 0x0024, 0x3410, 0x8024, 0x3490, 0xc024, 0x6dc2, 0x128c, 0x0000, + 0x0024, 0x2803, 0x0b88, 0x0000, 0x0024, 0x34c3, 0x0024, 0x3404, 0x0024, + 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, 0x1110, 0x003f, + 0xffc1, 0x2802, 0xd5c5, 0x3073, 0x0024, 0x2803, 0x0b80, 0x0000, 0x0024, + 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, + 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, + 0x2000, 0x0000, 0x0003, 0x0988, 0xf400, 0x4511, 0x36c3, 0x05cc, 0x3153, + 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x4d96, 0x0024, 0x3910, 0x8024, + 0x39f0, 0xc024, 0x3473, 0x0024, 0x3453, 0x0024, 0x3410, 0x0024, 0x3490, + 0x4024, 0x4c82, 0x128c, 0x0000, 0x0024, 0x2803, 0x1009, 0x0000, 0x0024, + 0x34c3, 0x184c, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0040, 0x2803, 0x06c5, 0x0000, 0x0024, + 0x36f3, 0x0024, 0x0000, 0x0300, 0xb882, 0x114c, 0x3410, 0x984c, 0x34b0, + 0xc024, 0x6dc2, 0x0024, 0x0000, 0x0100, 0x2802, 0xae58, 0x0000, 0x0024, + 0x2803, 0x1700, 0x36f3, 0x13cc, 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, + 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, + 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, 0x0003, 0x1548, 0x36c3, + 0x114c, 0xf400, 0x4511, 0x3110, 0x92cc, 0x31f0, 0xc024, 0x4d96, 0x0024, + 0x3910, 0x8024, 0x39f0, 0xc024, 0x3453, 0x0024, 0x3410, 0x0024, 0x34a0, + 0x4024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2803, 0x1b45, 0x0000, 0x0024, + 0x34c3, 0x184c, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0040, 0x2803, 0x1285, 0x0000, 0x0024, + 0x36f3, 0x0024, 0x3433, 0x0024, 0x3410, 0x8024, 0x3490, 0xc024, 0x4d86, + 0x13cc, 0x0000, 0x0024, 0x2803, 0x1f45, 0x0000, 0x0024, 0x3454, 0x184c, + 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0100, 0x2802, 0xa345, 0x0000, 0x0024, 0x36f3, 0x12cc, 0x2803, 0xd9c0, + 0x4480, 0x110c, 0x0011, 0x14c1, 0x3413, 0x0024, 0xf400, 0x4510, 0x34f0, + 0x004c, 0x6012, 0x0000, 0x0011, 0x0801, 0x2803, 0xd3d5, 0x6012, 0x0024, + 0x0000, 0x0024, 0x2803, 0xd3d5, 0x0000, 0x0024, 0xb888, 0x12cc, 0x3410, + 0x184c, 0x4080, 0x13c2, 0x0006, 0x0a40, 0x2803, 0x2485, 0x3414, 0x0024, + 0x3800, 0x0024, 0x3400, 0x8024, 0x2902, 0x0f00, 0x3e00, 0x91cc, 0x3c10, + 0x0024, 0x3cc0, 0x4024, 0x2902, 0x0f00, 0x3e00, 0x8024, 0x2902, 0x0f00, + 0x3e00, 0x8024, 0x0000, 0x0702, 0x36f3, 0x10cc, 0xb886, 0x4510, 0x3010, + 0x134c, 0x30f0, 0x494c, 0x6cd6, 0x0024, 0x3810, 0x8024, 0x38f0, 0xc024, + 0x0019, 0x9b41, 0x32b3, 0x104c, 0xf400, 0x4510, 0x34f0, 0x004c, 0x6012, + 0x0000, 0x001d, 0x0801, 0x2803, 0x42d5, 0x6012, 0x0024, 0x0000, 0x0024, + 0x2803, 0x42d5, 0x0000, 0x0024, 0x0000, 0x0511, 0x34c3, 0x184c, 0x3470, + 0x8024, 0x2902, 0x0f00, 0x3e00, 0x8024, 0x3c10, 0x0024, 0x3cc0, 0x4024, + 0x2902, 0x2440, 0x3e00, 0x8024, 0x2902, 0x2440, 0x3e00, 0x91cc, 0x3c10, + 0x0024, 0x3c10, 0x4024, 0x2902, 0x2440, 0x3e00, 0x8024, 0x3c10, 0x0024, + 0x3c10, 0x4024, 0x2902, 0x2440, 0x3e00, 0x8024, 0x3c10, 0x0024, 0x3c90, + 0x4024, 0x2902, 0x2440, 0x3e00, 0x92cc, 0x003f, 0xfe82, 0x3009, 0x11cc, + 0x3463, 0x0024, 0x3c10, 0x0024, 0x3cf0, 0x4024, 0x3410, 0x0024, 0x3490, + 0x4024, 0x3493, 0x0024, 0xac22, 0x130c, 0x3474, 0x0024, 0x3083, 0x11cc, + 0x3810, 0x104c, 0x38f0, 0x448c, 0x3490, 0x0024, 0x3493, 0x0024, 0x34f3, + 0x0024, 0x3404, 0x0024, 0x3083, 0x0024, 0x3800, 0x0024, 0x3440, 0x8024, + 0x2902, 0x2440, 0x3e00, 0x8024, 0xf400, 0x4510, 0x0000, 0x03d1, 0x3009, + 0x020c, 0x3810, 0x0024, 0x3830, 0x4024, 0x2902, 0x0f00, 0x3e00, 0x8024, + 0x3810, 0x0024, 0x38f0, 0x4024, 0x2902, 0x2440, 0x3e00, 0x8024, 0x36f3, + 0x038c, 0x3810, 0x0024, 0x38d0, 0x4024, 0x3010, 0x0024, 0x30b0, 0x4024, + 0x4c92, 0x0024, 0x0000, 0x0080, 0x2803, 0x3c85, 0xb882, 0x0024, 0x6890, + 0x4491, 0xb882, 0x054c, 0x3900, 0x0024, 0x0000, 0x0080, 0x3010, 0x90cc, + 0x30f0, 0xc024, 0x6dc2, 0x0024, 0x0000, 0x0c00, 0x2803, 0x4105, 0xb882, + 0x0024, 0x3493, 0x0024, 0x34f3, 0x0024, 0x3450, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0184, 0x2803, 0x4085, 0x0006, 0x0b00, 0x34b3, 0x0024, 0x3454, + 0x4024, 0x3900, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x0024, 0xf400, 0x4511, + 0x3110, 0x934c, 0x31f0, 0xc024, 0x6dc2, 0x0024, 0x3910, 0x0024, 0x2803, + 0xc740, 0x39f0, 0x4024, 0x0019, 0x1841, 0x3413, 0x0024, 0xf400, 0x4510, + 0x34f0, 0x004c, 0x6012, 0x0000, 0x001d, 0x1841, 0x2803, 0xc755, 0x6012, + 0x0024, 0x0000, 0x0024, 0x2803, 0xc755, 0x0000, 0x0024, 0x34c3, 0x184c, + 0x3440, 0x8024, 0x2902, 0x0f00, 0x3e00, 0x8024, 0x0000, 0x0302, 0x36f3, + 0x10cc, 0xb886, 0x3040, 0x3cf0, 0x4024, 0xf400, 0x4510, 0x3010, 0x134c, + 0x30f0, 0x4024, 0x6cd6, 0x0024, 0x3810, 0x8024, 0x3890, 0xc024, 0x30f3, + 0x0024, 0x3004, 0x4024, 0x3143, 0x0024, 0x3100, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0024, 0x2803, 0xbbc5, 0x0000, 0x0024, 0x31f3, 0x0024, 0x3100, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0xbbc5, 0x0000, 0x0024, + 0x3000, 0x984c, 0xf400, 0x4091, 0x3e00, 0x850c, 0x3102, 0x0024, 0x2000, + 0x0000, 0x0003, 0x4e08, 0xf400, 0x4493, 0x3073, 0x3812, 0x0000, 0x0612, + 0x3383, 0x1bd2, 0x3b10, 0x0024, 0x3b10, 0x4024, 0x3010, 0x0024, 0x30f0, + 0x4024, 0x3b10, 0x0024, 0x2803, 0xbbc0, 0x3bf0, 0x4024, 0x3483, 0x0024, + 0x1fff, 0xfb95, 0x3410, 0x0024, 0x3480, 0x4024, 0xf1c2, 0x4510, 0x003f, + 0xffc1, 0x3083, 0x130c, 0x3800, 0x0024, 0x3444, 0x4024, 0x3173, 0x0024, + 0x3153, 0x0024, 0x3190, 0x0024, 0x6012, 0x078c, 0x3100, 0x0024, 0x2803, + 0x8d05, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0x8d05, 0x0000, 0x0024, + 0x34c3, 0x0024, 0x3444, 0x4024, 0x3173, 0x0024, 0x3153, 0x0024, 0x3100, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0x6095, 0x0000, 0x0024, + 0xb880, 0x4493, 0x3613, 0x130c, 0x3e20, 0x0024, 0x3009, 0x3812, 0x0000, + 0x0612, 0x3383, 0x1bd2, 0x3310, 0x8024, 0x33f0, 0xc024, 0x3e10, 0x8024, + 0x3e10, 0xc024, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x00cc, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0003, 0x5bc8, 0xf400, 0x4490, 0x0000, 0x0691, + 0x3433, 0x020c, 0x3010, 0x1b0c, 0x30f0, 0x4024, 0x0000, 0x0410, 0x3c10, + 0x0024, 0xbc82, 0x3241, 0x34f3, 0x0024, 0x3404, 0x4024, 0x3183, 0x0024, + 0x3910, 0x0024, 0x39f0, 0x4024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3073, + 0x0024, 0x3810, 0x0024, 0x2803, 0x8b80, 0x38f0, 0x4024, 0xb182, 0x048c, + 0x3111, 0x804c, 0x3151, 0xd84c, 0x6cf2, 0x0442, 0x3110, 0xd30c, 0xfea2, + 0x0024, 0x48be, 0x0024, 0xff86, 0x0024, 0x51ae, 0x0024, 0x003f, 0xfdc2, + 0x46b2, 0x0024, 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0302, 0xac22, + 0x0024, 0x6890, 0x2040, 0x38f0, 0x4024, 0x3e10, 0x0024, 0x3100, 0x8024, + 0x3011, 0x8024, 0x30f1, 0xc024, 0xff74, 0x4087, 0x48b6, 0x0024, 0xffee, + 0x0024, 0x42b6, 0x0024, 0x3e10, 0x8024, 0x3e10, 0xc024, 0x3440, 0x0024, + 0xf400, 0x4013, 0x3e00, 0x0ccc, 0x3302, 0x0024, 0x2000, 0x0000, 0x0003, + 0x68c8, 0x0000, 0x05d5, 0x3100, 0x10cc, 0x0000, 0x05d1, 0x3011, 0x9b0c, + 0x30f1, 0xc024, 0xff70, 0x4007, 0x48b2, 0x4510, 0xffee, 0x934c, 0x40b2, + 0x0042, 0x30f0, 0xd20c, 0x1fff, 0xfa15, 0x4dc2, 0x0024, 0x003f, 0xff42, + 0x3810, 0x0024, 0x38f0, 0x4024, 0x3410, 0x0024, 0x3480, 0x4024, 0xac22, + 0x4510, 0x3083, 0x130c, 0x3810, 0x0024, 0x4c82, 0x23c1, 0x0000, 0x0510, + 0x2803, 0x7658, 0x4c86, 0x1111, 0x68c6, 0x060c, 0x3110, 0x0024, 0x2914, + 0xa580, 0x31f0, 0x4024, 0x0000, 0x0411, 0x0000, 0x05d5, 0x4d82, 0x130c, + 0x3444, 0x0024, 0x3083, 0x120c, 0x1fff, 0xfa15, 0x3010, 0x850c, 0x30f0, + 0xc024, 0x6dc2, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x3411, 0x8024, + 0x3481, 0xc024, 0x68f6, 0x130c, 0x3404, 0x0024, 0x3083, 0x0024, 0x3010, + 0x0024, 0x2914, 0xa580, 0x30f0, 0x4024, 0x3444, 0x0024, 0x3073, 0x0024, + 0x3073, 0x0024, 0x3010, 0x8024, 0x30f0, 0xc024, 0x2803, 0x7d80, 0x6dc2, + 0x0024, 0x3183, 0x0024, 0x3110, 0x0024, 0x2914, 0xa580, 0x31f0, 0x4024, + 0x0000, 0x0411, 0x0000, 0x05d5, 0x4d82, 0x130c, 0x3444, 0x0024, 0x3083, + 0x120c, 0x1fff, 0xfa15, 0x3010, 0x850c, 0x30f0, 0xc024, 0x4dc2, 0x0024, + 0x3810, 0x0024, 0x38f0, 0x4024, 0x3410, 0x8024, 0x3480, 0xc024, 0x34c3, + 0x0024, 0x3404, 0x0024, 0x3083, 0x0024, 0x3010, 0x0024, 0x2914, 0xa580, + 0x30f0, 0x4024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3073, 0x0024, 0x3010, + 0x8024, 0x30f0, 0xc024, 0x4dc2, 0x0024, 0x0000, 0x0411, 0x3810, 0x130c, + 0x38f0, 0x4024, 0x3404, 0x0024, 0x3083, 0x0024, 0x3010, 0x0024, 0x30f0, + 0x4024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2803, 0x8518, 0x0000, 0x0024, + 0x3404, 0x410c, 0x3010, 0x0024, 0x30f0, 0x4024, 0x0000, 0x0410, 0x3183, + 0x0024, 0x3111, 0x8024, 0x31f1, 0xc024, 0x4fc2, 0x0024, 0x3910, 0x0024, + 0x39f0, 0x4024, 0x0000, 0x0411, 0x3404, 0x0024, 0x3073, 0x0024, 0x3073, + 0x0024, 0x3010, 0x8024, 0x30f0, 0xc024, 0x4d96, 0x0024, 0x3810, 0x8024, + 0x38f0, 0xc024, 0x3444, 0x0024, 0x3083, 0x0024, 0x3010, 0x0024, 0x3030, + 0x4024, 0x3010, 0x8024, 0x30f0, 0xc024, 0x6cde, 0x0024, 0x0000, 0x0410, + 0x2803, 0x8b91, 0x0000, 0x0024, 0x34c3, 0x0024, 0x3404, 0x4024, 0x3183, + 0x0024, 0x3111, 0x8024, 0x31f1, 0xc024, 0x6fd6, 0x0024, 0x3910, 0x8024, + 0x39f0, 0xc024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3073, 0x0024, 0x3010, + 0x0024, 0x30f0, 0x4024, 0x6c92, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, + 0x003f, 0xffc0, 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3053, + 0x0024, 0x3800, 0x0024, 0x0000, 0x0551, 0xb880, 0x4510, 0x2803, 0xb040, + 0x3083, 0x0024, 0x0000, 0x0455, 0x3483, 0x184c, 0x1fff, 0xfb95, 0xb880, + 0x1046, 0x3481, 0xc024, 0x3e11, 0x930c, 0x3e10, 0x0024, 0x0004, 0x0000, + 0x3e10, 0x0024, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0003, 0x91c8, 0xb182, 0x1b0c, 0x6cf6, 0x0024, + 0x0000, 0x0555, 0x2803, 0xc208, 0x0000, 0x0024, 0x3433, 0x0024, 0xf400, + 0x4511, 0x3110, 0x934c, 0x31f0, 0xd20c, 0x1fff, 0xfad5, 0x6dfe, 0x0024, + 0x3911, 0x8024, 0x39f1, 0xc024, 0x3480, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0455, 0x2803, 0xa115, 0x0000, 0x0024, 0x3483, 0x184c, 0x1fff, 0xfb95, + 0x3410, 0x3804, 0x3480, 0x4024, 0x3473, 0x0024, 0x3443, 0x0024, 0x3410, + 0x8024, 0xfea2, 0x1243, 0x48ba, 0x3803, 0xfe86, 0x92cc, 0x51aa, 0x0024, + 0x44b2, 0x9bc4, 0x6fc6, 0x0024, 0x0000, 0x0595, 0x2803, 0xa118, 0x0000, + 0x0024, 0x3483, 0x0024, 0x1fff, 0xfa95, 0x3480, 0x0024, 0x4080, 0x0024, + 0x0005, 0xffd1, 0x2803, 0xa105, 0x3100, 0x0024, 0x4080, 0x4510, 0x0000, + 0x0595, 0x2803, 0xa115, 0x0000, 0x0024, 0x3613, 0x120c, 0x1fff, 0xfa95, + 0x3009, 0x3811, 0x0000, 0x0591, 0x3083, 0x1bd1, 0x3000, 0x07cc, 0x4090, + 0x0024, 0x3800, 0x0024, 0x3480, 0x0024, 0x4080, 0x4510, 0x3100, 0x0024, + 0x2803, 0xa105, 0x4080, 0x0024, 0x0000, 0x0595, 0x2803, 0x9d05, 0x0000, + 0x0024, 0x0000, 0x0455, 0x0000, 0x0142, 0x0004, 0x0010, 0x3613, 0x120c, + 0x1fff, 0xfb95, 0x3410, 0x3812, 0x0008, 0x0012, 0x3480, 0x4024, 0x0000, + 0x0555, 0xf1c2, 0x120c, 0x1fff, 0xfad5, 0x0006, 0x8081, 0x3480, 0xc024, + 0xff34, 0x0024, 0x48b6, 0x0024, 0x4122, 0x0024, 0x0000, 0x0142, 0x2901, + 0x9fc0, 0xf400, 0x4051, 0x000d, 0x0012, 0x0008, 0x0010, 0x0000, 0x0455, + 0x3483, 0x0024, 0x1fff, 0xfb95, 0x3410, 0x0024, 0x3480, 0x4024, 0x0000, + 0x0555, 0xf1c2, 0x120c, 0x1fff, 0xfad5, 0x0006, 0x8301, 0x3480, 0xc024, + 0xff34, 0x0024, 0x48b6, 0x0024, 0x4122, 0x0024, 0x2901, 0xce80, 0xf400, + 0x4051, 0x000d, 0x0010, 0x0000, 0x0143, 0x0000, 0x0455, 0x3483, 0x0024, + 0x1fff, 0xfb95, 0x3410, 0x0024, 0x3480, 0x4024, 0x0000, 0x0555, 0xf1c2, + 0x120c, 0x1fff, 0xfad5, 0xf1c2, 0x1202, 0x0002, 0x0001, 0x4122, 0x0024, + 0x4122, 0x0024, 0xff26, 0x4052, 0x0006, 0x8581, 0x48b6, 0x0024, 0x4122, + 0x0024, 0x2901, 0xdd00, 0xf400, 0x4051, 0xf400, 0x4510, 0x0000, 0x0551, + 0x3083, 0x1bd2, 0x3000, 0x0024, 0x6090, 0x0024, 0x0000, 0x0555, 0x0000, + 0x0041, 0x3800, 0x120c, 0x1fff, 0xfad5, 0x3480, 0x0024, 0xfe02, 0x11cc, + 0x48b2, 0x110c, 0x3411, 0x8024, 0x3491, 0xc024, 0x6cf6, 0x12cc, 0x0006, + 0x8050, 0x2803, 0x8e08, 0x0000, 0x0024, 0x0000, 0x8001, 0x3000, 0x984c, + 0x6122, 0x930c, 0x6810, 0x0024, 0x3e10, 0x0024, 0x0002, 0x0000, 0x4020, + 0x0024, 0x4020, 0x0024, 0x4020, 0x0024, 0x4020, 0x0024, 0x3e10, 0x0024, + 0x3440, 0x0024, 0xf400, 0x4011, 0x3e00, 0x054c, 0x3102, 0x0024, 0x2000, + 0x0000, 0x0003, 0xb7c8, 0x0000, 0x0455, 0x0000, 0x00c2, 0xb880, 0x920c, + 0x1fff, 0xfb95, 0x3800, 0x1b4c, 0x3410, 0x0024, 0x3480, 0x4024, 0xac22, + 0x4513, 0x3373, 0x0024, 0x3373, 0x0024, 0x3353, 0x0024, 0x3310, 0x8024, + 0x33f0, 0xc024, 0x6dc2, 0x0024, 0x3b10, 0x0024, 0x3bf0, 0x4024, 0x0000, + 0x04d5, 0x3483, 0x0024, 0x1fff, 0xfb15, 0x3410, 0x0024, 0x3480, 0x4024, + 0x4c82, 0x0024, 0x0000, 0x0024, 0x2803, 0xc209, 0x0000, 0x0024, 0x3433, + 0x0024, 0x3410, 0x0024, 0x34c0, 0x4024, 0x4c82, 0x0024, 0x0000, 0x0024, + 0x2803, 0xc209, 0x0000, 0x0024, 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, + 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, 0x0591, + 0x2803, 0x50c5, 0x0000, 0x0455, 0x2803, 0xd9c0, 0xb880, 0x0024, 0x6890, + 0x184c, 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, + 0x3e10, 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0003, 0xc588, 0x36c3, 0x10cc, 0xf400, 0x4511, + 0x3110, 0x934c, 0x31f0, 0xc024, 0x4d96, 0x0024, 0x3910, 0x8024, 0x39f0, + 0xc024, 0x3433, 0x184c, 0x3410, 0x0024, 0x34c0, 0x4024, 0x4c82, 0x0024, + 0x0000, 0x0040, 0x2803, 0xc2d5, 0x0000, 0x0024, 0x0000, 0x0100, 0x3e10, + 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, + 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, + 0x0000, 0x0003, 0xcc08, 0x0000, 0x0101, 0x6012, 0x094c, 0x3200, 0x1b0c, + 0x2803, 0xcdc1, 0x3073, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x0024, 0x4080, + 0x014c, 0x3070, 0x0024, 0x2803, 0xcfd5, 0x0000, 0x0024, 0x4080, 0x01cc, + 0x0000, 0x0024, 0x2803, 0x2885, 0x3053, 0x0024, 0x32b0, 0x024c, 0x3009, + 0x024c, 0x4080, 0x02cc, 0x0000, 0x0024, 0x2803, 0xd605, 0x0000, 0x0024, + 0x34b3, 0x0024, 0x3450, 0x0024, 0x4080, 0x0024, 0x0000, 0x0184, 0x2803, + 0xd605, 0x0006, 0x0ec0, 0x34b3, 0x0024, 0x3454, 0x0024, 0x2803, 0xd600, + 0x3800, 0x0024, 0x6898, 0x12cc, 0x3450, 0x0024, 0x4080, 0x0024, 0x0006, + 0x1440, 0x2803, 0xd605, 0x0000, 0x0024, 0x34b3, 0x0024, 0x3454, 0x0024, + 0x3800, 0x0024, 0x34c3, 0x0024, 0x3404, 0x0024, 0x3073, 0x0024, 0x3063, + 0x0024, 0x3000, 0x0024, 0x4080, 0x1110, 0x0000, 0x0000, 0x2803, 0xd945, + 0x3073, 0x0024, 0x0000, 0x0144, 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, + 0x0024, 0x3063, 0x0024, 0x4480, 0x2000, 0x36f4, 0xc024, 0x36f4, 0x5812, + 0x36f1, 0xd810, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0xb386, 0x40d7, 0x4284, 0x184c, 0x0000, 0x05c0, 0x2803, 0xde15, 0xf5d8, + 0x3804, 0x0000, 0x0984, 0x6400, 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, + 0x0000, 0x800a, 0x0000, 0x00ce, 0x2403, 0xe14e, 0xffa4, 0x0024, 0x48b6, + 0x0024, 0x0000, 0x0024, 0x2803, 0xe144, 0x4000, 0x40c2, 0x4224, 0x0024, + 0x6090, 0x0024, 0xffa4, 0x0024, 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, + 0xd80d, 0x48b6, 0x0024, 0x0fff, 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, + 0x36f1, 0x180a, 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6a00, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1b40, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x144e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x7280, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x0254, /*copy 596*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0164, 0x04b9, 0x09a5, + 0x0d57, 0x045f, 0xe8cd, 0xbc5c, 0x9380, 0xa08d, 0x0c3f, 0x1d7a, 0x43d9, + 0x68b4, 0x7fff, 0x7fff, 0x68b4, 0x43d9, 0x1d7a, 0x0c3f, 0xa08d, 0x9380, + 0xbc5c, 0xe8cd, 0x045f, 0x0d57, 0x09a5, 0x04b9, 0x0164, 0xfd25, 0xfb12, + 0x1042, 0x253f, 0xd5bc, 0xed41, 0x08de, 0x53f7, 0x7fff, 0x53f7, 0x08de, + 0xed41, 0xd5bc, 0x253f, 0x1042, 0xfb12, 0xfd25, 0x0006, 0x0000, 0xfff7, + 0x0000, 0x0012, 0x0000, 0xffe4, 0x0000, 0x002e, 0x0000, 0xffbb, 0x0000, + 0x0067, 0x0000, 0xff6f, 0x0000, 0x00cb, 0x0000, 0xfeed, 0x0000, 0x0170, + 0x0000, 0xfe1d, 0x0000, 0x0274, 0x0000, 0xfcde, 0x0000, 0x03f8, 0x0000, + 0xfb0a, 0x0000, 0x0629, 0x0000, 0xf86c, 0x0000, 0x0943, 0x0000, 0xf4c1, + 0x0000, 0x0d9a, 0x0000, 0xef9e, 0x0000, 0x13b4, 0x0000, 0xe851, 0x0000, + 0x1c8a, 0x0000, 0xdd72, 0x0000, 0x2a3c, 0x0000, 0xcb94, 0x0000, 0x42bd, + 0x0000, 0xa75f, 0x0000, 0x7f22, 0x0000, 0xe516, 0x0000, 0x5168, 0x7fff, + 0x5168, 0x0000, 0xe516, 0x0000, 0x7f22, 0x0000, 0xa75f, 0x0000, 0x42bd, + 0x0000, 0xcb94, 0x0000, 0x2a3c, 0x0000, 0xdd72, 0x0000, 0x1c8a, 0x0000, + 0xe851, 0x0000, 0x13b4, 0x0000, 0xef9e, 0x0000, 0x0d9a, 0x0000, 0xf4c1, + 0x0000, 0x0943, 0x0000, 0xf86c, 0x0000, 0x0629, 0x0000, 0xfb0a, 0x0000, + 0x03f8, 0x0000, 0xfcde, 0x0000, 0x0274, 0x0000, 0xfe1d, 0x0000, 0x0170, + 0x0000, 0xfeed, 0x0000, 0x00cb, 0x0000, 0xff6f, 0x0000, 0x0067, 0x0000, + 0xffbb, 0x0000, 0x002e, 0x0000, 0xffe4, 0x0000, 0x0012, 0x0000, 0xfff7, + 0x0000, 0x0006, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x0064, /*copy 100*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x0046, 0x006f, 0x0072, 0x006d, 0x0061, 0x0074, 0x0020, + 0x004e, 0x006f, 0x0074, 0x0020, 0x0044, 0x0053, 0x0046, 0x002f, 0x0044, + 0x0046, 0x0046, 0x0000, 0x004f, 0x006b, 0x0000, 0x004e, 0x006f, 0x0074, + 0x0020, 0x0032, 0x0020, 0x0063, 0x0068, 0x0061, 0x006e, 0x006e, 0x0065, + 0x006c, 0x0073, 0x0000, 0x0049, 0x006e, 0x0076, 0x0061, 0x006c, 0x0069, + 0x0064, 0x0020, 0x0044, 0x0053, 0x0044, 0x0020, 0x0062, 0x0069, 0x0074, + 0x0073, 0x0074, 0x0072, 0x0065, 0x0061, 0x006d, 0x0000, 0x004e, 0x006f, + 0x0074, 0x0020, 0x0044, 0x0053, 0x0044, 0x0020, 0x0062, 0x0069, 0x0074, + 0x0073, 0x0074, 0x0072, 0x0065, 0x0061, 0x006d, 0x0000, 0xff2f, 0x0295, + 0x0a83, 0x16ef, 0x2912, 0x3215, 0x3215, 0x2912, 0x16ef, 0x0a83, 0x0295, + 0xff2f, 0x0007, 0x0001, /*copy 1*/ + 0x8025, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x5d8e, 0x0007, 0x0001, /*copy 1*/ + 0x1a00, 0x0006, 0x0020, /*copy 32*/ + 0x0046, 0x0046, 0x0055, 0x1a40, 0xfc57, 0x0000, 0x0000, 0x0055, 0x1a60, + 0xfc57, 0x0000, 0x0000, 0x0000, 0x1a80, 0xfc73, 0x0000, 0x0000, 0x0000, + 0x1aa0, 0xfc73, 0x0000, 0x0000, 0x0000, 0x3000, 0xfc84, 0x0000, 0x0000, + 0x0000, 0x3200, 0xfc84, 0x0000, 0x0000, 0x0007, 0x0001, /*copy 1*/ + 0x1a40, 0x0006, 0x8080, 0x0000, /*Rle(128)*/ + 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 8608 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/patches_flac.h b/targets/esp32/components/VS1053/include/patches_flac.h new file mode 100644 index 00000000..c74a87d1 --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_flac.h @@ -0,0 +1,961 @@ +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x001e, /*copy 30*/ + 0x2a00, 0xc000, 0x3e12, 0xb817, 0x3e14, 0xf812, 0x3e01, 0xb811, 0x0007, + 0x9717, 0x0020, 0xffd2, 0x0030, 0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, + 0x3b81, 0x8024, 0x3101, 0x8024, 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, + 0x4800, 0x36f1, 0x9811, 0x0007, 0x0001, /*copy 1*/ + 0x8060, 0x0006, 0x0540, /*copy 1344*/ + 0xf400, 0x4095, 0x0000, 0x02c2, 0x6124, 0x0024, 0x0000, 0x0024, 0x2800, + 0x1ac5, 0x4192, 0x4542, 0x0000, 0x0041, 0x2000, 0x0015, 0x0030, 0x0317, + 0x2000, 0x0000, 0x3f00, 0x4024, 0x2000, 0x0000, 0x0000, 0x0000, 0x3e12, + 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, 0x8257, 0x3700, 0x984c, + 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, 0x2910, 0x0181, 0x0000, + 0x1bc8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, 0x0195, 0x0000, 0x1bc8, + 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2945, 0x3e13, 0x780e, 0x3e11, + 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, 0xb808, 0x003f, 0xe004, + 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, 0x48be, 0x4497, 0x4090, + 0x1c46, 0xf06c, 0x0024, 0x2400, 0x2580, 0x6090, 0x41c3, 0x6628, 0x1c47, + 0x0000, 0x0024, 0x2800, 0x2449, 0xf07e, 0x0024, 0xf400, 0x4182, 0x673a, + 0x1c46, 0x0000, 0x0024, 0x2800, 0x2589, 0xf06c, 0x0024, 0xf400, 0x41c3, + 0x0000, 0x0024, 0x4224, 0x3442, 0x2903, 0xd9c0, 0x4336, 0x37c3, 0x0000, + 0x1805, 0x2903, 0xd9c0, 0x4508, 0x40c2, 0x450a, 0x9808, 0x0000, 0x0207, + 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, 0x3d01, 0x5bc1, 0x36f3, + 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, 0x580e, 0x0007, 0x8257, + 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, 0xd428, 0x3c02, 0x0006, + 0xc717, 0x2800, 0x2d05, 0x4284, 0x0024, 0x3613, 0x3c02, 0x0006, 0xc357, + 0x2901, 0x6ac0, 0x3e11, 0x5c05, 0x4284, 0x1bc5, 0x0007, 0x8257, 0x2800, + 0x3285, 0x0002, 0x0001, 0x3701, 0x0024, 0x0006, 0xc357, 0xb412, 0x9c02, + 0x002e, 0xe001, 0x2800, 0x3005, 0x6212, 0x0024, 0x0000, 0x0024, 0x2800, + 0x3295, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, 0x0024, 0x3613, 0x0024, + 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, 0x2900, 0x4b40, 0x0006, + 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, 0x8257, 0x3700, 0x8024, + 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x3491, 0x3600, 0x9844, 0x2900, + 0x3a40, 0x0000, 0x3508, 0x2911, 0xf140, 0x0000, 0x0024, 0x0030, 0x0057, + 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, 0xa024, 0x164c, 0x8000, + 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, 0x6d82, 0xd024, 0x44c0, + 0x0006, 0xa402, 0x2800, 0x3955, 0xd024, 0x0024, 0x0000, 0x0000, 0x2800, + 0x3955, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, 0x8024, 0x36f2, 0x1800, + 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, 0x3e13, 0xb80d, 0x3e13, + 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0xf801, + 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, 0xbf8e, 0x9c42, 0x3e01, + 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, 0x8250, 0x0fff, 0xfd85, + 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, 0x2800, 0x4091, 0xf25a, + 0x104c, 0x34f3, 0x0024, 0x2800, 0x4091, 0x0000, 0x0024, 0x3413, 0x084c, + 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, 0x2400, 0x42c0, 0x4efa, + 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, 0x4d64, 0x48b2, 0xa201, + 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, 0x36f4, 0xd801, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0xd80a, 0x36f3, 0x980d, + 0x2000, 0x0000, 0x36f4, 0x5810, 0x36f3, 0x0024, 0x3009, 0x3848, 0x3e14, + 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, + 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, 0x9e40, 0x3604, 0x1811, 0x3613, + 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, + 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x36f4, 0x1811, 0x3009, + 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e13, 0x7801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, + 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, 0x34e5, 0xc024, 0x3524, + 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, 0x4a0c, 0x3d44, 0x8024, + 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, 0x6010, 0x3400, 0x3710, + 0x8024, 0x2800, 0x5704, 0x3af0, 0x8024, 0x3df0, 0x0024, 0x3591, 0x4024, + 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, 0x4020, 0x1753, 0xbf8e, + 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, 0x550e, 0xfe6d, 0x2819, + 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, 0xad56, 0x904c, 0xaf5e, + 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, 0x2046, 0x3cf4, 0x0024, + 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, 0x2800, 0x4f95, 0x3c00, + 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0x5801, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x2814, 0x9c91, + 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, 0x3e12, 0xb817, 0x3e12, + 0x7808, 0x3e11, 0xb811, 0x3e15, 0x7810, 0x3e18, 0xb823, 0x3e18, 0x3821, + 0x3e10, 0x3801, 0x48b2, 0x0024, 0x3e10, 0x3801, 0x3e11, 0x3802, 0x3009, + 0x3814, 0x0030, 0x0717, 0x3f05, 0xc024, 0x0030, 0x0351, 0x3100, 0x0024, + 0x4080, 0x0024, 0x0030, 0x10d1, 0x2800, 0x6745, 0x0001, 0x800a, 0x0006, + 0x6514, 0x3111, 0x8024, 0x6894, 0x13c1, 0x6618, 0x0024, 0xfe44, 0x1000, + 0x4cb2, 0x0406, 0x3c10, 0x0024, 0x3c50, 0x4024, 0x34f0, 0x4024, 0x661c, + 0x1040, 0xfe64, 0x0024, 0x4cb2, 0x0024, 0x3cf0, 0x4024, 0xbc82, 0x3080, + 0x0030, 0x0351, 0x3100, 0x8024, 0xfea8, 0x0024, 0x5ca2, 0x0024, 0x0000, + 0x0182, 0xac22, 0x0024, 0xf7c8, 0x0024, 0x48b2, 0x0024, 0xac22, 0x0024, + 0x2800, 0x6ac0, 0xf7cc, 0x1002, 0x0030, 0x0394, 0x3400, 0x4024, 0x3100, + 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, 0x6410, 0x4088, 0x1001, + 0x0030, 0x1111, 0x3100, 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, + 0x6550, 0x0006, 0x6694, 0x408c, 0x1002, 0xf224, 0x0024, 0x0006, 0xa017, + 0x2800, 0x6ed5, 0x0000, 0x0024, 0x2808, 0x3f41, 0x0006, 0x6410, 0x3050, + 0x0024, 0x3000, 0x4024, 0x6014, 0x0024, 0x0000, 0x0024, 0x2800, 0x6e19, + 0x0000, 0x0024, 0xf400, 0x4040, 0x38b0, 0x0024, 0x2808, 0x3f40, 0x3800, + 0x0024, 0x2800, 0x70c1, 0xf224, 0x0024, 0x0000, 0x0024, 0x2808, 0x3f45, + 0x4684, 0x4106, 0xf12c, 0x0024, 0xf148, 0x0024, 0x846c, 0x0024, 0x2808, + 0x3f40, 0xf400, 0x4184, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0xa090, 0x2912, 0x0d00, + 0x3e14, 0xc024, 0x4088, 0x8000, 0x4080, 0x0024, 0x0007, 0x90d1, 0x2800, + 0x7705, 0x0000, 0x0024, 0x0007, 0x9051, 0x3100, 0x4024, 0x4100, 0x0024, + 0x3900, 0x0024, 0x0007, 0x90d1, 0x0004, 0x0000, 0x31f0, 0x4024, 0x6014, + 0x0400, 0x0000, 0x0024, 0x2800, 0x7b51, 0x4080, 0x0024, 0x0000, 0x0000, + 0x2800, 0x7ac5, 0x0000, 0x0024, 0x0007, 0x9053, 0x3300, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0000, 0x2800, 0x7b58, 0x0000, 0x0024, 0x0007, 0x9051, + 0x3900, 0x0024, 0x3200, 0x504c, 0x6410, 0x0024, 0x3cf0, 0x0000, 0x4080, + 0x0024, 0x0006, 0xc691, 0x2800, 0x9405, 0x3009, 0x0400, 0x0007, 0x9051, + 0x0000, 0x1001, 0x3100, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2800, + 0x8849, 0x003f, 0xe000, 0x0006, 0xc693, 0x3900, 0x0c00, 0x3009, 0x0001, + 0x6014, 0x0024, 0x0007, 0x1ad0, 0x2800, 0x8855, 0x3009, 0x0000, 0x4080, + 0x0024, 0x0000, 0x0301, 0x2800, 0x8245, 0x4090, 0x0024, 0x0000, 0x0024, + 0x2800, 0x8355, 0x0000, 0x0024, 0x3009, 0x0000, 0xc012, 0x0024, 0x2800, + 0x8840, 0x3009, 0x2001, 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, 0x0341, + 0x2800, 0x8555, 0x0000, 0x0024, 0x6190, 0x0024, 0x2800, 0x8840, 0x3009, + 0x2000, 0x6012, 0x0024, 0x0000, 0x0381, 0x2800, 0x8715, 0x0000, 0x0024, + 0x6190, 0x0024, 0x2800, 0x8840, 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, + 0x00c0, 0x2800, 0x8855, 0x0000, 0x0024, 0x3009, 0x2000, 0x0006, 0xa090, + 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0081, 0x2800, 0x8d15, 0x0007, + 0x8c13, 0x3300, 0x104c, 0xb010, 0x0024, 0x0002, 0x8001, 0x2800, 0x8f85, + 0x34f0, 0x0024, 0x2800, 0x8d00, 0x0000, 0x0024, 0x0006, 0xc351, 0x3009, + 0x0000, 0x6090, 0x0024, 0x3009, 0x2000, 0x2900, 0x0b80, 0x3009, 0x0405, + 0x0006, 0xc690, 0x0006, 0xc6d1, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, + 0x0024, 0x0006, 0xa093, 0x2800, 0x8b91, 0xb880, 0x0024, 0x2800, 0x9cc0, + 0x3009, 0x2c00, 0x4040, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2800, + 0x9cd8, 0x0000, 0x0024, 0x0006, 0xc693, 0x3009, 0x0c00, 0x3009, 0x0001, + 0x6014, 0x0024, 0x0006, 0xc350, 0x2800, 0x9cc1, 0x0000, 0x0024, 0x6090, + 0x0024, 0x3009, 0x2c00, 0x3009, 0x0005, 0x2900, 0x0b80, 0x0000, 0x9cc8, + 0x3009, 0x0400, 0x4080, 0x0024, 0x0003, 0x8000, 0x2800, 0x9cc5, 0x0000, + 0x0024, 0x6400, 0x0024, 0x0000, 0x0081, 0x2800, 0x9cc9, 0x0000, 0x0024, + 0x0007, 0x8c13, 0x3300, 0x0024, 0xb010, 0x0024, 0x0006, 0xc650, 0x2800, + 0x9cd5, 0x0000, 0x0024, 0x0001, 0x0002, 0x3413, 0x0000, 0x3009, 0x0401, + 0x4010, 0x8406, 0x0000, 0x0281, 0xa010, 0x13c1, 0x4122, 0x0024, 0x0000, + 0x03c2, 0x6122, 0x8002, 0x462c, 0x0024, 0x469c, 0x0024, 0xfee2, 0x0024, + 0x48be, 0x0024, 0x6066, 0x8400, 0x0006, 0xc350, 0x2800, 0x9cc1, 0x0000, + 0x0024, 0x4090, 0x0024, 0x3009, 0x2400, 0x2900, 0x0b80, 0x3009, 0x0005, + 0x0007, 0x1b50, 0x2912, 0x0d00, 0x3613, 0x0024, 0x3a00, 0x0380, 0x4080, + 0x0024, 0x0000, 0x00c1, 0x2800, 0xa585, 0x3009, 0x0000, 0xb010, 0x008c, + 0x4192, 0x0024, 0x6012, 0x0024, 0x0006, 0xf051, 0x2800, 0xa398, 0x3009, + 0x0400, 0x0007, 0x1fd1, 0x30e3, 0x0400, 0x4080, 0x0024, 0x0000, 0x0301, + 0x2800, 0xa585, 0x3009, 0x0000, 0xb010, 0x0024, 0x0000, 0x0101, 0x6012, + 0x0024, 0x0006, 0xf051, 0x2800, 0xa595, 0x0000, 0x0024, 0x3023, 0x0400, + 0xf200, 0x184c, 0xb880, 0xa400, 0x3009, 0x2000, 0x3009, 0x0441, 0x3e10, + 0x4402, 0x2909, 0xa9c0, 0x3e10, 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, + 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, + 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0012, 0x5103, + 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x380d, 0x0030, 0x0250, 0x3e13, + 0xf80e, 0xbe8b, 0x83e0, 0x290c, 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, + 0x4086, 0x984c, 0x0000, 0x00ce, 0x2400, 0xaf8e, 0x3009, 0x1bc0, 0x0000, + 0x01c3, 0xae3a, 0x184c, 0x0000, 0x0043, 0x3009, 0x3842, 0x290c, 0x4840, + 0x3009, 0x3840, 0x4084, 0x9bc0, 0xfe26, 0x9bc2, 0xceba, 0x0024, 0x4e8e, + 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0000, 0x0102, 0x2800, 0xb4c5, + 0x0030, 0x0010, 0x0000, 0x0206, 0x3613, 0x0024, 0x290c, 0x4840, 0x3009, + 0x3840, 0x3000, 0xdbc0, 0xb366, 0x0024, 0x0000, 0x0024, 0x2800, 0xb4d5, + 0x4e8e, 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0030, 0x0010, 0x2800, + 0xb195, 0x0000, 0x0206, 0x36f3, 0xd80e, 0x36f4, 0x180d, 0x36f1, 0x9807, + 0x36f1, 0x1805, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3e10, 0xb812, 0x3e11, 0xb810, + 0x3e12, 0x0024, 0x0006, 0x9f92, 0x0025, 0xffd0, 0x3e04, 0x4bd1, 0x3181, + 0xf847, 0xb68c, 0x4440, 0x3009, 0x0802, 0x6024, 0x3806, 0x0006, 0x8a10, + 0x2903, 0xa905, 0x0000, 0xb948, 0x0000, 0x0800, 0x6101, 0x1602, 0xaf2e, + 0x0024, 0x4214, 0x1be3, 0xaf0e, 0x1811, 0x0fff, 0xfc00, 0xb200, 0x9bc7, + 0x0000, 0x03c0, 0x2800, 0xbd85, 0xb204, 0xa002, 0x2903, 0x6b00, 0x3613, + 0x2002, 0x4680, 0x1bc8, 0x36f1, 0x9810, 0x2000, 0x0000, 0x36f0, 0x9812, + 0x2a08, 0x1b8e, 0x2803, 0x8c80, 0x0000, 0xbe97, 0x0006, 0xd397, 0x2000, + 0x0000, 0x3f00, 0x0024, 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x191e, /*copy 6430*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x6a97, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x5b4e, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x003f, + 0xc000, 0xb600, 0x41c1, 0x0012, 0x5103, 0x000c, 0xc002, 0xdcd6, 0x0024, + 0x0019, 0xd4c2, 0x2800, 0xa845, 0x0001, 0x1188, 0x0013, 0xd9c3, 0x6fd6, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdf95, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xde4e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x1188, 0x0039, + 0x324f, 0x0001, 0x3e8e, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x0014, 0x1b01, 0x0015, 0x59c0, + 0x6fc2, 0x0024, 0x0019, 0x9301, 0x2800, 0xe9d5, 0x0018, 0x50c0, 0x290c, + 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, 0x4086, 0x184c, 0x0000, 0x18c2, + 0x6234, 0x0024, 0x0000, 0x1d02, 0x2800, 0xe5d5, 0x6234, 0x0024, 0x0030, + 0x0317, 0x2800, 0xeb40, 0x3f00, 0x0024, 0x0000, 0x1d82, 0x2800, 0xe855, + 0x6234, 0x0024, 0x2912, 0x0d00, 0x4084, 0x184c, 0xf200, 0x0024, 0x6200, + 0x0024, 0x0006, 0x0017, 0x2800, 0xe540, 0xb080, 0x3c40, 0x0000, 0x0202, + 0x2800, 0xeb55, 0xa024, 0x0024, 0xc020, 0x0024, 0x2800, 0xe540, 0x0030, + 0x02d7, 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, 0xeb55, 0x0000, 0x0024, + 0x2803, 0x2240, 0x000a, 0xcac8, 0x000a, 0x8c8f, 0x0000, 0xec8e, 0x000c, + 0x0981, 0x280a, 0x71c0, 0x002c, 0x9d40, 0x000a, 0x708f, 0x0000, 0xd7ce, + 0x280a, 0xc0d5, 0x0012, 0x5182, 0x6fd6, 0x0024, 0x003f, 0xfd81, 0x280a, + 0x8e45, 0xb710, 0x0024, 0xb710, 0x0024, 0x003f, 0xfc01, 0x6012, 0x0024, + 0x0000, 0x0101, 0x2801, 0x0855, 0xffd2, 0x0024, 0x48b2, 0x0024, 0x4190, + 0x0024, 0x0000, 0x190d, 0x2801, 0x0855, 0x0030, 0x0250, 0xb880, 0x104c, + 0x3cf0, 0x0024, 0x0010, 0x5500, 0xb880, 0x23c0, 0xb882, 0x2000, 0x0007, + 0x8590, 0x2914, 0xbec0, 0x0000, 0x0440, 0x0007, 0x8b50, 0xb880, 0x0024, + 0x2920, 0x0100, 0x3800, 0x0024, 0x2920, 0x0000, 0x0006, 0x8a91, 0x0000, + 0x0800, 0xb880, 0xa440, 0x003f, 0xfd81, 0xb710, 0xa7c0, 0x003f, 0xfc01, + 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x1195, 0x0000, 0x0024, 0xffe2, + 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x1195, + 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0006, + 0x8a90, 0x2801, 0x1195, 0x0000, 0x01c2, 0xb886, 0x8040, 0x3613, 0x03c1, + 0xbcd2, 0x0024, 0x0030, 0x0011, 0x2800, 0xfe15, 0x003f, 0xff42, 0xb886, + 0x8040, 0x3009, 0x03c1, 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0102, + 0x6cd2, 0x0024, 0x3e10, 0x0024, 0x2909, 0x8c80, 0x3e00, 0x4024, 0x36f3, + 0x0024, 0x3e11, 0x8024, 0x3e01, 0xc024, 0x2901, 0x3540, 0x0000, 0x0201, + 0xf400, 0x4512, 0x2900, 0x0c80, 0x3213, 0x1b8c, 0x3100, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2801, 0x1195, 0x0000, 0x0024, 0x291a, 0x8a40, + 0x0000, 0x0100, 0x2920, 0x0200, 0x3633, 0x0024, 0x2920, 0x0280, 0x0000, + 0x0401, 0x408e, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, 0x003f, 0xfd81, + 0xb710, 0x4006, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, + 0x1195, 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, + 0x0000, 0x0024, 0x2801, 0x1195, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, + 0x0780, 0x4080, 0x0024, 0x0000, 0x01c2, 0x2800, 0xfa05, 0x0006, 0x8a90, + 0x2a01, 0x1180, 0x2920, 0x0100, 0x0000, 0x0401, 0x0000, 0x0180, 0x2920, + 0x0200, 0x3613, 0x0024, 0x2920, 0x0280, 0x3613, 0x0024, 0x0000, 0x0401, + 0x2920, 0x0280, 0x4084, 0x984c, 0x0019, 0x9d01, 0x6212, 0x0024, 0x001e, + 0x5c01, 0x2801, 0x0cd5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x0ec5, + 0x0000, 0x0024, 0x001b, 0x5bc1, 0x6212, 0x0024, 0x001b, 0xdd81, 0x2801, + 0x1295, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x1295, 0x0000, 0x0024, + 0x0000, 0x004d, 0x000a, 0xbf4f, 0x280a, 0xb880, 0x0001, 0x0fce, 0x0020, + 0xfb4f, 0x0000, 0x190d, 0x0001, 0x16ce, 0x2920, 0xf440, 0x3009, 0x2bc1, + 0x291a, 0x8a40, 0x36e3, 0x0024, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, + 0xcac0, 0x0000, 0xd7ce, 0x0030, 0x0017, 0x3700, 0x4024, 0x0000, 0x0200, + 0xb102, 0x0024, 0x0000, 0x00c0, 0x2801, 0x15c5, 0x0005, 0x4f92, 0x2909, + 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, 0xa115, 0xb080, 0x0024, + 0x3f00, 0x3400, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xc0c0, 0x0000, + 0xd7ce, 0x0000, 0x004d, 0x0020, 0xfe0f, 0x2820, 0xfb40, 0x0001, 0x17ce, + 0x2801, 0x1995, 0x3009, 0x1000, 0x6012, 0x93cc, 0x0000, 0x0024, 0x2801, + 0x3445, 0x0000, 0x0024, 0x3413, 0x0024, 0x34b0, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0200, 0x2801, 0x1c95, 0xb882, 0x0024, 0x3453, 0x0024, 0x3009, + 0x13c0, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, 0x3445, 0x0000, 0x0024, + 0xb882, 0x130c, 0x0000, 0x004d, 0x0021, 0x058f, 0x2821, 0x0340, 0x0001, + 0x1d8e, 0x2801, 0x2dd5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x2dd5, + 0x0000, 0x0024, 0x34c3, 0x184c, 0x3e13, 0xb80f, 0xf400, 0x4500, 0x0026, + 0x9dcf, 0x0001, 0x218e, 0x0000, 0xfa0d, 0x2926, 0x8e80, 0x3e10, 0x110c, + 0x36f3, 0x0024, 0x2801, 0x2dc0, 0x36f3, 0x980f, 0x001c, 0xdd00, 0x001c, + 0xd901, 0x6ec2, 0x0024, 0x001c, 0xdd00, 0x2801, 0x2495, 0x0018, 0xdbc1, + 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0xc640, 0x3e00, 0x13cc, 0x2801, + 0x2b80, 0x36f3, 0x0024, 0x6ec2, 0x0024, 0x003f, 0xc000, 0x2801, 0x2715, + 0x002a, 0x4001, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0xafc0, 0x3e00, + 0x13cc, 0x2801, 0x2b80, 0x36f3, 0x0024, 0xb400, 0x0024, 0xd100, 0x0024, + 0x0000, 0x0024, 0x2801, 0x2b85, 0x0000, 0x0024, 0x3613, 0x0024, 0x3e11, + 0x4024, 0x2926, 0x8540, 0x3e01, 0x0024, 0x4080, 0x1b8c, 0x0000, 0x0024, + 0x2801, 0x2b85, 0x0000, 0x0024, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, + 0x8e80, 0x3e10, 0x13cc, 0x36f3, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, + 0x0000, 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x3110, 0x8024, 0x2826, + 0xa8c4, 0x31f0, 0xc024, 0x2a26, 0xad00, 0x34c3, 0x184c, 0x3410, 0x8024, + 0x3430, 0xc024, 0x0000, 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x0000, + 0x0024, 0x2801, 0x3454, 0x4d06, 0x0024, 0x0000, 0x0200, 0x2922, 0x1885, + 0x0001, 0x32c8, 0x0000, 0x0200, 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, + 0xc024, 0x291a, 0x8a40, 0x0000, 0x0024, 0x2922, 0x1880, 0x36f3, 0x0024, + 0x0000, 0x004d, 0x0021, 0x0ecf, 0x2821, 0x0bc0, 0x0001, 0x33ce, 0x2801, + 0x16c0, 0x3c30, 0x4024, 0x0000, 0x190d, 0x0000, 0x458e, 0x2821, 0x0f80, + 0x0027, 0x9e0f, 0x0020, 0xcd4f, 0x2820, 0xc780, 0x0001, 0x360e, 0x0006, + 0xf017, 0x0000, 0x0015, 0xb070, 0xbc15, 0x0000, 0x458e, 0x0027, 0x9e0f, + 0x2820, 0xcd80, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e10, 0xb803, 0x3e14, + 0x3811, 0x3e11, 0x3805, 0x3e00, 0x3801, 0x0007, 0xc390, 0x0006, 0xa011, + 0x3010, 0x0444, 0x3050, 0x4405, 0x6458, 0x0302, 0xff94, 0x4081, 0x0003, + 0xffc5, 0x48b6, 0x0024, 0xff82, 0x0024, 0x42b2, 0x0042, 0xb458, 0x0003, + 0x4cd6, 0x9801, 0xf248, 0x1bc0, 0xb58a, 0x0024, 0x6de6, 0x1804, 0x0006, + 0x0010, 0x3810, 0x9bc5, 0x3800, 0xc024, 0x36f4, 0x1811, 0x36f0, 0x9803, + 0x283e, 0x2d80, 0x0fff, 0xffc3, 0x2801, 0x4c40, 0x0000, 0x0024, 0x3413, + 0x0024, 0x2801, 0x4045, 0xf400, 0x4517, 0x2801, 0x4440, 0x6894, 0x13cc, + 0x37b0, 0x184c, 0x6090, 0x1d51, 0x0000, 0x0910, 0x3f00, 0x060c, 0x3100, + 0x4024, 0x6016, 0xb812, 0x000c, 0x8012, 0x2801, 0x42d1, 0xb884, 0x0024, + 0x6894, 0x3002, 0x0000, 0x028d, 0x003a, 0x5e0f, 0x0001, 0x544e, 0x2939, + 0xb0c0, 0x3e10, 0x93cc, 0x4084, 0x9bd2, 0x4282, 0x0024, 0x0000, 0x0040, + 0x2801, 0x4645, 0x4292, 0x130c, 0x3443, 0x0024, 0x2801, 0x4785, 0x000c, + 0x8390, 0x2a01, 0x4b00, 0x3444, 0x0024, 0x3073, 0x0024, 0xc090, 0x014c, + 0x2801, 0x4b00, 0x3800, 0x0024, 0x000c, 0x4113, 0xb880, 0x2380, 0x3304, + 0x4024, 0x3800, 0x05cc, 0xcc92, 0x05cc, 0x3910, 0x0024, 0x3910, 0x4024, + 0x000c, 0x8110, 0x3910, 0x0024, 0x39f0, 0x4024, 0x3810, 0x0024, 0x38d0, + 0x4024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x34c3, 0x0024, 0x3444, 0x0024, + 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x3613, 0x0024, 0x2801, 0x4e45, + 0x6898, 0xb804, 0x0000, 0x0084, 0x293b, 0x1cc0, 0x3613, 0x0024, 0x000c, + 0x8117, 0x3711, 0x0024, 0x37d1, 0x4024, 0x4e8a, 0x0024, 0x0000, 0x0015, + 0x2801, 0x5105, 0xce9a, 0x0024, 0x3f11, 0x0024, 0x3f01, 0x4024, 0x000c, + 0x8197, 0x408a, 0x9bc4, 0x3f15, 0x4024, 0x2801, 0x5345, 0x4284, 0x3c15, + 0x6590, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x0000, + 0x0024, 0x2801, 0x3f18, 0x458a, 0x0024, 0x2a39, 0x53c0, 0x003e, 0x2d4f, + 0x283a, 0x5ed5, 0x0001, 0x37ce, 0x000c, 0x4653, 0x0000, 0x0246, 0xffac, + 0x0c01, 0x48be, 0x0024, 0x4162, 0x4546, 0x6642, 0x4055, 0x3501, 0x8024, + 0x0000, 0x0087, 0x667c, 0x4057, 0x000c, 0x41d5, 0x283a, 0x62d5, 0x3501, + 0x8024, 0x667c, 0x1c47, 0x3701, 0x8024, 0x283a, 0x62d5, 0xc67c, 0x0024, + 0x0000, 0x0024, 0x283a, 0x62c5, 0x0000, 0x0024, 0x2a3a, 0x5ec0, 0x3009, + 0x3851, 0x3e14, 0xf812, 0x3e12, 0xb817, 0x3e11, 0x8024, 0x0006, 0x0293, + 0x3301, 0x8024, 0x468c, 0x3804, 0x0006, 0xa057, 0x2801, 0x6044, 0x0006, + 0x0011, 0x469c, 0x0024, 0x3be1, 0x8024, 0x2801, 0x6055, 0x0006, 0xc392, + 0x3311, 0x0024, 0x33f1, 0x2844, 0x3009, 0x2bc4, 0x0030, 0x04d2, 0x3311, + 0x0024, 0x3a11, 0x0024, 0x3201, 0x8024, 0x003f, 0xfc04, 0xb64c, 0x0fc4, + 0xc648, 0x0024, 0x3a01, 0x0024, 0x3111, 0x1fd3, 0x6498, 0x07c6, 0x868c, + 0x2444, 0x0023, 0xffd2, 0x3901, 0x8e06, 0x0030, 0x0551, 0x3911, 0x8e06, + 0x3961, 0x9c44, 0xf400, 0x44c6, 0xd46c, 0x1bc4, 0x36f1, 0xbc13, 0x2801, + 0x69d5, 0x36f2, 0x9817, 0x002b, 0xffd2, 0x3383, 0x188c, 0x3e01, 0x8c06, + 0x0006, 0xa097, 0x3009, 0x1c12, 0x3213, 0x0024, 0x468c, 0xbc12, 0x002b, + 0xffd2, 0xf400, 0x4197, 0x2801, 0x66c4, 0x3713, 0x0024, 0x2801, 0x6705, + 0x37e3, 0x0024, 0x3009, 0x2c17, 0x3383, 0x0024, 0x3009, 0x0c06, 0x468c, + 0x4197, 0x0006, 0xa052, 0x2801, 0x6904, 0x3713, 0x2813, 0x2801, 0x6945, + 0x37e3, 0x0024, 0x3009, 0x2c17, 0x36f1, 0x8024, 0x36f2, 0x9817, 0x36f4, + 0xd812, 0x2100, 0x0000, 0x3904, 0x5bd1, 0x2a01, 0x5a0e, 0x3e11, 0x7804, + 0x0030, 0x0257, 0x3701, 0x0024, 0x0013, 0x4d05, 0xd45b, 0xe0e1, 0x0007, + 0xc795, 0x2801, 0x7155, 0x0fff, 0xff45, 0x3511, 0x184c, 0x4488, 0xb808, + 0x0006, 0x8a97, 0x2801, 0x7105, 0x3009, 0x1c40, 0x3511, 0x1fc1, 0x0000, + 0x0020, 0xac52, 0x1405, 0x6ce2, 0x0024, 0x0000, 0x0024, 0x2801, 0x7101, + 0x68c2, 0x0024, 0x291a, 0x8a40, 0x3e10, 0x0024, 0x2921, 0xca80, 0x3e00, + 0x4024, 0x36f3, 0x0024, 0x3009, 0x1bc8, 0x36f0, 0x1801, 0x3601, 0x5804, + 0x3e13, 0x780f, 0x3e13, 0xb808, 0x0008, 0x9b0f, 0x0001, 0x740e, 0x2908, + 0x9300, 0x0000, 0x004d, 0x36f3, 0x9808, 0x2000, 0x0000, 0x36f3, 0x580f, + 0x0007, 0x81d7, 0x3711, 0x8024, 0x3711, 0xc024, 0x3700, 0x0024, 0x0000, + 0x2001, 0xb012, 0x0024, 0x0034, 0x0000, 0x2801, 0x7985, 0x0000, 0x01c1, + 0x3700, 0x0024, 0x0002, 0x0001, 0xb012, 0x0024, 0x002e, 0xe001, 0x2801, + 0x7885, 0x6512, 0x0024, 0x0034, 0x0000, 0x2801, 0x7995, 0x0000, 0x01c1, + 0x0030, 0x0117, 0x3f00, 0x0024, 0x0014, 0xc000, 0x0000, 0x01c1, 0x4fce, + 0x0024, 0xffea, 0x0024, 0x48b6, 0x0024, 0x4384, 0x4097, 0xb886, 0x45c6, + 0xfede, 0x0024, 0x4db6, 0x0024, 0x466c, 0x0024, 0x0006, 0xc610, 0x8dd6, + 0x8007, 0x0000, 0x00c6, 0xff6e, 0x0024, 0x48b2, 0x0024, 0x0034, 0x2406, + 0xffee, 0x0024, 0x2914, 0xaa80, 0x40b2, 0x0024, 0xf1c6, 0x0024, 0xf1d6, + 0x0024, 0x0000, 0x0201, 0x8d86, 0x0024, 0x61de, 0x0024, 0x0006, 0xc612, + 0x2801, 0x8001, 0x0006, 0xc713, 0x4c86, 0x0024, 0x2912, 0x1180, 0x0006, + 0xc351, 0x0006, 0x0210, 0x2912, 0x0d00, 0x3810, 0x984c, 0xf200, 0x2043, + 0x2808, 0xa000, 0x3800, 0x0024, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, + 0x3e14, 0x0024, 0x2900, 0xb740, 0x0000, 0x0201, 0x0000, 0x0601, 0x3413, + 0x184c, 0x2903, 0x7680, 0x3cf0, 0x0024, 0x3413, 0x184c, 0x3400, 0x3040, + 0x3009, 0x33c1, 0x0000, 0x1fc1, 0xb010, 0x0024, 0x6014, 0x9040, 0x0006, + 0x8010, 0x2801, 0x88d5, 0x0000, 0x0024, 0x34e3, 0x1bcc, 0x6890, 0x0024, + 0x2801, 0x8a80, 0xb880, 0x2000, 0x3e10, 0x1381, 0x2903, 0xb8c0, 0x3e00, + 0x4024, 0x003f, 0xfe41, 0x36e3, 0x104c, 0x34f0, 0x0024, 0xa010, 0x0024, + 0x36f4, 0x0024, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, + 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, + 0xb804, 0x3e01, 0x534c, 0xbe8a, 0x10c0, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2801, 0x93c5, 0x0000, 0x0024, 0x2903, 0x7680, 0x4082, 0x184c, 0x4c8a, + 0x134c, 0x0000, 0x0001, 0x6890, 0x10c2, 0x4294, 0x0024, 0xac22, 0x0024, + 0xbec2, 0x0024, 0x0000, 0x0024, 0x2801, 0x93c5, 0x0000, 0x0024, 0x6890, + 0x134c, 0xb882, 0x10c2, 0xac22, 0x0024, 0x4c92, 0x0024, 0xdc92, 0x0024, + 0xceca, 0x0024, 0x4e82, 0x1bc5, 0x36f0, 0x9804, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3645, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, + 0x3e14, 0x104c, 0x2900, 0xb740, 0x0000, 0x0081, 0x4080, 0x3040, 0x0000, + 0x0101, 0x2801, 0x9ac5, 0x0000, 0x0024, 0x4090, 0x0024, 0x0006, 0x8050, + 0x2801, 0xaed5, 0x0000, 0x0024, 0x2900, 0xb740, 0x3613, 0x0024, 0xb880, + 0x3000, 0x2801, 0xac80, 0x3009, 0x3380, 0x2900, 0xb740, 0x4122, 0x10cc, + 0x3cf0, 0x0024, 0x3001, 0x0024, 0x3400, 0x0024, 0x6800, 0x0024, 0xa408, + 0x9040, 0x4080, 0x0024, 0x0000, 0x07c1, 0x2801, 0xa055, 0x6894, 0x1380, + 0x6894, 0x130c, 0x3460, 0x0024, 0x6408, 0x4481, 0x4102, 0x1380, 0xf400, + 0x4052, 0x0000, 0x07c1, 0x34f0, 0xc024, 0x6234, 0x0024, 0x6824, 0x0024, + 0xa122, 0x0024, 0x6014, 0x0024, 0x0000, 0x0141, 0x2801, 0xa755, 0x0000, + 0x0024, 0x2900, 0xb740, 0x3613, 0x0024, 0x2801, 0xa5c0, 0xb88a, 0x4002, + 0x2901, 0x8c40, 0x3e00, 0x8024, 0x4c8e, 0xa801, 0x0000, 0x0201, 0x3a10, + 0x1bcc, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, 0xab55, + 0x659a, 0x0024, 0x6540, 0x184c, 0x0030, 0x0010, 0x2801, 0xa348, 0x0000, + 0x0024, 0x2801, 0xab40, 0x36f3, 0x0024, 0x2801, 0xaa00, 0xb88a, 0x0024, + 0x2903, 0x3ec0, 0x34d0, 0x4024, 0x4c8f, 0xa0a1, 0x0000, 0x0201, 0x3000, + 0x084c, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, 0xab55, 0x659a, 0x0024, + 0x6540, 0x10cc, 0x0030, 0x0010, 0x2801, 0xa7c8, 0x0000, 0x0024, 0x34d3, + 0x0024, 0x3423, 0x0024, 0xf400, 0x4510, 0x3009, 0x1380, 0x6090, 0x0024, + 0x3009, 0x2000, 0x6892, 0x108c, 0x34f0, 0x9000, 0xa122, 0x984c, 0x6016, + 0x13c1, 0x0000, 0x0102, 0x2801, 0x9c08, 0x0006, 0x8150, 0x2801, 0xaf40, + 0x3009, 0x1bcc, 0x6890, 0x938c, 0x3800, 0x0024, 0x36f4, 0x0024, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb804, 0x3e11, 0xb807, 0x3e14, + 0x3811, 0x3e04, 0x934c, 0x3430, 0x0024, 0x4080, 0x0024, 0x0000, 0x0206, + 0x2801, 0xb845, 0x0006, 0x8151, 0x3101, 0x130c, 0xff0c, 0x1102, 0x6408, + 0x0024, 0x4204, 0x0024, 0xb882, 0x4092, 0x1005, 0xfe02, 0x48be, 0x0024, + 0x4264, 0x0024, 0x2903, 0xc540, 0xf400, 0x4090, 0x36f4, 0x8024, 0x36f4, + 0x1811, 0x36f1, 0x9807, 0x36f0, 0x9804, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3675, 0x0024, + 0x3643, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, 0x0181, 0x3e10, + 0xb803, 0x3e11, 0x3806, 0x3e11, 0xf810, 0x3e14, 0x7812, 0x3e13, 0xf80e, + 0x2903, 0x47c0, 0x3e03, 0x4024, 0x2900, 0xb740, 0x4088, 0x184c, 0x3413, + 0x184c, 0x2900, 0xb740, 0x6892, 0x3040, 0x4080, 0x3040, 0x0000, 0x0000, + 0x2801, 0xc5c5, 0x0000, 0x0024, 0x6890, 0x0024, 0x2903, 0x47c0, 0x3cd0, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, 0xc615, 0x0000, 0x0024, + 0x3433, 0x0024, 0xf400, 0x4510, 0x34d0, 0x0024, 0x6090, 0x0024, 0x2903, + 0x47c0, 0x3800, 0x0024, 0x4080, 0x10cc, 0xf400, 0x4510, 0x2801, 0xc385, + 0x34d0, 0x0024, 0x2801, 0xc600, 0x0000, 0x0024, 0x3cd0, 0x0024, 0x3433, + 0x0024, 0x34a0, 0x0024, 0xf400, 0x4510, 0x3430, 0x4024, 0x6100, 0x0024, + 0x0000, 0x0341, 0x3840, 0x0024, 0x3000, 0x0024, 0x6012, 0x0024, 0x0006, + 0x0581, 0x2801, 0xe381, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, + 0x2000, 0x0000, 0x0000, 0x0024, 0x34d3, 0x184c, 0x3430, 0x8024, 0x2901, + 0x8c40, 0x3e00, 0x8024, 0x36f3, 0x11cc, 0xb888, 0x104c, 0x3c10, 0x0024, + 0x3c90, 0x4024, 0x2801, 0xcf40, 0x34e3, 0x0024, 0x3411, 0x8024, 0x3491, + 0xc024, 0x4f82, 0x128c, 0x3400, 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, + 0x3800, 0x0024, 0x3440, 0x4024, 0x4142, 0x0024, 0x6498, 0x4050, 0x3009, + 0x2007, 0x0006, 0x8150, 0x3000, 0x11cc, 0x6402, 0x104c, 0x0000, 0x0024, + 0x2801, 0xcc88, 0x0000, 0x0024, 0x3493, 0x0024, 0x2801, 0xff40, 0x34f3, + 0x0024, 0x2801, 0xd6c0, 0xb888, 0x0024, 0x3430, 0x8024, 0x2901, 0x8c40, + 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, 0x5bcc, 0x4142, 0x0024, 0xf400, + 0x4050, 0x3800, 0x0024, 0x3440, 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, + 0x0000, 0x0201, 0x3009, 0x2007, 0x0030, 0x0010, 0x3000, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2801, 0xff55, 0x6498, 0x0024, 0x0006, 0x8150, + 0x3000, 0x134c, 0x6402, 0x984c, 0x0000, 0x0024, 0x2801, 0xd208, 0x0000, + 0x0024, 0x2801, 0xff40, 0x3433, 0x1bcc, 0x0000, 0x0201, 0xb888, 0x104c, + 0x3430, 0x184c, 0x6010, 0x0024, 0x6402, 0x3000, 0x0000, 0x0201, 0x2801, + 0xdf58, 0x0030, 0x0010, 0x4090, 0x124c, 0x2401, 0xde40, 0x0000, 0x0024, + 0x3430, 0x8024, 0x2901, 0x8c40, 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, + 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, 0x3800, 0x0024, 0x3410, 0x4024, + 0x4142, 0x0024, 0x6498, 0x4050, 0x3009, 0x2007, 0x0030, 0x0010, 0x0000, + 0x0201, 0x3473, 0x0024, 0x3490, 0x0024, 0x3e00, 0x13cc, 0x2901, 0x9580, + 0x3444, 0x8024, 0x3000, 0x1bcc, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, + 0xff55, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3470, 0x0024, 0x3e10, 0x104c, + 0x34c0, 0x4024, 0x2901, 0xb1c0, 0x3e00, 0x4024, 0x2801, 0xff40, 0x36e3, + 0x0024, 0x0000, 0x0801, 0x3413, 0x0024, 0x34f0, 0x0024, 0x6012, 0x0024, + 0x0000, 0x07c1, 0x2801, 0xfe88, 0x0000, 0x0024, 0x6010, 0x114c, 0xb888, + 0x32c0, 0x6402, 0x0024, 0x0000, 0x0101, 0x2801, 0xeb18, 0x0000, 0x0024, + 0x4090, 0x134c, 0x2401, 0xea40, 0x3009, 0x184c, 0x3430, 0x8024, 0x2901, + 0x8c40, 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, 0x4024, 0x4142, 0x0024, + 0xf400, 0x4050, 0x3800, 0x0024, 0x3410, 0x4024, 0x4142, 0x0024, 0x6498, + 0x4050, 0x3009, 0x2007, 0x0000, 0x0101, 0x3433, 0x1bcc, 0x2900, 0xb740, + 0x3613, 0x0024, 0x0000, 0x0141, 0x6090, 0x118c, 0x2900, 0xb740, 0x3ca0, + 0x184c, 0x3473, 0x184c, 0xb888, 0x3380, 0x3400, 0x0024, 0x6402, 0x0024, + 0x0000, 0x0201, 0x2801, 0xf1d8, 0x0000, 0x0024, 0x4090, 0x104c, 0x2401, + 0xf100, 0x0000, 0x0024, 0x34a0, 0x8024, 0x2901, 0x8c40, 0x3e00, 0x8024, + 0x0006, 0x8002, 0x4244, 0x118c, 0x4244, 0x0024, 0x6498, 0x4095, 0x3009, + 0x3440, 0x3009, 0x37c1, 0x0000, 0x0201, 0x34f3, 0x0024, 0x0030, 0x0010, + 0x3490, 0x0024, 0x3e00, 0x138c, 0x2901, 0x9580, 0x3444, 0x8024, 0x3000, + 0x1bcc, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, 0xff55, 0x4112, 0x0024, + 0x3463, 0x0024, 0x34a0, 0x0024, 0x6012, 0x0024, 0x0006, 0x8111, 0x2801, + 0xfb19, 0x0000, 0x0024, 0x3100, 0x11cc, 0x3490, 0x4024, 0x4010, 0x0024, + 0x0000, 0x0a01, 0x6012, 0x0024, 0x0006, 0x8151, 0x2801, 0xfb18, 0x0000, + 0x0024, 0x3613, 0x114c, 0x3101, 0x3804, 0x3490, 0x8024, 0x6428, 0x138c, + 0x3470, 0x8024, 0x3423, 0x0024, 0x3420, 0xc024, 0x4234, 0x1241, 0x4380, + 0x4092, 0x2903, 0xc540, 0x0006, 0x8010, 0x2801, 0xff40, 0x3009, 0x1bcc, + 0x0006, 0x8151, 0x3613, 0x114c, 0x3101, 0x3804, 0x3490, 0x8024, 0x6428, + 0x138c, 0x3470, 0x8024, 0x3423, 0x0024, 0x3420, 0xc024, 0x4234, 0x1241, + 0x4380, 0x4092, 0x2903, 0xcf00, 0x0006, 0x8010, 0x2801, 0xff40, 0x3009, + 0x1bcc, 0x0006, 0x8050, 0x6890, 0x0024, 0x3800, 0x0024, 0x3433, 0x0024, + 0x34d0, 0x0024, 0x4080, 0x0024, 0x0006, 0x8150, 0x2802, 0x04c5, 0x0000, + 0x0024, 0x3000, 0x11cc, 0xb888, 0x10cc, 0x6402, 0x3240, 0x3493, 0x0024, + 0x3444, 0x8024, 0x2802, 0x04d8, 0x4090, 0x0024, 0x2402, 0x0480, 0x0000, + 0x0024, 0x6499, 0x2620, 0xb78e, 0x4001, 0x0000, 0x0000, 0x3433, 0x0024, + 0xcfce, 0x1340, 0xaf0e, 0x0024, 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x36f4, 0x5812, 0x36f1, 0xd810, 0x36f1, 0x1806, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, + 0xf804, 0x0000, 0x3fc3, 0x3e11, 0x7806, 0x3e11, 0xf810, 0xbc82, 0x12cc, + 0x3404, 0x0024, 0x3023, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x3454, + 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x2900, 0xb740, 0x0000, 0x0201, + 0x0006, 0x9301, 0x4088, 0x134c, 0x3400, 0x8024, 0xd204, 0x0024, 0xb234, + 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, 0x3c30, 0x0024, + 0x0000, 0x2000, 0xb400, 0x0024, 0x0000, 0x3001, 0x2802, 0x1255, 0x0000, + 0x3800, 0x0000, 0x0041, 0xfe42, 0x12cc, 0x48b2, 0x1090, 0x3810, 0x0024, + 0x38f0, 0x4024, 0x2802, 0x3340, 0x3430, 0x0024, 0xb400, 0x0024, 0x6012, + 0x0024, 0x0000, 0x3801, 0x2802, 0x1595, 0x0000, 0x3c00, 0x0000, 0x07c0, + 0x0000, 0x0041, 0xb400, 0x12cc, 0xfe02, 0x1150, 0x48b2, 0x0024, 0x689a, + 0x2040, 0x2802, 0x3200, 0x38f0, 0x4024, 0xb400, 0x0024, 0x6012, 0x0024, + 0x0000, 0x3c01, 0x2802, 0x1915, 0x0000, 0x3e00, 0x0000, 0x03c0, 0x0000, + 0x0085, 0x4592, 0x12cc, 0xb400, 0x1150, 0xfe02, 0x0024, 0x48b2, 0x0024, + 0x3810, 0x0024, 0x2802, 0x3200, 0x38f0, 0x4024, 0xb400, 0x0024, 0x6012, + 0x0024, 0x0000, 0x3e01, 0x2802, 0x1c95, 0x0000, 0x3f00, 0x0000, 0x01c0, + 0xf20a, 0x12cc, 0xb400, 0x1150, 0xf252, 0x0024, 0xfe02, 0x0024, 0x48b2, + 0x0024, 0x3810, 0x0024, 0x2802, 0x3200, 0x38f0, 0x4024, 0xb400, 0x130c, + 0x6012, 0x0024, 0x0000, 0x3f01, 0x2802, 0x2015, 0x4390, 0x0024, 0x0000, + 0x0041, 0x0000, 0x0105, 0x4590, 0x13cc, 0xb400, 0x1150, 0xfe02, 0x0024, + 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0x3200, 0x38f0, 0x4024, 0xb400, + 0x0024, 0x6012, 0x1100, 0x0000, 0x01c1, 0x2802, 0x2395, 0x0000, 0x0024, + 0x0000, 0x0041, 0x0000, 0x0145, 0x6890, 0x12cc, 0xb400, 0x1150, 0xfe02, + 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0x3200, 0x38f0, 0x4024, + 0x6012, 0x0024, 0x0000, 0x3f81, 0x2802, 0x2615, 0xb430, 0x0024, 0x6012, + 0x0024, 0x0000, 0x0024, 0x2802, 0x2615, 0x0000, 0x0024, 0x2802, 0x3200, + 0x0000, 0x0185, 0x2802, 0x3340, 0xc890, 0x0024, 0x0000, 0x3fc3, 0x0000, + 0x0201, 0x34d3, 0x0024, 0x2900, 0xb740, 0x3433, 0x184c, 0x0006, 0x9301, + 0x4088, 0x134c, 0x3400, 0x8024, 0xd204, 0x0024, 0xb234, 0x0024, 0x4122, + 0x0024, 0xf400, 0x4055, 0x0000, 0x2001, 0x3500, 0x0024, 0x3c30, 0x0024, + 0x0000, 0x3000, 0xb400, 0x0024, 0x6012, 0x0024, 0x0000, 0x0182, 0x2802, + 0x2c45, 0x0000, 0x0024, 0x2802, 0x3340, 0xc890, 0x0024, 0x459a, 0x12cc, + 0x3404, 0x0024, 0x3023, 0x0024, 0x3010, 0x0024, 0x30d0, 0x4024, 0xac22, + 0x0046, 0x003f, 0xf982, 0x3011, 0xc024, 0x0000, 0x0023, 0xaf2e, 0x0024, + 0x0000, 0x0182, 0xccf2, 0x0024, 0x0000, 0x0fc6, 0x0000, 0x0047, 0xb46c, + 0x2040, 0xfe6e, 0x23c1, 0x3454, 0x0024, 0x3010, 0x0024, 0x30f0, 0x4024, + 0xac22, 0x0024, 0xccb2, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x458a, + 0x134c, 0x0000, 0x0201, 0x2802, 0x2755, 0x0000, 0x3fc3, 0x3430, 0x0024, + 0x36f1, 0xd810, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3675, + 0x0024, 0x3633, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, 0x3e13, + 0xf80e, 0x3e03, 0x4024, 0x2903, 0xac40, 0x0000, 0x0381, 0x000f, 0xff81, + 0x6012, 0x184c, 0x0000, 0x0201, 0x2802, 0x3bc5, 0x0000, 0x0024, 0x2900, + 0xb740, 0x0003, 0x1f08, 0x3613, 0x0024, 0x0000, 0x0401, 0x0006, 0x8a10, + 0x2900, 0xbf40, 0xb880, 0x1bcc, 0xb880, 0x11cc, 0x3413, 0x184c, 0x3c90, + 0x0024, 0x2900, 0xb740, 0x34f3, 0x0024, 0x3473, 0x184c, 0x3c00, 0x0000, + 0x4080, 0x0024, 0x0006, 0x9301, 0x2802, 0x4145, 0x003f, 0xfe04, 0x3490, + 0x8024, 0xa244, 0x0024, 0x2903, 0x8f40, 0xb880, 0x0024, 0x2900, 0xbf40, + 0x003f, 0xfe04, 0x3473, 0x184c, 0x0006, 0x8091, 0x3413, 0x0024, 0x34f0, + 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, 0x3500, + 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0x6892, 0x4055, + 0x3500, 0x0024, 0x3cf0, 0x0024, 0x34a0, 0x0024, 0xf100, 0x0024, 0xb010, + 0x0024, 0x3c60, 0x0024, 0x34b0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0201, + 0x2900, 0xb740, 0x3ce0, 0x0024, 0x0006, 0x9301, 0x3473, 0x184c, 0x3c10, + 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x003f, 0xff01, 0x3500, + 0x0024, 0x3cf0, 0x0024, 0x34c0, 0x0024, 0xa010, 0x0024, 0x0000, 0x03c1, + 0x3c40, 0x0024, 0x34d0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0201, 0x2900, + 0xb740, 0x3cc0, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, + 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, 0x3fc3, 0xb234, + 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x003f, 0xff01, 0x3500, 0x0024, + 0x3cf0, 0x0024, 0x3400, 0x0024, 0xa010, 0x0024, 0x0000, 0x01c1, 0x3900, + 0x0024, 0x34e0, 0x0024, 0xf100, 0x0024, 0xb010, 0x0024, 0x6892, 0x3080, + 0x34f0, 0x0024, 0xb010, 0x0024, 0x3cb0, 0x0024, 0x3450, 0x0024, 0x34a0, + 0x4024, 0xc010, 0x0024, 0x0000, 0x0181, 0x2802, 0x55c5, 0x3100, 0x0024, + 0x6890, 0x07cc, 0x2803, 0x1f00, 0x3900, 0x0024, 0x6012, 0x0024, 0x0000, + 0x0201, 0x2802, 0x5758, 0x0000, 0x0024, 0x2802, 0x5a40, 0x6090, 0x044c, + 0x6012, 0x0024, 0x0000, 0x0281, 0x2802, 0x5988, 0x6012, 0x0024, 0x0000, + 0x0080, 0x2802, 0x5999, 0x0000, 0x0024, 0x2802, 0x5a40, 0x3113, 0x0024, + 0x6890, 0x07cc, 0x2803, 0x1f00, 0x3900, 0x0024, 0x0000, 0x0201, 0x3900, + 0x114c, 0x34b0, 0x0024, 0x6012, 0x0024, 0x0006, 0x08c1, 0x2802, 0x6481, + 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, 0x0000, 0x0000, + 0x0024, 0x2802, 0x6480, 0x0000, 0x0024, 0x0000, 0x0200, 0x0006, 0x8110, + 0x2802, 0x6480, 0x3800, 0x0024, 0x0000, 0x0300, 0x0006, 0x8110, 0x2802, + 0x6480, 0x3800, 0x0024, 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, 0x1f00, + 0x3800, 0x0024, 0x0000, 0x0400, 0x0006, 0x8110, 0x2802, 0x6480, 0x3800, + 0x0024, 0x0000, 0x0500, 0x0006, 0x8110, 0x2802, 0x6480, 0x3800, 0x0024, + 0x0000, 0x0600, 0x0006, 0x8110, 0x2802, 0x6480, 0x3800, 0x0024, 0x0006, + 0x8050, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, 0x0024, 0x3423, 0x184c, + 0x3460, 0x0024, 0x4080, 0x0024, 0x0006, 0x8200, 0x2802, 0x69c5, 0x3e10, + 0x0024, 0x0000, 0x01c0, 0x3e10, 0x0024, 0x3490, 0x0024, 0x2902, 0x07c0, + 0x3e00, 0x13cc, 0x36d3, 0x11cc, 0x3413, 0x0024, 0x4080, 0x3240, 0x34f3, + 0x0024, 0x2802, 0x6d98, 0x0000, 0x0024, 0x0006, 0x8010, 0x6890, 0x0024, + 0x2803, 0x1f00, 0x3800, 0x0024, 0x0000, 0x0180, 0x3e10, 0x0024, 0x3490, + 0x0024, 0x2902, 0x07c0, 0x3e00, 0x13cc, 0x36d3, 0x11cc, 0x3413, 0x0024, + 0x4080, 0x3240, 0x34f3, 0x0024, 0x2802, 0x6d98, 0x0000, 0x0024, 0x0006, + 0x8010, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, 0x0024, 0x0000, 0x0201, + 0x3433, 0x0024, 0x34d0, 0x0024, 0x6012, 0x0024, 0x0006, 0x0ac1, 0x2802, + 0x7f81, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, 0x0000, + 0x0000, 0x0024, 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, + 0x0024, 0x0000, 0x3000, 0x2802, 0x8140, 0x0006, 0x8150, 0x0000, 0x9000, + 0x0006, 0x8150, 0x3433, 0x0024, 0x34d0, 0x4024, 0x4192, 0x0024, 0x4192, + 0x0024, 0x2802, 0x8140, 0xa010, 0x0024, 0x0000, 0x0201, 0x0006, 0x8150, + 0x2900, 0xb740, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, + 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, 0x3cf0, + 0x0024, 0x3490, 0x0024, 0x2802, 0x8140, 0x6090, 0x0024, 0x003f, 0xfe04, + 0x0000, 0x0401, 0x0006, 0x8150, 0x2900, 0xb740, 0x3613, 0x0024, 0x0006, + 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3400, 0xc024, + 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, 0x3fc3, 0xb234, 0x0024, 0x4122, + 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, 0x3500, 0x0024, 0xd024, 0x3000, + 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, 0x3cf0, + 0x0024, 0x3490, 0x0024, 0x2802, 0x8140, 0x6090, 0x0024, 0x0000, 0x4000, + 0x0000, 0x0202, 0x0006, 0x8150, 0x3433, 0x0024, 0x34d0, 0x4024, 0x6122, + 0x0024, 0xa010, 0x0024, 0x0004, 0x8001, 0x3800, 0x110c, 0x0006, 0x8150, + 0x3000, 0x0024, 0x6012, 0x1300, 0x0000, 0x0401, 0x2802, 0x8409, 0x0000, + 0x0024, 0x6890, 0x82cc, 0x2803, 0x1f00, 0x3800, 0x0024, 0x6012, 0x0024, + 0x0006, 0x0cc1, 0x2802, 0xab81, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, + 0x0024, 0x2000, 0x0000, 0x0000, 0x0024, 0x2802, 0xab80, 0x0000, 0x0024, + 0x0016, 0x2200, 0x0006, 0x8190, 0x6892, 0x2040, 0x2802, 0xab80, 0x38f0, + 0x4024, 0x002c, 0x4400, 0x0000, 0x0081, 0x0006, 0x8190, 0x3810, 0x0024, + 0x2802, 0xab80, 0x38f0, 0x4024, 0x003b, 0x8000, 0x0000, 0x0081, 0x0006, + 0x8190, 0x3810, 0x0024, 0x2802, 0xab80, 0x38f0, 0x4024, 0x0007, 0xd000, + 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, 0xab80, 0x38f0, 0x4024, 0x000f, + 0xa000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, 0xab80, 0x38f0, 0x4024, + 0x0015, 0x8880, 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, 0xab80, 0x38f0, + 0x4024, 0x0017, 0x7000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, 0xab80, + 0x38f0, 0x4024, 0x001f, 0x4000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, + 0xab80, 0x38f0, 0x4024, 0x002b, 0x1100, 0x0006, 0x8190, 0xb882, 0x2040, + 0x2802, 0xab80, 0x38f0, 0x4024, 0x002e, 0xe000, 0x0006, 0x8190, 0xb882, + 0x2040, 0x2802, 0xab80, 0x38f0, 0x4024, 0x001d, 0xc000, 0x0006, 0x8190, + 0x6892, 0x2040, 0x2802, 0xab80, 0x38f0, 0x4024, 0x0006, 0x8190, 0x0000, + 0x0201, 0x0000, 0xfa04, 0x2900, 0xb740, 0x3613, 0x0024, 0x0006, 0x9301, + 0xb88a, 0x11cc, 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, + 0x0024, 0x0000, 0x3fc3, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, + 0x3500, 0x0024, 0x3cf0, 0x0024, 0x3490, 0x0024, 0xfe50, 0x4005, 0x48b2, + 0x0024, 0xfeca, 0x0024, 0x40b2, 0x0024, 0x3810, 0x0024, 0x2802, 0xab80, + 0x38f0, 0x4024, 0x003f, 0xfe04, 0x0000, 0x0401, 0x0006, 0x8190, 0x2900, + 0xb740, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, + 0x34f0, 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, + 0x3500, 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, + 0x4055, 0x0000, 0x0041, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x3490, 0x0024, + 0xfe02, 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0xab80, 0x38f0, + 0x4024, 0x003f, 0xfe04, 0x0000, 0x0401, 0x0006, 0x8190, 0x2900, 0xb740, + 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, 0x34f0, + 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, 0x3500, + 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, + 0x3500, 0x0024, 0x3cf0, 0x0024, 0x0000, 0x0280, 0x3490, 0x4024, 0xfe02, + 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0xab80, 0x38f0, 0x4024, + 0x0006, 0x8010, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, 0x0024, 0x0000, + 0x0201, 0x2900, 0xb740, 0x3613, 0x11cc, 0x3c10, 0x0024, 0x3490, 0x4024, + 0x6014, 0x13cc, 0x0000, 0x0081, 0x2802, 0xaec5, 0x0006, 0x80d0, 0x0006, + 0x8010, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, 0x0024, 0x3010, 0x0024, + 0x6012, 0x0024, 0x0000, 0x0241, 0x2802, 0xce49, 0x0006, 0x8112, 0x0008, + 0x0001, 0x3009, 0x184c, 0x3e10, 0x4024, 0x3000, 0x8024, 0x2901, 0xbac0, + 0x3e00, 0x8024, 0x36f3, 0x004c, 0x3000, 0x3844, 0x0008, 0x0010, 0xb884, + 0x3840, 0x0000, 0x0400, 0x3e00, 0x8024, 0x3201, 0x0024, 0x2903, 0x5680, + 0x6408, 0x4091, 0x0001, 0x0000, 0x000b, 0x8011, 0x0004, 0x0010, 0x36e3, + 0x0024, 0x2915, 0x8300, 0x3009, 0x1bc4, 0x000b, 0x8000, 0x3613, 0x0024, + 0x3e10, 0x0024, 0x3200, 0xc024, 0x2901, 0xbac0, 0x3e00, 0xc024, 0x36f3, + 0x084c, 0x32f0, 0xf844, 0x3e10, 0xc024, 0x3e00, 0x8024, 0x2b01, 0x0091, + 0x0000, 0x0400, 0xf204, 0x0804, 0x2903, 0x5680, 0x6408, 0x0024, 0x000b, + 0x8011, 0x0008, 0x0010, 0x0000, 0x0084, 0x36d3, 0x0024, 0x2915, 0x8300, + 0x0003, 0x8000, 0x0005, 0x0010, 0x0001, 0x0000, 0x2915, 0x8300, 0x000f, + 0x0011, 0x1006, 0x0ac0, 0x32f3, 0x11cc, 0x3200, 0xd08c, 0xff34, 0x0024, + 0x48b6, 0x0024, 0x4020, 0x0024, 0x3c90, 0x0024, 0x2802, 0xca80, 0x34e3, + 0x0024, 0x0006, 0x8112, 0x3613, 0x0024, 0x3e10, 0x0024, 0x3000, 0x4024, + 0x2901, 0xbac0, 0x3e00, 0x4024, 0x36f3, 0x004c, 0x3000, 0x7844, 0xb884, + 0x3841, 0x2b01, 0x0091, 0x0000, 0x0400, 0x3e00, 0x8024, 0x3201, 0x0024, + 0x2903, 0x5680, 0x6408, 0x0024, 0x0003, 0x8000, 0x000b, 0x8011, 0x0008, + 0x0010, 0x36e3, 0x11cc, 0x3423, 0x0024, 0x3494, 0xc024, 0x2903, 0x7ac0, + 0x3301, 0x138c, 0x0001, 0x0000, 0x000f, 0x0011, 0x0004, 0x0010, 0x2903, + 0x8000, 0x3301, 0x0024, 0xf400, 0x4510, 0x000b, 0x8011, 0x3073, 0x0024, + 0x3023, 0x0024, 0x3000, 0x0024, 0x6090, 0x0024, 0x3800, 0x0024, 0x0003, + 0x8000, 0x3004, 0xc024, 0x0008, 0x0010, 0x2903, 0x8000, 0x3301, 0x0024, + 0x0001, 0x0000, 0x000f, 0x0011, 0x0005, 0x0010, 0x2903, 0x8000, 0x3301, + 0x0024, 0xf400, 0x4510, 0x3073, 0x1bc4, 0x6498, 0x008c, 0x3000, 0x0024, + 0x6090, 0x0024, 0x3800, 0x0024, 0x0006, 0x80d0, 0x3000, 0x0024, 0x6402, + 0x0024, 0x0006, 0x8110, 0x2802, 0xbdc8, 0x000b, 0x8000, 0x000b, 0x8010, + 0x0001, 0x0000, 0x2903, 0xe0c0, 0x0004, 0x0011, 0x0005, 0x0011, 0x000b, + 0x8010, 0x0001, 0x0000, 0x291f, 0xc6c0, 0x0002, 0xdf88, 0x30e1, 0x184c, + 0x3000, 0x0024, 0x6012, 0x0024, 0x0008, 0x0001, 0x2802, 0xd015, 0x0000, + 0x0024, 0x6498, 0x0024, 0x3e10, 0x4024, 0x0000, 0x0081, 0x2901, 0xbac0, + 0x3e01, 0x0024, 0x36e3, 0x004c, 0x3000, 0x0024, 0x6012, 0x0024, 0x000b, + 0x8011, 0x2802, 0xdc55, 0x0006, 0x8112, 0x0000, 0x0201, 0x0004, 0x0010, + 0x2915, 0x8300, 0x0001, 0x0000, 0x000b, 0x8011, 0x0005, 0x0010, 0x291f, + 0xc6c0, 0x0001, 0x0000, 0x0006, 0x8110, 0x30e1, 0x0024, 0x3000, 0x0024, + 0x6012, 0x0024, 0x0000, 0x0281, 0x2802, 0xd745, 0x6012, 0x0024, 0x000b, + 0x8001, 0x2802, 0xd7d5, 0x3613, 0x0024, 0x36f3, 0x0024, 0x000b, 0x8001, + 0x6498, 0x184c, 0x0006, 0x8112, 0x0003, 0x8000, 0x3e10, 0x4024, 0x2901, + 0xbac0, 0x3e01, 0x0024, 0x36f3, 0x0024, 0x3009, 0x3844, 0x3e10, 0x0024, + 0x0000, 0x0400, 0x3000, 0x8024, 0x0008, 0x0010, 0x3e00, 0x8024, 0x3201, + 0x0024, 0x2903, 0x5680, 0x6408, 0x4051, 0x36e3, 0x0024, 0x2802, 0xdf80, + 0x3009, 0x1bc4, 0x0000, 0x0400, 0x0000, 0x0011, 0x3613, 0x008c, 0x30d0, + 0x7844, 0x3e10, 0x4024, 0x3000, 0x8024, 0x0008, 0x0010, 0x3e00, 0x8024, + 0x3201, 0x0024, 0x2903, 0x5680, 0x6408, 0x0024, 0x36e3, 0x0024, 0x3009, + 0x1bc4, 0x0006, 0x8a10, 0x0000, 0x01c1, 0x3009, 0x0000, 0xb010, 0x0024, + 0x0000, 0x0024, 0x2802, 0xe385, 0x6192, 0x0024, 0x2900, 0xb740, 0x6102, + 0x184c, 0x4088, 0x0024, 0x0000, 0x0024, 0x2802, 0xe385, 0x0000, 0x0024, + 0x0006, 0x8051, 0x6890, 0x0024, 0x3900, 0x0024, 0x3009, 0x0000, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2903, 0x8e85, 0x0002, 0xe848, 0x0006, 0x9f92, + 0x0000, 0x4003, 0x3009, 0x0811, 0x3100, 0x8024, 0xffa6, 0x0024, 0x48b6, + 0x0024, 0x2903, 0x8e80, 0x4384, 0x0024, 0x2903, 0x8f40, 0x3613, 0x0024, + 0x2900, 0xbf40, 0x0000, 0x0024, 0x2903, 0x8e80, 0x0000, 0x0024, 0x0000, + 0x0401, 0x3473, 0x184c, 0x2900, 0xb740, 0x3c10, 0x0024, 0x3c90, 0x0024, + 0x290b, 0x1400, 0x34f3, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, + 0x1b95, 0x0000, 0x0024, 0x3473, 0x0024, 0x3410, 0x0024, 0x34a0, 0x4024, + 0x6014, 0x1380, 0x0000, 0x0024, 0x2802, 0xf045, 0x4080, 0x0024, 0x0006, + 0x8011, 0x6890, 0x0024, 0xb882, 0x2400, 0x0004, 0x8000, 0x2914, 0xbec0, + 0x0008, 0x0010, 0x0000, 0x0400, 0x3143, 0x108c, 0x6890, 0x27c0, 0x3920, + 0x0024, 0x0004, 0x8000, 0x3900, 0x0024, 0x34e0, 0x0024, 0x4080, 0x0024, + 0x0006, 0x8150, 0x2802, 0xf445, 0x0000, 0x3200, 0x0000, 0x0142, 0x0006, + 0x8210, 0x3613, 0x0024, 0x3e00, 0x7800, 0x3011, 0x8024, 0x30d1, 0xc024, + 0xfef4, 0x4087, 0x48b6, 0x0040, 0xfeee, 0x03c1, 0x2914, 0xa580, 0x42b6, + 0x0024, 0x2802, 0xf840, 0x0007, 0x89d0, 0x0000, 0x0142, 0x3613, 0x0024, + 0x3e00, 0x7800, 0x3031, 0x8024, 0x3010, 0x0024, 0x30d0, 0x4024, 0xfe9c, + 0x4181, 0x48be, 0x0024, 0xfe82, 0x0040, 0x46be, 0x03c1, 0xfef4, 0x4087, + 0x48b6, 0x0024, 0xfeee, 0x0024, 0x2914, 0xa580, 0x42b6, 0x0024, 0x0007, + 0x89d0, 0x0006, 0x8191, 0x4c8a, 0x9800, 0xfed0, 0x4005, 0x48b2, 0x0024, + 0xfeca, 0x0024, 0x40b2, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x3111, + 0x8024, 0x468a, 0x0707, 0x2908, 0xbe80, 0x3101, 0x0024, 0x3123, 0x11cc, + 0x3100, 0x108c, 0x3009, 0x3000, 0x0004, 0x8000, 0x3009, 0x1241, 0x6014, + 0x138c, 0x000b, 0x8011, 0x2802, 0xfe81, 0x0000, 0x0024, 0x3473, 0x0024, + 0x3423, 0x0024, 0x3009, 0x3240, 0x34e3, 0x0024, 0x2803, 0x19c0, 0x0008, + 0x0012, 0x0000, 0x0081, 0x2803, 0x0009, 0x0006, 0x80d0, 0xf400, 0x4004, + 0x3000, 0x0024, 0x6012, 0x0024, 0x0000, 0x0005, 0x2803, 0x0589, 0x0000, + 0x0024, 0x6540, 0x0024, 0x0000, 0x0024, 0x2803, 0x15d8, 0x4490, 0x0024, + 0x2403, 0x04c0, 0x0000, 0x0024, 0x0006, 0x8301, 0x4554, 0x0800, 0x4122, + 0x0024, 0x659a, 0x4055, 0x0006, 0x8341, 0x3d00, 0x0840, 0x4122, 0x0024, + 0xf400, 0x4055, 0x3d00, 0x0024, 0x2803, 0x15c0, 0x0000, 0x0024, 0x4090, + 0x0024, 0xf400, 0x4480, 0x2803, 0x0ad5, 0x000b, 0x8001, 0x6540, 0x0024, + 0x0000, 0x0024, 0x2803, 0x15d8, 0x4490, 0x0024, 0x2403, 0x0a00, 0x0000, + 0x0024, 0x0006, 0x8301, 0x4554, 0x0800, 0x4122, 0x0024, 0x659a, 0x4055, + 0x0006, 0x8341, 0x4122, 0x3400, 0xf400, 0x4055, 0x3210, 0x0024, 0x3d00, + 0x0024, 0x2803, 0x15c0, 0x0000, 0x0024, 0x6014, 0x0024, 0x0001, 0x0000, + 0x2803, 0x1215, 0x0003, 0x8001, 0x0008, 0x0012, 0x0008, 0x0010, 0x0006, + 0x8153, 0x3613, 0x0024, 0x3009, 0x3811, 0x2903, 0xe0c0, 0x0004, 0x0011, + 0x0008, 0x0010, 0x0001, 0x0000, 0x291f, 0xc6c0, 0x0005, 0x0011, 0x000f, + 0x0011, 0x0008, 0x0010, 0x33d0, 0x184c, 0x6010, 0xb844, 0x3e10, 0x0024, + 0x0000, 0x0400, 0x3320, 0x4024, 0x3e00, 0x4024, 0x3301, 0x0024, 0x2903, + 0x5680, 0x6408, 0x0024, 0x36e3, 0x0024, 0x3009, 0x1bc4, 0x3009, 0x1bd1, + 0x6540, 0x0024, 0x0000, 0x0024, 0x2803, 0x15d8, 0x4490, 0x0024, 0x2403, + 0x1580, 0x0000, 0x0024, 0x0006, 0x8301, 0x4554, 0x0840, 0x4122, 0x0024, + 0x659a, 0x4055, 0x0006, 0x8341, 0x4122, 0x3400, 0xf400, 0x4055, 0x3110, + 0x0024, 0x3d00, 0x0024, 0xf400, 0x4510, 0x0030, 0x0013, 0x3073, 0x184c, + 0x3e11, 0x008c, 0x3009, 0x0001, 0x6140, 0x0024, 0x0000, 0x0201, 0x3009, + 0x2000, 0x0006, 0x8300, 0x290c, 0x7300, 0x3e10, 0x0024, 0x3300, 0x1b8c, + 0xb010, 0x0024, 0x0000, 0x0024, 0x2803, 0x1b95, 0x0000, 0x0024, 0x3473, + 0x0024, 0x3423, 0x0024, 0x3009, 0x1240, 0x4080, 0x138c, 0x0000, 0x0804, + 0x2802, 0xff15, 0x6402, 0x0024, 0x0006, 0xd312, 0x0006, 0xd310, 0x0006, + 0x8191, 0x3010, 0x984c, 0x30f0, 0xc024, 0x0000, 0x0021, 0xf2d6, 0x07c6, + 0x290a, 0xf5c0, 0x4682, 0x0400, 0x6894, 0x0840, 0xb886, 0x0bc1, 0xbcd6, + 0x0024, 0x3a10, 0x8024, 0x3af0, 0xc024, 0x36f3, 0x4024, 0x36f3, 0xd80e, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, + 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, + 0x0020, 0x0001, 0x3e14, 0x3811, 0x0030, 0x0050, 0x0030, 0x0251, 0x3e04, + 0xb813, 0x3000, 0x0024, 0xc012, 0x0024, 0x0019, 0x9300, 0x3800, 0x4024, + 0x2903, 0x8c40, 0x3900, 0x0024, 0x2903, 0xa040, 0x0000, 0x0300, 0xb882, + 0x0024, 0x2914, 0xbec0, 0x0006, 0x8010, 0x0000, 0x1540, 0x0007, 0x8190, + 0x2901, 0x8200, 0x3800, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, + 0x2f55, 0x0000, 0x0024, 0x0006, 0x8012, 0x3200, 0x0024, 0x4080, 0x0024, + 0x0030, 0x0010, 0x2803, 0x2f55, 0x0000, 0x0201, 0x3000, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2803, 0x2f55, 0x0000, 0x0024, 0x2901, 0x8200, + 0x0000, 0x0024, 0x4080, 0x0024, 0x0006, 0x8010, 0x2803, 0x2f55, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0201, 0x2803, 0x2b85, 0x0030, 0x0010, + 0x0030, 0x0050, 0xf292, 0x0000, 0xb012, 0x0024, 0x3800, 0x4024, 0x0030, + 0x0010, 0x0000, 0x0201, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2900, 0xbed5, 0x0003, 0x3908, 0x0006, 0x8011, 0x3100, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2803, 0x3745, 0x0000, 0x0024, 0x0007, 0x8a52, + 0x3200, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0x3749, 0x0000, + 0x0024, 0xf292, 0x0800, 0x6012, 0x0024, 0x0000, 0x0000, 0x2803, 0x3705, + 0x0000, 0x0024, 0x3200, 0x0024, 0x4090, 0x0024, 0xb880, 0x2800, 0x3900, + 0x0024, 0x3100, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2902, 0x3585, + 0x0003, 0x3048, 0x2900, 0xbec0, 0x0000, 0x0024, 0x0000, 0x0010, 0x0006, + 0x9f51, 0x0006, 0x9f92, 0x0030, 0x0493, 0x0000, 0x0201, 0x6890, 0xa410, + 0x3b00, 0x2810, 0x0006, 0x8a10, 0x3009, 0x0000, 0x6012, 0x0024, 0x0006, + 0x9fd0, 0x2803, 0x3c88, 0xb880, 0x0024, 0x6890, 0x0024, 0x3009, 0x2000, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e10, 0xb810, 0x3e11, 0x3805, 0x3e02, 0x0024, 0x0030, 0x0010, 0xce9a, + 0x0002, 0x0000, 0x0200, 0x2903, 0x47c0, 0xb024, 0x0024, 0xc020, 0x0024, + 0x0000, 0x0200, 0x2803, 0x4085, 0x6e9a, 0x0002, 0x4182, 0x0024, 0x0000, + 0x0400, 0x2803, 0x4645, 0xae1a, 0x0024, 0x6104, 0x984c, 0x0000, 0x0024, + 0x2900, 0xb749, 0x0003, 0x4608, 0x6103, 0xe4e5, 0x2900, 0xb740, 0x408a, + 0x188c, 0x2900, 0xb740, 0x408a, 0x4141, 0x4583, 0x6465, 0x2803, 0x4640, + 0xceca, 0x1bcc, 0xc408, 0x0024, 0xf2e2, 0x1bc8, 0x36f1, 0x1805, 0x2000, + 0x0011, 0x36f0, 0x9810, 0x2000, 0x0000, 0xdc92, 0x0024, 0x0006, 0x8a17, + 0x3613, 0x1c00, 0x6093, 0xe1e3, 0x0000, 0x03c3, 0x0006, 0x9f95, 0xb132, + 0x9415, 0x3500, 0xfc01, 0x2803, 0x55d5, 0xa306, 0x0024, 0x0006, 0xd397, + 0x003f, 0xc001, 0x3500, 0x184c, 0xb011, 0xe4e5, 0xb182, 0x1c04, 0xd400, + 0x184c, 0x0000, 0x0205, 0xac52, 0x3802, 0x0006, 0xd3c2, 0x4212, 0x0024, + 0xf400, 0x4057, 0xb182, 0x1c04, 0xd400, 0x0024, 0xac52, 0x1404, 0xd142, + 0x0024, 0x0000, 0x3fc4, 0xb142, 0x0024, 0x4122, 0x1bc2, 0xf400, 0x4057, + 0x3700, 0x4024, 0xd101, 0x6465, 0x0006, 0xd397, 0x3f00, 0x3814, 0x0025, + 0xffd4, 0x0006, 0xd317, 0x3710, 0x160c, 0x0006, 0x9f94, 0x37f0, 0x73d5, + 0x6c92, 0x3808, 0x3f10, 0x0024, 0x3ff0, 0x4024, 0x3009, 0x1040, 0x3009, + 0x13c1, 0x6010, 0x0024, 0x0000, 0x0024, 0x2903, 0xa905, 0x0003, 0x51c8, + 0x2803, 0x5414, 0x0006, 0x0001, 0x4010, 0x0024, 0x0005, 0xf601, 0x6010, + 0x0024, 0x0000, 0x0040, 0x2803, 0x5594, 0x0030, 0x0497, 0x3f00, 0x0024, + 0x36f2, 0x1814, 0x4330, 0x9803, 0x2000, 0x0000, 0x8880, 0x1bc1, 0x3613, + 0x0024, 0x3e22, 0xb806, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x7807, 0x6848, 0x930c, 0x3411, + 0x780d, 0x459a, 0x10c0, 0x0000, 0x0201, 0x6012, 0x384e, 0x0000, 0x0241, + 0x2803, 0x5d15, 0x6012, 0x380f, 0x2403, 0x5c45, 0x0000, 0x0024, 0x3000, + 0x0001, 0x3101, 0x8407, 0x6cfe, 0x0024, 0xac42, 0x0024, 0xaf4e, 0x2040, + 0x3911, 0x8024, 0x2803, 0x68c0, 0x0000, 0x0024, 0x0000, 0x0281, 0x2803, + 0x6055, 0x6012, 0x4455, 0x2403, 0x5f85, 0x0000, 0x0024, 0x3000, 0x0001, + 0x3101, 0x8407, 0x4cf2, 0x0024, 0xac42, 0x0024, 0xaf4e, 0x2040, 0x3911, + 0x8024, 0x2803, 0x68c0, 0x0000, 0x0024, 0x0000, 0x0024, 0x2803, 0x6495, + 0x4080, 0x0024, 0x3110, 0x0401, 0xf20f, 0x0203, 0x2403, 0x63c5, 0x8dd6, + 0x0024, 0x4dce, 0x0024, 0xf1fe, 0x0024, 0xaf4e, 0x0024, 0x6dc6, 0x2046, + 0xf1df, 0x0203, 0xaf4f, 0x1011, 0xf20e, 0x07cc, 0x8dd6, 0x2486, 0x2803, + 0x68c0, 0x0000, 0x0024, 0x0000, 0x0024, 0x2803, 0x6715, 0x0000, 0x0024, + 0x0fff, 0xffd1, 0x2403, 0x6645, 0x3010, 0x0001, 0xac4f, 0x0801, 0x3821, + 0x8024, 0x2803, 0x68c0, 0x0000, 0x0024, 0x0fff, 0xffd1, 0x2403, 0x6885, + 0x3010, 0x0001, 0x3501, 0x9407, 0xac47, 0x0801, 0xaf4e, 0x2082, 0x3d11, + 0x8024, 0x36f3, 0xc024, 0x36f3, 0x980d, 0x36f1, 0x5807, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, + 0x9806, 0x0006, 0x9f97, 0x3e00, 0x5c15, 0x0006, 0xd397, 0x003f, 0xc001, + 0x3500, 0x3840, 0xb011, 0xe4e5, 0xb182, 0x1c04, 0xd400, 0x184c, 0x0000, + 0x0205, 0xac52, 0x3802, 0x0006, 0xd3c2, 0x4212, 0x0024, 0xb182, 0x4057, + 0x3701, 0x0024, 0xd400, 0x0024, 0xac52, 0x1404, 0xd142, 0x0024, 0x0000, + 0x3fc4, 0xb142, 0x0024, 0x4122, 0x1bc2, 0xf400, 0x4057, 0x3700, 0x4024, + 0xd101, 0x6465, 0x0006, 0xd397, 0x3f00, 0x3814, 0x0025, 0xffd4, 0x0006, + 0xd317, 0x3710, 0x160c, 0x0006, 0x9f94, 0x37f0, 0x73d5, 0x6c92, 0x0024, + 0x3f10, 0x1040, 0x3ff0, 0x53c1, 0x6010, 0x0024, 0x0000, 0x0024, 0x2803, + 0x7494, 0x0006, 0x0001, 0x4010, 0x0024, 0x0005, 0xf601, 0x6010, 0x9bd4, + 0x0000, 0x0040, 0x2803, 0x7614, 0x0030, 0x0497, 0x3f00, 0x0024, 0x2000, + 0x0000, 0x36f0, 0x5800, 0x0000, 0x0400, 0x6102, 0x0024, 0x3e11, 0x3805, + 0x2803, 0x7989, 0x3e02, 0x0024, 0x2900, 0xb740, 0x408a, 0x188c, 0x2900, + 0xb740, 0x408a, 0x4141, 0x4582, 0x1bc8, 0x2000, 0x0000, 0x36f1, 0x1805, + 0x2900, 0xb740, 0x4102, 0x184c, 0xb182, 0x1bc8, 0x2000, 0x0000, 0x36f1, + 0x1805, 0x3613, 0x0024, 0x3e12, 0xb815, 0x3e11, 0xb807, 0x3e13, 0xf80e, + 0x3e03, 0x4024, 0x680c, 0x0024, 0x0000, 0x0024, 0x2803, 0x7ed8, 0x409c, + 0x0024, 0x2403, 0x7e86, 0x0000, 0x000a, 0x3111, 0xc024, 0xfe4e, 0x0007, + 0x47be, 0x0024, 0xf6fe, 0x0024, 0x3811, 0xc024, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x36f1, 0x9807, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, + 0x3e12, 0xb815, 0x3e11, 0xb807, 0x3e13, 0xf80e, 0x3e03, 0x4024, 0x680c, + 0x0024, 0x0000, 0x0024, 0x2803, 0x8418, 0x409c, 0x0024, 0x2403, 0x83c6, + 0x0000, 0x000a, 0x3111, 0xc024, 0xfe4e, 0x8007, 0x47be, 0x0024, 0xf6fe, + 0x0024, 0x3009, 0x2047, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, 0x9807, + 0x2000, 0x0000, 0x36f2, 0x9815, 0x2a03, 0x858e, 0x3e12, 0xb817, 0x3e10, + 0x3802, 0x0000, 0x800a, 0x0006, 0x9f97, 0x3009, 0x1fc2, 0x3e04, 0x5c00, + 0x6020, 0xb810, 0x0030, 0x0451, 0x2803, 0x8854, 0x0006, 0x0002, 0x4020, + 0x0024, 0x0005, 0xfb02, 0x6024, 0x0024, 0x0025, 0xffd0, 0x2803, 0x8a91, + 0x3100, 0x1c11, 0xb284, 0x0024, 0x0030, 0x0490, 0x3800, 0x8024, 0x0025, + 0xffd0, 0x3980, 0x1810, 0x36f4, 0x7c11, 0x36f0, 0x1802, 0x0030, 0x0717, + 0x3602, 0x8024, 0x2100, 0x0000, 0x3f05, 0xdbd7, 0x0003, 0x8557, 0x3613, + 0x0024, 0x3e00, 0x3801, 0xf400, 0x55c0, 0x0000, 0x0897, 0xf400, 0x57c0, + 0x0000, 0x0024, 0x2000, 0x0000, 0x36f0, 0x1801, 0x0006, 0xd397, 0x2000, + 0x0000, 0x3700, 0x0024, 0xb183, 0xe1e3, 0x0000, 0x0203, 0xac32, 0x40d5, + 0xd122, 0x0024, 0x0000, 0x3fc3, 0xb132, 0x0024, 0x0006, 0xd3c3, 0x4316, + 0x0024, 0xf400, 0x40d5, 0x3500, 0x5803, 0x2000, 0x0000, 0xd010, 0x1bc1, + 0x3613, 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0xb884, 0xb805, 0xb888, 0x3844, + 0x3e11, 0xb80d, 0x3e03, 0xf80e, 0x0000, 0x03ce, 0xf400, 0x4083, 0x2403, + 0x9ace, 0xf400, 0x4105, 0x0000, 0x0206, 0xa562, 0x0024, 0x455a, 0x0024, + 0x0020, 0x0006, 0xd312, 0x0024, 0xb16c, 0x0024, 0x0020, 0x0006, 0x2803, + 0x9945, 0xd342, 0x0024, 0x0000, 0x01c6, 0xd342, 0x0024, 0xd56a, 0x0024, + 0x0020, 0x0006, 0x4448, 0x0024, 0xb16c, 0x0024, 0x0020, 0x0146, 0x2803, + 0x9ac5, 0x0000, 0x0024, 0xd468, 0x0024, 0x4336, 0x0024, 0x0000, 0x4000, + 0x0006, 0xd3c1, 0x0006, 0x9306, 0x4122, 0x0024, 0x462c, 0x4055, 0x4092, + 0x3404, 0xb512, 0x4195, 0x6294, 0x3401, 0x6200, 0x0024, 0x0000, 0x03ce, + 0x2803, 0x9551, 0xb888, 0x0024, 0x36f3, 0xd80e, 0x36f1, 0x980d, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36e3, 0x0024, + 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, + 0xb880, 0xb810, 0x0006, 0x9fd0, 0x3e10, 0x8001, 0x4182, 0x3811, 0x0006, + 0xd311, 0x2803, 0xa405, 0x0006, 0x8a10, 0x0000, 0x0200, 0xbc82, 0xa000, + 0x3910, 0x0024, 0x2903, 0x9240, 0x39f0, 0x4024, 0x0006, 0x9f90, 0x0006, + 0x9f51, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, 0x0000, 0x0024, + 0x2903, 0xa905, 0x0003, 0xa508, 0x36f4, 0x4024, 0x36f0, 0x9810, 0x36f0, + 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x290a, 0xd900, 0x3605, 0x0024, 0x2910, 0x0180, 0x3613, 0x0024, + 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, + 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0006, 0x0002, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0x9f90, 0x3e04, 0xb813, + 0x3009, 0x0012, 0x3213, 0x0024, 0xf400, 0x4480, 0x6026, 0x0024, 0x0000, + 0x0024, 0x2803, 0xb195, 0x0000, 0x0024, 0x0000, 0x0012, 0xf400, 0x4480, + 0x0006, 0x9f50, 0x3009, 0x0002, 0x6026, 0x0024, 0x0000, 0x0024, 0x2903, + 0xa905, 0x0003, 0xb188, 0x0006, 0x9f93, 0x3201, 0x0c11, 0xb58a, 0x0406, + 0x0006, 0x8a11, 0x468e, 0x8400, 0xb68c, 0x9813, 0xcfee, 0x1bd2, 0x0000, + 0x0804, 0xaf0e, 0x9811, 0x4f86, 0x1bd0, 0x0000, 0x0021, 0x6418, 0x9807, + 0x6848, 0x1bc6, 0xad46, 0x9805, 0xf400, 0x4080, 0x36f1, 0x0024, 0x36f0, + 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x2803, 0xbfc0, 0x3e04, 0x3811, 0x0000, 0x0401, 0x2900, + 0xb740, 0x3613, 0x0024, 0x0000, 0x0080, 0xb882, 0x130c, 0xf400, 0x4510, + 0x3010, 0x910c, 0x30f0, 0xc024, 0x6dc2, 0x0024, 0x3810, 0x0024, 0x38f0, + 0x4024, 0x0000, 0x0201, 0x3100, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2803, 0xc315, 0x0000, 0x0024, 0x6894, 0x130c, 0xb886, 0x1040, 0x3430, + 0x4024, 0x6dca, 0x0024, 0x0030, 0x0011, 0x2803, 0xbb91, 0x0000, 0x0024, + 0xbcd2, 0x0024, 0x0000, 0x0201, 0x2803, 0xc305, 0x0000, 0x0024, 0x2900, + 0xb740, 0x3613, 0x0024, 0x36f4, 0x1811, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, 0x800a, + 0x3e14, 0x7813, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e13, + 0xf80e, 0x6812, 0x0024, 0x3e03, 0x7810, 0x0fff, 0xffd3, 0x0000, 0x0091, + 0xbd86, 0x9850, 0x3e10, 0x3804, 0x3e00, 0x7812, 0xbe8a, 0x8bcc, 0x409e, + 0x8086, 0x2403, 0xca47, 0xfe49, 0x2821, 0x526a, 0x8801, 0x5c87, 0x280e, + 0x4eba, 0x9812, 0x4286, 0x40e1, 0xb284, 0x1bc1, 0x4de6, 0x0024, 0xad17, + 0x2627, 0x4fde, 0x9804, 0x4498, 0x1bc0, 0x0000, 0x0024, 0x2803, 0xc855, + 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, 0x9807, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x36f4, 0x5813, 0x2000, 0x0000, 0x36f2, 0x9815, + 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, 0x800a, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e13, 0xf80e, 0x6812, 0x0024, 0x3e03, 0x7810, + 0x3009, 0x1850, 0x3e10, 0x3804, 0x3e10, 0x7812, 0x32f3, 0x0024, 0xbd86, + 0x0024, 0x4091, 0xe2e3, 0x3009, 0x0046, 0x2403, 0xd5c0, 0x3009, 0x0047, + 0x32f0, 0x0801, 0xfe1f, 0x6465, 0x5e8a, 0x0024, 0x44ba, 0x0024, 0xfee2, + 0x0024, 0x5d8a, 0x1800, 0x4482, 0x4160, 0x48ba, 0x8046, 0x4dc6, 0x1822, + 0x4de6, 0x8047, 0x36f3, 0x0024, 0x36f0, 0x5812, 0xad17, 0x2627, 0x4fde, + 0x9804, 0x4498, 0x1bc0, 0x0000, 0x0024, 0x2803, 0xd155, 0x3a11, 0xa807, + 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, + 0x9803, 0x2000, 0x0000, 0x36f2, 0x9815, 0xb386, 0x40d7, 0x4284, 0x184c, + 0x0000, 0x05c0, 0x2803, 0xdb55, 0xf5d8, 0x3804, 0x0000, 0x0984, 0x6400, + 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, 0x0000, 0x800a, 0x0000, 0x00ce, + 0x2403, 0xde8e, 0xffa4, 0x0024, 0x48b6, 0x0024, 0x0000, 0x0024, 0x2803, + 0xde84, 0x4000, 0x40c2, 0x4224, 0x0024, 0x6090, 0x0024, 0xffa4, 0x0024, + 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, 0xd80d, 0x48b6, 0x0024, 0x0fff, + 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, 0x36f1, 0x180a, 0x4080, 0x184c, + 0x3e13, 0x780f, 0x2803, 0xe2c5, 0x4090, 0xb80e, 0x2403, 0xe240, 0x3e04, + 0x0440, 0x3810, 0x0440, 0x3604, 0x0024, 0x3009, 0x1bce, 0x3603, 0x5bcf, + 0x2000, 0x0000, 0x0000, 0x0024, 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6ac0, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1b40, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x144e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x7140, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x01a4, /*copy 420*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x000d, /*copy 13*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x0728, 0x0746, 0x0006, 0x8006, 0x078e, /*Rle(6)*/ + 0x0006, 0x0027, /*copy 39*/ + 0x0763, 0x0763, 0x0763, 0x0763, 0x0763, 0x0992, 0x0976, 0x097a, 0x097e, + 0x0982, 0x0986, 0x098a, 0x098e, 0x09c1, 0x09c5, 0x09c8, 0x09c8, 0x09c8, + 0x09c8, 0x09d0, 0x09e3, 0x0aae, 0x0a1a, 0x0a1f, 0x0a25, 0x0a2b, 0x0a30, + 0x0a35, 0x0a3a, 0x0a3f, 0x0a44, 0x0a49, 0x0a4e, 0x0a53, 0x0a6c, 0x0a8b, + 0x0aaa, 0x5a82, 0x5a82, 0x0006, 0x8006, 0x0000, /*Rle(6)*/ + 0x0006, 0x0018, /*copy 24*/ + 0x6fb8, 0xc180, 0xc180, 0x6fb8, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a82, + 0x5a82, 0x6fb8, 0xc180, 0xc180, 0x6fb8, 0x0000, 0x0000, 0x5a82, 0x5a82, + 0x5a82, 0x5a82, 0x6fb8, 0xc180, 0xc180, 0x6fb8, 0x0007, 0x0001, /*copy 1*/ + 0x8025, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x5c4e, 0x0007, 0x0001, /*copy 1*/ + 0x5800, 0x0006, 0x0001, /*copy 1*/ + 0x0001, 0x0006, 0x8007, 0x0000, /*Rle(7)*/ + 0x0006, 0x0018, /*copy 24*/ + 0x0002, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, + 0x0000, 0xfffd, 0xffff, 0x0001, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, + 0xfffa, 0xffff, 0x0004, 0x0000, 0xffff, 0xffff, 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 8414 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/patches_flac_latm.h b/targets/esp32/components/VS1053/include/patches_flac_latm.h new file mode 100644 index 00000000..e44ba0ba --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_flac_latm.h @@ -0,0 +1,980 @@ + +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x0558, /*copy 1368*/ + 0x2a00, 0xc000, 0x3e12, 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, + 0x8257, 0x3700, 0x984c, 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, + 0x2910, 0x0181, 0x0000, 0x14c8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, + 0x0195, 0x0000, 0x14c8, 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2245, + 0x3e13, 0x780e, 0x3e11, 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, + 0xb808, 0x003f, 0xe004, 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, + 0x48be, 0x4497, 0x4090, 0x1c46, 0xf06c, 0x0024, 0x2400, 0x1e80, 0x6090, + 0x41c3, 0x6628, 0x1c47, 0x0000, 0x0024, 0x2800, 0x1d49, 0xf07e, 0x0024, + 0xf400, 0x4182, 0x673a, 0x1c46, 0x0000, 0x0024, 0x2800, 0x1e89, 0xf06c, + 0x0024, 0xf400, 0x41c3, 0x0000, 0x0024, 0x4224, 0x3442, 0x2903, 0xf500, + 0x4336, 0x37c3, 0x0000, 0x1805, 0x2903, 0xf500, 0x4508, 0x40c2, 0x450a, + 0x9808, 0x0000, 0x0207, 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, + 0x3d01, 0x5bc1, 0x36f3, 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, + 0x580e, 0x0007, 0x8257, 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, + 0xd428, 0x3c02, 0x0006, 0xc717, 0x2800, 0x2605, 0x4284, 0x0024, 0x3613, + 0x3c02, 0x0006, 0xc357, 0x2901, 0x6280, 0x3e11, 0x5c05, 0x4284, 0x1bc5, + 0x0000, 0x0024, 0x2800, 0x2945, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, + 0x0024, 0x3613, 0x0024, 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, + 0x2900, 0x48c0, 0x0006, 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, + 0x8257, 0x3700, 0x8024, 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x2b51, + 0x3600, 0x9844, 0x2900, 0x3100, 0x0000, 0x2bc8, 0x2911, 0xf140, 0x0000, + 0x0024, 0x0030, 0x0057, 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, + 0xa024, 0x164c, 0x8000, 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, + 0x6d82, 0xd024, 0x44c0, 0x0006, 0xa402, 0x2800, 0x3015, 0xd024, 0x0024, + 0x0000, 0x0000, 0x2800, 0x3015, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, + 0x8024, 0x36f2, 0x1800, 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, + 0x3e13, 0xb80d, 0x3e13, 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, + 0xb807, 0x3e14, 0xf801, 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, + 0xbf8e, 0x9c42, 0x3e01, 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, + 0x8250, 0x0fff, 0xfd85, 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, + 0x2800, 0x3751, 0xf25a, 0x104c, 0x34f3, 0x0024, 0x2800, 0x3751, 0x0000, + 0x0024, 0x3413, 0x084c, 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, + 0x2400, 0x3980, 0x4efa, 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, + 0x4d64, 0x48b2, 0xa201, 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, + 0x36f4, 0xd801, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, + 0xd80a, 0x36f3, 0x980d, 0x2000, 0x0000, 0x36f4, 0x5810, 0x3e12, 0xb817, + 0x3e14, 0xf812, 0x3e01, 0xb811, 0x0007, 0x9717, 0x0020, 0xffd2, 0x0030, + 0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, 0x3b81, 0x8024, 0x3101, 0x8024, + 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, 0x4800, 0x36f1, 0x9811, 0x36f3, + 0x0024, 0x3009, 0x3848, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, + 0x0001, 0x0010, 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, + 0x9e40, 0x3604, 0x1811, 0x3613, 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, + 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, + 0x0024, 0x36f4, 0x1811, 0x3009, 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, + 0x3600, 0x3840, 0x3e13, 0x780e, 0x3e13, 0xf808, 0x3e00, 0x0024, 0x0000, + 0x3fce, 0x0027, 0x9e0f, 0x2922, 0xb680, 0x0000, 0x190d, 0x36f3, 0x0024, + 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, 0x0000, 0x3009, 0x1800, 0x3613, + 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, + 0x3e13, 0x7801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, + 0x3811, 0x3e14, 0xb813, 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, + 0x34e5, 0xc024, 0x3524, 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, + 0x4a0c, 0x3d44, 0x8024, 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, + 0x6010, 0x3400, 0x3710, 0x8024, 0x2800, 0x5484, 0x3af0, 0x8024, 0x3df0, + 0x0024, 0x3591, 0x4024, 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, + 0x4020, 0x1753, 0xbf8e, 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, + 0x528e, 0xfe6d, 0x2819, 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, + 0xad56, 0x904c, 0xaf5e, 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, + 0x2046, 0x3cf4, 0x0024, 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, + 0x2800, 0x4d15, 0x3c00, 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, + 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f3, 0x5801, 0x3405, 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, + 0x9815, 0x2814, 0x9c91, 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, + 0x3e14, 0x3811, 0x0006, 0xa090, 0x2912, 0x0d00, 0x3e14, 0xc024, 0x4088, + 0x8000, 0x4080, 0x0024, 0x0007, 0x90d1, 0x2800, 0x5f85, 0x0000, 0x0024, + 0x0007, 0x9051, 0x3100, 0x4024, 0x4100, 0x0024, 0x3900, 0x0024, 0x0007, + 0x90d1, 0x0004, 0x0000, 0x31f0, 0x4024, 0x6014, 0x0400, 0x0000, 0x0024, + 0x2800, 0x63d1, 0x4080, 0x0024, 0x0000, 0x0000, 0x2800, 0x6345, 0x0000, + 0x0024, 0x0007, 0x9053, 0x3300, 0x0024, 0x4080, 0x0024, 0x0000, 0x0000, + 0x2800, 0x63d8, 0x0000, 0x0024, 0x0007, 0x9051, 0x3900, 0x0024, 0x3200, + 0x504c, 0x6410, 0x0024, 0x3cf0, 0x0000, 0x4080, 0x0024, 0x0006, 0xc691, + 0x2800, 0x7c85, 0x3009, 0x0400, 0x0000, 0x1001, 0x0007, 0x9051, 0x3100, + 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2800, 0x70c9, 0x003f, 0xe000, + 0x0006, 0xc693, 0x3900, 0x0c00, 0x3009, 0x0001, 0x6014, 0x0024, 0x0007, + 0x1ad0, 0x2800, 0x70d5, 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0301, + 0x2800, 0x6ac5, 0x4090, 0x0024, 0x0000, 0x0024, 0x2800, 0x6bd5, 0x0000, + 0x0024, 0x3009, 0x0000, 0xc012, 0x0024, 0x2800, 0x70c0, 0x3009, 0x2001, + 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, 0x0341, 0x2800, 0x6dd5, 0x0000, + 0x0024, 0x6190, 0x0024, 0x2800, 0x70c0, 0x3009, 0x2000, 0x6012, 0x0024, + 0x0000, 0x0381, 0x2800, 0x6f95, 0x0000, 0x0024, 0x6190, 0x0024, 0x2800, + 0x70c0, 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, 0x00c0, 0x2800, 0x70d5, + 0x0000, 0x0024, 0x3009, 0x2000, 0x0006, 0xa090, 0x3009, 0x0000, 0x4080, + 0x0024, 0x0000, 0x0081, 0x2800, 0x7595, 0x0007, 0x8c13, 0x3300, 0x104c, + 0xb010, 0x0024, 0x0002, 0x8001, 0x2800, 0x7805, 0x34f0, 0x0024, 0x2800, + 0x7580, 0x0000, 0x0024, 0x0006, 0xc351, 0x3009, 0x0000, 0x6090, 0x0024, + 0x3009, 0x2000, 0x2900, 0x0b80, 0x3009, 0x0405, 0x0006, 0xc6d1, 0x0006, + 0xc690, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, 0x0006, 0xa093, + 0x2800, 0x7411, 0xb880, 0x0024, 0x2800, 0x8540, 0x3009, 0x2c00, 0x4040, + 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2800, 0x8558, 0x0000, 0x0024, + 0x0006, 0xc693, 0x3009, 0x0c00, 0x3009, 0x0001, 0x6014, 0x0024, 0x0006, + 0xc350, 0x2800, 0x8541, 0x0000, 0x0024, 0x6090, 0x0024, 0x3009, 0x2c00, + 0x3009, 0x0005, 0x2900, 0x0b80, 0x0000, 0x8548, 0x3009, 0x0400, 0x4080, + 0x0024, 0x0003, 0x8000, 0x2800, 0x8545, 0x0000, 0x0024, 0x6400, 0x0024, + 0x0000, 0x0081, 0x2800, 0x8549, 0x0000, 0x0024, 0x0007, 0x8c13, 0x3300, + 0x0024, 0xb010, 0x0024, 0x0006, 0xc650, 0x2800, 0x8555, 0x0000, 0x0024, + 0x0001, 0x0002, 0x3413, 0x0000, 0x3009, 0x0401, 0x4010, 0x8406, 0x0000, + 0x0281, 0xa010, 0x13c1, 0x4122, 0x0024, 0x0000, 0x03c2, 0x6122, 0x8002, + 0x462c, 0x0024, 0x469c, 0x0024, 0xfee2, 0x0024, 0x48be, 0x0024, 0x6066, + 0x8400, 0x0006, 0xc350, 0x2800, 0x8541, 0x0000, 0x0024, 0x4090, 0x0024, + 0x3009, 0x2400, 0x2900, 0x0b80, 0x3009, 0x0005, 0x0007, 0x1b50, 0x2912, + 0x0d00, 0x3613, 0x0024, 0x3a00, 0x0380, 0x4080, 0x0024, 0x0000, 0x00c1, + 0x2800, 0x8e05, 0x3009, 0x0000, 0xb010, 0x008c, 0x4192, 0x0024, 0x6012, + 0x0024, 0x0006, 0xf051, 0x2800, 0x8c18, 0x3009, 0x0400, 0x0007, 0x1fd1, + 0x30e3, 0x0400, 0x4080, 0x0024, 0x0000, 0x0301, 0x2800, 0x8e05, 0x3009, + 0x0000, 0xb010, 0x0024, 0x0000, 0x0101, 0x6012, 0x0024, 0x0006, 0xf051, + 0x2800, 0x8e15, 0x0000, 0x0024, 0x3023, 0x0400, 0xf200, 0x184c, 0xb880, + 0xa400, 0x3009, 0x2000, 0x3009, 0x0441, 0x3e10, 0x4402, 0x2909, 0xa9c0, + 0x3e10, 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x1811, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, 0x0081, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0xf250, 0x3e04, 0xb813, + 0x3009, 0x0000, 0x6012, 0x0024, 0x003f, 0xff01, 0x2800, 0x9905, 0x0006, + 0x0611, 0x6194, 0x0400, 0x0000, 0x0041, 0xa020, 0x984c, 0x0000, 0x01c2, + 0xfe02, 0x0024, 0x48b2, 0x0024, 0x3e10, 0x0024, 0x2921, 0xca80, 0x3e00, + 0x4024, 0x3100, 0x5bcc, 0x2921, 0xdd40, 0xb122, 0x0024, 0x291a, 0x8a40, + 0x0000, 0xab08, 0x0007, 0x2052, 0x0006, 0x8a93, 0x3100, 0x184c, 0xa010, + 0x0024, 0x0000, 0x0041, 0x6090, 0x0024, 0x2922, 0x1880, 0x6090, 0x0024, + 0xb880, 0x010c, 0x3100, 0x2800, 0xfe02, 0x8c44, 0x3613, 0x0fc5, 0x4eb2, + 0x0024, 0x3009, 0x2040, 0x0000, 0x00c0, 0x2921, 0xbb80, 0x3e00, 0x23c1, + 0x0000, 0x01c1, 0x6012, 0x0024, 0x0003, 0xf680, 0x2800, 0x9f55, 0x0000, + 0x0024, 0x36f3, 0x0024, 0x291a, 0x8a40, 0x0000, 0xab08, 0x2900, 0x4580, + 0x3e00, 0x0024, 0x3413, 0x0040, 0x36f3, 0x03c1, 0x3009, 0x0c44, 0x3009, + 0x0fc5, 0x6ce2, 0x0024, 0x3c10, 0x0024, 0xbc82, 0x33c1, 0x3410, 0x2040, + 0x34e0, 0x63c1, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2800, 0xa809, 0x4c82, + 0x0024, 0x0000, 0x01c4, 0x4c86, 0x184c, 0x003f, 0xff40, 0xad06, 0x0024, + 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, 0xc024, 0x36f3, 0x0024, 0x2921, + 0x9440, 0x0000, 0x0080, 0xb88a, 0x104c, 0x3410, 0x0c46, 0x34e0, 0x4fc7, + 0xbce2, 0x984c, 0x4cf2, 0x0024, 0x3e10, 0x0024, 0x2921, 0x9780, 0x3e00, + 0x4024, 0x2800, 0xaa00, 0x36e3, 0x0024, 0x0000, 0x0024, 0x2800, 0xaa18, + 0x0000, 0x0024, 0x4ce6, 0x184c, 0x3e10, 0x8024, 0x2921, 0x9780, 0x3e00, + 0xc024, 0x36e3, 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2922, 0x1880, + 0x3613, 0x0024, 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, + 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x7802, 0x3e14, 0x0024, 0x2903, 0x9bc0, 0x0000, 0x0201, 0x0000, + 0x0601, 0x3413, 0x184c, 0x2903, 0xa300, 0x3cf0, 0x0024, 0x3413, 0x184c, + 0x3400, 0x3040, 0x3009, 0x33c1, 0x0000, 0x1fc1, 0xb010, 0x0024, 0x6014, + 0x9040, 0x0006, 0x8010, 0x2800, 0xb495, 0x0000, 0x0024, 0x34e3, 0x1bcc, + 0x6890, 0x0024, 0x2800, 0xb640, 0xb880, 0x2000, 0x3e10, 0x1381, 0x2903, + 0xd400, 0x3e00, 0x4024, 0x003f, 0xfe41, 0x36e3, 0x104c, 0x34f0, 0x0024, + 0xa010, 0x0024, 0x36f4, 0x0024, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x0006, 0x9f97, + 0x3e00, 0x5c15, 0x3009, 0x3840, 0x3009, 0x3814, 0x0025, 0xffd4, 0x0006, + 0xd317, 0x3710, 0x160c, 0x0006, 0x9f94, 0x37f0, 0x73d5, 0x6c92, 0x0024, + 0x3f10, 0x1040, 0x3ff0, 0x53c1, 0x6010, 0x0024, 0x0000, 0x0024, 0x2800, + 0xbc54, 0x0006, 0x0001, 0x4010, 0x0024, 0x0005, 0xf601, 0x6010, 0x9bd4, + 0x0000, 0x0040, 0x2800, 0xbdd4, 0x0030, 0x0497, 0x3f00, 0x0024, 0x2000, + 0x0000, 0x36f0, 0x5800, 0x2a08, 0x1b8e, 0x2803, 0xae80, 0x0000, 0xbe57, + 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x19f8, /*copy 6648*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x6257, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x58ce, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x4d86, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdd55, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xdc0e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x0948, 0x0039, + 0x324f, 0x0001, 0x364e, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x0019, 0x9301, 0x2800, 0xdfc0, + 0x0018, 0x50c0, 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, 0xe155, 0x0000, + 0x0024, 0x2803, 0x5840, 0x000a, 0xcac8, 0x000a, 0x8c8f, 0x0000, 0xe28e, + 0x000c, 0x0981, 0x280a, 0x71c0, 0x002c, 0x9d40, 0x000a, 0x708f, 0x0000, + 0xd7ce, 0x280a, 0xc0d5, 0x0012, 0x5182, 0x6fd6, 0x0024, 0x003f, 0xfd81, + 0x280a, 0x8e45, 0xb710, 0x0024, 0x003f, 0xf800, 0xb600, 0x0024, 0x0015, + 0xb801, 0x6012, 0x0024, 0x003f, 0xfd81, 0x2801, 0xbac5, 0x0001, 0x0a48, + 0xb710, 0x0024, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, + 0x0015, 0xffd2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x190d, + 0x2801, 0x0015, 0x0030, 0x0250, 0xb880, 0x104c, 0x3cf0, 0x0024, 0x0010, + 0x5500, 0xb880, 0x23c0, 0xb882, 0x2000, 0x0007, 0x8590, 0x2914, 0xbec0, + 0x0000, 0x0440, 0x0007, 0x8b50, 0xb880, 0x0024, 0x2920, 0x0100, 0x3800, + 0x0024, 0x2920, 0x0000, 0x0006, 0x8a91, 0x0000, 0x0800, 0xb880, 0xa440, + 0x003f, 0xfd81, 0xb710, 0xa7c0, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, + 0x0101, 0x2801, 0x0955, 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, + 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x0955, 0x0000, 0x0024, 0x2912, + 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0006, 0x8a90, 0x2801, 0x0955, + 0x0000, 0x01c2, 0xb886, 0x8040, 0x3613, 0x03c1, 0xbcd2, 0x0024, 0x0030, + 0x0011, 0x2800, 0xf5d5, 0x003f, 0xff42, 0xb886, 0x8040, 0x3009, 0x03c1, + 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0102, 0x6cd2, 0x0024, 0x3e10, + 0x0024, 0x2909, 0x8c80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3e11, 0x8024, + 0x3e01, 0xc024, 0x2901, 0x2d00, 0x0000, 0x0201, 0xf400, 0x4512, 0x2900, + 0x0c80, 0x3213, 0x1b8c, 0x3100, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2801, 0x0955, 0x0000, 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2920, + 0x0200, 0x3633, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, 0x408e, 0x0024, + 0x2920, 0x0280, 0x0000, 0x0401, 0x003f, 0xfd81, 0xb710, 0x4006, 0x003f, + 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x0955, 0x0000, 0x0024, + 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, + 0x0955, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, + 0x0000, 0x01c2, 0x2800, 0xf1c5, 0x0006, 0x8a90, 0x2a01, 0x0940, 0x2920, + 0x0100, 0x0000, 0x0401, 0x0000, 0x0180, 0x2920, 0x0200, 0x3613, 0x0024, + 0x2920, 0x0280, 0x3613, 0x0024, 0x0000, 0x0401, 0x2920, 0x0280, 0x4084, + 0x984c, 0x0019, 0x9d01, 0x6212, 0x0024, 0x001e, 0x5c01, 0x2801, 0x0495, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x0685, 0x0000, 0x0024, 0x001b, + 0x5bc1, 0x6212, 0x0024, 0x001b, 0xdd81, 0x2801, 0x0a55, 0x6012, 0x0024, + 0x0000, 0x0024, 0x2801, 0x0a55, 0x0000, 0x0024, 0x0000, 0x004d, 0x000a, + 0xbf4f, 0x280a, 0xb880, 0x0001, 0x078e, 0x0020, 0xfb4f, 0x0000, 0x190d, + 0x0001, 0x0e8e, 0x2920, 0xf440, 0x3009, 0x2bc1, 0x291a, 0x8a40, 0x36e3, + 0x0024, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xcac0, 0x0000, 0xd7ce, + 0x0030, 0x0017, 0x3700, 0x4024, 0x0000, 0x0200, 0xb102, 0x0024, 0x0000, + 0x00c0, 0x2801, 0x0d85, 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, + 0x0006, 0x0197, 0x0006, 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0000, + 0x190d, 0x000a, 0x708f, 0x280a, 0xc0c0, 0x0000, 0xd7ce, 0x0000, 0x004d, + 0x0020, 0xfe0f, 0x2820, 0xfb40, 0x0001, 0x0f8e, 0x2801, 0x1155, 0x3009, + 0x1000, 0x6012, 0x93cc, 0x0000, 0x0024, 0x2801, 0x2c05, 0x0000, 0x0024, + 0x3413, 0x0024, 0x34b0, 0x0024, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, + 0x1455, 0xb882, 0x0024, 0x3453, 0x0024, 0x3009, 0x13c0, 0x4080, 0x0024, + 0x0000, 0x0200, 0x2801, 0x2c05, 0x0000, 0x0024, 0xb882, 0x130c, 0x0000, + 0x004d, 0x0021, 0x058f, 0x2821, 0x0340, 0x0001, 0x154e, 0x2801, 0x2595, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x2595, 0x0000, 0x0024, 0x34c3, + 0x184c, 0x3e13, 0xb80f, 0xf400, 0x4500, 0x0026, 0x9dcf, 0x0001, 0x194e, + 0x0000, 0xfa0d, 0x2926, 0x8e80, 0x3e10, 0x110c, 0x36f3, 0x0024, 0x2801, + 0x2580, 0x36f3, 0x980f, 0x001c, 0xdd00, 0x001c, 0xd901, 0x6ec2, 0x0024, + 0x001c, 0xdd00, 0x2801, 0x1c55, 0x0018, 0xdbc1, 0x3413, 0x184c, 0xf400, + 0x4500, 0x2926, 0xc640, 0x3e00, 0x13cc, 0x2801, 0x2340, 0x36f3, 0x0024, + 0x6ec2, 0x0024, 0x003f, 0xc000, 0x2801, 0x1ed5, 0x002a, 0x4001, 0x3413, + 0x184c, 0xf400, 0x4500, 0x2926, 0xafc0, 0x3e00, 0x13cc, 0x2801, 0x2340, + 0x36f3, 0x0024, 0xb400, 0x0024, 0xd100, 0x0024, 0x0000, 0x0024, 0x2801, + 0x2345, 0x0000, 0x0024, 0x3613, 0x0024, 0x3e11, 0x4024, 0x2926, 0x8540, + 0x3e01, 0x0024, 0x4080, 0x1b8c, 0x0000, 0x0024, 0x2801, 0x2345, 0x0000, + 0x0024, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0x8e80, 0x3e10, 0x13cc, + 0x36f3, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x0000, 0x4000, 0x0000, + 0x0021, 0x6d06, 0x0024, 0x3110, 0x8024, 0x2826, 0xa8c4, 0x31f0, 0xc024, + 0x2a26, 0xad00, 0x34c3, 0x184c, 0x3410, 0x8024, 0x3430, 0xc024, 0x0000, + 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x0000, 0x0024, 0x2801, 0x2c14, + 0x4d06, 0x0024, 0x0000, 0x0200, 0x2922, 0x1885, 0x0001, 0x2a88, 0x0000, + 0x0200, 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, 0xc024, 0x291a, 0x8a40, + 0x0000, 0x0024, 0x2922, 0x1880, 0x36f3, 0x0024, 0x0000, 0x004d, 0x0021, + 0x0ecf, 0x2821, 0x0bc0, 0x0001, 0x2b8e, 0x2801, 0x0e80, 0x3c30, 0x4024, + 0x0000, 0x190d, 0x0000, 0x3fce, 0x2821, 0x0f80, 0x0027, 0x9e0f, 0x0020, + 0xcd4f, 0x2820, 0xc780, 0x0001, 0x2dce, 0x0006, 0xf017, 0x0000, 0x0015, + 0xb070, 0xbc15, 0x0000, 0x3fce, 0x0027, 0x9e0f, 0x2820, 0xcd80, 0x0000, + 0x190d, 0x3613, 0x0024, 0x3e10, 0xb803, 0x3e14, 0x3811, 0x3e11, 0x3805, + 0x3e00, 0x3801, 0x0007, 0xc390, 0x0006, 0xa011, 0x3010, 0x0444, 0x3050, + 0x4405, 0x6458, 0x0302, 0xff94, 0x4081, 0x0003, 0xffc5, 0x48b6, 0x0024, + 0xff82, 0x0024, 0x42b2, 0x0042, 0xb458, 0x0003, 0x4cd6, 0x9801, 0xf248, + 0x1bc0, 0xb58a, 0x0024, 0x6de6, 0x1804, 0x0006, 0x0010, 0x3810, 0x9bc5, + 0x3800, 0xc024, 0x36f4, 0x1811, 0x36f0, 0x9803, 0x283e, 0x2d80, 0x0fff, + 0xffc3, 0x2801, 0x4400, 0x0000, 0x0024, 0x3413, 0x0024, 0x2801, 0x3805, + 0xf400, 0x4517, 0x2801, 0x3c00, 0x6894, 0x13cc, 0x37b0, 0x184c, 0x6090, + 0x1d51, 0x0000, 0x0910, 0x3f00, 0x060c, 0x3100, 0x4024, 0x6016, 0xb812, + 0x000c, 0x8012, 0x2801, 0x3a91, 0xb884, 0x0024, 0x6894, 0x3002, 0x0000, + 0x028d, 0x003a, 0x5e0f, 0x0001, 0x4c0e, 0x2939, 0xb0c0, 0x3e10, 0x93cc, + 0x4084, 0x9bd2, 0x4282, 0x0024, 0x0000, 0x0040, 0x2801, 0x3e05, 0x4292, + 0x130c, 0x3443, 0x0024, 0x2801, 0x3f45, 0x000c, 0x8390, 0x2a01, 0x42c0, + 0x3444, 0x0024, 0x3073, 0x0024, 0xc090, 0x014c, 0x2801, 0x42c0, 0x3800, + 0x0024, 0x000c, 0x4113, 0xb880, 0x2380, 0x3304, 0x4024, 0x3800, 0x05cc, + 0xcc92, 0x05cc, 0x3910, 0x0024, 0x3910, 0x4024, 0x000c, 0x8110, 0x3910, + 0x0024, 0x39f0, 0x4024, 0x3810, 0x0024, 0x38d0, 0x4024, 0x3810, 0x0024, + 0x38f0, 0x4024, 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, + 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, + 0x4284, 0x0024, 0x3613, 0x0024, 0x2801, 0x4605, 0x6898, 0xb804, 0x0000, + 0x0084, 0x293b, 0x1cc0, 0x3613, 0x0024, 0x000c, 0x8117, 0x3711, 0x0024, + 0x37d1, 0x4024, 0x4e8a, 0x0024, 0x0000, 0x0015, 0x2801, 0x48c5, 0xce9a, + 0x0024, 0x3f11, 0x0024, 0x3f01, 0x4024, 0x000c, 0x8197, 0x408a, 0x9bc4, + 0x3f15, 0x4024, 0x2801, 0x4b05, 0x4284, 0x3c15, 0x6590, 0x0024, 0x0000, + 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x0000, 0x0024, 0x2801, 0x36d8, + 0x458a, 0x0024, 0x2a39, 0x53c0, 0x003e, 0x2d4f, 0x283a, 0x5ed5, 0x0001, + 0x2f8e, 0x000c, 0x4653, 0x0000, 0x0246, 0xffac, 0x0c01, 0x48be, 0x0024, + 0x4162, 0x4546, 0x6642, 0x4055, 0x3501, 0x8024, 0x0000, 0x0087, 0x667c, + 0x4057, 0x000c, 0x41d5, 0x283a, 0x62d5, 0x3501, 0x8024, 0x667c, 0x1c47, + 0x3701, 0x8024, 0x283a, 0x62d5, 0xc67c, 0x0024, 0x0000, 0x0024, 0x283a, + 0x62c5, 0x0000, 0x0024, 0x2a3a, 0x5ec0, 0x3009, 0x3851, 0x3e14, 0xf812, + 0x3e12, 0xb817, 0x3e11, 0x8024, 0x0006, 0x0293, 0x3301, 0x8024, 0x468c, + 0x3804, 0x0006, 0xa057, 0x2801, 0x5804, 0x0006, 0x0011, 0x469c, 0x0024, + 0x3be1, 0x8024, 0x2801, 0x5815, 0x0006, 0xc392, 0x3311, 0x0024, 0x33f1, + 0x2844, 0x3009, 0x2bc4, 0x0030, 0x04d2, 0x3311, 0x0024, 0x3a11, 0x0024, + 0x3201, 0x8024, 0x003f, 0xfc04, 0xb64c, 0x0fc4, 0xc648, 0x0024, 0x3a01, + 0x0024, 0x3111, 0x1fd3, 0x6498, 0x07c6, 0x868c, 0x2444, 0x0023, 0xffd2, + 0x3901, 0x8e06, 0x0030, 0x0551, 0x3911, 0x8e06, 0x3961, 0x9c44, 0xf400, + 0x44c6, 0xd46c, 0x1bc4, 0x36f1, 0xbc13, 0x2801, 0x6195, 0x36f2, 0x9817, + 0x002b, 0xffd2, 0x3383, 0x188c, 0x3e01, 0x8c06, 0x0006, 0xa097, 0x3009, + 0x1c12, 0x3213, 0x0024, 0x468c, 0xbc12, 0x002b, 0xffd2, 0xf400, 0x4197, + 0x2801, 0x5e84, 0x3713, 0x0024, 0x2801, 0x5ec5, 0x37e3, 0x0024, 0x3009, + 0x2c17, 0x3383, 0x0024, 0x3009, 0x0c06, 0x468c, 0x4197, 0x0006, 0xa052, + 0x2801, 0x60c4, 0x3713, 0x2813, 0x2801, 0x6105, 0x37e3, 0x0024, 0x3009, + 0x2c17, 0x36f1, 0x8024, 0x36f2, 0x9817, 0x36f4, 0xd812, 0x2100, 0x0000, + 0x3904, 0x5bd1, 0x2a01, 0x51ce, 0x3e11, 0x7804, 0x0030, 0x0257, 0x3701, + 0x0024, 0x0013, 0x4d05, 0xd45b, 0xe0e1, 0x0007, 0xc795, 0x2801, 0x6915, + 0x0fff, 0xff45, 0x3511, 0x184c, 0x4488, 0xb808, 0x0006, 0x8a97, 0x2801, + 0x68c5, 0x3009, 0x1c40, 0x3511, 0x1fc1, 0x0000, 0x0020, 0xac52, 0x1405, + 0x6ce2, 0x0024, 0x0000, 0x0024, 0x2801, 0x68c1, 0x68c2, 0x0024, 0x291a, + 0x8a40, 0x3e10, 0x0024, 0x2921, 0xca80, 0x3e00, 0x4024, 0x36f3, 0x0024, + 0x3009, 0x1bc8, 0x36f0, 0x1801, 0x3601, 0x5804, 0x3e13, 0x780f, 0x3e13, + 0xb808, 0x0008, 0x9b0f, 0x0001, 0x6bce, 0x2908, 0x9300, 0x0000, 0x004d, + 0x36f3, 0x9808, 0x2000, 0x0000, 0x36f3, 0x580f, 0x0007, 0x81d7, 0x3711, + 0x8024, 0x3711, 0xc024, 0x3700, 0x0024, 0x0000, 0x2001, 0xb012, 0x0024, + 0x0034, 0x0000, 0x2801, 0x6f05, 0x0000, 0x01c1, 0x0030, 0x0117, 0x3f00, + 0x0024, 0x0014, 0xc000, 0x0000, 0x01c1, 0x4fce, 0x0024, 0xffea, 0x0024, + 0x48b6, 0x0024, 0x4384, 0x4097, 0xb886, 0x45c6, 0xfede, 0x0024, 0x4db6, + 0x0024, 0x466c, 0x0024, 0x0006, 0xc610, 0x8dd6, 0x8007, 0x0000, 0x00c6, + 0xff6e, 0x0024, 0x48b2, 0x0024, 0x0034, 0x2406, 0xffee, 0x0024, 0x2914, + 0xaa80, 0x40b2, 0x0024, 0xf1c6, 0x0024, 0xf1d6, 0x0024, 0x0000, 0x0201, + 0x8d86, 0x0024, 0x61de, 0x0024, 0x0006, 0xc612, 0x2801, 0x7581, 0x0006, + 0xc713, 0x4c86, 0x0024, 0x2912, 0x1180, 0x0006, 0xc351, 0x0006, 0x0210, + 0x2912, 0x0d00, 0x3810, 0x984c, 0xf200, 0x2043, 0x2808, 0xa000, 0x3800, + 0x0024, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, + 0x7810, 0x3e14, 0x7812, 0x3e14, 0xc024, 0x2922, 0x1880, 0x0000, 0x0180, + 0x2921, 0xdd40, 0x6892, 0x184c, 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, + 0x7cc5, 0x0000, 0x0024, 0x2801, 0xb840, 0xb880, 0x0024, 0x2921, 0xdd40, + 0x6892, 0x184c, 0x4080, 0x0024, 0x0000, 0x0181, 0x2801, 0x7ed5, 0x0000, + 0x0024, 0x2801, 0xb840, 0xb880, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0101, 0x2801, 0x80c5, 0x0000, 0x0024, 0x2801, + 0xb840, 0xb880, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, + 0x0000, 0x00c1, 0x2801, 0x82c5, 0x0000, 0x0024, 0x2801, 0xb840, 0xb880, + 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, 0x0000, 0x0141, + 0x2801, 0x84c5, 0x0006, 0xf250, 0x2801, 0xb840, 0xb880, 0x0024, 0x2921, + 0xdd40, 0x3613, 0x0024, 0x0000, 0x0101, 0x2921, 0xdd40, 0x3613, 0x2000, + 0x0000, 0x03c1, 0x6012, 0x03cc, 0x3613, 0x2000, 0x2801, 0x8a15, 0x0006, + 0xf051, 0x3009, 0x3841, 0x2921, 0xdd40, 0x0000, 0x0201, 0xb080, 0x024c, + 0x3009, 0x2000, 0x2921, 0xdd40, 0x0000, 0x0401, 0x3009, 0x0401, 0xc100, + 0x0024, 0x2801, 0x8b40, 0x3009, 0x2400, 0x3009, 0x0002, 0x2920, 0x5d00, + 0x3e00, 0x8024, 0x36f3, 0x024c, 0x3009, 0x2000, 0x0000, 0x0101, 0x2921, + 0xdd40, 0x3613, 0x0024, 0x0000, 0x0141, 0x3013, 0x0024, 0x3009, 0x21c0, + 0x3009, 0x0000, 0x6012, 0x0024, 0x0007, 0x1b51, 0x2801, 0x9c95, 0x0000, + 0x0101, 0x0007, 0xc251, 0x2921, 0xdd40, 0x3613, 0x0024, 0x0000, 0x03c1, + 0x6012, 0x2400, 0x3100, 0x984c, 0x2801, 0x93d5, 0x0007, 0xc292, 0x3009, + 0x3841, 0x2921, 0xdd40, 0x0000, 0x0201, 0x4082, 0x044c, 0xb080, 0x0024, + 0x3910, 0x0024, 0x39f0, 0x7841, 0x2921, 0xdd40, 0x0000, 0x0401, 0x3211, + 0x1bcc, 0xb182, 0x0bc5, 0xcec2, 0x0024, 0x3a10, 0x0024, 0x2801, 0x9500, + 0x3af0, 0x4024, 0x2920, 0x5d00, 0x3e00, 0x8024, 0x36f3, 0x044c, 0x3910, + 0x0024, 0x39f0, 0x4024, 0x0007, 0x1b52, 0x0000, 0x0141, 0x2921, 0xdd40, + 0x3613, 0x0024, 0x3111, 0x2240, 0xb880, 0x03cc, 0x31f1, 0x6800, 0xb182, + 0x8000, 0x6ce6, 0x0024, 0x002e, 0xe002, 0x2801, 0xa385, 0xb886, 0x0024, + 0x6de2, 0x0b8c, 0x0000, 0x00c1, 0x2801, 0x9b51, 0x3009, 0x0800, 0xb010, + 0x0024, 0x4192, 0x0024, 0x6012, 0x0024, 0x0007, 0x1b52, 0x2801, 0x9b58, + 0x0000, 0x0024, 0x6890, 0xa004, 0x2801, 0xa380, 0x3009, 0x2800, 0x4e82, + 0x0024, 0x0000, 0x0020, 0xf2c2, 0x0024, 0x2801, 0xa380, 0x3009, 0x2000, + 0x3009, 0x07c0, 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, 0xa385, 0x0000, + 0x0024, 0x3093, 0x0400, 0x4080, 0x03cc, 0x0017, 0x7001, 0x2801, 0xa295, + 0x3009, 0x0000, 0x6012, 0x0024, 0x0007, 0x1b50, 0x2801, 0xa201, 0xb880, + 0x0024, 0x0000, 0x00c1, 0x31f3, 0x0024, 0x3009, 0x0400, 0xb010, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0000, 0x2801, 0xa289, 0x0000, 0x0024, 0x2801, + 0xa380, 0x3009, 0x2000, 0x0006, 0xf050, 0x3009, 0x0000, 0x4000, 0x0024, + 0x3009, 0x2000, 0x0000, 0x0081, 0x0006, 0xf250, 0x3009, 0x0000, 0x6012, + 0x0024, 0x0007, 0xc151, 0x2801, 0xa5c5, 0x0000, 0x0024, 0x2801, 0xb840, + 0xb880, 0x0024, 0x2921, 0xdd40, 0x6892, 0x184c, 0x6892, 0x2400, 0x2921, + 0xdd40, 0x3009, 0x184c, 0x4080, 0x0024, 0x0000, 0x0381, 0x2801, 0xa885, + 0x0000, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x2921, 0xdd40, 0x6892, + 0x184c, 0x4080, 0x0024, 0x0000, 0x0240, 0x2801, 0xab05, 0x0000, 0x00c1, + 0x2921, 0xdd40, 0x6892, 0x184c, 0x0000, 0x00c1, 0x0000, 0x0240, 0x0006, + 0x0592, 0x2922, 0x1880, 0x3613, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x4080, 0x2800, 0x0000, 0x0201, 0x2801, 0xae15, 0x3613, 0x0024, 0x2921, + 0xdd40, 0x0001, 0xb088, 0x3613, 0x0024, 0x4090, 0x1bcc, 0x0000, 0x0241, + 0x2801, 0xb015, 0x0006, 0x0613, 0x2921, 0xdd40, 0x3613, 0x0024, 0x2801, + 0xb080, 0x3b00, 0x0024, 0x2801, 0xb840, 0xb880, 0x0024, 0x0006, 0x0653, + 0xb880, 0x184c, 0x2921, 0xdd40, 0x6892, 0x2c00, 0x4080, 0x0024, 0x0006, + 0x0650, 0x2801, 0xb605, 0x0000, 0x4003, 0x3000, 0x184c, 0xff86, 0x0024, + 0x48b6, 0x0024, 0x2921, 0xdd40, 0x6892, 0x2002, 0x0000, 0x0201, 0x2921, + 0xdd40, 0x4088, 0x184c, 0x3000, 0x4024, 0x4100, 0x0024, 0x4488, 0x2000, + 0x0000, 0x4003, 0x2801, 0xb295, 0x0006, 0x0650, 0x2921, 0xdd40, 0x6892, + 0x184c, 0x4080, 0x0024, 0x0000, 0x0201, 0x2801, 0xb805, 0x0000, 0x0024, + 0x2921, 0xdd40, 0x3613, 0x0024, 0x6890, 0x0024, 0x36f4, 0xc024, 0x36f4, + 0x5812, 0x36f1, 0x5810, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e14, 0x3811, 0x0006, + 0x8a91, 0x0006, 0x05d0, 0x3e14, 0xb813, 0x0007, 0x8b52, 0x3e13, 0xf80e, + 0x3e03, 0x504c, 0xb880, 0x0024, 0x3c00, 0x33c0, 0x2921, 0xb380, 0x3800, + 0x0024, 0x2920, 0x6a00, 0x0030, 0x0253, 0x0000, 0x0400, 0xb882, 0xa440, + 0xb880, 0xa7c1, 0x3a00, 0x0024, 0x0013, 0x1040, 0x3b00, 0x0024, 0x0000, + 0x0180, 0x2922, 0x1880, 0x3613, 0x0024, 0x4f82, 0x0024, 0x003f, 0xf801, + 0xb010, 0x0024, 0x0015, 0xb801, 0x6012, 0x0024, 0x0007, 0x8a50, 0x2801, + 0xdfd5, 0x0000, 0x0201, 0x0006, 0x8a90, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x003f, 0xfe00, 0x3613, 0x0042, 0xb882, 0x83c3, 0xbdc2, 0x0024, 0x3009, + 0x2040, 0x2921, 0xdd40, 0x6892, 0xa3c1, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2801, 0xca95, 0x0000, 0x0024, 0x2901, 0x7780, 0x0006, 0x05d1, 0x4080, + 0x2400, 0x0006, 0xf052, 0x2801, 0xca85, 0x0000, 0x0024, 0x3613, 0x0841, + 0x3e10, 0x4802, 0x2909, 0xa9c0, 0x3e10, 0x8024, 0x36e3, 0x0024, 0x0006, + 0x05d1, 0x3100, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2921, 0xc305, + 0x0001, 0xdb48, 0x0006, 0x0592, 0xb880, 0x104c, 0x3613, 0x33c0, 0x2922, + 0x1880, 0x0000, 0x0100, 0x3200, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2900, 0x90d5, 0x0001, 0xd3c8, 0x0006, 0x0613, 0xb880, 0x0024, 0x0006, + 0x0610, 0x3b00, 0x0024, 0x0000, 0x0201, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x0000, 0x00c1, 0x3423, 0x0024, 0x3c00, 0x0024, 0xa010, 0x0001, 0x4100, + 0x0024, 0x0000, 0x3fc1, 0x3800, 0x0024, 0x34e0, 0x0024, 0x6012, 0x0024, + 0x0006, 0x0610, 0x2801, 0xcf85, 0x0000, 0x0024, 0x2900, 0x90c0, 0x0000, + 0x0024, 0x0006, 0x0650, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2801, 0xdac5, 0x0000, 0x0024, 0xf200, 0x184c, 0xf200, 0x0024, 0xf200, + 0x0024, 0xb182, 0x3840, 0x2921, 0xca80, 0x3e00, 0x4024, 0x0000, 0x01c1, + 0x291a, 0x8a40, 0x36e3, 0x0024, 0xb888, 0x4411, 0x3000, 0x0024, 0xb012, + 0x0024, 0x6410, 0x2001, 0x0000, 0x0024, 0x2801, 0xdac1, 0x0000, 0x0024, + 0x4192, 0x0024, 0x2401, 0xda81, 0x0000, 0x0024, 0x2921, 0xdd40, 0x6892, + 0x184c, 0x6498, 0x0024, 0x2921, 0xc300, 0x0000, 0x0024, 0x291a, 0x8a40, + 0x3413, 0x0024, 0xf400, 0x4512, 0x0030, 0x0010, 0x0000, 0x0201, 0x2900, + 0x0c80, 0x34f3, 0x0024, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0100, + 0x2801, 0xec95, 0x0000, 0x0401, 0x2922, 0x1880, 0x3613, 0x0024, 0x2921, + 0xdd40, 0x3613, 0x0024, 0x2801, 0xeac0, 0xb78e, 0x4006, 0x3000, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, 0xec89, 0xf292, 0x0024, 0x6012, + 0x904c, 0x0006, 0x05d1, 0x2801, 0xe318, 0x3100, 0x0024, 0x3000, 0x0024, + 0x4090, 0x0024, 0x3800, 0x0024, 0x3100, 0x0024, 0x4080, 0x4512, 0x34f3, + 0x184c, 0x2801, 0xe5d5, 0x0007, 0x0553, 0x36f3, 0x0800, 0x6090, 0x0024, + 0x4080, 0xa800, 0x0000, 0x0024, 0x2801, 0xec88, 0x0000, 0x0024, 0x3009, + 0x184c, 0x0006, 0xf312, 0x4ffe, 0xb841, 0x2921, 0xdd40, 0x6892, 0x41c7, + 0xb182, 0x9bcc, 0x291a, 0x8a40, 0xcfce, 0x0024, 0x0004, 0x0001, 0xb880, + 0x010c, 0x6890, 0x2000, 0x0007, 0x80d0, 0xb880, 0xa800, 0x3000, 0x2c00, + 0x0007, 0x1ad0, 0xff82, 0x0024, 0x48b2, 0x0024, 0xf400, 0x4040, 0x0000, + 0x03c1, 0xb010, 0x0024, 0x3009, 0x2000, 0x0000, 0x0201, 0x0030, 0x0010, + 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0180, 0x2801, 0xc1c5, 0x0000, + 0x0024, 0x6890, 0x1bcd, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, + 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, + 0xb804, 0x3e01, 0x534c, 0xbe8a, 0x10c0, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2801, 0xf6c5, 0x0000, 0x0024, 0x2903, 0xa300, 0x4082, 0x184c, 0x4c8a, + 0x134c, 0x0000, 0x0001, 0x6890, 0x10c2, 0x4294, 0x0024, 0xac22, 0x0024, + 0xbec2, 0x0024, 0x0000, 0x0024, 0x2801, 0xf6c5, 0x0000, 0x0024, 0x6890, + 0x134c, 0xb882, 0x10c2, 0xac22, 0x0024, 0x4c92, 0x0024, 0xdc92, 0x0024, + 0xceca, 0x0024, 0x4e82, 0x1bc5, 0x36f0, 0x9804, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3645, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, + 0x3e14, 0x104c, 0x2903, 0x9bc0, 0x0000, 0x0081, 0x4080, 0x3040, 0x0000, + 0x0101, 0x2801, 0xfdc5, 0x0000, 0x0024, 0x4090, 0x0024, 0x0006, 0x8050, + 0x2802, 0x11d5, 0x0000, 0x0024, 0x2903, 0x9bc0, 0x3613, 0x0024, 0xb880, + 0x3000, 0x2802, 0x0f80, 0x3009, 0x3380, 0x2903, 0x9bc0, 0x4122, 0x10cc, + 0x3cf0, 0x0024, 0x3001, 0x0024, 0x3400, 0x0024, 0x6800, 0x0024, 0xa408, + 0x9040, 0x4080, 0x0024, 0x0000, 0x07c1, 0x2802, 0x0355, 0x6894, 0x1380, + 0x6894, 0x130c, 0x3460, 0x0024, 0x6408, 0x4481, 0x4102, 0x1380, 0xf400, + 0x4052, 0x0000, 0x07c1, 0x34f0, 0xc024, 0x6234, 0x0024, 0x6824, 0x0024, + 0xa122, 0x0024, 0x6014, 0x0024, 0x0000, 0x0141, 0x2802, 0x0a55, 0x0000, + 0x0024, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x2802, 0x08c0, 0xb88a, 0x4002, + 0x2901, 0xef40, 0x3e00, 0x8024, 0x4c8e, 0xa801, 0x0000, 0x0201, 0x3a10, + 0x1bcc, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, 0x2802, 0x0e55, + 0x659a, 0x0024, 0x6540, 0x184c, 0x0030, 0x0010, 0x2802, 0x0648, 0x0000, + 0x0024, 0x2802, 0x0e40, 0x36f3, 0x0024, 0x2802, 0x0d00, 0xb88a, 0x0024, + 0x2903, 0x74c0, 0x34d0, 0x4024, 0x4c8f, 0xa0a1, 0x0000, 0x0201, 0x3000, + 0x084c, 0xb010, 0x0024, 0x0000, 0x0024, 0x2802, 0x0e55, 0x659a, 0x0024, + 0x6540, 0x10cc, 0x0030, 0x0010, 0x2802, 0x0ac8, 0x0000, 0x0024, 0x34d3, + 0x0024, 0x3423, 0x0024, 0xf400, 0x4510, 0x3009, 0x1380, 0x6090, 0x0024, + 0x3009, 0x2000, 0x6892, 0x108c, 0x34f0, 0x9000, 0xa122, 0x984c, 0x6016, + 0x13c1, 0x0000, 0x0102, 0x2801, 0xff08, 0x0006, 0x8150, 0x2802, 0x1240, + 0x3009, 0x1bcc, 0x6890, 0x938c, 0x3800, 0x0024, 0x36f4, 0x0024, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb804, 0x3e11, 0xb807, 0x3e14, + 0x3811, 0x3e04, 0x934c, 0x3430, 0x0024, 0x4080, 0x0024, 0x0000, 0x0206, + 0x2802, 0x1b45, 0x0006, 0x8151, 0x3101, 0x130c, 0xff0c, 0x1102, 0x6408, + 0x0024, 0x4204, 0x0024, 0xb882, 0x4092, 0x1005, 0xfe02, 0x48be, 0x0024, + 0x4264, 0x0024, 0x2903, 0xe080, 0xf400, 0x4090, 0x36f4, 0x8024, 0x36f4, + 0x1811, 0x36f1, 0x9807, 0x36f0, 0x9804, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3675, 0x0024, + 0x3643, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, 0x0181, 0x3e10, + 0xb803, 0x3e11, 0x3806, 0x3e11, 0xf810, 0x3e14, 0x7812, 0x3e13, 0xf80e, + 0x2903, 0x7dc0, 0x3e03, 0x4024, 0x2903, 0x9bc0, 0x4088, 0x184c, 0x3413, + 0x184c, 0x2903, 0x9bc0, 0x6892, 0x3040, 0x4080, 0x3040, 0x0000, 0x0000, + 0x2802, 0x28c5, 0x0000, 0x0024, 0x6890, 0x0024, 0x2903, 0x7dc0, 0x3cd0, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2802, 0x2915, 0x0000, 0x0024, + 0x3433, 0x0024, 0xf400, 0x4510, 0x34d0, 0x0024, 0x6090, 0x0024, 0x2903, + 0x7dc0, 0x3800, 0x0024, 0x4080, 0x10cc, 0xf400, 0x4510, 0x2802, 0x2685, + 0x34d0, 0x0024, 0x2802, 0x2900, 0x0000, 0x0024, 0x3cd0, 0x0024, 0x3433, + 0x0024, 0x34a0, 0x0024, 0xf400, 0x4510, 0x3430, 0x4024, 0x6100, 0x0024, + 0x0000, 0x0341, 0x3840, 0x0024, 0x3000, 0x0024, 0x6012, 0x0024, 0x0006, + 0x0681, 0x2802, 0x4681, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, + 0x2000, 0x0000, 0x0000, 0x0024, 0x34d3, 0x184c, 0x3430, 0x8024, 0x2901, + 0xef40, 0x3e00, 0x8024, 0x36f3, 0x11cc, 0xb888, 0x104c, 0x3c10, 0x0024, + 0x3c90, 0x4024, 0x2802, 0x3240, 0x34e3, 0x0024, 0x3411, 0x8024, 0x3491, + 0xc024, 0x4f82, 0x128c, 0x3400, 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, + 0x3800, 0x0024, 0x3440, 0x4024, 0x4142, 0x0024, 0x6498, 0x4050, 0x3009, + 0x2007, 0x0006, 0x8150, 0x3000, 0x11cc, 0x6402, 0x104c, 0x0000, 0x0024, + 0x2802, 0x2f88, 0x0000, 0x0024, 0x3493, 0x0024, 0x2802, 0x6240, 0x34f3, + 0x0024, 0x2802, 0x39c0, 0xb888, 0x0024, 0x3430, 0x8024, 0x2901, 0xef40, + 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, 0x5bcc, 0x4142, 0x0024, 0xf400, + 0x4050, 0x3800, 0x0024, 0x3440, 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, + 0x0000, 0x0201, 0x3009, 0x2007, 0x0030, 0x0010, 0x3000, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2802, 0x6255, 0x6498, 0x0024, 0x0006, 0x8150, + 0x3000, 0x134c, 0x6402, 0x984c, 0x0000, 0x0024, 0x2802, 0x3508, 0x0000, + 0x0024, 0x2802, 0x6240, 0x3433, 0x1bcc, 0x0000, 0x0201, 0xb888, 0x104c, + 0x3430, 0x184c, 0x6010, 0x0024, 0x6402, 0x3000, 0x0000, 0x0201, 0x2802, + 0x4258, 0x0030, 0x0010, 0x4090, 0x124c, 0x2402, 0x4140, 0x0000, 0x0024, + 0x3430, 0x8024, 0x2901, 0xef40, 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, + 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, 0x3800, 0x0024, 0x3410, 0x4024, + 0x4142, 0x0024, 0x6498, 0x4050, 0x3009, 0x2007, 0x0030, 0x0010, 0x0000, + 0x0201, 0x3473, 0x0024, 0x3490, 0x0024, 0x3e00, 0x13cc, 0x2901, 0xf880, + 0x3444, 0x8024, 0x3000, 0x1bcc, 0xb010, 0x0024, 0x0000, 0x0024, 0x2802, + 0x6255, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3470, 0x0024, 0x3e10, 0x104c, + 0x34c0, 0x4024, 0x2902, 0x14c0, 0x3e00, 0x4024, 0x2802, 0x6240, 0x36e3, + 0x0024, 0x0000, 0x0801, 0x3413, 0x0024, 0x34f0, 0x0024, 0x6012, 0x0024, + 0x0000, 0x07c1, 0x2802, 0x6188, 0x0000, 0x0024, 0x6010, 0x114c, 0xb888, + 0x32c0, 0x6402, 0x0024, 0x0000, 0x0101, 0x2802, 0x4e18, 0x0000, 0x0024, + 0x4090, 0x134c, 0x2402, 0x4d40, 0x3009, 0x184c, 0x3430, 0x8024, 0x2901, + 0xef40, 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, 0x4024, 0x4142, 0x0024, + 0xf400, 0x4050, 0x3800, 0x0024, 0x3410, 0x4024, 0x4142, 0x0024, 0x6498, + 0x4050, 0x3009, 0x2007, 0x0000, 0x0101, 0x3433, 0x1bcc, 0x2903, 0x9bc0, + 0x3613, 0x0024, 0x0000, 0x0141, 0x6090, 0x118c, 0x2903, 0x9bc0, 0x3ca0, + 0x184c, 0x3473, 0x184c, 0xb888, 0x3380, 0x3400, 0x0024, 0x6402, 0x0024, + 0x0000, 0x0201, 0x2802, 0x54d8, 0x0000, 0x0024, 0x4090, 0x104c, 0x2402, + 0x5400, 0x0000, 0x0024, 0x34a0, 0x8024, 0x2901, 0xef40, 0x3e00, 0x8024, + 0x0006, 0x8002, 0x4244, 0x118c, 0x4244, 0x0024, 0x6498, 0x4095, 0x3009, + 0x3440, 0x3009, 0x37c1, 0x0000, 0x0201, 0x34f3, 0x0024, 0x0030, 0x0010, + 0x3490, 0x0024, 0x3e00, 0x138c, 0x2901, 0xf880, 0x3444, 0x8024, 0x3000, + 0x1bcc, 0xb010, 0x0024, 0x0000, 0x0024, 0x2802, 0x6255, 0x4112, 0x0024, + 0x3463, 0x0024, 0x34a0, 0x0024, 0x6012, 0x0024, 0x0006, 0x8111, 0x2802, + 0x5e19, 0x0000, 0x0024, 0x3100, 0x11cc, 0x3490, 0x4024, 0x4010, 0x0024, + 0x0000, 0x0a01, 0x6012, 0x0024, 0x0006, 0x8151, 0x2802, 0x5e18, 0x0000, + 0x0024, 0x3613, 0x114c, 0x3101, 0x3804, 0x3490, 0x8024, 0x6428, 0x138c, + 0x3470, 0x8024, 0x3423, 0x0024, 0x3420, 0xc024, 0x4234, 0x1241, 0x4380, + 0x4092, 0x2903, 0xe080, 0x0006, 0x8010, 0x2802, 0x6240, 0x3009, 0x1bcc, + 0x0006, 0x8151, 0x3613, 0x114c, 0x3101, 0x3804, 0x3490, 0x8024, 0x6428, + 0x138c, 0x3470, 0x8024, 0x3423, 0x0024, 0x3420, 0xc024, 0x4234, 0x1241, + 0x4380, 0x4092, 0x2903, 0xea40, 0x0006, 0x8010, 0x2802, 0x6240, 0x3009, + 0x1bcc, 0x0006, 0x8050, 0x6890, 0x0024, 0x3800, 0x0024, 0x3433, 0x0024, + 0x34d0, 0x0024, 0x4080, 0x0024, 0x0006, 0x8150, 0x2802, 0x67c5, 0x0000, + 0x0024, 0x3000, 0x11cc, 0xb888, 0x10cc, 0x6402, 0x3240, 0x3493, 0x0024, + 0x3444, 0x8024, 0x2802, 0x67d8, 0x4090, 0x0024, 0x2402, 0x6780, 0x0000, + 0x0024, 0x6499, 0x2620, 0xb78e, 0x4001, 0x0000, 0x0000, 0x3433, 0x0024, + 0xcfce, 0x1340, 0xaf0e, 0x0024, 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x36f4, 0x5812, 0x36f1, 0xd810, 0x36f1, 0x1806, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, + 0xf804, 0x0000, 0x3fc3, 0x3e11, 0x7806, 0x3e11, 0xf810, 0xbc82, 0x12cc, + 0x3404, 0x0024, 0x3023, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x3454, + 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x2903, 0x9bc0, 0x0000, 0x0201, + 0x0006, 0x9301, 0x4088, 0x134c, 0x3400, 0x8024, 0xd204, 0x0024, 0xb234, + 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, 0x3c30, 0x0024, + 0x0000, 0x2000, 0xb400, 0x0024, 0x0000, 0x3001, 0x2802, 0x7555, 0x0000, + 0x3800, 0x0000, 0x0041, 0xfe42, 0x12cc, 0x48b2, 0x1090, 0x3810, 0x0024, + 0x38f0, 0x4024, 0x2802, 0x9640, 0x3430, 0x0024, 0xb400, 0x0024, 0x6012, + 0x0024, 0x0000, 0x3801, 0x2802, 0x7895, 0x0000, 0x3c00, 0x0000, 0x07c0, + 0x0000, 0x0041, 0xb400, 0x12cc, 0xfe02, 0x1150, 0x48b2, 0x0024, 0x689a, + 0x2040, 0x2802, 0x9500, 0x38f0, 0x4024, 0xb400, 0x0024, 0x6012, 0x0024, + 0x0000, 0x3c01, 0x2802, 0x7c15, 0x0000, 0x3e00, 0x0000, 0x03c0, 0x0000, + 0x0085, 0x4592, 0x12cc, 0xb400, 0x1150, 0xfe02, 0x0024, 0x48b2, 0x0024, + 0x3810, 0x0024, 0x2802, 0x9500, 0x38f0, 0x4024, 0xb400, 0x0024, 0x6012, + 0x0024, 0x0000, 0x3e01, 0x2802, 0x7f95, 0x0000, 0x3f00, 0x0000, 0x01c0, + 0xf20a, 0x12cc, 0xb400, 0x1150, 0xf252, 0x0024, 0xfe02, 0x0024, 0x48b2, + 0x0024, 0x3810, 0x0024, 0x2802, 0x9500, 0x38f0, 0x4024, 0xb400, 0x130c, + 0x6012, 0x0024, 0x0000, 0x3f01, 0x2802, 0x8315, 0x4390, 0x0024, 0x0000, + 0x0041, 0x0000, 0x0105, 0x4590, 0x13cc, 0xb400, 0x1150, 0xfe02, 0x0024, + 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0x9500, 0x38f0, 0x4024, 0xb400, + 0x0024, 0x6012, 0x1100, 0x0000, 0x01c1, 0x2802, 0x8695, 0x0000, 0x0024, + 0x0000, 0x0041, 0x0000, 0x0145, 0x6890, 0x12cc, 0xb400, 0x1150, 0xfe02, + 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0x9500, 0x38f0, 0x4024, + 0x6012, 0x0024, 0x0000, 0x3f81, 0x2802, 0x8915, 0xb430, 0x0024, 0x6012, + 0x0024, 0x0000, 0x0024, 0x2802, 0x8915, 0x0000, 0x0024, 0x2802, 0x9500, + 0x0000, 0x0185, 0x2802, 0x9640, 0xc890, 0x0024, 0x0000, 0x3fc3, 0x0000, + 0x0201, 0x34d3, 0x0024, 0x2903, 0x9bc0, 0x3433, 0x184c, 0x0006, 0x9301, + 0x4088, 0x134c, 0x3400, 0x8024, 0xd204, 0x0024, 0xb234, 0x0024, 0x4122, + 0x0024, 0xf400, 0x4055, 0x0000, 0x2001, 0x3500, 0x0024, 0x3c30, 0x0024, + 0x0000, 0x3000, 0xb400, 0x0024, 0x6012, 0x0024, 0x0000, 0x0182, 0x2802, + 0x8f45, 0x0000, 0x0024, 0x2802, 0x9640, 0xc890, 0x0024, 0x459a, 0x12cc, + 0x3404, 0x0024, 0x3023, 0x0024, 0x3010, 0x0024, 0x30d0, 0x4024, 0xac22, + 0x0046, 0x003f, 0xf982, 0x3011, 0xc024, 0x0000, 0x0023, 0xaf2e, 0x0024, + 0x0000, 0x0182, 0xccf2, 0x0024, 0x0000, 0x0fc6, 0x0000, 0x0047, 0xb46c, + 0x2040, 0xfe6e, 0x23c1, 0x3454, 0x0024, 0x3010, 0x0024, 0x30f0, 0x4024, + 0xac22, 0x0024, 0xccb2, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x458a, + 0x134c, 0x0000, 0x0201, 0x2802, 0x8a55, 0x0000, 0x3fc3, 0x3430, 0x0024, + 0x36f1, 0xd810, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3675, + 0x0024, 0x3633, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, 0x3e13, + 0xf80e, 0x3e03, 0x4024, 0x2903, 0xc780, 0x0000, 0x0381, 0x000f, 0xff81, + 0x6012, 0x0024, 0x0000, 0x0401, 0x2802, 0x9f05, 0x0000, 0x0024, 0x0000, + 0x0201, 0x3613, 0x0024, 0x2903, 0x9bc0, 0x0003, 0x5508, 0x003f, 0xfe04, + 0x0006, 0x8090, 0xb880, 0x11cc, 0x3413, 0x184c, 0x3c90, 0x0024, 0x2903, + 0x9bc0, 0x34f3, 0x0024, 0x0006, 0x9301, 0x3473, 0x184c, 0x3c10, 0x0024, + 0x34f0, 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, + 0x3500, 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0x6892, + 0x4055, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x34a0, 0x0024, 0xf100, 0x0024, + 0xb010, 0x0024, 0x3c60, 0x0024, 0x34b0, 0x0024, 0xb010, 0x0024, 0x0000, + 0x0201, 0x2903, 0x9bc0, 0x3ce0, 0x0024, 0x0006, 0x9301, 0x3473, 0x184c, + 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x003f, 0xff01, + 0x3500, 0x0024, 0x3cf0, 0x0024, 0x34c0, 0x0024, 0xa010, 0x0024, 0x0000, + 0x03c1, 0x3c40, 0x0024, 0x34d0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0201, + 0x2903, 0x9bc0, 0x3cc0, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, + 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x003f, 0xff01, 0x3500, + 0x0024, 0x3cf0, 0x0024, 0x3400, 0x0024, 0xa010, 0x0024, 0x0000, 0x01c1, + 0x3800, 0x0024, 0x34e0, 0x0024, 0xf100, 0x0024, 0xb010, 0x0024, 0x6892, + 0x3080, 0x34f0, 0x0024, 0xb010, 0x0024, 0x3cb0, 0x0024, 0x3450, 0x0024, + 0x34a0, 0x4024, 0xc010, 0x0024, 0x0000, 0x0181, 0x2802, 0xb585, 0x3000, + 0x0024, 0x6890, 0x03cc, 0x2803, 0x5500, 0x3800, 0x0024, 0x6012, 0x0024, + 0x0000, 0x0201, 0x2802, 0xb718, 0x0000, 0x0024, 0x2802, 0xba00, 0x6090, + 0x004c, 0x6012, 0x0024, 0x0000, 0x0281, 0x2802, 0xb948, 0x6012, 0x0024, + 0x0000, 0x0080, 0x2802, 0xb959, 0x0000, 0x0024, 0x2802, 0xba00, 0x3013, + 0x0024, 0x6890, 0x03cc, 0x2803, 0x5500, 0x3800, 0x0024, 0x0000, 0x0201, + 0x3800, 0x114c, 0x34b0, 0x0024, 0x6012, 0x0024, 0x0006, 0x09c1, 0x2802, + 0xc441, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, 0x0000, + 0x0000, 0x0024, 0x2802, 0xc440, 0x0000, 0x0024, 0x0000, 0x0200, 0x0006, + 0x8110, 0x2802, 0xc440, 0x3800, 0x0024, 0x0000, 0x0300, 0x0006, 0x8110, + 0x2802, 0xc440, 0x3800, 0x0024, 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, + 0x5500, 0x3800, 0x0024, 0x0000, 0x0400, 0x0006, 0x8110, 0x2802, 0xc440, + 0x3800, 0x0024, 0x0000, 0x0500, 0x0006, 0x8110, 0x2802, 0xc440, 0x3800, + 0x0024, 0x0000, 0x0600, 0x0006, 0x8110, 0x2802, 0xc440, 0x3800, 0x0024, + 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, 0x3423, + 0x184c, 0x3460, 0x0024, 0x4080, 0x0024, 0x0006, 0x8200, 0x2802, 0xc985, + 0x3e10, 0x0024, 0x0000, 0x01c0, 0x3e10, 0x0024, 0x3490, 0x0024, 0x2902, + 0x6ac0, 0x3e00, 0x13cc, 0x36d3, 0x11cc, 0x3413, 0x0024, 0x4080, 0x3240, + 0x34f3, 0x0024, 0x2802, 0xcd58, 0x0000, 0x0024, 0x0006, 0x8010, 0x6890, + 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, 0x0000, 0x0180, 0x3e10, 0x0024, + 0x3490, 0x0024, 0x2902, 0x6ac0, 0x3e00, 0x13cc, 0x36d3, 0x11cc, 0x3413, + 0x0024, 0x4080, 0x3240, 0x34f3, 0x0024, 0x2802, 0xcd58, 0x0000, 0x0024, + 0x0006, 0x8010, 0x6890, 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, 0x0000, + 0x0201, 0x3433, 0x0024, 0x34d0, 0x0024, 0x6012, 0x0024, 0x0006, 0x0bc1, + 0x2802, 0xdf41, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, + 0x0000, 0x0000, 0x0024, 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, 0x5500, + 0x3800, 0x0024, 0x0000, 0x3000, 0x2802, 0xe100, 0x0006, 0x8150, 0x0000, + 0x9000, 0x0006, 0x8150, 0x3433, 0x0024, 0x34d0, 0x4024, 0x4192, 0x0024, + 0x4192, 0x0024, 0x2802, 0xe100, 0xa010, 0x0024, 0x0000, 0x0201, 0x0006, + 0x8150, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, + 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, + 0x3cf0, 0x0024, 0x3490, 0x0024, 0x2802, 0xe100, 0x6090, 0x0024, 0x003f, + 0xfe04, 0x0000, 0x0401, 0x0006, 0x8150, 0x2903, 0x9bc0, 0x3613, 0x0024, + 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3400, + 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, 0x3fc3, 0xb234, 0x0024, + 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, 0x3500, 0x0024, 0xd024, + 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, + 0x3cf0, 0x0024, 0x3490, 0x0024, 0x2802, 0xe100, 0x6090, 0x0024, 0x0000, + 0x4000, 0x0000, 0x0202, 0x0006, 0x8150, 0x3433, 0x0024, 0x34d0, 0x4024, + 0x6122, 0x0024, 0xa010, 0x0024, 0x0004, 0x8001, 0x3800, 0x110c, 0x0006, + 0x8150, 0x3000, 0x0024, 0x6012, 0x1300, 0x0000, 0x0401, 0x2802, 0xe3c9, + 0x0000, 0x0024, 0x6890, 0x82cc, 0x2803, 0x5500, 0x3800, 0x0024, 0x6012, + 0x0024, 0x0006, 0x0dc1, 0x2803, 0x0b41, 0x4012, 0x0024, 0xf400, 0x4057, + 0x3702, 0x0024, 0x2000, 0x0000, 0x0000, 0x0024, 0x2803, 0x0b40, 0x0000, + 0x0024, 0x0016, 0x2200, 0x0006, 0x8190, 0x6892, 0x2040, 0x2803, 0x0b40, + 0x38f0, 0x4024, 0x002c, 0x4400, 0x0000, 0x0081, 0x0006, 0x8190, 0x3810, + 0x0024, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x003b, 0x8000, 0x0000, 0x0081, + 0x0006, 0x8190, 0x3810, 0x0024, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x0007, + 0xd000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2803, 0x0b40, 0x38f0, 0x4024, + 0x000f, 0xa000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2803, 0x0b40, 0x38f0, + 0x4024, 0x0015, 0x8880, 0x0006, 0x8190, 0xb882, 0x2040, 0x2803, 0x0b40, + 0x38f0, 0x4024, 0x0017, 0x7000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2803, + 0x0b40, 0x38f0, 0x4024, 0x001f, 0x4000, 0x0006, 0x8190, 0xb882, 0x2040, + 0x2803, 0x0b40, 0x38f0, 0x4024, 0x002b, 0x1100, 0x0006, 0x8190, 0xb882, + 0x2040, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x002e, 0xe000, 0x0006, 0x8190, + 0xb882, 0x2040, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x001d, 0xc000, 0x0006, + 0x8190, 0x6892, 0x2040, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x0006, 0x8190, + 0x0000, 0x0201, 0x0000, 0xfa04, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x0006, + 0x9301, 0xb88a, 0x11cc, 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, + 0xd234, 0x0024, 0x0000, 0x3fc3, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, + 0x4055, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x3490, 0x0024, 0xfe50, 0x4005, + 0x48b2, 0x0024, 0xfeca, 0x0024, 0x40b2, 0x0024, 0x3810, 0x0024, 0x2803, + 0x0b40, 0x38f0, 0x4024, 0x003f, 0xfe04, 0x0000, 0x0401, 0x0006, 0x8190, + 0x2903, 0x9bc0, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, + 0x0024, 0x34f0, 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, + 0x0000, 0x3fc3, 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, + 0x9301, 0x3500, 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, + 0xf400, 0x4055, 0x0000, 0x0041, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x3490, + 0x0024, 0xfe02, 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2803, 0x0b40, + 0x38f0, 0x4024, 0x003f, 0xfe04, 0x0000, 0x0401, 0x0006, 0x8190, 0x2903, + 0x9bc0, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, + 0x34f0, 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, + 0x3500, 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, + 0x4055, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x0000, 0x0280, 0x3490, 0x4024, + 0xfe02, 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2803, 0x0b40, 0x38f0, + 0x4024, 0x0006, 0x8010, 0x6890, 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, + 0x0000, 0x0201, 0x2903, 0x9bc0, 0x3613, 0x11cc, 0x3c10, 0x0024, 0x3490, + 0x4024, 0x6014, 0x13cc, 0x0000, 0x0081, 0x2803, 0x0e85, 0x0006, 0x80d0, + 0x0006, 0x8010, 0x6890, 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, 0x3000, + 0x0024, 0x6012, 0x0024, 0x0000, 0x0241, 0x2803, 0x1309, 0x0000, 0x0024, + 0x6890, 0x034c, 0xb882, 0x2000, 0x0006, 0x8310, 0x2914, 0xbec0, 0x0000, + 0x1000, 0x0000, 0x0800, 0x3613, 0x0024, 0x3e10, 0x0024, 0x0006, 0x8300, + 0x290c, 0x7300, 0x3e10, 0x0024, 0x2803, 0x5500, 0x36e3, 0x0024, 0x0006, + 0x8110, 0x30e1, 0x184c, 0x3000, 0x0024, 0x6012, 0x0024, 0x0008, 0x0001, + 0x2803, 0x1515, 0x0000, 0x0024, 0x6498, 0x0024, 0x3e10, 0x4024, 0x0000, + 0x0081, 0x2902, 0x1dc0, 0x3e01, 0x0024, 0x36e3, 0x004c, 0x3000, 0x0024, + 0x6012, 0x0024, 0x000b, 0x8011, 0x2803, 0x20d5, 0x0006, 0x8112, 0x0000, + 0x0201, 0x0004, 0x0010, 0x2915, 0x8300, 0x0001, 0x0000, 0x000b, 0x8011, + 0x0005, 0x0010, 0x291f, 0xc6c0, 0x0001, 0x0000, 0x0006, 0x8110, 0x30e1, + 0x0024, 0x3000, 0x0024, 0x6012, 0x0024, 0x0000, 0x0281, 0x2803, 0x1c45, + 0x6012, 0x0024, 0x000b, 0x8001, 0x2803, 0x1cd5, 0x3613, 0x0024, 0x36f3, + 0x0024, 0x000b, 0x8001, 0x6498, 0x184c, 0x0006, 0x8112, 0x0003, 0x8000, + 0x3e10, 0x4024, 0x2902, 0x1dc0, 0x3e01, 0x0024, 0x36f3, 0x0024, 0x3009, + 0x3844, 0x3e10, 0x0024, 0x0000, 0x0400, 0x3000, 0x8024, 0x0008, 0x0010, + 0x3e00, 0x8024, 0x3201, 0x0024, 0x6408, 0x4051, 0x2903, 0x8740, 0x0003, + 0x2388, 0x0000, 0x0400, 0x0000, 0x0011, 0x3613, 0x008c, 0x30d0, 0x7844, + 0x3e10, 0x4024, 0x3000, 0x8024, 0x0008, 0x0010, 0x3e00, 0x8024, 0x3201, + 0x0024, 0x2903, 0x8740, 0x6408, 0x0024, 0x0006, 0x8a10, 0x0000, 0x01c1, + 0x36e3, 0x0000, 0xb010, 0x9bc4, 0x0000, 0x0024, 0x2803, 0x2785, 0x0000, + 0x0024, 0x6192, 0x184c, 0x2903, 0x9bc0, 0x6102, 0x0024, 0x4088, 0x0024, + 0x0000, 0x0024, 0x2803, 0x2785, 0x0000, 0x0024, 0x6890, 0x0b4c, 0x3a00, + 0x0024, 0x0000, 0x0401, 0x2903, 0x9bc0, 0x3613, 0x11cc, 0x3413, 0x0024, + 0x3c90, 0x0024, 0x290b, 0x1400, 0x34f3, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0024, 0x2803, 0x5195, 0x0000, 0x0024, 0x3423, 0x0024, 0x34e0, 0x0024, + 0x4080, 0x0024, 0x0006, 0x8151, 0x2803, 0x2f05, 0x0000, 0x3200, 0x0000, + 0x0142, 0x0006, 0x8211, 0x3613, 0x0024, 0x3e00, 0x7800, 0x3111, 0x8024, + 0x31d1, 0xc024, 0xfef4, 0x4087, 0x48b6, 0x0440, 0xfeee, 0x07c1, 0x2914, + 0xa580, 0x42b6, 0x0024, 0x2803, 0x3300, 0x0007, 0x89d0, 0x0000, 0x0142, + 0x3613, 0x0024, 0x3e00, 0x7800, 0x3131, 0x8024, 0x3110, 0x0024, 0x31d0, + 0x4024, 0xfe9c, 0x4181, 0x48be, 0x0024, 0xfe82, 0x0440, 0x46be, 0x07c1, + 0xfef4, 0x4087, 0x48b6, 0x0024, 0xfeee, 0x0024, 0x2914, 0xa580, 0x42b6, + 0x0024, 0x0007, 0x89d0, 0x0006, 0x8191, 0x4c8a, 0x9800, 0xfed0, 0x4005, + 0x48b2, 0x0024, 0xfeca, 0x0024, 0x40b2, 0x0024, 0x3810, 0x0024, 0x38f0, + 0x4024, 0x3111, 0x8024, 0x468a, 0x0707, 0x2908, 0xbe80, 0x3101, 0x0024, + 0x3123, 0x11cc, 0x3100, 0x108c, 0x3009, 0x3000, 0x0004, 0x8000, 0x3009, + 0x1241, 0x6014, 0x138c, 0x000b, 0x8011, 0x2803, 0x3941, 0x0000, 0x0024, + 0x3473, 0x0024, 0x3423, 0x0024, 0x3009, 0x3240, 0x34e3, 0x0024, 0x2803, + 0x4fc0, 0x0008, 0x0012, 0x0006, 0x80d0, 0x2803, 0x3ac9, 0x0000, 0x0024, + 0xf400, 0x4004, 0x3000, 0x0024, 0x4090, 0x0024, 0xf400, 0x4480, 0x2803, + 0x4095, 0x000b, 0x8001, 0x0000, 0x0005, 0x6540, 0x0024, 0x0000, 0x0024, + 0x2803, 0x4bd8, 0x4490, 0x0024, 0x2403, 0x3fc0, 0x0000, 0x0024, 0x0006, + 0x8301, 0x4554, 0x0800, 0x4122, 0x0024, 0x659a, 0x4055, 0x0006, 0x8341, + 0x4122, 0x3400, 0xf400, 0x4055, 0x3210, 0x0024, 0x3d00, 0x0024, 0x2803, + 0x4bc0, 0x0000, 0x0024, 0x6014, 0x0024, 0x0001, 0x0000, 0x2803, 0x4815, + 0x0000, 0x0005, 0x0008, 0x0012, 0x0008, 0x0010, 0x0003, 0x8001, 0x0006, + 0x8153, 0x3613, 0x0024, 0x3009, 0x3811, 0x2903, 0xfc00, 0x0004, 0x0011, + 0x0008, 0x0010, 0x0001, 0x0000, 0x291f, 0xc6c0, 0x0005, 0x0011, 0x000f, + 0x0011, 0x0008, 0x0010, 0x33d0, 0x184c, 0x6010, 0xb844, 0x3e10, 0x0024, + 0x0000, 0x0400, 0x3320, 0x4024, 0x3e00, 0x4024, 0x3301, 0x0024, 0x2903, + 0x8740, 0x6408, 0x0024, 0x36e3, 0x0024, 0x3009, 0x1bc4, 0x3009, 0x1bd1, + 0x6540, 0x0024, 0x0000, 0x0024, 0x2803, 0x4bd8, 0x4490, 0x0024, 0x2403, + 0x4b80, 0x0000, 0x0024, 0x0006, 0x8301, 0x4554, 0x0840, 0x4122, 0x0024, + 0x659a, 0x4055, 0x0006, 0x8341, 0x4122, 0x3400, 0xf400, 0x4055, 0x3110, + 0x0024, 0x3d00, 0x0024, 0xf400, 0x4510, 0x0030, 0x0013, 0x3073, 0x184c, + 0x3e11, 0x008c, 0x3009, 0x0001, 0x6140, 0x0024, 0x0000, 0x0201, 0x3009, + 0x2000, 0x0006, 0x8300, 0x290c, 0x7300, 0x3e10, 0x0024, 0x3300, 0x1b8c, + 0xb010, 0x0024, 0x0000, 0x0024, 0x2803, 0x5195, 0x0000, 0x0024, 0x3473, + 0x0024, 0x3423, 0x0024, 0x3009, 0x1240, 0x4080, 0x138c, 0x0000, 0x0804, + 0x2803, 0x39d5, 0x6402, 0x0024, 0x0006, 0xd312, 0x0006, 0xd310, 0x0006, + 0x8191, 0x3010, 0x984c, 0x30f0, 0xc024, 0x0000, 0x0021, 0xf2d6, 0x07c6, + 0x290a, 0xf5c0, 0x4682, 0x0400, 0x6894, 0x0840, 0xb886, 0x0bc1, 0xbcd6, + 0x0024, 0x3a10, 0x8024, 0x3af0, 0xc024, 0x36f3, 0x4024, 0x36f3, 0xd80e, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, + 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, + 0x0020, 0x0001, 0x3e14, 0x3811, 0x0030, 0x0050, 0x0030, 0x0251, 0x3e04, + 0xb813, 0x3000, 0x0024, 0xc012, 0x0024, 0x0019, 0x9300, 0x3800, 0x4024, + 0x2903, 0xae40, 0x3900, 0x0024, 0x2903, 0xbb80, 0x0000, 0x0300, 0xb882, + 0x0024, 0x2914, 0xbec0, 0x0006, 0x8010, 0x0000, 0x1540, 0x0007, 0x8190, + 0x2900, 0xadc0, 0x3800, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, + 0x6555, 0x0000, 0x0024, 0x0006, 0x8012, 0x3200, 0x0024, 0x4080, 0x0024, + 0x0030, 0x0010, 0x2803, 0x6555, 0x0000, 0x0201, 0x3000, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2803, 0x6555, 0x0000, 0x0024, 0x2900, 0xadc0, + 0x0000, 0x0024, 0x4080, 0x0024, 0x0006, 0x8010, 0x2803, 0x6555, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0201, 0x2803, 0x6185, 0x0030, 0x0010, + 0x0030, 0x0050, 0xf292, 0x0000, 0xb012, 0x0024, 0x3800, 0x4024, 0x0030, + 0x0010, 0x0000, 0x0201, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2900, 0xbe95, 0x0003, 0x6f08, 0x0006, 0x8011, 0x3100, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2803, 0x6d45, 0x0000, 0x0024, 0x0007, 0x8a52, + 0x3200, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0x6d49, 0x0000, + 0x0024, 0xf292, 0x0800, 0x6012, 0x0024, 0x0000, 0x0000, 0x2803, 0x6d05, + 0x0000, 0x0024, 0x3200, 0x0024, 0x4090, 0x0024, 0xb880, 0x2800, 0x3900, + 0x0024, 0x3100, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2902, 0x9885, + 0x0003, 0x6648, 0x2900, 0xbe80, 0x0000, 0x0024, 0x0000, 0x0010, 0x0006, + 0x9f51, 0x0006, 0x9f92, 0x0030, 0x0493, 0x0000, 0x0201, 0x6890, 0xa410, + 0x3b00, 0x2810, 0x0006, 0x8a10, 0x3009, 0x0000, 0x6012, 0x0024, 0x0006, + 0x9fd0, 0x2803, 0x7288, 0xb880, 0x0024, 0x6890, 0x0024, 0x3009, 0x2000, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e10, 0xb810, 0x3e11, 0x3805, 0x3e02, 0x0024, 0x0030, 0x0010, 0xce9a, + 0x0002, 0x0000, 0x0200, 0x2903, 0x7dc0, 0xb024, 0x0024, 0xc020, 0x0024, + 0x0000, 0x0200, 0x2803, 0x7685, 0x6e9a, 0x0002, 0x4182, 0x0024, 0x0000, + 0x0400, 0x2803, 0x7c45, 0xae1a, 0x0024, 0x6104, 0x984c, 0x0000, 0x0024, + 0x2903, 0x9bc9, 0x0003, 0x7c08, 0x6103, 0xe4e5, 0x2903, 0x9bc0, 0x408a, + 0x188c, 0x2903, 0x9bc0, 0x408a, 0x4141, 0x4583, 0x6465, 0x2803, 0x7c40, + 0xceca, 0x1bcc, 0xc408, 0x0024, 0xf2e2, 0x1bc8, 0x36f1, 0x1805, 0x2000, + 0x0011, 0x36f0, 0x9810, 0x2000, 0x0000, 0xdc92, 0x0024, 0x0006, 0x8a17, + 0x3613, 0x1c00, 0x6093, 0xe1e3, 0x0000, 0x03c3, 0x0006, 0x9f95, 0xb132, + 0x9415, 0x3500, 0xfc01, 0x2803, 0x8695, 0xa306, 0x0024, 0x3009, 0x184c, + 0x3009, 0x3814, 0x0025, 0xffd4, 0x0006, 0xd317, 0x3710, 0x160c, 0x0006, + 0x9f94, 0x37f0, 0x73d5, 0x6c92, 0x3808, 0x3f10, 0x0024, 0x3ff0, 0x4024, + 0x3009, 0x1040, 0x3009, 0x13c1, 0x6010, 0x0024, 0x0000, 0x0024, 0x2903, + 0xc445, 0x0003, 0x8288, 0x2803, 0x84d4, 0x0006, 0x0001, 0x4010, 0x0024, + 0x0005, 0xf601, 0x6010, 0x0024, 0x0000, 0x0040, 0x2803, 0x8654, 0x0030, + 0x0497, 0x3f00, 0x0024, 0x36f2, 0x1814, 0x4330, 0x9803, 0x2000, 0x0000, + 0x8880, 0x1bc1, 0x3613, 0x0024, 0x3e22, 0xb806, 0x3e05, 0xb814, 0x3615, + 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x7807, + 0x6848, 0x930c, 0x3411, 0x780d, 0x459a, 0x10c0, 0x0000, 0x0201, 0x6012, + 0x384e, 0x0000, 0x0241, 0x2803, 0x8dd5, 0x6012, 0x380f, 0x2403, 0x8d05, + 0x0000, 0x0024, 0x3000, 0x0001, 0x3101, 0x8407, 0x6cfe, 0x0024, 0xac42, + 0x0024, 0xaf4e, 0x2040, 0x3911, 0x8024, 0x2803, 0x9980, 0x0000, 0x0024, + 0x0000, 0x0281, 0x2803, 0x9115, 0x6012, 0x4455, 0x2403, 0x9045, 0x0000, + 0x0024, 0x3000, 0x0001, 0x3101, 0x8407, 0x4cf2, 0x0024, 0xac42, 0x0024, + 0xaf4e, 0x2040, 0x3911, 0x8024, 0x2803, 0x9980, 0x0000, 0x0024, 0x0000, + 0x0024, 0x2803, 0x9555, 0x4080, 0x0024, 0x3110, 0x0401, 0xf20f, 0x0203, + 0x2403, 0x9485, 0x8dd6, 0x0024, 0x4dce, 0x0024, 0xf1fe, 0x0024, 0xaf4e, + 0x0024, 0x6dc6, 0x2046, 0xf1df, 0x0203, 0xaf4f, 0x1011, 0xf20e, 0x07cc, + 0x8dd6, 0x2486, 0x2803, 0x9980, 0x0000, 0x0024, 0x0000, 0x0024, 0x2803, + 0x97d5, 0x0000, 0x0024, 0x0fff, 0xffd1, 0x2403, 0x9705, 0x3010, 0x0001, + 0xac4f, 0x0801, 0x3821, 0x8024, 0x2803, 0x9980, 0x0000, 0x0024, 0x0fff, + 0xffd1, 0x2403, 0x9945, 0x3010, 0x0001, 0x3501, 0x9407, 0xac47, 0x0801, + 0xaf4e, 0x2082, 0x3d11, 0x8024, 0x36f3, 0xc024, 0x36f3, 0x980d, 0x36f1, + 0x5807, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36e3, 0x0024, + 0x2000, 0x0000, 0x36f2, 0x9806, 0x3e10, 0xb812, 0x3e11, 0xb810, 0x3e12, + 0x0024, 0x0006, 0x9f92, 0x0025, 0xffd0, 0x3e04, 0x4bd1, 0x3181, 0xf847, + 0xb68c, 0x4440, 0x3009, 0x0802, 0x6024, 0x3806, 0x0006, 0x8a10, 0x2903, + 0xc445, 0x0003, 0x9dc8, 0x0000, 0x0800, 0x6101, 0x1602, 0xaf2e, 0x0024, + 0x4214, 0x1be3, 0xaf0e, 0x1811, 0x0fff, 0xfc00, 0xb200, 0x9bc7, 0x0000, + 0x03c0, 0x2803, 0xa205, 0xb204, 0xa002, 0x2900, 0xb800, 0x3613, 0x2002, + 0x4680, 0x1bc8, 0x36f1, 0x9810, 0x2000, 0x0000, 0x36f0, 0x9812, 0x0000, + 0x0400, 0x6102, 0x0024, 0x3e11, 0x3805, 0x2803, 0xa609, 0x3e02, 0x0024, + 0x2903, 0x9bc0, 0x408a, 0x188c, 0x2903, 0x9bc0, 0x408a, 0x4141, 0x4582, + 0x1bc8, 0x2000, 0x0000, 0x36f1, 0x1805, 0x2903, 0x9bc0, 0x4102, 0x184c, + 0xb182, 0x1bc8, 0x2000, 0x0000, 0x36f1, 0x1805, 0x2a03, 0xa78e, 0x3e12, + 0xb817, 0x3e10, 0x3802, 0x0000, 0x800a, 0x0006, 0x9f97, 0x3009, 0x1fc2, + 0x3e04, 0x5c00, 0x6020, 0xb810, 0x0030, 0x0451, 0x2803, 0xaa54, 0x0006, + 0x0002, 0x4020, 0x0024, 0x0005, 0xfb02, 0x6024, 0x0024, 0x0025, 0xffd0, + 0x2803, 0xac91, 0x3100, 0x1c11, 0xb284, 0x0024, 0x0030, 0x0490, 0x3800, + 0x8024, 0x0025, 0xffd0, 0x3980, 0x1810, 0x36f4, 0x7c11, 0x36f0, 0x1802, + 0x0030, 0x0717, 0x3602, 0x8024, 0x2100, 0x0000, 0x3f05, 0xdbd7, 0x0003, + 0xa757, 0x3613, 0x0024, 0x3e00, 0x3801, 0xf400, 0x55c0, 0x0000, 0x0897, + 0xf400, 0x57c0, 0x0000, 0x0024, 0x2000, 0x0000, 0x36f0, 0x1801, 0x3613, + 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0xb884, 0xb805, 0xb88a, 0x3844, 0x3e11, + 0xb80d, 0x3e03, 0xf80e, 0x0000, 0x03ce, 0x2403, 0xb68e, 0xf400, 0x4083, + 0x0000, 0x0206, 0xa562, 0x0024, 0x455a, 0x0024, 0x0020, 0x0006, 0xd312, + 0x0024, 0xb16c, 0x0024, 0x0000, 0x01c6, 0x2803, 0xb685, 0x0000, 0x0024, + 0xd56a, 0x0024, 0x4336, 0x0024, 0x0000, 0x4000, 0x0006, 0x9306, 0x4092, + 0x0024, 0xb512, 0x0024, 0x462c, 0x0024, 0x6294, 0x4195, 0x6200, 0x3401, + 0x0000, 0x03ce, 0x2803, 0xb391, 0xb88a, 0x0024, 0x36f3, 0xd80e, 0x36f1, + 0x980d, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0xb880, 0xb810, 0x0006, 0x9fd0, 0x3e10, 0x8001, 0x4182, + 0x3811, 0x0006, 0xd311, 0x2803, 0xbf45, 0x0006, 0x8a10, 0x0000, 0x0200, + 0xbc82, 0xa000, 0x3910, 0x0024, 0x2903, 0xb080, 0x39f0, 0x4024, 0x0006, + 0x9f90, 0x0006, 0x9f51, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, + 0x0000, 0x0024, 0x2903, 0xc445, 0x0003, 0xc048, 0x36f4, 0x4024, 0x36f0, + 0x9810, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x290a, 0xd900, 0x3605, 0x0024, 0x2910, 0x0180, + 0x3613, 0x0024, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0006, + 0x0002, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0x9f90, + 0x3e04, 0xb813, 0x3009, 0x0012, 0x3213, 0x0024, 0xf400, 0x4480, 0x6026, + 0x0024, 0x0000, 0x0024, 0x2803, 0xccd5, 0x0000, 0x0024, 0x0000, 0x0012, + 0xf400, 0x4480, 0x0006, 0x9f50, 0x3009, 0x0002, 0x6026, 0x0024, 0x0000, + 0x0024, 0x2903, 0xc445, 0x0003, 0xccc8, 0x0006, 0x9f93, 0x3201, 0x0c11, + 0xb58a, 0x0406, 0x0006, 0x8a11, 0x468e, 0x8400, 0xb68c, 0x9813, 0xcfee, + 0x1bd2, 0x0000, 0x0804, 0xaf0e, 0x9811, 0x4f86, 0x1bd0, 0x0000, 0x0021, + 0x6418, 0x9807, 0x6848, 0x1bc6, 0xad46, 0x9805, 0xf400, 0x4080, 0x36f1, + 0x0024, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, + 0x3e10, 0xb803, 0x3e11, 0x3805, 0x2803, 0xdb00, 0x3e04, 0x3811, 0x0000, + 0x0401, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x0000, 0x0080, 0xb882, 0x130c, + 0xf400, 0x4510, 0x3010, 0x910c, 0x30f0, 0xc024, 0x6dc2, 0x0024, 0x3810, + 0x0024, 0x38f0, 0x4024, 0x0000, 0x0201, 0x3100, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0024, 0x2803, 0xde55, 0x0000, 0x0024, 0x6894, 0x130c, 0xb886, + 0x1040, 0x3430, 0x4024, 0x6dca, 0x0024, 0x0030, 0x0011, 0x2803, 0xd6d1, + 0x0000, 0x0024, 0xbcd2, 0x0024, 0x0000, 0x0201, 0x2803, 0xde45, 0x0000, + 0x0024, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x36f4, 0x1811, 0x36f1, 0x1805, + 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb815, + 0x0000, 0x800a, 0x3e14, 0x7813, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, + 0xb807, 0x3e13, 0xf80e, 0x6812, 0x0024, 0x3e03, 0x7810, 0x0fff, 0xffd3, + 0x0000, 0x0091, 0xbd86, 0x9850, 0x3e10, 0x3804, 0x3e00, 0x7812, 0xbe8a, + 0x8bcc, 0x409e, 0x8086, 0x2403, 0xe587, 0xfe49, 0x2821, 0x526a, 0x8801, + 0x5c87, 0x280e, 0x4eba, 0x9812, 0x4286, 0x40e1, 0xb284, 0x1bc1, 0x4de6, + 0x0024, 0xad17, 0x2627, 0x4fde, 0x9804, 0x4498, 0x1bc0, 0x0000, 0x0024, + 0x2803, 0xe395, 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f4, 0x5813, 0x2000, 0x0000, + 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, 0x800a, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e13, 0xf80e, 0x6812, 0x0024, + 0x3e03, 0x7810, 0x3009, 0x1850, 0x3e10, 0x3804, 0x3e10, 0x7812, 0x32f3, + 0x0024, 0xbd86, 0x0024, 0x4091, 0xe2e3, 0x3009, 0x0046, 0x2403, 0xf100, + 0x3009, 0x0047, 0x32f0, 0x0801, 0xfe1f, 0x6465, 0x5e8a, 0x0024, 0x44ba, + 0x0024, 0xfee2, 0x0024, 0x5d8a, 0x1800, 0x4482, 0x4160, 0x48ba, 0x8046, + 0x4dc6, 0x1822, 0x4de6, 0x8047, 0x36f3, 0x0024, 0x36f0, 0x5812, 0xad17, + 0x2627, 0x4fde, 0x9804, 0x4498, 0x1bc0, 0x0000, 0x0024, 0x2803, 0xec95, + 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, 0x9807, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x2000, 0x0000, 0x36f2, 0x9815, 0xb386, 0x40d7, + 0x4284, 0x184c, 0x0000, 0x05c0, 0x2803, 0xf695, 0xf5d8, 0x3804, 0x0000, + 0x0984, 0x6400, 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, 0x0000, 0x800a, + 0x0000, 0x00ce, 0x2403, 0xf9ce, 0xffa4, 0x0024, 0x48b6, 0x0024, 0x0000, + 0x0024, 0x2803, 0xf9c4, 0x4000, 0x40c2, 0x4224, 0x0024, 0x6090, 0x0024, + 0xffa4, 0x0024, 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, 0xd80d, 0x48b6, + 0x0024, 0x0fff, 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, 0x36f1, 0x180a, + 0x4080, 0x184c, 0x3e13, 0x780f, 0x2803, 0xfe05, 0x4090, 0xb80e, 0x2403, + 0xfd80, 0x3e04, 0x0440, 0x3810, 0x0440, 0x3604, 0x0024, 0x3009, 0x1bce, + 0x3603, 0x5bcf, 0x2000, 0x0000, 0x0000, 0x0024, 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6280, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1440, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x3c4e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x59c0, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x01a4, /*copy 420*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x000b, /*copy 11*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x0007, 0x0001, /*copy 1*/ + 0x181a, 0x0006, 0x0002, /*copy 2*/ + 0x08b4, 0x08d2, 0x0006, 0x8006, 0x091a, /*Rle(6)*/ + 0x0006, 0x0025, /*copy 37*/ + 0x08ef, 0x08ef, 0x08ef, 0x08ef, 0x08ef, 0x0b11, 0x0af5, 0x0af9, 0x0afd, + 0x0b01, 0x0b05, 0x0b09, 0x0b0d, 0x0b40, 0x0b44, 0x0b47, 0x0b47, 0x0b47, + 0x0b47, 0x0b4f, 0x0b62, 0x0c2d, 0x0b99, 0x0b9e, 0x0ba4, 0x0baa, 0x0baf, + 0x0bb4, 0x0bb9, 0x0bbe, 0x0bc3, 0x0bc8, 0x0bcd, 0x0bd2, 0x0beb, 0x0c0a, + 0x0c29, 0x0007, 0x0001, /*copy 1*/ + 0x5800, 0x0006, 0x0001, /*copy 1*/ + 0x0001, 0x0006, 0x8007, 0x0000, /*Rle(7)*/ + 0x0006, 0x0018, /*copy 24*/ + 0x0002, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, + 0x0000, 0xfffd, 0xffff, 0x0001, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, + 0xfffa, 0xffff, 0x0004, 0x0000, 0xffff, 0xffff, 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 8588 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/patches_latm.h b/targets/esp32/components/VS1053/include/patches_latm.h new file mode 100644 index 00000000..115525f1 --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_latm.h @@ -0,0 +1,644 @@ + +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x001e, /*copy 30*/ + 0x2a00, 0xc000, 0x3e12, 0xb817, 0x3e14, 0xf812, 0x3e01, 0xb811, 0x0007, + 0x9717, 0x0020, 0xffd2, 0x0030, 0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, + 0x3b81, 0x8024, 0x3101, 0x8024, 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, + 0x4800, 0x36f1, 0x9811, 0x0007, 0x0001, /*copy 1*/ + 0x8060, 0x0006, 0x0536, /*copy 1334*/ + 0xf400, 0x4095, 0x0000, 0x02c2, 0x6124, 0x0024, 0x0000, 0x0024, 0x2800, + 0x1ac5, 0x4192, 0x4542, 0x0000, 0x0041, 0x2000, 0x0015, 0x0030, 0x0317, + 0x2000, 0x0000, 0x3f00, 0x4024, 0x2000, 0x0000, 0x0000, 0x0000, 0x3e12, + 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, 0x8257, 0x3700, 0x984c, + 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, 0x2910, 0x0181, 0x0000, + 0x1bc8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, 0x0195, 0x0000, 0x1bc8, + 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2945, 0x3e13, 0x780e, 0x3e11, + 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, 0xb808, 0x003f, 0xe004, + 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, 0x48be, 0x4497, 0x4090, + 0x1c46, 0xf06c, 0x0024, 0x2400, 0x2580, 0x6090, 0x41c3, 0x6628, 0x1c47, + 0x0000, 0x0024, 0x2800, 0x2449, 0xf07e, 0x0024, 0xf400, 0x4182, 0x673a, + 0x1c46, 0x0000, 0x0024, 0x2800, 0x2589, 0xf06c, 0x0024, 0xf400, 0x41c3, + 0x0000, 0x0024, 0x4224, 0x3442, 0x2900, 0xb7c0, 0x4336, 0x37c3, 0x0000, + 0x1805, 0x2900, 0xb7c0, 0x4508, 0x40c2, 0x450a, 0x9808, 0x0000, 0x0207, + 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, 0x3d01, 0x5bc1, 0x36f3, + 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, 0x580e, 0x0007, 0x8257, + 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, 0xd428, 0x3c02, 0x0006, + 0xc717, 0x2800, 0x2d05, 0x4284, 0x0024, 0x3613, 0x3c02, 0x0006, 0xc357, + 0x2901, 0x6480, 0x3e11, 0x5c05, 0x4284, 0x1bc5, 0x0000, 0x0024, 0x2800, + 0x3045, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, 0x0024, 0x3613, 0x0024, + 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, 0x2900, 0x4900, 0x0006, + 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, 0x8257, 0x3700, 0x8024, + 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x3251, 0x3600, 0x9844, 0x2900, + 0x3800, 0x0000, 0x32c8, 0x2911, 0xf140, 0x0000, 0x0024, 0x0030, 0x0057, + 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, 0xa024, 0x164c, 0x8000, + 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, 0x6d82, 0xd024, 0x44c0, + 0x0006, 0xa402, 0x2800, 0x3715, 0xd024, 0x0024, 0x0000, 0x0000, 0x2800, + 0x3715, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, 0x8024, 0x36f2, 0x1800, + 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, 0x3e13, 0xb80d, 0x3e13, + 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0xf801, + 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, 0xbf8e, 0x9c42, 0x3e01, + 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, 0x8250, 0x0fff, 0xfd85, + 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, 0x2800, 0x3e51, 0xf25a, + 0x104c, 0x34f3, 0x0024, 0x2800, 0x3e51, 0x0000, 0x0024, 0x3413, 0x084c, + 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, 0x2400, 0x4080, 0x4efa, + 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, 0x4d64, 0x48b2, 0xa201, + 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, 0x36f4, 0xd801, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0xd80a, 0x36f3, 0x980d, + 0x2000, 0x0000, 0x36f4, 0x5810, 0x36f3, 0x0024, 0x3009, 0x3848, 0x3e14, + 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, + 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, 0x9e40, 0x3604, 0x1811, 0x3613, + 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, + 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x36f4, 0x1811, 0x3009, + 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e13, 0x7801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, + 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, 0x34e5, 0xc024, 0x3524, + 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, 0x4a0c, 0x3d44, 0x8024, + 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, 0x6010, 0x3400, 0x3710, + 0x8024, 0x2800, 0x54c4, 0x3af0, 0x8024, 0x3df0, 0x0024, 0x3591, 0x4024, + 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, 0x4020, 0x1753, 0xbf8e, + 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, 0x52ce, 0xfe6d, 0x2819, + 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, 0xad56, 0x904c, 0xaf5e, + 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, 0x2046, 0x3cf4, 0x0024, + 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, 0x2800, 0x4d55, 0x3c00, + 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0x5801, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x2814, 0x9c91, + 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3655, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb810, 0x3e13, + 0xf80e, 0x3e03, 0x534c, 0x3450, 0x4024, 0x6814, 0x0024, 0x0000, 0x0024, + 0x2800, 0x73d8, 0x4192, 0x0024, 0x2400, 0x7381, 0x0000, 0x0024, 0xf400, + 0x4450, 0x2938, 0x1880, 0x3613, 0x0024, 0x3c10, 0x050c, 0x3c10, 0x4024, + 0x3c90, 0x8024, 0x34f3, 0x0024, 0x3464, 0x0024, 0x3011, 0x0c40, 0x3011, + 0x4c41, 0x2915, 0x9900, 0x3011, 0x8f82, 0x3411, 0x2c40, 0x3411, 0x6c41, + 0x2915, 0xa580, 0x34e1, 0xaf82, 0x3009, 0x3040, 0x4c8a, 0x0040, 0x3010, + 0x7041, 0x2800, 0x6614, 0x3010, 0xb382, 0x3411, 0x0024, 0x3411, 0x6c44, + 0x34e1, 0xac45, 0xbe8a, 0xaf86, 0x0fe0, 0x0006, 0x3009, 0x3044, 0x3009, + 0x3045, 0x3009, 0x3386, 0x3411, 0x0024, 0x3411, 0x4ccc, 0x2915, 0x9900, + 0x34e1, 0x984c, 0x3e10, 0x7800, 0x3009, 0x3802, 0x3011, 0x0c40, 0x3011, + 0x4c41, 0x2915, 0x9900, 0x30e1, 0x8f82, 0x3009, 0x1bc6, 0x2915, 0xa940, + 0x36f1, 0x5804, 0x3011, 0x2c40, 0x3011, 0x6c41, 0x30b1, 0xac42, 0x3009, + 0x0c40, 0x3009, 0x0c41, 0x2915, 0x9900, 0x3613, 0x0f82, 0x3e10, 0x7800, + 0x3009, 0x3802, 0x3010, 0x1044, 0x3010, 0x5045, 0x2915, 0x9900, 0x3010, + 0x9386, 0x3009, 0x1bc6, 0x2915, 0xa940, 0x36f1, 0x5804, 0xf1ca, 0xac40, + 0x4ce2, 0xac41, 0x3009, 0x2ec2, 0x2800, 0x6ed2, 0x629c, 0x0024, 0xf1c2, + 0x4182, 0x3c10, 0x0c44, 0x3c10, 0x4c45, 0x2915, 0x4780, 0x3ce0, 0x8f86, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2800, 0x7395, 0x0020, 0x0000, 0x3411, + 0x0c40, 0x3411, 0x4c41, 0x2915, 0xb780, 0x34e1, 0x8f82, 0x0000, 0x03c3, + 0x4234, 0x0024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2915, 0x4355, 0x0000, + 0x7388, 0x0000, 0x0000, 0x3a10, 0x0d8c, 0x36f3, 0x538c, 0x36f3, 0xd80e, + 0x36f1, 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3645, + 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, + 0x3e11, 0xb810, 0x3e13, 0xf80e, 0x3e03, 0x534c, 0x3440, 0x4024, 0x4192, + 0x0024, 0x2400, 0x8f81, 0x0000, 0x0024, 0xb68c, 0x4450, 0x2938, 0x1880, + 0x3613, 0x050c, 0x3c10, 0x0c40, 0x3c10, 0x4c41, 0x3ce0, 0x8f82, 0x003c, + 0x2584, 0x2915, 0x9900, 0x0018, 0x8245, 0x3411, 0x2c40, 0x3411, 0x6c41, + 0x2915, 0xa580, 0x34e1, 0xac42, 0x4c8a, 0xb040, 0x3009, 0x3041, 0x2800, + 0x8094, 0x3009, 0x3382, 0x3411, 0x0f4c, 0x3411, 0x6c44, 0x34e1, 0xac45, + 0xbe8a, 0xac46, 0x499c, 0xb044, 0xf38c, 0xb045, 0x3009, 0x3386, 0x3009, + 0x0c40, 0x3009, 0x0c41, 0xf1ca, 0x8f82, 0x4ce2, 0x1044, 0x3411, 0x4024, + 0x2800, 0x82d2, 0x4294, 0x1386, 0x6294, 0x0024, 0xf1c2, 0x0024, 0x4e8a, + 0x4195, 0x35e3, 0x0024, 0x2915, 0xa955, 0xf400, 0x4546, 0x3009, 0x2c40, + 0x3009, 0x2c41, 0x3009, 0x2c42, 0x3009, 0x0c40, 0x3009, 0x0c41, 0xf1ca, + 0x8f82, 0x4ce2, 0x9044, 0x3009, 0x1045, 0x2800, 0x8745, 0x3009, 0x1386, + 0x2800, 0x8752, 0x4294, 0x0024, 0x6294, 0x0024, 0xf1c2, 0x0024, 0x4e8a, + 0x4195, 0x35e3, 0x0024, 0x2915, 0xa955, 0xf400, 0x4546, 0xf1ca, 0xac40, + 0x4ce2, 0xac41, 0x3009, 0x2ec2, 0x2800, 0x89d2, 0x629c, 0x0024, 0xf1c2, + 0x4182, 0x3c20, 0x0c84, 0x3cf0, 0x8fc6, 0x6264, 0x4017, 0x3cf0, 0x4fc5, + 0x2800, 0x8f88, 0x0020, 0x0000, 0x2800, 0x8cd9, 0xf400, 0x45c0, 0x6cea, + 0x0024, 0x0000, 0x0024, 0x2800, 0x8f89, 0x0020, 0x0000, 0x3411, 0x0c40, + 0x3411, 0x4c41, 0x2915, 0xb780, 0x34e1, 0x8f82, 0x0000, 0x03c3, 0x4234, + 0x0024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2915, 0x4355, 0x0000, 0x8f88, + 0x0000, 0x0000, 0x3a10, 0x0d8c, 0x36f3, 0x53cc, 0x36f3, 0xd80e, 0x36f1, + 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0xf400, + 0x4595, 0x35e3, 0x3840, 0x3e13, 0xf80e, 0x3e13, 0x7808, 0x3510, 0x0024, + 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, + 0x0024, 0x0001, 0xb0ce, 0x002b, 0xb30f, 0x292d, 0xa940, 0x0000, 0x004d, + 0x36d3, 0x0024, 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, + 0x1800, 0xf400, 0x4595, 0x35f3, 0x3840, 0x3e13, 0xf80e, 0x3e13, 0x7808, + 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, 0x0024, 0x0000, + 0x9b8e, 0x0028, 0x088f, 0x2927, 0xff80, 0x0000, 0x008d, 0x36e3, 0x0024, + 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, 0x1800, 0x0028, + 0x2b0f, 0x0000, 0xa10e, 0x2828, 0x0b15, 0x0007, 0x2605, 0x3613, 0x0001, + 0x3e14, 0x3811, 0x0001, 0x0011, 0x0001, 0xcc10, 0x2915, 0x94c0, 0x0000, + 0x4000, 0x3e10, 0x534c, 0x3430, 0xc024, 0x3e10, 0xc024, 0x2927, 0xc4c0, + 0x3e01, 0x0024, 0x36d3, 0x0024, 0x0001, 0x0011, 0x0001, 0xcc10, 0x2915, + 0x94c0, 0x0000, 0x4000, 0x2828, 0x0b00, 0x36f4, 0x1811, 0x3e00, 0x0024, + 0x2800, 0xa500, 0x0028, 0x2bc8, 0x3605, 0x7840, 0x3e13, 0x780e, 0x3e13, + 0xf808, 0x3e05, 0x4024, 0x0000, 0x434e, 0x0027, 0x9e0f, 0x2922, 0xa6c0, + 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, + 0x0000, 0x3009, 0x1800, 0xf400, 0x4595, 0x35d3, 0x3840, 0x3e13, 0xf80e, + 0x3e13, 0x7808, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e10, + 0x0024, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, 0x0024, + 0x0000, 0xaa4e, 0x0025, 0xf54f, 0x2925, 0xe580, 0x0000, 0x004d, 0x36c3, + 0x0024, 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, 0x1800, + 0x3433, 0x0000, 0x6890, 0x3040, 0x3cc0, 0xa000, 0x0008, 0x6201, 0x000d, + 0x3500, 0x3613, 0x110c, 0x3e10, 0x0024, 0x3e10, 0x4024, 0x34c0, 0x8024, + 0x2900, 0x9280, 0x3e00, 0x8024, 0x0026, 0x0a4f, 0x0000, 0xae0e, 0x2825, + 0xf880, 0x0000, 0x07cd, 0x0000, 0x0801, 0x6012, 0x0024, 0x0000, 0x0024, + 0x2826, 0x0a85, 0x0000, 0x0024, 0x2800, 0xab00, 0x0000, 0x0024, 0x3605, + 0x7840, 0x3e13, 0x780e, 0x3e13, 0xf808, 0x3e05, 0x4024, 0x0000, 0xb30e, + 0x0022, 0xf54f, 0x2922, 0xda80, 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, + 0xd808, 0x36f3, 0x580e, 0x2000, 0x0000, 0x3009, 0x1800, 0x3e00, 0x0024, + 0x2800, 0x9740, 0x0022, 0xf608, 0x3605, 0x7840, 0x3e13, 0x780e, 0x3e13, + 0xf808, 0x3e05, 0x4024, 0x0000, 0xb70e, 0x0022, 0xa1cf, 0x2922, 0x9980, + 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, + 0x0000, 0x3009, 0x1800, 0x3009, 0x3400, 0x2800, 0xafc0, 0x0022, 0xa288, + 0xb386, 0x40d7, 0x4284, 0x184c, 0x0000, 0x05c0, 0x2800, 0xb955, 0xf5d8, + 0x3804, 0x0000, 0x0984, 0x6400, 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, + 0x0000, 0x800a, 0x0000, 0x00ce, 0x2400, 0xbc8e, 0xffa4, 0x0024, 0x48b6, + 0x0024, 0x0000, 0x0024, 0x2800, 0xbc84, 0x4000, 0x40c2, 0x4224, 0x0024, + 0x6090, 0x0024, 0xffa4, 0x0024, 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, + 0xd80d, 0x48b6, 0x0024, 0x0fff, 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, + 0x36f1, 0x180a, 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x0e92, /*copy 3730*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x6457, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x590e, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x003f, + 0xc000, 0xb600, 0x41c1, 0x0012, 0x5103, 0x000c, 0xc002, 0xdcd6, 0x0024, + 0x0019, 0xd4c2, 0x2802, 0x8345, 0x0001, 0x0988, 0x0013, 0xd9c3, 0x6fd6, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdf95, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xde4e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x0988, 0x0039, + 0x324f, 0x0001, 0x384e, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x2a00, 0xe180, 0x000a, 0x8c8f, + 0x0000, 0xe2ce, 0x000c, 0x0981, 0x280a, 0x71c0, 0x002c, 0x9d40, 0x000a, + 0x708f, 0x0000, 0xd7ce, 0x280a, 0xc0d5, 0x0012, 0x5182, 0x6fd6, 0x0024, + 0x003f, 0xfd81, 0x280a, 0x8e45, 0xb710, 0x0024, 0x003f, 0xf800, 0xb600, + 0x0024, 0x0015, 0xb801, 0x6012, 0x0024, 0x003f, 0xfd81, 0x2802, 0x4ec5, + 0x0001, 0x0a88, 0xb710, 0x0024, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, + 0x0101, 0x2801, 0x0055, 0xffd2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, + 0x0000, 0x190d, 0x2801, 0x0055, 0x0030, 0x0250, 0xb880, 0x104c, 0x3cf0, + 0x0024, 0x0010, 0x5500, 0xb880, 0x23c0, 0xb882, 0x2000, 0x0007, 0x8590, + 0x2914, 0xbec0, 0x0000, 0x0440, 0x0007, 0x8b50, 0xb880, 0x0024, 0x2920, + 0x0100, 0x3800, 0x0024, 0x2920, 0x0000, 0x0006, 0x8a91, 0x0000, 0x0800, + 0xb880, 0xa440, 0x003f, 0xfd81, 0xb710, 0xa7c0, 0x003f, 0xfc01, 0x6012, + 0x0024, 0x0000, 0x0101, 0x2801, 0x0995, 0x0000, 0x0024, 0xffe2, 0x0024, + 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x0995, 0x0000, + 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0006, 0x8a90, + 0x2801, 0x0995, 0x0000, 0x01c2, 0xb886, 0x8040, 0x3613, 0x03c1, 0xbcd2, + 0x0024, 0x0030, 0x0011, 0x2800, 0xf615, 0x003f, 0xff42, 0xb886, 0x8040, + 0x3009, 0x03c1, 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0102, 0x6cd2, + 0x0024, 0x3e10, 0x0024, 0x2909, 0x8c80, 0x3e00, 0x4024, 0x36f3, 0x0024, + 0x3e11, 0x8024, 0x3e01, 0xc024, 0x2901, 0x2e40, 0x0000, 0x0201, 0xf400, + 0x4512, 0x2900, 0x0c80, 0x3213, 0x1b8c, 0x3100, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0024, 0x2801, 0x0995, 0x0000, 0x0024, 0x291a, 0x8a40, 0x0000, + 0x0100, 0x2920, 0x0200, 0x3633, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, + 0x408e, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, 0x003f, 0xfd81, 0xb710, + 0x4006, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x0995, + 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, + 0x0024, 0x2801, 0x0995, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, + 0x4080, 0x0024, 0x0000, 0x01c2, 0x2800, 0xf205, 0x0006, 0x8a90, 0x2a01, + 0x0980, 0x2920, 0x0100, 0x0000, 0x0401, 0x0000, 0x0180, 0x2920, 0x0200, + 0x3613, 0x0024, 0x2920, 0x0280, 0x3613, 0x0024, 0x0000, 0x0401, 0x2920, + 0x0280, 0x4084, 0x984c, 0x0019, 0x9d01, 0x6212, 0x0024, 0x001e, 0x5c01, + 0x2801, 0x04d5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x06c5, 0x0000, + 0x0024, 0x001b, 0x5bc1, 0x6212, 0x0024, 0x001b, 0xdd81, 0x2801, 0x0a95, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x0a95, 0x0000, 0x0024, 0x0000, + 0x004d, 0x000a, 0xbf4f, 0x280a, 0xb880, 0x0001, 0x07ce, 0x0020, 0xfb4f, + 0x0000, 0x190d, 0x0001, 0x0ece, 0x2920, 0xf440, 0x3009, 0x2bc1, 0x291a, + 0x8a40, 0x36e3, 0x0024, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xcac0, + 0x0000, 0xd7ce, 0x0030, 0x0017, 0x3700, 0x4024, 0x0000, 0x0200, 0xb102, + 0x0024, 0x0000, 0x00c0, 0x2801, 0x0dc5, 0x0005, 0x4f92, 0x2909, 0xf840, + 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, 0xa115, 0xb080, 0x0024, 0x3f00, + 0x3400, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xc0c0, 0x0000, 0xd7ce, + 0x0000, 0x004d, 0x0020, 0xfe0f, 0x2820, 0xfb40, 0x0001, 0x0fce, 0x2801, + 0x1195, 0x3009, 0x1000, 0x6012, 0x93cc, 0x0000, 0x0024, 0x2801, 0x2c45, + 0x0000, 0x0024, 0x3413, 0x0024, 0x34b0, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0200, 0x2801, 0x1495, 0xb882, 0x0024, 0x3453, 0x0024, 0x3009, 0x13c0, + 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, 0x2c45, 0x0000, 0x0024, 0xb882, + 0x130c, 0x0000, 0x004d, 0x0021, 0x058f, 0x2821, 0x0340, 0x0001, 0x158e, + 0x2801, 0x25d5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x25d5, 0x0000, + 0x0024, 0x34c3, 0x184c, 0x3e13, 0xb80f, 0xf400, 0x4500, 0x0026, 0x9dcf, + 0x0001, 0x198e, 0x0000, 0xfa0d, 0x2926, 0x8e80, 0x3e10, 0x110c, 0x36f3, + 0x0024, 0x2801, 0x25c0, 0x36f3, 0x980f, 0x001c, 0xdd00, 0x001c, 0xd901, + 0x6ec2, 0x0024, 0x001c, 0xdd00, 0x2801, 0x1c95, 0x0018, 0xdbc1, 0x3413, + 0x184c, 0xf400, 0x4500, 0x2926, 0xc640, 0x3e00, 0x13cc, 0x2801, 0x2380, + 0x36f3, 0x0024, 0x6ec2, 0x0024, 0x003f, 0xc000, 0x2801, 0x1f15, 0x002a, + 0x4001, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0xafc0, 0x3e00, 0x13cc, + 0x2801, 0x2380, 0x36f3, 0x0024, 0xb400, 0x0024, 0xd100, 0x0024, 0x0000, + 0x0024, 0x2801, 0x2385, 0x0000, 0x0024, 0x3613, 0x0024, 0x3e11, 0x4024, + 0x2926, 0x8540, 0x3e01, 0x0024, 0x4080, 0x1b8c, 0x0000, 0x0024, 0x2801, + 0x2385, 0x0000, 0x0024, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0x8e80, + 0x3e10, 0x13cc, 0x36f3, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x0000, + 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x3110, 0x8024, 0x2826, 0xa8c4, + 0x31f0, 0xc024, 0x2a26, 0xad00, 0x34c3, 0x184c, 0x3410, 0x8024, 0x3430, + 0xc024, 0x0000, 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x0000, 0x0024, + 0x2801, 0x2c54, 0x4d06, 0x0024, 0x0000, 0x0200, 0x2922, 0x1885, 0x0001, + 0x2ac8, 0x0000, 0x0200, 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, 0xc024, + 0x291a, 0x8a40, 0x0000, 0x0024, 0x2922, 0x1880, 0x36f3, 0x0024, 0x0000, + 0x004d, 0x0021, 0x0ecf, 0x2821, 0x0bc0, 0x0001, 0x2bce, 0x2801, 0x0ec0, + 0x3c30, 0x4024, 0x0000, 0x190d, 0x0001, 0x2d4e, 0x2821, 0x0f80, 0x0021, + 0x420f, 0x0000, 0x190d, 0x3e00, 0x0024, 0x2801, 0xca80, 0x0021, 0x42c8, + 0x0020, 0xcd4f, 0x2820, 0xc780, 0x0001, 0x2f0e, 0x0006, 0xf017, 0x0000, + 0x0015, 0xb070, 0xbc15, 0x0001, 0x30ce, 0x0020, 0xdf0f, 0x2820, 0xcd80, + 0x0000, 0x190d, 0x3e00, 0x23c1, 0x2801, 0xca80, 0x0020, 0xdfc8, 0x3613, + 0x0024, 0x3e10, 0xb803, 0x3e14, 0x3811, 0x3e11, 0x3805, 0x3e00, 0x3801, + 0x0007, 0xc390, 0x0006, 0xa011, 0x3010, 0x0444, 0x3050, 0x4405, 0x6458, + 0x0302, 0xff94, 0x4081, 0x0003, 0xffc5, 0x48b6, 0x0024, 0xff82, 0x0024, + 0x42b2, 0x0042, 0xb458, 0x0003, 0x4cd6, 0x9801, 0xf248, 0x1bc0, 0xb58a, + 0x0024, 0x6de6, 0x1804, 0x0006, 0x0010, 0x3810, 0x9bc5, 0x3800, 0xc024, + 0x36f4, 0x1811, 0x36f0, 0x9803, 0x283e, 0x2d80, 0x0fff, 0xffc3, 0x2801, + 0x4600, 0x0000, 0x0024, 0x3413, 0x0024, 0x2801, 0x3a05, 0xf400, 0x4517, + 0x2801, 0x3e00, 0x6894, 0x13cc, 0x37b0, 0x184c, 0x6090, 0x1d51, 0x0000, + 0x0910, 0x3f00, 0x060c, 0x3100, 0x4024, 0x6016, 0xb812, 0x000c, 0x8012, + 0x2801, 0x3c91, 0xb884, 0x0024, 0x6894, 0x3002, 0x0000, 0x028d, 0x003a, + 0x5e0f, 0x0001, 0x4e0e, 0x2939, 0xb0c0, 0x3e10, 0x93cc, 0x4084, 0x9bd2, + 0x4282, 0x0024, 0x0000, 0x0040, 0x2801, 0x4005, 0x4292, 0x130c, 0x3443, + 0x0024, 0x2801, 0x4145, 0x000c, 0x8390, 0x2a01, 0x44c0, 0x3444, 0x0024, + 0x3073, 0x0024, 0xc090, 0x014c, 0x2801, 0x44c0, 0x3800, 0x0024, 0x000c, + 0x4113, 0xb880, 0x2380, 0x3304, 0x4024, 0x3800, 0x05cc, 0xcc92, 0x05cc, + 0x3910, 0x0024, 0x3910, 0x4024, 0x000c, 0x8110, 0x3910, 0x0024, 0x39f0, + 0x4024, 0x3810, 0x0024, 0x38d0, 0x4024, 0x3810, 0x0024, 0x38f0, 0x4024, + 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, + 0x3613, 0x0024, 0x2801, 0x4805, 0x6898, 0xb804, 0x0000, 0x0084, 0x293b, + 0x1cc0, 0x3613, 0x0024, 0x000c, 0x8117, 0x3711, 0x0024, 0x37d1, 0x4024, + 0x4e8a, 0x0024, 0x0000, 0x0015, 0x2801, 0x4ac5, 0xce9a, 0x0024, 0x3f11, + 0x0024, 0x3f01, 0x4024, 0x000c, 0x8197, 0x408a, 0x9bc4, 0x3f15, 0x4024, + 0x2801, 0x4d05, 0x4284, 0x3c15, 0x6590, 0x0024, 0x0000, 0x0024, 0x2839, + 0x53d5, 0x4284, 0x0024, 0x0000, 0x0024, 0x2801, 0x38d8, 0x458a, 0x0024, + 0x2a39, 0x53c0, 0x003e, 0x2d4f, 0x283a, 0x5ed5, 0x0001, 0x318e, 0x000c, + 0x4653, 0x0000, 0x0246, 0xffac, 0x0c01, 0x48be, 0x0024, 0x4162, 0x4546, + 0x6642, 0x4055, 0x3501, 0x8024, 0x0000, 0x0087, 0x667c, 0x4057, 0x000c, + 0x41d5, 0x283a, 0x62d5, 0x3501, 0x8024, 0x667c, 0x1c47, 0x3701, 0x8024, + 0x283a, 0x62d5, 0xc67c, 0x0024, 0x0000, 0x0024, 0x283a, 0x62c5, 0x0000, + 0x0024, 0x2a3a, 0x5ec0, 0x3009, 0x3851, 0x3e14, 0xf812, 0x3e12, 0xb817, + 0x3e11, 0x8024, 0x0006, 0x0293, 0x3301, 0x8024, 0x468c, 0x3804, 0x0006, + 0xa057, 0x2801, 0x5a04, 0x0006, 0x0011, 0x469c, 0x0024, 0x3be1, 0x8024, + 0x2801, 0x5a15, 0x0006, 0xc392, 0x3311, 0x0024, 0x33f1, 0x2844, 0x3009, + 0x2bc4, 0x0030, 0x04d2, 0x3311, 0x0024, 0x3a11, 0x0024, 0x3201, 0x8024, + 0x003f, 0xfc04, 0xb64c, 0x0fc4, 0xc648, 0x0024, 0x3a01, 0x0024, 0x3111, + 0x1fd3, 0x6498, 0x07c6, 0x868c, 0x2444, 0x0023, 0xffd2, 0x3901, 0x8e06, + 0x0030, 0x0551, 0x3911, 0x8e06, 0x3961, 0x9c44, 0xf400, 0x44c6, 0xd46c, + 0x1bc4, 0x36f1, 0xbc13, 0x2801, 0x6395, 0x36f2, 0x9817, 0x002b, 0xffd2, + 0x3383, 0x188c, 0x3e01, 0x8c06, 0x0006, 0xa097, 0x3009, 0x1c12, 0x3213, + 0x0024, 0x468c, 0xbc12, 0x002b, 0xffd2, 0xf400, 0x4197, 0x2801, 0x6084, + 0x3713, 0x0024, 0x2801, 0x60c5, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x3383, + 0x0024, 0x3009, 0x0c06, 0x468c, 0x4197, 0x0006, 0xa052, 0x2801, 0x62c4, + 0x3713, 0x2813, 0x2801, 0x6305, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x36f1, + 0x8024, 0x36f2, 0x9817, 0x36f4, 0xd812, 0x2100, 0x0000, 0x3904, 0x5bd1, + 0x2a01, 0x53ce, 0x3e11, 0x7804, 0x0030, 0x0257, 0x3701, 0x0024, 0x0013, + 0x4d05, 0xd45b, 0xe0e1, 0x0007, 0xc795, 0x2801, 0x6b15, 0x0fff, 0xff45, + 0x3511, 0x184c, 0x4488, 0xb808, 0x0006, 0x8a97, 0x2801, 0x6ac5, 0x3009, + 0x1c40, 0x3511, 0x1fc1, 0x0000, 0x0020, 0xac52, 0x1405, 0x6ce2, 0x0024, + 0x0000, 0x0024, 0x2801, 0x6ac1, 0x68c2, 0x0024, 0x291a, 0x8a40, 0x3e10, + 0x0024, 0x2921, 0xca80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3009, 0x1bc8, + 0x36f0, 0x1801, 0x3601, 0x5804, 0x3e13, 0x780f, 0x3e13, 0xb808, 0x0008, + 0x9b0f, 0x0001, 0x6dce, 0x2908, 0x9300, 0x0000, 0x004d, 0x36f3, 0x9808, + 0x2000, 0x0000, 0x36f3, 0x580f, 0x0007, 0x81d7, 0x3711, 0x8024, 0x3711, + 0xc024, 0x3700, 0x0024, 0x0000, 0x2001, 0xb012, 0x0024, 0x0034, 0x0000, + 0x2801, 0x7105, 0x0000, 0x01c1, 0x0030, 0x0117, 0x3f00, 0x0024, 0x0014, + 0xc000, 0x0000, 0x01c1, 0x4fce, 0x0024, 0xffea, 0x0024, 0x48b6, 0x0024, + 0x4384, 0x4097, 0xb886, 0x45c6, 0xfede, 0x0024, 0x4db6, 0x0024, 0x466c, + 0x0024, 0x0006, 0xc610, 0x8dd6, 0x8007, 0x0000, 0x00c6, 0xff6e, 0x0024, + 0x48b2, 0x0024, 0x0034, 0x2406, 0xffee, 0x0024, 0x2914, 0xaa80, 0x40b2, + 0x0024, 0xf1c6, 0x0024, 0xf1d6, 0x0024, 0x0000, 0x0201, 0x8d86, 0x0024, + 0x61de, 0x0024, 0x0006, 0xc612, 0x2801, 0x7781, 0x0006, 0xc713, 0x4c86, + 0x0024, 0x2912, 0x1180, 0x0006, 0xc351, 0x0006, 0x0210, 0x2912, 0x0d00, + 0x3810, 0x984c, 0xf200, 0x2043, 0x2808, 0xa000, 0x3800, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, + 0x3811, 0x0006, 0xa090, 0x2912, 0x0d00, 0x3e14, 0xc024, 0x4088, 0x8000, + 0x4080, 0x0024, 0x0007, 0x90d1, 0x2801, 0x7f45, 0x0000, 0x0024, 0x0007, + 0x9051, 0x3100, 0x4024, 0x4100, 0x0024, 0x3900, 0x0024, 0x0007, 0x90d1, + 0x0004, 0x0000, 0x31f0, 0x4024, 0x6014, 0x0400, 0x0000, 0x0024, 0x2801, + 0x8391, 0x4080, 0x0024, 0x0000, 0x0000, 0x2801, 0x8305, 0x0000, 0x0024, + 0x0007, 0x9053, 0x3300, 0x0024, 0x4080, 0x0024, 0x0000, 0x0000, 0x2801, + 0x8398, 0x0000, 0x0024, 0x0007, 0x9051, 0x3900, 0x0024, 0x3200, 0x504c, + 0x6410, 0x0024, 0x3cf0, 0x0000, 0x4080, 0x0024, 0x0006, 0xc691, 0x2801, + 0x9c45, 0x3009, 0x0400, 0x0000, 0x1001, 0x0007, 0x9051, 0x3100, 0x0024, + 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2801, 0x9089, 0x003f, 0xe000, 0x0006, + 0xc693, 0x3900, 0x0c00, 0x3009, 0x0001, 0x6014, 0x0024, 0x0007, 0x1ad0, + 0x2801, 0x9095, 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0301, 0x2801, + 0x8a85, 0x4090, 0x0024, 0x0000, 0x0024, 0x2801, 0x8b95, 0x0000, 0x0024, + 0x3009, 0x0000, 0xc012, 0x0024, 0x2801, 0x9080, 0x3009, 0x2001, 0x3009, + 0x0000, 0x6012, 0x0024, 0x0000, 0x0341, 0x2801, 0x8d95, 0x0000, 0x0024, + 0x6190, 0x0024, 0x2801, 0x9080, 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, + 0x0381, 0x2801, 0x8f55, 0x0000, 0x0024, 0x6190, 0x0024, 0x2801, 0x9080, + 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, 0x00c0, 0x2801, 0x9095, 0x0000, + 0x0024, 0x3009, 0x2000, 0x0006, 0xa090, 0x3009, 0x0000, 0x4080, 0x0024, + 0x0000, 0x0081, 0x2801, 0x9555, 0x0007, 0x8c13, 0x3300, 0x104c, 0xb010, + 0x0024, 0x0002, 0x8001, 0x2801, 0x97c5, 0x34f0, 0x0024, 0x2801, 0x9540, + 0x0000, 0x0024, 0x0006, 0xc351, 0x3009, 0x0000, 0x6090, 0x0024, 0x3009, + 0x2000, 0x2900, 0x0b80, 0x3009, 0x0405, 0x0006, 0xc6d1, 0x0006, 0xc690, + 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, 0x0006, 0xa093, 0x2801, + 0x93d1, 0xb880, 0x0024, 0x2801, 0xa500, 0x3009, 0x2c00, 0x4040, 0x0024, + 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2801, 0xa518, 0x0000, 0x0024, 0x0006, + 0xc693, 0x3009, 0x0c00, 0x3009, 0x0001, 0x6014, 0x0024, 0x0006, 0xc350, + 0x2801, 0xa501, 0x0000, 0x0024, 0x6090, 0x0024, 0x3009, 0x2c00, 0x3009, + 0x0005, 0x2900, 0x0b80, 0x0001, 0xa508, 0x3009, 0x0400, 0x4080, 0x0024, + 0x0003, 0x8000, 0x2801, 0xa505, 0x0000, 0x0024, 0x6400, 0x0024, 0x0000, + 0x0081, 0x2801, 0xa509, 0x0000, 0x0024, 0x0007, 0x8c13, 0x3300, 0x0024, + 0xb010, 0x0024, 0x0006, 0xc650, 0x2801, 0xa515, 0x0000, 0x0024, 0x0001, + 0x0002, 0x3413, 0x0000, 0x3009, 0x0401, 0x4010, 0x8406, 0x0000, 0x0281, + 0xa010, 0x13c1, 0x4122, 0x0024, 0x0000, 0x03c2, 0x6122, 0x8002, 0x462c, + 0x0024, 0x469c, 0x0024, 0xfee2, 0x0024, 0x48be, 0x0024, 0x6066, 0x8400, + 0x0006, 0xc350, 0x2801, 0xa501, 0x0000, 0x0024, 0x4090, 0x0024, 0x3009, + 0x2400, 0x2900, 0x0b80, 0x3009, 0x0005, 0x0007, 0x1b50, 0x2912, 0x0d00, + 0x3613, 0x0024, 0x3a00, 0x0380, 0x4080, 0x0024, 0x0000, 0x00c1, 0x2801, + 0xadc5, 0x3009, 0x0000, 0xb010, 0x008c, 0x4192, 0x0024, 0x6012, 0x0024, + 0x0006, 0xf051, 0x2801, 0xabd8, 0x3009, 0x0400, 0x0007, 0x1fd1, 0x30e3, + 0x0400, 0x4080, 0x0024, 0x0000, 0x0301, 0x2801, 0xadc5, 0x3009, 0x0000, + 0xb010, 0x0024, 0x0000, 0x0101, 0x6012, 0x0024, 0x0006, 0xf051, 0x2801, + 0xadd5, 0x0000, 0x0024, 0x3023, 0x0400, 0xf200, 0x184c, 0xb880, 0xa400, + 0x3009, 0x2000, 0x3009, 0x0441, 0x3e10, 0x4402, 0x2909, 0xa9c0, 0x3e10, + 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x1811, 0x36f1, 0x9807, + 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xf810, + 0x0001, 0x0010, 0x3e14, 0x7812, 0xb882, 0x3813, 0x2914, 0xbec0, 0x0000, + 0x2200, 0xb886, 0x12cc, 0x2801, 0xba40, 0x3454, 0x8024, 0x0001, 0x0000, + 0x3000, 0x984c, 0x4234, 0xb843, 0xf400, 0x4095, 0x003b, 0xffc2, 0x3500, + 0x4024, 0xb122, 0x0842, 0x4010, 0x0bc3, 0x4010, 0x0024, 0x4010, 0x0024, + 0x4010, 0x0024, 0x4d82, 0x4011, 0x2938, 0x0600, 0xf400, 0x4450, 0x3223, + 0x184c, 0x3210, 0x8024, 0x32d0, 0xc024, 0x2938, 0x0600, 0x4d82, 0x4450, + 0x3243, 0x1bc3, 0x6396, 0x0024, 0x0005, 0xdf90, 0x3000, 0x0024, 0x6302, + 0x0024, 0x0005, 0xe110, 0x2801, 0xb511, 0x0000, 0x0024, 0x2801, 0xc0c0, + 0x4086, 0x0024, 0x3200, 0x930c, 0x6398, 0x1111, 0x4244, 0x0844, 0xf400, + 0x4095, 0x3500, 0x584c, 0x4438, 0x0805, 0x453a, 0x4115, 0x3500, 0x8024, + 0x6122, 0x4155, 0x4280, 0x1404, 0x0001, 0x0002, 0x4244, 0x0024, 0x4244, + 0x0024, 0x4244, 0x0024, 0x4244, 0x0024, 0x2938, 0x2f80, 0xf400, 0x4090, + 0x6396, 0x0024, 0x0005, 0xdf50, 0x3000, 0x0024, 0x6302, 0x0024, 0x0005, + 0xe0d2, 0x2801, 0xbc51, 0x0000, 0x0381, 0x3073, 0x0024, 0x3023, 0x0024, + 0x3000, 0x0024, 0x6012, 0x0024, 0x0001, 0x2212, 0x2801, 0xc5d5, 0x0005, + 0x1453, 0x0001, 0x0011, 0x3093, 0x184c, 0x3000, 0x4024, 0x2900, 0x7680, + 0x3e00, 0x4024, 0x2801, 0xc7c0, 0x36f3, 0x0024, 0x0001, 0x0011, 0x0005, + 0xe3c1, 0x3613, 0x024c, 0x3e10, 0x4024, 0x3000, 0x8024, 0x2900, 0x5a00, + 0x3e00, 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x5812, 0x36f1, + 0xd810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, 0x00c1, 0xb880, 0xb803, 0x3e10, + 0x904c, 0x3e11, 0x3806, 0x3e11, 0xf810, 0x0006, 0xf450, 0x3e14, 0x7812, + 0x3e14, 0xc024, 0x3cf0, 0x2080, 0x3009, 0x23c0, 0x3009, 0x2380, 0x0000, + 0x0640, 0x3009, 0x2000, 0x2921, 0x9440, 0x0000, 0x00c0, 0x2921, 0xdd40, + 0x3613, 0x0024, 0xf400, 0x4004, 0x0000, 0x01c0, 0x6400, 0x0024, 0x0000, + 0x00c0, 0x2801, 0xeac5, 0x0000, 0x01c1, 0x6412, 0x4100, 0x0006, 0x0581, + 0x2801, 0xe041, 0x4412, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, + 0x0000, 0x0000, 0x0024, 0x0000, 0x0641, 0x0006, 0xf410, 0x3613, 0x0000, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0xd615, 0x0000, 0x0024, 0x3009, + 0x2004, 0x2900, 0xb3c0, 0x3e01, 0x0024, 0x2801, 0xe040, 0x36f3, 0x0024, + 0x0000, 0x0641, 0x0006, 0xf410, 0x3613, 0x0000, 0x6012, 0x0024, 0x0000, + 0x0024, 0x2801, 0xd915, 0x0000, 0x0024, 0x3009, 0x2004, 0x2900, 0xa1c0, + 0x3e01, 0x0024, 0x2801, 0xe040, 0x36f3, 0x0024, 0x0006, 0xf450, 0x3613, + 0x0000, 0x6090, 0x3804, 0x2900, 0xb3c0, 0x3009, 0x2000, 0x2801, 0xe040, + 0x36f3, 0x0024, 0x2923, 0x4f00, 0x0007, 0x2050, 0x2801, 0xe040, 0x3009, + 0x2000, 0x2923, 0x7580, 0x0001, 0xe048, 0x34d3, 0x184c, 0x3430, 0x0024, + 0x2922, 0x4fc0, 0x3e00, 0x0024, 0x2801, 0xe040, 0x36f3, 0x0024, 0x0007, + 0x2050, 0x0000, 0x3fc0, 0x3613, 0x0024, 0x2923, 0x8480, 0x3e00, 0x0024, + 0x36f3, 0x2000, 0x0000, 0x1800, 0x3413, 0x0024, 0xf400, 0x4510, 0x34f0, + 0x4024, 0x6192, 0x0024, 0x6014, 0x2001, 0x0007, 0x2051, 0x2801, 0xe2c1, + 0x0000, 0x0280, 0x3009, 0x2400, 0x3009, 0x0400, 0x4080, 0x0024, 0x0006, + 0xf352, 0x2801, 0xebd5, 0x3009, 0x0842, 0x3009, 0x0bc3, 0x4d86, 0x0024, + 0x0000, 0x0201, 0x2801, 0xe705, 0x0030, 0x0013, 0x0006, 0x8a93, 0x3009, + 0x0c40, 0x3009, 0x0fc1, 0x6cde, 0x0024, 0x0000, 0x0201, 0x2801, 0xebc1, + 0x0030, 0x0013, 0x3300, 0x0024, 0xb010, 0x0024, 0x0000, 0x0100, 0x2801, + 0xebd5, 0x0000, 0x00c1, 0x2921, 0x9440, 0x3613, 0x0024, 0x2921, 0xdd40, + 0x3613, 0x0024, 0xf400, 0x4004, 0x0000, 0x01c0, 0x6400, 0x0024, 0x0000, + 0x01c1, 0x2801, 0xd215, 0x0000, 0x00c0, 0x2921, 0x9440, 0x3613, 0x0024, + 0x2921, 0xc300, 0x0000, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x5812, 0x36f1, + 0xd810, 0x36f1, 0x1806, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7810, 0x3e14, + 0x7812, 0x3e14, 0xc024, 0x2922, 0x1880, 0x0000, 0x0180, 0x2921, 0xdd40, + 0x6892, 0x184c, 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, 0xf3c5, 0x0000, + 0x0024, 0x2802, 0x2f40, 0xb880, 0x0024, 0x2921, 0xdd40, 0x6892, 0x184c, + 0x4080, 0x0024, 0x0000, 0x0181, 0x2801, 0xf5d5, 0x0000, 0x0024, 0x2802, + 0x2f40, 0xb880, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0101, 0x2801, 0xf7c5, 0x0000, 0x0024, 0x2802, 0x2f40, 0xb880, + 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, 0x0000, 0x00c1, + 0x2801, 0xf9c5, 0x0000, 0x0024, 0x2802, 0x2f40, 0xb880, 0x0024, 0x2921, + 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, 0x0000, 0x0141, 0x2801, 0xfbc5, + 0x0006, 0xf250, 0x2802, 0x2f40, 0xb880, 0x0024, 0x2921, 0xdd40, 0x3613, + 0x0024, 0x0000, 0x0101, 0x2921, 0xdd40, 0x3613, 0x2000, 0x0000, 0x03c1, + 0x6012, 0x03cc, 0x3613, 0x2000, 0x2802, 0x0115, 0x0006, 0xf051, 0x3009, + 0x3841, 0x2921, 0xdd40, 0x0000, 0x0201, 0xb080, 0x024c, 0x3009, 0x2000, + 0x2921, 0xdd40, 0x0000, 0x0401, 0x3009, 0x0401, 0xc100, 0x0024, 0x2802, + 0x0240, 0x3009, 0x2400, 0x3009, 0x0002, 0x2920, 0x5d00, 0x3e00, 0x8024, + 0x36f3, 0x024c, 0x3009, 0x2000, 0x0000, 0x0101, 0x2921, 0xdd40, 0x3613, + 0x0024, 0x0000, 0x0141, 0x3013, 0x0024, 0x3009, 0x21c0, 0x3009, 0x0000, + 0x6012, 0x0024, 0x0007, 0x1b51, 0x2802, 0x1395, 0x0000, 0x0101, 0x0007, + 0xc251, 0x2921, 0xdd40, 0x3613, 0x0024, 0x0000, 0x03c1, 0x6012, 0x2400, + 0x3100, 0x984c, 0x2802, 0x0ad5, 0x0007, 0xc292, 0x3009, 0x3841, 0x2921, + 0xdd40, 0x0000, 0x0201, 0x4082, 0x044c, 0xb080, 0x0024, 0x3910, 0x0024, + 0x39f0, 0x7841, 0x2921, 0xdd40, 0x0000, 0x0401, 0x3211, 0x1bcc, 0xb182, + 0x0bc5, 0xcec2, 0x0024, 0x3a10, 0x0024, 0x2802, 0x0c00, 0x3af0, 0x4024, + 0x2920, 0x5d00, 0x3e00, 0x8024, 0x36f3, 0x044c, 0x3910, 0x0024, 0x39f0, + 0x4024, 0x0007, 0x1b52, 0x0000, 0x0141, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x3111, 0x2240, 0xb880, 0x03cc, 0x31f1, 0x6800, 0xb182, 0x8000, 0x6ce6, + 0x0024, 0x002e, 0xe002, 0x2802, 0x1a85, 0xb886, 0x0024, 0x6de2, 0x0b8c, + 0x0000, 0x00c1, 0x2802, 0x1251, 0x3009, 0x0800, 0xb010, 0x0024, 0x4192, + 0x0024, 0x6012, 0x0024, 0x0007, 0x1b52, 0x2802, 0x1258, 0x0000, 0x0024, + 0x6890, 0xa004, 0x2802, 0x1a80, 0x3009, 0x2800, 0x4e82, 0x0024, 0x0000, + 0x0020, 0xf2c2, 0x0024, 0x2802, 0x1a80, 0x3009, 0x2000, 0x3009, 0x07c0, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2802, 0x1a85, 0x0000, 0x0024, 0x3093, + 0x0400, 0x4080, 0x03cc, 0x0017, 0x7001, 0x2802, 0x1995, 0x3009, 0x0000, + 0x6012, 0x0024, 0x0007, 0x1b50, 0x2802, 0x1901, 0xb880, 0x0024, 0x0000, + 0x00c1, 0x31f3, 0x0024, 0x3009, 0x0400, 0xb010, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0000, 0x2802, 0x1989, 0x0000, 0x0024, 0x2802, 0x1a80, 0x3009, + 0x2000, 0x0006, 0xf050, 0x3009, 0x0000, 0x4000, 0x0024, 0x3009, 0x2000, + 0x0000, 0x0081, 0x0006, 0xf250, 0x3009, 0x0000, 0x6012, 0x0024, 0x0007, + 0xc151, 0x2802, 0x1cc5, 0x0000, 0x0024, 0x2802, 0x2f40, 0xb880, 0x0024, + 0x2921, 0xdd40, 0x6892, 0x184c, 0x6892, 0x2400, 0x2921, 0xdd40, 0x3009, + 0x184c, 0x4080, 0x0024, 0x0000, 0x0381, 0x2802, 0x1f85, 0x0000, 0x0024, + 0x2921, 0xdd40, 0x3613, 0x0024, 0x2921, 0xdd40, 0x6892, 0x184c, 0x4080, + 0x0024, 0x0000, 0x0240, 0x2802, 0x2205, 0x0000, 0x00c1, 0x2921, 0xdd40, + 0x6892, 0x184c, 0x0000, 0x00c1, 0x0000, 0x0240, 0x0006, 0x0752, 0x2922, + 0x1880, 0x3613, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x2800, + 0x0000, 0x0201, 0x2802, 0x2515, 0x3613, 0x0024, 0x2921, 0xdd40, 0x0002, + 0x2788, 0x3613, 0x0024, 0x4090, 0x1bcc, 0x0000, 0x0241, 0x2802, 0x2715, + 0x0006, 0x07d3, 0x2921, 0xdd40, 0x3613, 0x0024, 0x2802, 0x2780, 0x3b00, + 0x0024, 0x2802, 0x2f40, 0xb880, 0x0024, 0x0006, 0x0813, 0xb880, 0x184c, + 0x2921, 0xdd40, 0x6892, 0x2c00, 0x4080, 0x0024, 0x0006, 0x0810, 0x2802, + 0x2d05, 0x0000, 0x4003, 0x3000, 0x184c, 0xff86, 0x0024, 0x48b6, 0x0024, + 0x2921, 0xdd40, 0x6892, 0x2002, 0x0000, 0x0201, 0x2921, 0xdd40, 0x4088, + 0x184c, 0x3000, 0x4024, 0x4100, 0x0024, 0x4488, 0x2000, 0x0000, 0x4003, + 0x2802, 0x2995, 0x0006, 0x0810, 0x2921, 0xdd40, 0x6892, 0x184c, 0x4080, + 0x0024, 0x0000, 0x0201, 0x2802, 0x2f05, 0x0000, 0x0024, 0x2921, 0xdd40, + 0x3613, 0x0024, 0x6890, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x5812, 0x36f1, + 0x5810, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, + 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x0000, 0x0081, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, + 0xb807, 0x3e14, 0x3811, 0x0006, 0xf250, 0x3e04, 0xb813, 0x3009, 0x0000, + 0x6012, 0x0024, 0x003f, 0xff01, 0x2802, 0x3a05, 0x0006, 0x07d1, 0x6194, + 0x0400, 0x0000, 0x0041, 0xa020, 0x984c, 0x0000, 0x01c2, 0xfe02, 0x0024, + 0x48b2, 0x0024, 0x3e10, 0x0024, 0x2921, 0xca80, 0x3e00, 0x4024, 0x3100, + 0x5bcc, 0x2921, 0xdd40, 0xb122, 0x0024, 0x291a, 0x8a40, 0x0002, 0x4c08, + 0x0007, 0x2052, 0x0006, 0x8a93, 0x3100, 0x184c, 0xa010, 0x0024, 0x0000, + 0x0041, 0x6090, 0x0024, 0x2922, 0x1880, 0x6090, 0x0024, 0xb880, 0x010c, + 0x3100, 0x2800, 0xfe02, 0x8c44, 0x3613, 0x0fc5, 0x4eb2, 0x0024, 0x3009, + 0x2040, 0x0000, 0x00c0, 0x2921, 0xbb80, 0x3e00, 0x23c1, 0x0000, 0x01c1, + 0x6012, 0x0024, 0x0003, 0xf680, 0x2802, 0x4055, 0x0000, 0x0024, 0x36f3, + 0x0024, 0x291a, 0x8a40, 0x0002, 0x4c08, 0x2901, 0xca80, 0x3e00, 0x0024, + 0x3413, 0x0040, 0x36f3, 0x03c1, 0x3009, 0x0c44, 0x3009, 0x0fc5, 0x6ce2, + 0x0024, 0x3c10, 0x0024, 0xbc82, 0x33c1, 0x3410, 0x2040, 0x34e0, 0x63c1, + 0x4c82, 0x0024, 0x0000, 0x0024, 0x2802, 0x4909, 0x4c82, 0x0024, 0x0000, + 0x01c4, 0x4c86, 0x184c, 0x003f, 0xff40, 0xad06, 0x0024, 0x3e10, 0x8024, + 0x2921, 0xca80, 0x3e00, 0xc024, 0x36f3, 0x0024, 0x2921, 0x9440, 0x0000, + 0x0080, 0xb88a, 0x104c, 0x3410, 0x0c46, 0x34e0, 0x4fc7, 0xbce2, 0x984c, + 0x4cf2, 0x0024, 0x3e10, 0x0024, 0x2921, 0x9780, 0x3e00, 0x4024, 0x2802, + 0x4b00, 0x36e3, 0x0024, 0x0000, 0x0024, 0x2802, 0x4b18, 0x0000, 0x0024, + 0x4ce6, 0x184c, 0x3e10, 0x8024, 0x2921, 0x9780, 0x3e00, 0xc024, 0x36e3, + 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2922, 0x1880, 0x3613, 0x0024, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, + 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, + 0x3e10, 0xf804, 0x3e14, 0x3811, 0x0006, 0x8a91, 0x0006, 0x0790, 0x3e14, + 0xb813, 0x0007, 0x8b52, 0x3e13, 0xf80e, 0x3e03, 0x504c, 0xb880, 0x0024, + 0x3c00, 0x33c0, 0x2921, 0xb380, 0x3800, 0x0024, 0x2920, 0x6a00, 0x0030, + 0x0253, 0x0000, 0x0400, 0xb882, 0xa440, 0xb880, 0xa7c1, 0x3a00, 0x0024, + 0x0013, 0x1040, 0x3b00, 0x0024, 0x0000, 0x0180, 0x2922, 0x1880, 0x3613, + 0x0024, 0x4f82, 0x0024, 0x003f, 0xf801, 0xb010, 0x0024, 0x0015, 0xb801, + 0x6012, 0x0024, 0x0007, 0x8a50, 0x2802, 0x73d5, 0x0000, 0x0201, 0x0006, + 0x8a90, 0x2921, 0xdd40, 0x3613, 0x0024, 0x003f, 0xfe00, 0x3613, 0x0042, + 0xb882, 0x83c3, 0xbdc2, 0x0024, 0x3009, 0x2040, 0x2921, 0xdd40, 0x6892, + 0xa3c1, 0x4080, 0x0024, 0x0000, 0x0024, 0x2802, 0x5e95, 0x0000, 0x0024, + 0x2901, 0xee80, 0x0006, 0x0791, 0x4080, 0x2400, 0x0006, 0xf052, 0x2802, + 0x5e85, 0x0000, 0x0024, 0x3613, 0x0841, 0x3e10, 0x4802, 0x2909, 0xa9c0, + 0x3e10, 0x8024, 0x36e3, 0x0024, 0x0006, 0x0791, 0x3100, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2921, 0xc305, 0x0002, 0x6f48, 0x0006, 0x0752, + 0xb880, 0x104c, 0x3613, 0x33c0, 0x2922, 0x1880, 0x0000, 0x0100, 0x3200, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2902, 0x31d5, 0x0002, 0x67c8, + 0x0006, 0x07d3, 0xb880, 0x0024, 0x0006, 0x07d0, 0x3b00, 0x0024, 0x0000, + 0x0201, 0x2921, 0xdd40, 0x3613, 0x0024, 0x0000, 0x00c1, 0x3423, 0x0024, + 0x3c00, 0x0024, 0xa010, 0x0001, 0x4100, 0x0024, 0x0000, 0x3fc1, 0x3800, + 0x0024, 0x34e0, 0x0024, 0x6012, 0x0024, 0x0006, 0x07d0, 0x2802, 0x6385, + 0x0000, 0x0024, 0x2902, 0x31c0, 0x0000, 0x0024, 0x0006, 0x0810, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2802, 0x6ec5, 0x0000, 0x0024, + 0xf200, 0x184c, 0xf200, 0x0024, 0xf200, 0x0024, 0xb182, 0x3840, 0x2921, + 0xca80, 0x3e00, 0x4024, 0x0000, 0x01c1, 0x291a, 0x8a40, 0x36e3, 0x0024, + 0xb888, 0x4411, 0x3000, 0x0024, 0xb012, 0x0024, 0x6410, 0x2001, 0x0000, + 0x0024, 0x2802, 0x6ec1, 0x0000, 0x0024, 0x4192, 0x0024, 0x2402, 0x6e81, + 0x0000, 0x0024, 0x2921, 0xdd40, 0x6892, 0x184c, 0x6498, 0x0024, 0x2921, + 0xc300, 0x0000, 0x0024, 0x291a, 0x8a40, 0x3413, 0x0024, 0xf400, 0x4512, + 0x0030, 0x0010, 0x0000, 0x0201, 0x2900, 0x0c80, 0x34f3, 0x0024, 0x3000, + 0x0024, 0xb010, 0x0024, 0x0000, 0x0100, 0x2802, 0x8095, 0x0000, 0x0401, + 0x2922, 0x1880, 0x3613, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x2802, + 0x7ec0, 0xb78e, 0x4006, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2802, 0x8089, 0xf292, 0x0024, 0x6012, 0x904c, 0x0006, 0x0791, 0x2802, + 0x7718, 0x3100, 0x0024, 0x3000, 0x0024, 0x4090, 0x0024, 0x3800, 0x0024, + 0x3100, 0x0024, 0x4080, 0x4512, 0x34f3, 0x184c, 0x2802, 0x79d5, 0x0007, + 0x0553, 0x36f3, 0x0800, 0x6090, 0x0024, 0x4080, 0xa800, 0x0000, 0x0024, + 0x2802, 0x8088, 0x0000, 0x0024, 0x3009, 0x184c, 0x0006, 0xf312, 0x4ffe, + 0xb841, 0x2921, 0xdd40, 0x6892, 0x41c7, 0xb182, 0x9bcc, 0x291a, 0x8a40, + 0xcfce, 0x0024, 0x0004, 0x0001, 0xb880, 0x010c, 0x6890, 0x2000, 0x0007, + 0x80d0, 0xb880, 0xa800, 0x3000, 0x2c00, 0x0007, 0x1ad0, 0xff82, 0x0024, + 0x48b2, 0x0024, 0xf400, 0x4040, 0x0000, 0x03c1, 0xb010, 0x0024, 0x3009, + 0x2000, 0x0000, 0x0201, 0x0030, 0x0010, 0x3000, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0180, 0x2802, 0x55c5, 0x0000, 0x0024, 0x6890, 0x1bcd, 0x36f3, + 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f0, 0xd804, 0x36f0, 0x5802, + 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, + 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0012, 0x5103, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x380d, 0x0030, 0x0250, 0x3e13, 0xf80e, + 0xbe8b, 0x83e0, 0x290c, 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, 0x4086, + 0x984c, 0x0000, 0x00ce, 0x2402, 0x8a8e, 0x3009, 0x1bc0, 0x0000, 0x01c3, + 0xae3a, 0x184c, 0x0000, 0x0043, 0x3009, 0x3842, 0x290c, 0x4840, 0x3009, + 0x3840, 0x4084, 0x9bc0, 0xfe26, 0x9bc2, 0xceba, 0x0024, 0x4e8e, 0x0024, + 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0000, 0x0102, 0x2802, 0x8fc5, 0x0030, + 0x0010, 0x0000, 0x0206, 0x3613, 0x0024, 0x290c, 0x4840, 0x3009, 0x3840, + 0x3000, 0xdbc0, 0xb366, 0x0024, 0x0000, 0x0024, 0x2802, 0x8fd5, 0x4e8e, + 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0030, 0x0010, 0x2802, 0x8c95, + 0x0000, 0x0206, 0x36f3, 0xd80e, 0x36f4, 0x180d, 0x36f1, 0x9807, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6480, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1b40, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x144e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x7980, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x01a4, /*copy 420*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x0012, /*copy 18*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x0750, 0x075c, 0x076f, 0x0768, 0x0773, 0x0775, 0x077b, + 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 5594 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/patches_pitch.h b/targets/esp32/components/VS1053/include/patches_pitch.h new file mode 100644 index 00000000..5c2effe7 --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_pitch.h @@ -0,0 +1,688 @@ + +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x0020, /*copy 32*/ + 0x2a00, 0xc000, 0x2a02, 0x75c0, 0x3e12, 0xb817, 0x3e14, 0xf812, 0x3e01, + 0xb811, 0x0007, 0x9717, 0x0020, 0xffd2, 0x0030, 0x11d1, 0x3111, 0x8024, + 0x3704, 0xc024, 0x3b81, 0x8024, 0x3101, 0x8024, 0x3b81, 0x8024, 0x3f04, + 0xc024, 0x2808, 0x4800, 0x36f1, 0x9811, 0x0007, 0x0001, /*copy 1*/ + 0x8060, 0x0006, 0x0516, /*copy 1302*/ + 0xf400, 0x4095, 0x0000, 0x02c2, 0x6124, 0x0024, 0x0000, 0x0024, 0x2800, + 0x1ac5, 0x4192, 0x4542, 0x0000, 0x0041, 0x2000, 0x0015, 0x0030, 0x0317, + 0x2000, 0x0000, 0x3f00, 0x4024, 0x2000, 0x0000, 0x0000, 0x0000, 0x3e12, + 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, 0x8257, 0x3700, 0x984c, + 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, 0x2910, 0x0181, 0x0000, + 0x1bc8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, 0x0195, 0x0000, 0x1bc8, + 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2945, 0x3e13, 0x780e, 0x3e11, + 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, 0xb808, 0x003f, 0xe004, + 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, 0x48be, 0x4497, 0x4090, + 0x1c46, 0xf06c, 0x0024, 0x2400, 0x2580, 0x6090, 0x41c3, 0x6628, 0x1c47, + 0x0000, 0x0024, 0x2800, 0x2449, 0xf07e, 0x0024, 0xf400, 0x4182, 0x673a, + 0x1c46, 0x0000, 0x0024, 0x2800, 0x2589, 0xf06c, 0x0024, 0xf400, 0x41c3, + 0x0000, 0x0024, 0x4224, 0x3442, 0x2902, 0xb7c0, 0x4336, 0x37c3, 0x0000, + 0x1805, 0x2902, 0xb7c0, 0x4508, 0x40c2, 0x450a, 0x9808, 0x0000, 0x0207, + 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, 0x3d01, 0x5bc1, 0x36f3, + 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, 0x580e, 0x0007, 0x8257, + 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, 0xd428, 0x3c02, 0x0006, + 0xc717, 0x2800, 0x2d05, 0x4284, 0x0024, 0x3613, 0x3c02, 0x0006, 0xc357, + 0x2901, 0x6b00, 0x3e11, 0x5c05, 0x4284, 0x1bc5, 0x0007, 0x8257, 0x2800, + 0x3285, 0x0002, 0x0001, 0x3701, 0x0024, 0x0006, 0xc357, 0xb412, 0x9c02, + 0x002e, 0xe001, 0x2800, 0x3005, 0x6212, 0x0024, 0x0000, 0x0024, 0x2800, + 0x3295, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, 0x0024, 0x3613, 0x0024, + 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, 0x2900, 0x4b40, 0x0006, + 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, 0x8257, 0x3700, 0x8024, + 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x3491, 0x3600, 0x9844, 0x2900, + 0x3a40, 0x0000, 0x3508, 0x2911, 0xf140, 0x0000, 0x0024, 0x0030, 0x0057, + 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, 0xa024, 0x164c, 0x8000, + 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, 0x6d82, 0xd024, 0x44c0, + 0x0006, 0xa402, 0x2800, 0x3955, 0xd024, 0x0024, 0x0000, 0x0000, 0x2800, + 0x3955, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, 0x8024, 0x36f2, 0x1800, + 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, 0x3e13, 0xb80d, 0x3e13, + 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0xf801, + 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, 0xbf8e, 0x9c42, 0x3e01, + 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, 0x8250, 0x0fff, 0xfd85, + 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, 0x2800, 0x4091, 0xf25a, + 0x104c, 0x34f3, 0x0024, 0x2800, 0x4091, 0x0000, 0x0024, 0x3413, 0x084c, + 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, 0x2400, 0x42c0, 0x4efa, + 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, 0x4d64, 0x48b2, 0xa201, + 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, 0x36f4, 0xd801, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0xd80a, 0x36f3, 0x980d, + 0x2000, 0x0000, 0x36f4, 0x5810, 0x36f3, 0x0024, 0x3009, 0x3848, 0x3e14, + 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, + 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, 0x9e40, 0x3604, 0x1811, 0x3613, + 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, + 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x36f4, 0x1811, 0x3009, + 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e13, 0x7801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, + 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, 0x34e5, 0xc024, 0x3524, + 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, 0x4a0c, 0x3d44, 0x8024, + 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, 0x6010, 0x3400, 0x3710, + 0x8024, 0x2800, 0x5704, 0x3af0, 0x8024, 0x3df0, 0x0024, 0x3591, 0x4024, + 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, 0x4020, 0x1753, 0xbf8e, + 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, 0x550e, 0xfe6d, 0x2819, + 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, 0xad56, 0x904c, 0xaf5e, + 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, 0x2046, 0x3cf4, 0x0024, + 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, 0x2800, 0x4f95, 0x3c00, + 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0x5801, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x2814, 0x9c91, + 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3655, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb810, 0x3e13, + 0xf80e, 0x3e03, 0x534c, 0x3450, 0x4024, 0x6814, 0x0024, 0x0000, 0x0024, + 0x2800, 0x7618, 0x4192, 0x0024, 0x2400, 0x75c1, 0x0000, 0x0024, 0xf400, + 0x4450, 0x2938, 0x1880, 0x3613, 0x0024, 0x3c10, 0x050c, 0x3c10, 0x4024, + 0x3c90, 0x8024, 0x34f3, 0x0024, 0x3464, 0x0024, 0x3011, 0x0c40, 0x3011, + 0x4c41, 0x2915, 0x9900, 0x3011, 0x8f82, 0x3411, 0x2c40, 0x3411, 0x6c41, + 0x2915, 0xa580, 0x34e1, 0xaf82, 0x3009, 0x3040, 0x4c8a, 0x0040, 0x3010, + 0x7041, 0x2800, 0x6854, 0x3010, 0xb382, 0x3411, 0x0024, 0x3411, 0x6c44, + 0x34e1, 0xac45, 0xbe8a, 0xaf86, 0x0fe0, 0x0006, 0x3009, 0x3044, 0x3009, + 0x3045, 0x3009, 0x3386, 0x3411, 0x0024, 0x3411, 0x4ccc, 0x2915, 0x9900, + 0x34e1, 0x984c, 0x3e10, 0x7800, 0x3009, 0x3802, 0x3011, 0x0c40, 0x3011, + 0x4c41, 0x2915, 0x9900, 0x30e1, 0x8f82, 0x3009, 0x1bc6, 0x2915, 0xa940, + 0x36f1, 0x5804, 0x3011, 0x2c40, 0x3011, 0x6c41, 0x30b1, 0xac42, 0x3009, + 0x0c40, 0x3009, 0x0c41, 0x2915, 0x9900, 0x3613, 0x0f82, 0x3e10, 0x7800, + 0x3009, 0x3802, 0x3010, 0x1044, 0x3010, 0x5045, 0x2915, 0x9900, 0x3010, + 0x9386, 0x3009, 0x1bc6, 0x2915, 0xa940, 0x36f1, 0x5804, 0xf1ca, 0xac40, + 0x4ce2, 0xac41, 0x3009, 0x2ec2, 0x2800, 0x7112, 0x629c, 0x0024, 0xf1c2, + 0x4182, 0x3c10, 0x0c44, 0x3c10, 0x4c45, 0x2915, 0x4780, 0x3ce0, 0x8f86, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2800, 0x75d5, 0x0020, 0x0000, 0x3411, + 0x0c40, 0x3411, 0x4c41, 0x2915, 0xb780, 0x34e1, 0x8f82, 0x0000, 0x03c3, + 0x4234, 0x0024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2915, 0x4355, 0x0000, + 0x75c8, 0x0000, 0x0000, 0x3a10, 0x0d8c, 0x36f3, 0x538c, 0x36f3, 0xd80e, + 0x36f1, 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3645, + 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, + 0x3e11, 0xb810, 0x3e13, 0xf80e, 0x3e03, 0x534c, 0x3440, 0x4024, 0x4192, + 0x0024, 0x2400, 0x91c1, 0x0000, 0x0024, 0xb68c, 0x4450, 0x2938, 0x1880, + 0x3613, 0x050c, 0x3c10, 0x0c40, 0x3c10, 0x4c41, 0x3ce0, 0x8f82, 0x003c, + 0x2584, 0x2915, 0x9900, 0x0018, 0x8245, 0x3411, 0x2c40, 0x3411, 0x6c41, + 0x2915, 0xa580, 0x34e1, 0xac42, 0x4c8a, 0xb040, 0x3009, 0x3041, 0x2800, + 0x82d4, 0x3009, 0x3382, 0x3411, 0x0f4c, 0x3411, 0x6c44, 0x34e1, 0xac45, + 0xbe8a, 0xac46, 0x499c, 0xb044, 0xf38c, 0xb045, 0x3009, 0x3386, 0x3009, + 0x0c40, 0x3009, 0x0c41, 0xf1ca, 0x8f82, 0x4ce2, 0x1044, 0x3411, 0x4024, + 0x2800, 0x8512, 0x4294, 0x1386, 0x6294, 0x0024, 0xf1c2, 0x0024, 0x4e8a, + 0x4195, 0x35e3, 0x0024, 0x2915, 0xa955, 0xf400, 0x4546, 0x3009, 0x2c40, + 0x3009, 0x2c41, 0x3009, 0x2c42, 0x3009, 0x0c40, 0x3009, 0x0c41, 0xf1ca, + 0x8f82, 0x4ce2, 0x9044, 0x3009, 0x1045, 0x2800, 0x8985, 0x3009, 0x1386, + 0x2800, 0x8992, 0x4294, 0x0024, 0x6294, 0x0024, 0xf1c2, 0x0024, 0x4e8a, + 0x4195, 0x35e3, 0x0024, 0x2915, 0xa955, 0xf400, 0x4546, 0xf1ca, 0xac40, + 0x4ce2, 0xac41, 0x3009, 0x2ec2, 0x2800, 0x8c12, 0x629c, 0x0024, 0xf1c2, + 0x4182, 0x3c20, 0x0c84, 0x3cf0, 0x8fc6, 0x6264, 0x4017, 0x3cf0, 0x4fc5, + 0x2800, 0x91c8, 0x0020, 0x0000, 0x2800, 0x8f19, 0xf400, 0x45c0, 0x6cea, + 0x0024, 0x0000, 0x0024, 0x2800, 0x91c9, 0x0020, 0x0000, 0x3411, 0x0c40, + 0x3411, 0x4c41, 0x2915, 0xb780, 0x34e1, 0x8f82, 0x0000, 0x03c3, 0x4234, + 0x0024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2915, 0x4355, 0x0000, 0x91c8, + 0x0000, 0x0000, 0x3a10, 0x0d8c, 0x36f3, 0x53cc, 0x36f3, 0xd80e, 0x36f1, + 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0xf400, + 0x4595, 0x35e3, 0x3840, 0x3e13, 0xf80e, 0x3e13, 0x7808, 0x3510, 0x0024, + 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, + 0x0024, 0x0001, 0xce8e, 0x002b, 0xb30f, 0x292d, 0xa940, 0x0000, 0x004d, + 0x36d3, 0x0024, 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, + 0x1800, 0xf400, 0x4595, 0x35f3, 0x3840, 0x3e13, 0xf80e, 0x3e13, 0x7808, + 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, 0x0024, 0x0000, + 0x9dce, 0x0028, 0x088f, 0x2927, 0xff80, 0x0000, 0x008d, 0x36e3, 0x0024, + 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, 0x1800, 0x0028, + 0x2b0f, 0x0000, 0xa34e, 0x2828, 0x0b15, 0x0007, 0x2605, 0x3613, 0x0001, + 0x3e14, 0x3811, 0x0001, 0x0011, 0x0001, 0xcc10, 0x2915, 0x94c0, 0x0000, + 0x4000, 0x3e10, 0x534c, 0x3430, 0xc024, 0x3e10, 0xc024, 0x2927, 0xc4c0, + 0x3e01, 0x0024, 0x36d3, 0x0024, 0x0001, 0x0011, 0x0001, 0xcc10, 0x2915, + 0x94c0, 0x0000, 0x4000, 0x2828, 0x0b00, 0x36f4, 0x1811, 0x3e00, 0x0024, + 0x2800, 0xa740, 0x0028, 0x2bc8, 0x3605, 0x7840, 0x3e13, 0x780e, 0x3e13, + 0xf808, 0x3e05, 0x4024, 0x0000, 0x458e, 0x0027, 0x9e0f, 0x2922, 0xa6c0, + 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, + 0x0000, 0x3009, 0x1800, 0xf400, 0x4595, 0x35d3, 0x3840, 0x3e13, 0xf80e, + 0x3e13, 0x7808, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e10, + 0x0024, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, 0x0024, + 0x0000, 0xac8e, 0x0025, 0xf54f, 0x2925, 0xe580, 0x0000, 0x004d, 0x36c3, + 0x0024, 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, 0x1800, + 0x3433, 0x0000, 0x6890, 0x3040, 0x3cc0, 0xa000, 0x0008, 0x6201, 0x000d, + 0x3500, 0x3613, 0x110c, 0x3e10, 0x0024, 0x3e10, 0x4024, 0x34c0, 0x8024, + 0x2900, 0x94c0, 0x3e00, 0x8024, 0x0026, 0x0a4f, 0x0000, 0xb04e, 0x2825, + 0xf880, 0x0000, 0x07cd, 0x0000, 0x0801, 0x6012, 0x0024, 0x0000, 0x0024, + 0x2826, 0x0a85, 0x0000, 0x0024, 0x2800, 0xad40, 0x0000, 0x0024, 0x3605, + 0x7840, 0x3e13, 0x780e, 0x3e13, 0xf808, 0x3e05, 0x4024, 0x0000, 0xb54e, + 0x0022, 0xf54f, 0x2922, 0xda80, 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, + 0xd808, 0x36f3, 0x580e, 0x2000, 0x0000, 0x3009, 0x1800, 0x3e00, 0x0024, + 0x2800, 0x9980, 0x0022, 0xf608, 0x3605, 0x7840, 0x3e13, 0x780e, 0x3e13, + 0xf808, 0x3e05, 0x4024, 0x0000, 0xb94e, 0x0022, 0xa1cf, 0x2922, 0x9980, + 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, + 0x0000, 0x3009, 0x1800, 0x3009, 0x3400, 0x2800, 0xb200, 0x0022, 0xa288, + 0x2a01, 0x5a4e, 0x2a02, 0x7c0e, 0x2a02, 0x964e, 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x0ff6, /*copy 4086*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x6ad7, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x5b4e, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x003f, + 0xc000, 0xb600, 0x41c1, 0x0012, 0x5103, 0x000c, 0xc002, 0xdcd6, 0x0024, + 0x0019, 0xd4c2, 0x2802, 0x0c45, 0x0001, 0x1008, 0x0013, 0xd9c3, 0x6fd6, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdf95, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xde4e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x1008, 0x0039, + 0x324f, 0x0001, 0x3ece, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x0014, 0x1b01, 0x0015, 0x59c0, + 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, 0xe9d5, 0x0000, 0x0024, 0x290c, + 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, 0x4086, 0x184c, 0x0000, 0x18c2, + 0x6234, 0x0024, 0x0000, 0x1d02, 0x2800, 0xe5d5, 0x6234, 0x0024, 0x0030, + 0x0317, 0x2800, 0xe9c0, 0x3f00, 0x0024, 0x0000, 0x1d82, 0x2800, 0xe855, + 0x6234, 0x0024, 0x2912, 0x0d00, 0x4084, 0x184c, 0xf200, 0x0024, 0x6200, + 0x0024, 0x0006, 0x0017, 0x2800, 0xe540, 0xb080, 0x3c40, 0x0000, 0x0202, + 0x2800, 0xe9d5, 0xa024, 0x0024, 0xc020, 0x0024, 0x2800, 0xe540, 0x0030, + 0x02d7, 0x000a, 0x8c8f, 0x0000, 0xeb0e, 0x000c, 0x0981, 0x280a, 0x71c0, + 0x002c, 0x9d40, 0x000a, 0x708f, 0x0000, 0xd7ce, 0x280a, 0xc0d5, 0x0012, + 0x5182, 0x6fd6, 0x0024, 0x003f, 0xfd81, 0x280a, 0x8e45, 0xb710, 0x0024, + 0xb710, 0x0024, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, + 0x06d5, 0xffd2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x190d, + 0x2801, 0x06d5, 0x0030, 0x0250, 0xb880, 0x104c, 0x3cf0, 0x0024, 0x0010, + 0x5500, 0xb880, 0x23c0, 0xb882, 0x2000, 0x0007, 0x8590, 0x2914, 0xbec0, + 0x0000, 0x0440, 0x0007, 0x8b50, 0xb880, 0x0024, 0x2920, 0x0100, 0x3800, + 0x0024, 0x2920, 0x0000, 0x0006, 0x8a91, 0x0000, 0x0800, 0xb880, 0xa440, + 0x003f, 0xfd81, 0xb710, 0xa7c0, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, + 0x0101, 0x2801, 0x1015, 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, + 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x1015, 0x0000, 0x0024, 0x2912, + 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0006, 0x8a90, 0x2801, 0x1015, + 0x0000, 0x01c2, 0xb886, 0x8040, 0x3613, 0x03c1, 0xbcd2, 0x0024, 0x0030, + 0x0011, 0x2800, 0xfc95, 0x003f, 0xff42, 0xb886, 0x8040, 0x3009, 0x03c1, + 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0102, 0x6cd2, 0x0024, 0x3e10, + 0x0024, 0x2909, 0x8c80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3e11, 0x8024, + 0x3e01, 0xc024, 0x2901, 0x34c0, 0x0000, 0x0201, 0xf400, 0x4512, 0x2900, + 0x0c80, 0x3213, 0x1b8c, 0x3100, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2801, 0x1015, 0x0000, 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2920, + 0x0200, 0x3633, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, 0x408e, 0x0024, + 0x2920, 0x0280, 0x0000, 0x0401, 0x003f, 0xfd81, 0xb710, 0x4006, 0x003f, + 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x1015, 0x0000, 0x0024, + 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, + 0x1015, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, + 0x0000, 0x01c2, 0x2800, 0xf885, 0x0006, 0x8a90, 0x2a01, 0x1000, 0x2920, + 0x0100, 0x0000, 0x0401, 0x0000, 0x0180, 0x2920, 0x0200, 0x3613, 0x0024, + 0x2920, 0x0280, 0x3613, 0x0024, 0x0000, 0x0401, 0x2920, 0x0280, 0x4084, + 0x984c, 0x0019, 0x9d01, 0x6212, 0x0024, 0x001e, 0x5c01, 0x2801, 0x0b55, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x0d45, 0x0000, 0x0024, 0x001b, + 0x5bc1, 0x6212, 0x0024, 0x001b, 0xdd81, 0x2801, 0x1115, 0x6012, 0x0024, + 0x0000, 0x0024, 0x2801, 0x1115, 0x0000, 0x0024, 0x0000, 0x004d, 0x000a, + 0xbf4f, 0x280a, 0xb880, 0x0001, 0x0e4e, 0x0020, 0xfb4f, 0x0000, 0x190d, + 0x0001, 0x154e, 0x2920, 0xf440, 0x3009, 0x2bc1, 0x291a, 0x8a40, 0x36e3, + 0x0024, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xcac0, 0x0000, 0xd7ce, + 0x0030, 0x0017, 0x3700, 0x4024, 0x0000, 0x0200, 0xb102, 0x0024, 0x0000, + 0x00c0, 0x2801, 0x1445, 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, + 0x0006, 0x0197, 0x0006, 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0000, + 0x190d, 0x000a, 0x708f, 0x280a, 0xc0c0, 0x0000, 0xd7ce, 0x0000, 0x004d, + 0x0020, 0xfe0f, 0x2820, 0xfb40, 0x0001, 0x164e, 0x2801, 0x1815, 0x3009, + 0x1000, 0x6012, 0x93cc, 0x0000, 0x0024, 0x2801, 0x32c5, 0x0000, 0x0024, + 0x3413, 0x0024, 0x34b0, 0x0024, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, + 0x1b15, 0xb882, 0x0024, 0x3453, 0x0024, 0x3009, 0x13c0, 0x4080, 0x0024, + 0x0000, 0x0200, 0x2801, 0x32c5, 0x0000, 0x0024, 0xb882, 0x130c, 0x0000, + 0x004d, 0x0021, 0x058f, 0x2821, 0x0340, 0x0001, 0x1c0e, 0x2801, 0x2c55, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x2c55, 0x0000, 0x0024, 0x34c3, + 0x184c, 0x3e13, 0xb80f, 0xf400, 0x4500, 0x0026, 0x9dcf, 0x0001, 0x200e, + 0x0000, 0xfa0d, 0x2926, 0x8e80, 0x3e10, 0x110c, 0x36f3, 0x0024, 0x2801, + 0x2c40, 0x36f3, 0x980f, 0x001c, 0xdd00, 0x001c, 0xd901, 0x6ec2, 0x0024, + 0x001c, 0xdd00, 0x2801, 0x2315, 0x0018, 0xdbc1, 0x3413, 0x184c, 0xf400, + 0x4500, 0x2926, 0xc640, 0x3e00, 0x13cc, 0x2801, 0x2a00, 0x36f3, 0x0024, + 0x6ec2, 0x0024, 0x003f, 0xc000, 0x2801, 0x2595, 0x002a, 0x4001, 0x3413, + 0x184c, 0xf400, 0x4500, 0x2926, 0xafc0, 0x3e00, 0x13cc, 0x2801, 0x2a00, + 0x36f3, 0x0024, 0xb400, 0x0024, 0xd100, 0x0024, 0x0000, 0x0024, 0x2801, + 0x2a05, 0x0000, 0x0024, 0x3613, 0x0024, 0x3e11, 0x4024, 0x2926, 0x8540, + 0x3e01, 0x0024, 0x4080, 0x1b8c, 0x0000, 0x0024, 0x2801, 0x2a05, 0x0000, + 0x0024, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0x8e80, 0x3e10, 0x13cc, + 0x36f3, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x0000, 0x4000, 0x0000, + 0x0021, 0x6d06, 0x0024, 0x3110, 0x8024, 0x2826, 0xa8c4, 0x31f0, 0xc024, + 0x2a26, 0xad00, 0x34c3, 0x184c, 0x3410, 0x8024, 0x3430, 0xc024, 0x0000, + 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x0000, 0x0024, 0x2801, 0x32d4, + 0x4d06, 0x0024, 0x0000, 0x0200, 0x2922, 0x1885, 0x0001, 0x3148, 0x0000, + 0x0200, 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, 0xc024, 0x291a, 0x8a40, + 0x0000, 0x0024, 0x2922, 0x1880, 0x36f3, 0x0024, 0x0000, 0x004d, 0x0021, + 0x0ecf, 0x2821, 0x0bc0, 0x0001, 0x324e, 0x2801, 0x1540, 0x3c30, 0x4024, + 0x0000, 0x190d, 0x0001, 0x33ce, 0x2821, 0x0f80, 0x0021, 0x420f, 0x0000, + 0x190d, 0x3e00, 0x0024, 0x2801, 0xe840, 0x0021, 0x42c8, 0x0020, 0xcd4f, + 0x2820, 0xc780, 0x0001, 0x358e, 0x0006, 0xf017, 0x0000, 0x0015, 0xb070, + 0xbc15, 0x0001, 0x374e, 0x0020, 0xdf0f, 0x2820, 0xcd80, 0x0000, 0x190d, + 0x3e00, 0x23c1, 0x2801, 0xe840, 0x0020, 0xdfc8, 0x3613, 0x0024, 0x3e10, + 0xb803, 0x3e14, 0x3811, 0x3e11, 0x3805, 0x3e00, 0x3801, 0x0007, 0xc390, + 0x0006, 0xa011, 0x3010, 0x0444, 0x3050, 0x4405, 0x6458, 0x0302, 0xff94, + 0x4081, 0x0003, 0xffc5, 0x48b6, 0x0024, 0xff82, 0x0024, 0x42b2, 0x0042, + 0xb458, 0x0003, 0x4cd6, 0x9801, 0xf248, 0x1bc0, 0xb58a, 0x0024, 0x6de6, + 0x1804, 0x0006, 0x0010, 0x3810, 0x9bc5, 0x3800, 0xc024, 0x36f4, 0x1811, + 0x36f0, 0x9803, 0x283e, 0x2d80, 0x0fff, 0xffc3, 0x2801, 0x4c80, 0x0000, + 0x0024, 0x3413, 0x0024, 0x2801, 0x4085, 0xf400, 0x4517, 0x2801, 0x4480, + 0x6894, 0x13cc, 0x37b0, 0x184c, 0x6090, 0x1d51, 0x0000, 0x0910, 0x3f00, + 0x060c, 0x3100, 0x4024, 0x6016, 0xb812, 0x000c, 0x8012, 0x2801, 0x4311, + 0xb884, 0x0024, 0x6894, 0x3002, 0x0000, 0x028d, 0x003a, 0x5e0f, 0x0001, + 0x548e, 0x2939, 0xb0c0, 0x3e10, 0x93cc, 0x4084, 0x9bd2, 0x4282, 0x0024, + 0x0000, 0x0040, 0x2801, 0x4685, 0x4292, 0x130c, 0x3443, 0x0024, 0x2801, + 0x47c5, 0x000c, 0x8390, 0x2a01, 0x4b40, 0x3444, 0x0024, 0x3073, 0x0024, + 0xc090, 0x014c, 0x2801, 0x4b40, 0x3800, 0x0024, 0x000c, 0x4113, 0xb880, + 0x2380, 0x3304, 0x4024, 0x3800, 0x05cc, 0xcc92, 0x05cc, 0x3910, 0x0024, + 0x3910, 0x4024, 0x000c, 0x8110, 0x3910, 0x0024, 0x39f0, 0x4024, 0x3810, + 0x0024, 0x38d0, 0x4024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x34c3, 0x0024, + 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x3613, 0x0024, + 0x2801, 0x4e85, 0x6898, 0xb804, 0x0000, 0x0084, 0x293b, 0x1cc0, 0x3613, + 0x0024, 0x000c, 0x8117, 0x3711, 0x0024, 0x37d1, 0x4024, 0x4e8a, 0x0024, + 0x0000, 0x0015, 0x2801, 0x5145, 0xce9a, 0x0024, 0x3f11, 0x0024, 0x3f01, + 0x4024, 0x000c, 0x8197, 0x408a, 0x9bc4, 0x3f15, 0x4024, 0x2801, 0x5385, + 0x4284, 0x3c15, 0x6590, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, + 0x0024, 0x0000, 0x0024, 0x2801, 0x3f58, 0x458a, 0x0024, 0x2a39, 0x53c0, + 0x003e, 0x2d4f, 0x283a, 0x5ed5, 0x0001, 0x380e, 0x000c, 0x4653, 0x0000, + 0x0246, 0xffac, 0x0c01, 0x48be, 0x0024, 0x4162, 0x4546, 0x6642, 0x4055, + 0x3501, 0x8024, 0x0000, 0x0087, 0x667c, 0x4057, 0x000c, 0x41d5, 0x283a, + 0x62d5, 0x3501, 0x8024, 0x667c, 0x1c47, 0x3701, 0x8024, 0x283a, 0x62d5, + 0xc67c, 0x0024, 0x0000, 0x0024, 0x283a, 0x62c5, 0x0000, 0x0024, 0x2a3a, + 0x5ec0, 0x3009, 0x3851, 0x3e14, 0xf812, 0x3e12, 0xb817, 0x3e11, 0x8024, + 0x0006, 0x0293, 0x3301, 0x8024, 0x468c, 0x3804, 0x0006, 0xa057, 0x2801, + 0x6084, 0x0006, 0x0011, 0x469c, 0x0024, 0x3be1, 0x8024, 0x2801, 0x6095, + 0x0006, 0xc392, 0x3311, 0x0024, 0x33f1, 0x2844, 0x3009, 0x2bc4, 0x0030, + 0x04d2, 0x3311, 0x0024, 0x3a11, 0x0024, 0x3201, 0x8024, 0x003f, 0xfc04, + 0xb64c, 0x0fc4, 0xc648, 0x0024, 0x3a01, 0x0024, 0x3111, 0x1fd3, 0x6498, + 0x07c6, 0x868c, 0x2444, 0x0023, 0xffd2, 0x3901, 0x8e06, 0x0030, 0x0551, + 0x3911, 0x8e06, 0x3961, 0x9c44, 0xf400, 0x44c6, 0xd46c, 0x1bc4, 0x36f1, + 0xbc13, 0x2801, 0x6a15, 0x36f2, 0x9817, 0x002b, 0xffd2, 0x3383, 0x188c, + 0x3e01, 0x8c06, 0x0006, 0xa097, 0x3009, 0x1c12, 0x3213, 0x0024, 0x468c, + 0xbc12, 0x002b, 0xffd2, 0xf400, 0x4197, 0x2801, 0x6704, 0x3713, 0x0024, + 0x2801, 0x6745, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x3383, 0x0024, 0x3009, + 0x0c06, 0x468c, 0x4197, 0x0006, 0xa052, 0x2801, 0x6944, 0x3713, 0x2813, + 0x2801, 0x6985, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x36f1, 0x8024, 0x36f2, + 0x9817, 0x36f4, 0xd812, 0x2100, 0x0000, 0x3904, 0x5bd1, 0x2a01, 0x5a4e, + 0x3e11, 0x7804, 0x0030, 0x0257, 0x3701, 0x0024, 0x0013, 0x4d05, 0xd45b, + 0xe0e1, 0x0007, 0xc795, 0x2801, 0x7195, 0x0fff, 0xff45, 0x3511, 0x184c, + 0x4488, 0xb808, 0x0006, 0x8a97, 0x2801, 0x7145, 0x3009, 0x1c40, 0x3511, + 0x1fc1, 0x0000, 0x0020, 0xac52, 0x1405, 0x6ce2, 0x0024, 0x0000, 0x0024, + 0x2801, 0x7141, 0x68c2, 0x0024, 0x291a, 0x8a40, 0x3e10, 0x0024, 0x2921, + 0xca80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3009, 0x1bc8, 0x36f0, 0x1801, + 0x3601, 0x5804, 0x3e13, 0x780f, 0x3e13, 0xb808, 0x0008, 0x9b0f, 0x0001, + 0x744e, 0x2908, 0x9300, 0x0000, 0x004d, 0x36f3, 0x9808, 0x2000, 0x0000, + 0x36f3, 0x580f, 0x0007, 0x81d7, 0x3711, 0x8024, 0x3711, 0xc024, 0x3700, + 0x0024, 0x0000, 0x2001, 0xb012, 0x0024, 0x0034, 0x0000, 0x2801, 0x79c5, + 0x0000, 0x01c1, 0x3700, 0x0024, 0x0002, 0x0001, 0xb012, 0x0024, 0x002e, + 0xe001, 0x2801, 0x78c5, 0x6512, 0x0024, 0x0034, 0x0000, 0x2801, 0x79d5, + 0x0000, 0x01c1, 0x0030, 0x0117, 0x3f00, 0x0024, 0x0014, 0xc000, 0x0000, + 0x01c1, 0x4fce, 0x0024, 0xffea, 0x0024, 0x48b6, 0x0024, 0x4384, 0x4097, + 0xb886, 0x45c6, 0xfede, 0x0024, 0x4db6, 0x0024, 0x466c, 0x0024, 0x0006, + 0xc610, 0x8dd6, 0x8007, 0x0000, 0x00c6, 0xff6e, 0x0024, 0x48b2, 0x0024, + 0x0034, 0x2406, 0xffee, 0x0024, 0x2914, 0xaa80, 0x40b2, 0x0024, 0xf1c6, + 0x0024, 0xf1d6, 0x0024, 0x0000, 0x0201, 0x8d86, 0x0024, 0x61de, 0x0024, + 0x0006, 0xc612, 0x2801, 0x8041, 0x0006, 0xc713, 0x4c86, 0x0024, 0x2912, + 0x1180, 0x0006, 0xc351, 0x0006, 0x0210, 0x2912, 0x0d00, 0x3810, 0x984c, + 0xf200, 0x2043, 0x2808, 0xa000, 0x3800, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x7808, 0x3e11, 0xb811, 0x3e15, 0x7810, 0x3e18, 0xb823, 0x3e18, 0x3821, + 0x3e10, 0x3801, 0x48b2, 0x0024, 0x3e10, 0x3801, 0x3e11, 0x3802, 0x3009, + 0x3814, 0x0030, 0x0717, 0x3f05, 0xc024, 0x0030, 0x0351, 0x3100, 0x0024, + 0x4080, 0x0024, 0x0030, 0x10d1, 0x2801, 0x8d45, 0x0001, 0x800a, 0x0006, + 0x6514, 0x3111, 0x8024, 0x6894, 0x13c1, 0x6618, 0x0024, 0xfe44, 0x1000, + 0x4cb2, 0x0406, 0x3c10, 0x0024, 0x3c50, 0x4024, 0x34f0, 0x4024, 0x661c, + 0x1040, 0xfe64, 0x0024, 0x4cb2, 0x0024, 0x3cf0, 0x4024, 0xbc82, 0x3080, + 0x0030, 0x0351, 0x3100, 0x8024, 0xfea8, 0x0024, 0x5ca2, 0x0024, 0x0000, + 0x0182, 0xac22, 0x0024, 0xf7c8, 0x0024, 0x48b2, 0x0024, 0xac22, 0x0024, + 0x2801, 0x90c0, 0xf7cc, 0x1002, 0x0030, 0x0394, 0x3400, 0x4024, 0x3100, + 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, 0x6410, 0x4088, 0x1001, + 0x0030, 0x1111, 0x3100, 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, + 0x6550, 0x0006, 0x6694, 0x408c, 0x1002, 0xf224, 0x0024, 0x0006, 0xa017, + 0x2801, 0x94d5, 0x0000, 0x0024, 0x2808, 0x3f41, 0x0006, 0x6410, 0x3050, + 0x0024, 0x3000, 0x4024, 0x6014, 0x0024, 0x0000, 0x0024, 0x2801, 0x9419, + 0x0000, 0x0024, 0xf400, 0x4040, 0x38b0, 0x0024, 0x2808, 0x3f40, 0x3800, + 0x0024, 0x2801, 0x96c1, 0xf224, 0x0024, 0x0000, 0x0024, 0x2808, 0x3f45, + 0x4684, 0x4106, 0xf12c, 0x0024, 0xf148, 0x0024, 0x846c, 0x0024, 0x2808, + 0x3f40, 0xf400, 0x4184, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0xa090, 0x2912, 0x0d00, + 0x3e14, 0xc024, 0x4088, 0x8000, 0x4080, 0x0024, 0x0007, 0x90d1, 0x2801, + 0x9d05, 0x0000, 0x0024, 0x0007, 0x9051, 0x3100, 0x4024, 0x4100, 0x0024, + 0x3900, 0x0024, 0x0007, 0x90d1, 0x0004, 0x0000, 0x31f0, 0x4024, 0x6014, + 0x0400, 0x0000, 0x0024, 0x2801, 0xa151, 0x4080, 0x0024, 0x0000, 0x0000, + 0x2801, 0xa0c5, 0x0000, 0x0024, 0x0007, 0x9053, 0x3300, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0000, 0x2801, 0xa158, 0x0000, 0x0024, 0x0007, 0x9051, + 0x3900, 0x0024, 0x3200, 0x504c, 0x6410, 0x0024, 0x3cf0, 0x0000, 0x4080, + 0x0024, 0x0006, 0xc691, 0x2801, 0xba05, 0x3009, 0x0400, 0x0007, 0x9051, + 0x0000, 0x1001, 0x3100, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2801, + 0xae49, 0x003f, 0xe000, 0x0006, 0xc693, 0x3900, 0x0c00, 0x3009, 0x0001, + 0x6014, 0x0024, 0x0007, 0x1ad0, 0x2801, 0xae55, 0x3009, 0x0000, 0x4080, + 0x0024, 0x0000, 0x0301, 0x2801, 0xa845, 0x4090, 0x0024, 0x0000, 0x0024, + 0x2801, 0xa955, 0x0000, 0x0024, 0x3009, 0x0000, 0xc012, 0x0024, 0x2801, + 0xae40, 0x3009, 0x2001, 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, 0x0341, + 0x2801, 0xab55, 0x0000, 0x0024, 0x6190, 0x0024, 0x2801, 0xae40, 0x3009, + 0x2000, 0x6012, 0x0024, 0x0000, 0x0381, 0x2801, 0xad15, 0x0000, 0x0024, + 0x6190, 0x0024, 0x2801, 0xae40, 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, + 0x00c0, 0x2801, 0xae55, 0x0000, 0x0024, 0x3009, 0x2000, 0x0006, 0xa090, + 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0081, 0x2801, 0xb315, 0x0007, + 0x8c13, 0x3300, 0x104c, 0xb010, 0x0024, 0x0002, 0x8001, 0x2801, 0xb585, + 0x34f0, 0x0024, 0x2801, 0xb300, 0x0000, 0x0024, 0x0006, 0xc351, 0x3009, + 0x0000, 0x6090, 0x0024, 0x3009, 0x2000, 0x2900, 0x0b80, 0x3009, 0x0405, + 0x0006, 0xc690, 0x0006, 0xc6d1, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, + 0x0024, 0x0006, 0xa093, 0x2801, 0xb191, 0xb880, 0x0024, 0x2801, 0xc2c0, + 0x3009, 0x2c00, 0x4040, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2801, + 0xc2d8, 0x0000, 0x0024, 0x0006, 0xc693, 0x3009, 0x0c00, 0x3009, 0x0001, + 0x6014, 0x0024, 0x0006, 0xc350, 0x2801, 0xc2c1, 0x0000, 0x0024, 0x6090, + 0x0024, 0x3009, 0x2c00, 0x3009, 0x0005, 0x2900, 0x0b80, 0x0001, 0xc2c8, + 0x3009, 0x0400, 0x4080, 0x0024, 0x0003, 0x8000, 0x2801, 0xc2c5, 0x0000, + 0x0024, 0x6400, 0x0024, 0x0000, 0x0081, 0x2801, 0xc2c9, 0x0000, 0x0024, + 0x0007, 0x8c13, 0x3300, 0x0024, 0xb010, 0x0024, 0x0006, 0xc650, 0x2801, + 0xc2d5, 0x0000, 0x0024, 0x0001, 0x0002, 0x3413, 0x0000, 0x3009, 0x0401, + 0x4010, 0x8406, 0x0000, 0x0281, 0xa010, 0x13c1, 0x4122, 0x0024, 0x0000, + 0x03c2, 0x6122, 0x8002, 0x462c, 0x0024, 0x469c, 0x0024, 0xfee2, 0x0024, + 0x48be, 0x0024, 0x6066, 0x8400, 0x0006, 0xc350, 0x2801, 0xc2c1, 0x0000, + 0x0024, 0x4090, 0x0024, 0x3009, 0x2400, 0x2900, 0x0b80, 0x3009, 0x0005, + 0x0007, 0x1b50, 0x2912, 0x0d00, 0x3613, 0x0024, 0x3a00, 0x0380, 0x4080, + 0x0024, 0x0000, 0x00c1, 0x2801, 0xcb85, 0x3009, 0x0000, 0xb010, 0x008c, + 0x4192, 0x0024, 0x6012, 0x0024, 0x0006, 0xf051, 0x2801, 0xc998, 0x3009, + 0x0400, 0x0007, 0x1fd1, 0x30e3, 0x0400, 0x4080, 0x0024, 0x0000, 0x0301, + 0x2801, 0xcb85, 0x3009, 0x0000, 0xb010, 0x0024, 0x0000, 0x0101, 0x6012, + 0x0024, 0x0006, 0xf051, 0x2801, 0xcb95, 0x0000, 0x0024, 0x3023, 0x0400, + 0xf200, 0x184c, 0xb880, 0xa400, 0x3009, 0x2000, 0x3009, 0x0441, 0x3e10, + 0x4402, 0x2909, 0xa9c0, 0x3e10, 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, + 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, + 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x3e11, 0xf810, 0x0001, 0x0010, 0x3e14, 0x7812, 0xb882, + 0x3813, 0x2914, 0xbec0, 0x0000, 0x2200, 0xb886, 0x12cc, 0x2801, 0xd800, + 0x3454, 0x8024, 0x0001, 0x0000, 0x3000, 0x984c, 0x4234, 0xb843, 0xf400, + 0x4095, 0x003b, 0xffc2, 0x3500, 0x4024, 0xb122, 0x0842, 0x4010, 0x0bc3, + 0x4010, 0x0024, 0x4010, 0x0024, 0x4010, 0x0024, 0x4d82, 0x4011, 0x2938, + 0x0600, 0xf400, 0x4450, 0x3223, 0x184c, 0x3210, 0x8024, 0x32d0, 0xc024, + 0x2938, 0x0600, 0x4d82, 0x4450, 0x3243, 0x1bc3, 0x6396, 0x0024, 0x0005, + 0xdf90, 0x3000, 0x0024, 0x6302, 0x0024, 0x0005, 0xe110, 0x2801, 0xd2d1, + 0x0000, 0x0024, 0x2801, 0xde80, 0x4086, 0x0024, 0x3200, 0x930c, 0x6398, + 0x1111, 0x4244, 0x0844, 0xf400, 0x4095, 0x3500, 0x584c, 0x4438, 0x0805, + 0x453a, 0x4115, 0x3500, 0x8024, 0x6122, 0x4155, 0x4280, 0x1404, 0x0001, + 0x0002, 0x4244, 0x0024, 0x4244, 0x0024, 0x4244, 0x0024, 0x4244, 0x0024, + 0x2938, 0x2f80, 0xf400, 0x4090, 0x6396, 0x0024, 0x0005, 0xdf50, 0x3000, + 0x0024, 0x6302, 0x0024, 0x0005, 0xe0d2, 0x2801, 0xda11, 0x0000, 0x0381, + 0x3073, 0x0024, 0x3023, 0x0024, 0x3000, 0x0024, 0x6012, 0x0024, 0x0001, + 0x2212, 0x2801, 0xe395, 0x0005, 0x1453, 0x0001, 0x0011, 0x3093, 0x184c, + 0x3000, 0x4024, 0x2900, 0x78c0, 0x3e00, 0x4024, 0x2801, 0xe580, 0x36f3, + 0x0024, 0x0005, 0xe3c1, 0x0001, 0x0011, 0x3613, 0x024c, 0x3e10, 0x4024, + 0x3000, 0x8024, 0x2900, 0x5c40, 0x3e00, 0x8024, 0x36e3, 0x0024, 0x36f4, + 0xc024, 0x36f4, 0x5812, 0x36f1, 0xd810, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, + 0x00c1, 0xb880, 0xb803, 0x3e10, 0x904c, 0x3e11, 0x3806, 0x3e11, 0xf810, + 0x0006, 0xf450, 0x3e14, 0x7812, 0x3e14, 0xc024, 0x3cf0, 0x2080, 0x3009, + 0x23c0, 0x3009, 0x2380, 0x0000, 0x0640, 0x3009, 0x2000, 0x2921, 0x9440, + 0x0000, 0x00c0, 0x2921, 0xdd40, 0x3613, 0x0024, 0xf400, 0x4004, 0x0000, + 0x01c0, 0x6400, 0x0024, 0x0000, 0x00c0, 0x2802, 0x0885, 0x0000, 0x01c1, + 0x6412, 0x4100, 0x0006, 0x0581, 0x2801, 0xfe01, 0x4412, 0x0024, 0xf400, + 0x4057, 0x3702, 0x0024, 0x2000, 0x0000, 0x0000, 0x0024, 0x0006, 0xf410, + 0x0000, 0x0641, 0x3613, 0x0000, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, + 0xf3d5, 0x0000, 0x0024, 0x3009, 0x2004, 0x2900, 0xb600, 0x3e01, 0x0024, + 0x2801, 0xfe00, 0x36f3, 0x0024, 0x0006, 0xf410, 0x0000, 0x0641, 0x3613, + 0x0000, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0xf6d5, 0x0000, 0x0024, + 0x3009, 0x2004, 0x2900, 0xa400, 0x3e01, 0x0024, 0x2801, 0xfe00, 0x36f3, + 0x0024, 0x0006, 0xf450, 0x3613, 0x0000, 0x6090, 0x3804, 0x2900, 0xb600, + 0x3009, 0x2000, 0x2801, 0xfe00, 0x36f3, 0x0024, 0x2923, 0x4f00, 0x0007, + 0x2050, 0x2801, 0xfe00, 0x3009, 0x2000, 0x2923, 0x7580, 0x0001, 0xfe08, + 0x34d3, 0x184c, 0x3430, 0x0024, 0x2922, 0x4fc0, 0x3e00, 0x0024, 0x2801, + 0xfe00, 0x36f3, 0x0024, 0x0000, 0x3fc0, 0x0007, 0x2050, 0x3613, 0x0024, + 0x2923, 0x8480, 0x3e00, 0x0024, 0x36f3, 0x2000, 0x0000, 0x1800, 0x3413, + 0x0024, 0xf400, 0x4510, 0x34f0, 0x4024, 0x6192, 0x0024, 0x6014, 0x2001, + 0x0007, 0x2051, 0x2802, 0x0081, 0x0000, 0x0280, 0x3009, 0x2400, 0x3009, + 0x0400, 0x4080, 0x0024, 0x0006, 0xf352, 0x2802, 0x0995, 0x3009, 0x0842, + 0x3009, 0x0bc3, 0x4d86, 0x0024, 0x0000, 0x0201, 0x2802, 0x04c5, 0x0030, + 0x0013, 0x0006, 0x8a93, 0x3009, 0x0c40, 0x3009, 0x0fc1, 0x6cde, 0x0024, + 0x0000, 0x0201, 0x2802, 0x0981, 0x0030, 0x0013, 0x3300, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0100, 0x2802, 0x0995, 0x0000, 0x00c1, 0x2921, 0x9440, + 0x3613, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0xf400, 0x4004, 0x0000, + 0x01c0, 0x6400, 0x0024, 0x0000, 0x01c1, 0x2801, 0xefd5, 0x0000, 0x00c0, + 0x2921, 0x9440, 0x3613, 0x0024, 0x2921, 0xc300, 0x0000, 0x0024, 0x36f4, + 0xc024, 0x36f4, 0x5812, 0x36f1, 0xd810, 0x36f1, 0x1806, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0012, + 0x5103, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x380d, 0x0030, 0x0250, + 0x3e13, 0xf80e, 0xbe8b, 0x83e0, 0x290c, 0x4840, 0x3613, 0x0024, 0x290c, + 0x4840, 0x4086, 0x984c, 0x0000, 0x00ce, 0x2402, 0x138e, 0x3009, 0x1bc0, + 0x0000, 0x01c3, 0xae3a, 0x184c, 0x0000, 0x0043, 0x3009, 0x3842, 0x290c, + 0x4840, 0x3009, 0x3840, 0x4084, 0x9bc0, 0xfe26, 0x9bc2, 0xceba, 0x0024, + 0x4e8e, 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0000, 0x0102, 0x2802, + 0x18c5, 0x0030, 0x0010, 0x0000, 0x0206, 0x3613, 0x0024, 0x290c, 0x4840, + 0x3009, 0x3840, 0x3000, 0xdbc0, 0xb366, 0x0024, 0x0000, 0x0024, 0x2802, + 0x18d5, 0x4e8e, 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0030, 0x0010, + 0x2802, 0x1595, 0x0000, 0x0206, 0x36f3, 0xd80e, 0x36f4, 0x180d, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, + 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb810, 0x3e04, + 0x7812, 0x34d3, 0x0024, 0x3400, 0x0024, 0xf200, 0x1102, 0xf200, 0x0024, + 0xf200, 0x0024, 0x3cf0, 0x0024, 0x2914, 0xba00, 0x0000, 0x1600, 0x0000, + 0x4001, 0x6012, 0x108c, 0x3ce0, 0x0024, 0x2802, 0x2209, 0x0000, 0x0386, + 0x0000, 0x4000, 0x3423, 0x0024, 0x3ce0, 0x0024, 0x0000, 0x0041, 0x3413, + 0x0024, 0x34b0, 0x8024, 0xfe22, 0x1100, 0x48b6, 0x0024, 0xad66, 0x0024, + 0xfe02, 0x0024, 0x2915, 0x8600, 0x48b2, 0x0024, 0x4c8a, 0x104c, 0x0000, + 0x0041, 0x34f0, 0x0024, 0xfe02, 0x0024, 0x0000, 0xf001, 0x6eba, 0x0024, + 0xf040, 0x0024, 0x6012, 0x0024, 0x0000, 0x0041, 0x2802, 0x2a08, 0x0000, + 0xf002, 0xf040, 0x104c, 0x3400, 0xc024, 0xfe26, 0x0024, 0x48b6, 0x0024, + 0xfe02, 0x0024, 0x2915, 0x8600, 0x48b2, 0x0024, 0x4480, 0x33c0, 0x0000, + 0xf004, 0x2802, 0x2a18, 0x0000, 0x0024, 0x003f, 0x1004, 0x0006, 0x0090, + 0x0000, 0x0041, 0xb884, 0x108c, 0x6896, 0xa004, 0x34e0, 0x0024, 0xfe02, + 0x0024, 0x2914, 0xa580, 0x48b2, 0x0024, 0x0006, 0x0110, 0x3423, 0x23c0, + 0x34f0, 0x0024, 0x3410, 0x2380, 0xb880, 0xa140, 0x3009, 0x23c0, 0x3009, + 0x2340, 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0xba11, 0x2802, 0x2f95, + 0x0000, 0x0024, 0x2802, 0x3780, 0x3ce4, 0x4024, 0x4080, 0x138c, 0x0000, + 0x0001, 0x2802, 0x3418, 0x0006, 0x0011, 0x0000, 0xba00, 0x6090, 0x108c, + 0x3ce0, 0x0400, 0x6014, 0x0024, 0x0006, 0xa052, 0x2802, 0x3351, 0x0004, + 0x0001, 0x6014, 0x0024, 0x0000, 0x0024, 0x2802, 0x3791, 0x0000, 0x0024, + 0x3009, 0x0800, 0x2802, 0x3780, 0x3009, 0x2400, 0x0000, 0xba00, 0x6090, + 0x108c, 0x6090, 0x0024, 0x3ce0, 0x0400, 0x6014, 0x0024, 0x0006, 0xa052, + 0x2802, 0x3711, 0x0004, 0x0001, 0x6014, 0x0024, 0x0000, 0x0024, 0x2802, + 0x3791, 0x0000, 0x0024, 0x3009, 0x0800, 0x3009, 0x2400, 0x3613, 0x108c, + 0x290f, 0xfdc0, 0x34e4, 0x3810, 0x0000, 0x0810, 0x290f, 0xfcc0, 0x3009, + 0x1bcc, 0x36f4, 0x5812, 0x36f1, 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e14, 0x3811, 0x0006, 0x01d1, 0x0006, 0xc610, + 0x3e04, 0xb813, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, 0x0030, + 0x0312, 0x2802, 0x4355, 0x0000, 0x0024, 0x3200, 0x044c, 0x3009, 0x0401, + 0x6014, 0x0024, 0x0006, 0x0292, 0x2802, 0x4355, 0x0006, 0xc351, 0x3009, + 0x0400, 0x3009, 0x0801, 0x6014, 0x0024, 0x0000, 0x0024, 0x2802, 0x5985, + 0x0000, 0x0024, 0x0030, 0x0311, 0x3100, 0x0024, 0x4080, 0x0024, 0x0010, + 0x0000, 0x2802, 0x4515, 0x0000, 0x0024, 0x3900, 0x0024, 0x3100, 0x0024, + 0x4080, 0x0024, 0x0001, 0xffc0, 0x2802, 0x4b98, 0x0030, 0x00d2, 0x3201, + 0x0024, 0xb408, 0x0024, 0x0006, 0x01d3, 0x2802, 0x47d5, 0x0001, 0xf400, + 0x0001, 0x0c04, 0x4408, 0x0401, 0x3613, 0x2004, 0x0006, 0xc350, 0x6810, + 0xac44, 0x3009, 0x2c81, 0x3e10, 0x0000, 0x2902, 0x1b40, 0x3e00, 0x2c00, + 0x36f3, 0x0000, 0x6090, 0x0024, 0x3009, 0x2000, 0x3009, 0x0005, 0x459a, + 0x0024, 0x2908, 0x9300, 0x0002, 0x5988, 0x3201, 0x0024, 0xb408, 0x0024, + 0x0000, 0x0081, 0x2802, 0x4d15, 0x0006, 0x02d3, 0x0001, 0x0c04, 0x0001, + 0xf400, 0x4408, 0x8c00, 0x6012, 0x044c, 0x3009, 0x184c, 0x2802, 0x4ed5, + 0x0004, 0x0003, 0x4448, 0x0024, 0x39f0, 0x3800, 0xb884, 0x3801, 0x0000, + 0x0041, 0x3100, 0x0024, 0xfe02, 0x0024, 0x2915, 0x8600, 0x48b2, 0x0024, + 0x0006, 0x01d0, 0x0006, 0x02d1, 0xffc0, 0x1bcc, 0x48b2, 0x0024, 0x4cc2, + 0x0024, 0x4cc2, 0x0024, 0x3009, 0x2001, 0x0000, 0x0081, 0x3009, 0x0400, + 0x6012, 0x0024, 0x0006, 0xc353, 0x2802, 0x5595, 0x0030, 0x0312, 0x3200, + 0x404c, 0x3613, 0x2001, 0x3e10, 0x4c01, 0xf212, 0x0024, 0x3e00, 0x4024, + 0x2902, 0x1b40, 0x0002, 0x56c8, 0x3200, 0x404c, 0x3613, 0x2001, 0x3e10, + 0x4c01, 0x2902, 0x1b40, 0x3e00, 0x4024, 0x3023, 0x0c00, 0x36f3, 0x2340, + 0x3009, 0x0000, 0x0006, 0xc610, 0x3009, 0x2000, 0x3009, 0x0c00, 0x6090, + 0x0024, 0x3009, 0x2c00, 0x3009, 0x0c05, 0x2908, 0x9300, 0x459a, 0x0024, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, + 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x3e11, 0x3811, + 0x3e14, 0xb813, 0x3e13, 0xf80e, 0x2902, 0x3b80, 0x3e03, 0x4024, 0x4194, + 0x0024, 0x002b, 0x1103, 0x2802, 0x7355, 0x0006, 0xc351, 0x3009, 0x0402, + 0x6236, 0x0024, 0x0010, 0x0003, 0x2802, 0x7351, 0x0030, 0x0311, 0x3100, + 0x8024, 0x6236, 0x0024, 0x0000, 0x0024, 0x2802, 0x7105, 0x0000, 0x0024, + 0x3100, 0x8024, 0x4284, 0x0024, 0x0006, 0x0793, 0x2802, 0x7109, 0x0000, + 0x0024, 0xf100, 0x0012, 0xb888, 0x4491, 0x3300, 0x8024, 0x0006, 0x0753, + 0x6404, 0x2c02, 0x0000, 0x0024, 0x2802, 0x6818, 0x4094, 0x0024, 0x2402, + 0x6782, 0x3613, 0x0024, 0x3220, 0x3840, 0x2902, 0xafc0, 0x32e0, 0x7801, + 0x3243, 0x1bc1, 0x6498, 0x0024, 0x3920, 0x1800, 0x36f3, 0x0024, 0x0006, + 0x0753, 0xb888, 0x0c02, 0x0006, 0x0793, 0x3b10, 0x8024, 0x3004, 0x8024, + 0x3300, 0x884c, 0x0006, 0x0753, 0x6404, 0x2c02, 0x0000, 0x0024, 0x2802, + 0x6d18, 0x4094, 0x4491, 0x2402, 0x6c82, 0x3613, 0x0024, 0x3220, 0x3840, + 0x2902, 0xafc0, 0x32e0, 0x7801, 0x3243, 0x1bc1, 0x6498, 0x0024, 0x3920, + 0x1800, 0x36f3, 0x0024, 0x0006, 0x0753, 0x0000, 0x0083, 0x3300, 0x984c, + 0x0006, 0x07d3, 0x3b00, 0x8024, 0x0006, 0x02d3, 0x3009, 0x0c02, 0x6236, + 0x0024, 0x0000, 0x0082, 0x2802, 0x7085, 0x0000, 0x0024, 0xb884, 0xac02, + 0x0006, 0x0293, 0x3009, 0x2c02, 0x2802, 0x7340, 0x3009, 0x1bcc, 0x0006, + 0x02d2, 0x3613, 0x0802, 0x4294, 0x0024, 0x0006, 0x0293, 0x2802, 0x7305, + 0x6894, 0x0024, 0xb884, 0xa802, 0x3009, 0x2c02, 0x3009, 0x1bcc, 0x36f3, + 0x4024, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f1, 0x1811, 0x36f0, 0x9803, + 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, + 0x9817, 0x3613, 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0xb880, 0x1854, + 0x3e10, 0xb811, 0x0007, 0x9251, 0xb884, 0x3812, 0x0006, 0x0792, 0x3900, + 0xb813, 0x0006, 0x0753, 0x0006, 0x1002, 0x0002, 0x5c11, 0x3a10, 0x8024, + 0x0006, 0x8002, 0x3a00, 0x8024, 0x0006, 0x1002, 0x0007, 0x9252, 0x3b00, + 0x9813, 0x3a04, 0x4024, 0x36f4, 0x8024, 0x36f0, 0x9811, 0x3405, 0x9014, + 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3009, 0x3857, 0x3e18, + 0x3822, 0x3e18, 0x780a, 0x3e10, 0x3801, 0x48b2, 0x3855, 0x3e10, 0x3801, + 0x0000, 0x800a, 0x3e14, 0x3811, 0x3e14, 0xb813, 0x0006, 0x0013, 0x0023, + 0xffd1, 0x0006, 0x0192, 0x3009, 0x0800, 0x4080, 0x8c10, 0x0030, 0x0552, + 0x2802, 0x8bc5, 0xf400, 0x4401, 0x0006, 0x0093, 0x3e10, 0xb803, 0x3e01, + 0x0c40, 0x4000, 0x8cc4, 0x4010, 0x8c02, 0x0000, 0x0001, 0x6010, 0x4012, + 0x0006, 0x0113, 0x2802, 0x8398, 0x6428, 0x8c80, 0x0004, 0x0013, 0x3283, + 0x0024, 0x0006, 0x0193, 0x3009, 0x0203, 0x3009, 0x0c02, 0xfe26, 0x0024, + 0x48b6, 0x8841, 0xfe42, 0x0024, 0x4db6, 0x0024, 0xffb0, 0x4003, 0x48b2, + 0x0024, 0xffa6, 0x8203, 0x40b2, 0x8f82, 0x0030, 0x0555, 0x3d10, 0x4c80, + 0xfe26, 0x0024, 0x48b6, 0x8bc1, 0xfe42, 0x0024, 0x4db6, 0x0024, 0xffb0, + 0x4003, 0x48b2, 0x0024, 0xffa6, 0x1bc4, 0x40b2, 0x8c02, 0x4290, 0x3401, + 0x3009, 0x2f00, 0x2802, 0x8c95, 0x3009, 0x0c00, 0x4000, 0x4401, 0x4100, + 0x0024, 0x0000, 0x0001, 0x6014, 0x4010, 0x0004, 0x0001, 0x2802, 0x8c98, + 0x4010, 0x0024, 0x2802, 0x8c80, 0xf400, 0x4010, 0x3e00, 0x8200, 0x3a10, + 0x0200, 0x3a00, 0x3803, 0x0006, 0x0152, 0x6104, 0x8b00, 0x6090, 0x8901, + 0x6014, 0xa800, 0x0006, 0xa053, 0x2802, 0x8f48, 0xb880, 0x4402, 0x3009, + 0x2b80, 0x3009, 0x08c0, 0x4090, 0x4402, 0x3009, 0x2800, 0x0006, 0x0012, + 0x3009, 0x2810, 0x3009, 0x0c01, 0x6214, 0x0024, 0x0006, 0x0092, 0x2802, + 0x9198, 0x0000, 0x0100, 0x0004, 0x0001, 0x4214, 0x0024, 0x3009, 0x0801, + 0x4112, 0x8c10, 0x6010, 0x020c, 0x6204, 0x020c, 0x3083, 0x1803, 0x2802, + 0x9389, 0x36f0, 0x820c, 0x3009, 0x2c10, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f0, 0x1801, 0x2210, 0x0000, 0x36f5, 0x4024, 0x36f0, 0x1801, 0x36f8, + 0x580a, 0x36f8, 0x1822, 0x0030, 0x0717, 0x2100, 0x0000, 0x3f05, 0xdbd7, + 0x3009, 0x3853, 0x3e18, 0x3823, 0x3e18, 0x780a, 0x3e10, 0x3801, 0x48b2, + 0x0024, 0x3e10, 0x3801, 0x0000, 0x800a, 0x3e10, 0xb803, 0x3e11, 0x3810, + 0x3e04, 0x7812, 0x0006, 0x0010, 0x0006, 0x0191, 0x3009, 0x0400, 0x4080, + 0x8012, 0x0030, 0x0553, 0x2802, 0xa385, 0x3009, 0x0840, 0x0006, 0x0093, + 0x32f3, 0x0c40, 0x4000, 0x4481, 0x4010, 0x8843, 0xf400, 0x4011, 0x0004, + 0x0001, 0x6014, 0x8cc4, 0x0030, 0x0550, 0x2802, 0x9dd1, 0x3009, 0x0f82, + 0x0ffc, 0x0010, 0x3183, 0x0024, 0x0030, 0x0550, 0x6428, 0x184c, 0xfe27, + 0xe6e7, 0x48b6, 0x8447, 0xfe4e, 0x8c87, 0x4db6, 0x0024, 0xffbe, 0x8bc3, + 0x48b2, 0x0024, 0xffae, 0x8f82, 0x40b2, 0x0024, 0xfe26, 0x2041, 0x48b6, + 0x87c7, 0xfe4e, 0x0024, 0x4db6, 0x8c87, 0xffbe, 0x0024, 0x48b2, 0x0024, + 0xffae, 0x0024, 0x40b2, 0x8c02, 0x4290, 0x2001, 0x3009, 0x2c00, 0x2802, + 0xa415, 0x36f1, 0x9807, 0x2802, 0xa400, 0xf400, 0x4452, 0x3b10, 0x0bc0, + 0x3b00, 0x0024, 0x0006, 0x0150, 0x3223, 0x0300, 0x6090, 0x8101, 0x6014, + 0x4484, 0x0004, 0x0001, 0x2802, 0xa708, 0x6414, 0xa300, 0xb880, 0x810c, + 0x3009, 0x2380, 0x3009, 0x00c0, 0x4090, 0x4484, 0x6414, 0xa000, 0x0006, + 0xa051, 0x2802, 0xa891, 0x0006, 0x0010, 0x0ffc, 0x0013, 0x3283, 0x0024, + 0xf400, 0x4484, 0x3009, 0x0400, 0x6408, 0xa012, 0x0000, 0x0400, 0x2802, + 0xaa98, 0x6404, 0x8412, 0x0004, 0x0002, 0x4428, 0x0024, 0x6404, 0x0024, + 0x0000, 0x0413, 0x2802, 0xad08, 0x3283, 0x0024, 0xf400, 0x4480, 0x6014, + 0x0024, 0x0ffc, 0x0013, 0x2802, 0xacd1, 0x0000, 0x0024, 0x3283, 0x0024, + 0x3009, 0x2412, 0x36f4, 0x5812, 0x36f1, 0x1810, 0x36f0, 0x9803, 0x36f0, + 0x1801, 0x2210, 0x0000, 0x36f0, 0x1801, 0x36f8, 0x580a, 0x36f8, 0x1823, + 0x0030, 0x0713, 0x2100, 0x0000, 0x3b04, 0xdbd3, 0x3613, 0x0024, 0x3e12, + 0x8024, 0x3e10, 0xb803, 0x3e14, 0x3811, 0x3e14, 0xb813, 0x3e13, 0x780e, + 0x3e03, 0xc024, 0x0001, 0x000a, 0x0006, 0x0755, 0x3504, 0x0024, 0x0020, + 0x0b91, 0x3880, 0x0024, 0x3880, 0x4024, 0xbd86, 0x3410, 0x0008, 0x2b91, + 0x003f, 0x15d2, 0x0000, 0x0053, 0x0000, 0x058e, 0x2402, 0xb4ce, 0xfe25, + 0x0829, 0x5017, 0x0829, 0x000e, 0x7b91, 0x5016, 0x020c, 0x4db6, 0x0001, + 0x4d16, 0x1bcf, 0xf1d6, 0x980e, 0xf7d0, 0x1bcd, 0x36f4, 0x9813, 0x36f4, + 0x1811, 0x36f0, 0x9803, 0x2000, 0x0000, 0x36f2, 0x8024, 0xb386, 0x40d7, + 0x4284, 0x184c, 0x0000, 0x05c0, 0x2802, 0xb955, 0xf5d8, 0x3804, 0x0000, + 0x0984, 0x6400, 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, 0x0000, 0x800a, + 0x0000, 0x00ce, 0x2402, 0xbc8e, 0xffa4, 0x0024, 0x48b6, 0x0024, 0x0000, + 0x0024, 0x2802, 0xbc84, 0x4000, 0x40c2, 0x4224, 0x0024, 0x6090, 0x0024, + 0xffa4, 0x0024, 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, 0xd80d, 0x48b6, + 0x0024, 0x0fff, 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, 0x36f1, 0x180a, + 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6b00, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1b40, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x148e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x9740, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x01bc, /*copy 444*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffd8, 0x0052, 0xff62, + 0x0116, 0xfe3a, 0x02c3, 0xfbd5, 0x0633, 0xf6b8, 0x0e89, 0xe5ee, 0x511e, + 0x511e, 0xe5ee, 0x0e89, 0xf6b8, 0x0633, 0xfbd5, 0x02c3, 0xfe3a, 0x0116, + 0xff62, 0x0052, 0xffd8, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x0012, /*copy 18*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x07c7, 0x07d3, 0x07e6, 0x07df, 0x07ea, 0x07ec, 0x07f2, + 0x0007, 0x0001, /*copy 1*/ + 0x8025, 0x0006, 0x0002, /*copy 2*/ + 0x2a01, 0x824e, 0x0007, 0x0001, /*copy 1*/ + 0x5800, 0x0006, 0x0005, /*copy 5*/ + 0x0000, 0x0c00, 0x0000, 0x0100, 0x0100, 0x0006, 0x8006, 0x0000, /*Rle(6)*/ + 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 5964 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/spectrum_analyzer.h b/targets/esp32/components/VS1053/include/spectrum_analyzer.h new file mode 100644 index 00000000..f163468f --- /dev/null +++ b/targets/esp32/components/VS1053/include/spectrum_analyzer.h @@ -0,0 +1,124 @@ + +const unsigned short PLUGIN[950] = { + /* Compressed plugin */ + 0x0007, 0x0001, 0x8050, 0x0006, 0x0018, 0x3613, 0x0024, 0x3e00, /* 0 */ + 0x3801, 0x0000, 0x16d7, 0xf400, 0x55c0, 0x0000, 0x0c17, 0xf400, /* 8 */ + 0x57c0, 0x0007, 0x9257, 0xb080, 0x0024, 0x3f00, 0x0024, 0x2000, /* 10 */ + 0x0000, 0x36f0, 0x1801, 0x2800, 0x31c0, 0x0007, 0x0001, 0x805c, /* 18 */ + 0x0006, 0x00d6, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, /* 20 */ + 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x0006, 0x0000, /* 28 */ + 0x3e10, 0xb803, 0x0000, 0x0303, 0x3e11, 0x3805, 0x3e11, 0xb807, /* 30 */ + 0x3e14, 0x3812, 0xb884, 0x130c, 0x3410, 0x4024, 0x4112, 0x10d0, /* 38 */ + 0x4010, 0x008c, 0x4010, 0x0024, 0xf400, 0x4012, 0x3000, 0x3840, /* 40 */ + 0x3009, 0x3801, 0x0000, 0x0041, 0xfe02, 0x0024, 0x2900, 0x8200, /* 48 */ + 0x48b2, 0x0024, 0x36f3, 0x0844, 0x6306, 0x8845, 0xae3a, 0x8840, /* 50 */ + 0xbf8e, 0x8b41, 0xac32, 0xa846, 0xffc8, 0xabc7, 0x3e01, 0x7800, /* 58 */ + 0xf400, 0x4480, 0x6090, 0x0024, 0x6090, 0x0024, 0xf400, 0x4015, /* 60 */ + 0x3009, 0x3446, 0x3009, 0x37c7, 0x3009, 0x1800, 0x3009, 0x3844, /* 68 */ + 0x48b3, 0xe1e0, 0x4882, 0x4040, 0xfeca, 0x0024, 0x5ac2, 0x0024, /* 70 */ + 0x5a52, 0x0024, 0x4cc2, 0x0024, 0x48ba, 0x4040, 0x4eea, 0x4801, /* 78 */ + 0x4eca, 0x9800, 0xff80, 0x1bc1, 0xf1eb, 0xe3e2, 0xf1ea, 0x184c, /* 80 */ + 0x4c8b, 0xe5e4, 0x48be, 0x9804, 0x488e, 0x41c6, 0xfe82, 0x0024, /* 88 */ + 0x5a8e, 0x0024, 0x525e, 0x1b85, 0x4ffe, 0x0024, 0x48b6, 0x41c6, /* 90 */ + 0x4dd6, 0x48c7, 0x4df6, 0x0024, 0xf1d6, 0x0024, 0xf1d6, 0x0024, /* 98 */ + 0x4eda, 0x0024, 0x0000, 0x0fc3, 0x2900, 0x8200, 0x4e82, 0x0024, /* a0 */ + 0x4084, 0x130c, 0x0006, 0x0100, 0x3440, 0x4024, 0x4010, 0x0024, /* a8 */ + 0xf400, 0x4012, 0x3200, 0x4024, 0xb132, 0x0024, 0x4214, 0x0024, /* b0 */ + 0xf224, 0x0024, 0x6230, 0x0024, 0x0001, 0x0001, 0x2800, 0x2b49, /* b8 */ + 0x0000, 0x0024, 0xf400, 0x40c2, 0x3200, 0x0024, 0xff82, 0x0024, /* c0 */ + 0x48b2, 0x0024, 0xb130, 0x0024, 0x6202, 0x0024, 0x003f, 0xf001, /* c8 */ + 0x2800, 0x2e51, 0x0000, 0x1046, 0xfe64, 0x0024, 0x48be, 0x0024, /* d0 */ + 0x2800, 0x2f40, 0x3a01, 0x8024, 0x3200, 0x0024, 0xb010, 0x0024, /* d8 */ + 0xc020, 0x0024, 0x3a00, 0x0024, 0x36f4, 0x1812, 0x36f1, 0x9807, /* e0 */ + 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, /* e8 */ + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, /* f0 */ + 0x0007, 0x0001, 0x80c7, 0x0006, 0x01ae, 0x3e12, 0xb817, 0x3e12, /* f8 */ + 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, /* 100 */ + 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7810, 0x3e14, 0x7813, 0x0006, /* 108 */ + 0x0051, 0x3e13, 0xf80e, 0x3e13, 0x4024, 0x3009, 0x3840, 0x3009, /* 110 */ + 0x3852, 0x2911, 0xf140, 0x0006, 0x06d0, 0x3100, 0x5bd2, 0x0006, /* 118 */ + 0xc351, 0x3009, 0x1bc0, 0x3009, 0x0402, 0x6126, 0x0024, 0x0006, /* 120 */ + 0x00d1, 0x2800, 0x4d45, 0x0000, 0x0024, 0x0006, 0x0011, 0xb882, /* 128 */ + 0x184c, 0x3009, 0x3850, 0x0006, 0x0010, 0x3009, 0x3800, 0x2914, /* 130 */ + 0xbec0, 0x0000, 0x1800, 0x0006, 0x0010, 0xb882, 0x0024, 0x2915, /* 138 */ + 0x7ac0, 0x0000, 0x1700, 0x0000, 0x0301, 0x3900, 0x5bc0, 0x0006, /* 140 */ + 0xc351, 0x3009, 0x1bd0, 0x3009, 0x0404, 0x0006, 0x0051, 0x2800, /* 148 */ + 0x3d40, 0x3901, 0x0024, 0x4448, 0x0401, 0x4192, 0x0024, 0x6498, /* 150 */ + 0x2401, 0x001f, 0x4001, 0x6412, 0x0024, 0x0006, 0x0011, 0x2800, /* 158 */ + 0x3c91, 0x0000, 0x058e, 0x2400, 0x4c4e, 0x0000, 0x0013, 0x0006, /* 160 */ + 0x0051, 0x0006, 0x1a03, 0x3100, 0x4024, 0xf212, 0x44c4, 0x4346, /* 168 */ + 0x0024, 0xf400, 0x40d5, 0x3500, 0x8024, 0x612a, 0x0024, 0x0000, /* 170 */ + 0x0024, 0x2800, 0x4c91, 0x0000, 0x0024, 0x3613, 0x0024, 0x3100, /* 178 */ + 0x3800, 0x2915, 0x7dc0, 0xf200, 0x0024, 0x003f, 0xfec2, 0x4082, /* 180 */ + 0x4411, 0x3113, 0x1bc0, 0xa122, 0x0024, 0x0000, 0x2002, 0x6124, /* 188 */ + 0x2401, 0x0000, 0x1002, 0x2800, 0x4648, 0x0000, 0x0024, 0x003f, /* 190 */ + 0xf802, 0x3100, 0x4024, 0xb124, 0x0024, 0x2800, 0x4c00, 0x3900, /* 198 */ + 0x8024, 0x6124, 0x0024, 0x0000, 0x0802, 0x2800, 0x4888, 0x0000, /* 1a0 */ + 0x0024, 0x003f, 0xfe02, 0x3100, 0x4024, 0xb124, 0x0024, 0x2800, /* 1a8 */ + 0x4c00, 0x3900, 0x8024, 0x6124, 0x0024, 0x0000, 0x0402, 0x2800, /* 1b0 */ + 0x4ac8, 0x0000, 0x0024, 0x003f, 0xff02, 0x3100, 0x4024, 0xb124, /* 1b8 */ + 0x0024, 0x2800, 0x4c00, 0x3900, 0x8024, 0x6124, 0x0401, 0x003f, /* 1c0 */ + 0xff82, 0x2800, 0x4c08, 0xb124, 0x0024, 0x3900, 0x8024, 0xb882, /* 1c8 */ + 0x8c4c, 0x3830, 0x4024, 0x0006, 0x0091, 0x3904, 0xc024, 0x0006, /* 1d0 */ + 0x00d1, 0x0000, 0x0013, 0x3100, 0x904c, 0x4202, 0x0024, 0x39f0, /* 1d8 */ + 0x4024, 0x3100, 0x4024, 0x3c00, 0x4024, 0xf400, 0x44c1, 0x34f0, /* 1e0 */ + 0x8024, 0x6126, 0x0024, 0x0006, 0x06d0, 0x2800, 0x5b98, 0x4294, /* 1e8 */ + 0x0024, 0x2400, 0x5b42, 0x0000, 0x0024, 0xf400, 0x4411, 0x3123, /* 1f0 */ + 0x0024, 0x3100, 0x8024, 0x4202, 0x0024, 0x4182, 0x2401, 0x0000, /* 1f8 */ + 0x2002, 0x2800, 0x5b49, 0x0000, 0x0024, 0x3013, 0x184c, 0x30f0, /* 200 */ + 0x7852, 0x6124, 0xb850, 0x0006, 0x0001, 0x2800, 0x55c8, 0x4088, /* 208 */ + 0x44c2, 0x4224, 0x0024, 0x4122, 0x0024, 0x4122, 0x0024, 0xf400, /* 210 */ + 0x4051, 0x2900, 0x7200, 0x0000, 0x5708, 0x4224, 0x0024, 0x4122, /* 218 */ + 0x0024, 0x4122, 0x0024, 0x2900, 0x6780, 0xf400, 0x4051, 0x0002, /* 220 */ + 0x0002, 0x3009, 0x1bd0, 0x3023, 0x1bd2, 0x30e0, 0x4024, 0x6124, /* 228 */ + 0x0024, 0x0000, 0x0024, 0x2800, 0x5b48, 0x0000, 0x0024, 0x3613, /* 230 */ + 0x0024, 0x3e14, 0xc024, 0x2900, 0x1700, 0x3e14, 0x0024, 0x36e3, /* 238 */ + 0x008c, 0x30e0, 0x8024, 0x6822, 0x4411, 0x3123, 0x0024, 0x3900, /* 240 */ + 0x4024, 0x3033, 0x0c4c, 0x0006, 0x0011, 0x6892, 0x04c2, 0xa122, /* 248 */ + 0x0402, 0x6126, 0x0024, 0x0006, 0x0093, 0x2800, 0x64c1, 0x0000, /* 250 */ + 0x0024, 0xb882, 0x184c, 0x3413, 0x3812, 0x0006, 0x00d2, 0x3a00, /* 258 */ + 0x5bd2, 0x3300, 0x4024, 0x0000, 0x0013, 0x3c00, 0x4024, 0xf400, /* 260 */ + 0x44c1, 0x34f0, 0x8024, 0x6126, 0x0024, 0x0006, 0x0111, 0x2800, /* 268 */ + 0x64d8, 0x4294, 0x0024, 0x2400, 0x6482, 0x0000, 0x0024, 0x0003, /* 270 */ + 0xf001, 0x3101, 0x0024, 0xb412, 0x0024, 0x0028, 0x0001, 0x2800, /* 278 */ + 0x6485, 0x6144, 0x0024, 0x0004, 0x0002, 0x2800, 0x6441, 0x4422, /* 280 */ + 0x0024, 0x0000, 0x1002, 0x6422, 0x0024, 0x2800, 0x6480, 0x3900, /* 288 */ + 0x4024, 0x3900, 0x4024, 0x3113, 0x0c4c, 0x36f3, 0x4024, 0x36f3, /* 290 */ + 0xd80e, 0x36f4, 0x5813, 0x36f1, 0x5810, 0x36f0, 0xd804, 0x36f0, /* 298 */ + 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, /* 2a0 */ + 0x0000, 0x36f2, 0x9817, 0x0007, 0x0001, 0x1868, 0x0006, 0x000f, /* 2a8 */ + 0x0032, 0x004f, 0x007e, 0x00c8, 0x013d, 0x01f8, 0x0320, 0x04f6, /* 2b0 */ + 0x07e0, 0x0c80, 0x13d8, 0x1f7f, 0x3200, 0x4f5f, 0x61a8, 0x0006, /* 2b8 */ + 0x8008, 0x0000, 0x0007, 0x0001, 0x819e, 0x0006, 0x0054, 0x3e12, /* 2c0 */ + 0xb814, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, /* 2c8 */ + 0x7806, 0x3e11, 0xf813, 0x3e13, 0xf80e, 0x3e13, 0x4024, 0x3e04, /* 2d0 */ + 0x7810, 0x449a, 0x0040, 0x0001, 0x0003, 0x2800, 0x70c4, 0x4036, /* 2d8 */ + 0x03c1, 0x0003, 0xffc2, 0xb326, 0x0024, 0x0018, 0x0042, 0x4326, /* 2e0 */ + 0x4495, 0x4024, 0x40d2, 0x0000, 0x0180, 0xa100, 0x4090, 0x0010, /* 2e8 */ + 0x0fc2, 0x4204, 0x0024, 0xbc82, 0x4091, 0x459a, 0x0024, 0x0000, /* 2f0 */ + 0x0054, 0x2800, 0x6fc4, 0xbd86, 0x4093, 0x2400, 0x6f85, 0xfe01, /* 2f8 */ + 0x5e0c, 0x5c43, 0x5f2d, 0x5e46, 0x020c, 0x5c56, 0x8a0c, 0x5e53, /* 300 */ + 0x5e0c, 0x5c43, 0x5f2d, 0x5e46, 0x020c, 0x5c56, 0x8a0c, 0x5e52, /* 308 */ + 0x0024, 0x4cb2, 0x4405, 0x0018, 0x0044, 0x654a, 0x0024, 0x2800, /* 310 */ + 0x7dc0, 0x36f4, 0x5810, 0x0007, 0x0001, 0x81c8, 0x0006, 0x0080, /* 318 */ + 0x3e12, 0xb814, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, /* 320 */ + 0x3e11, 0x7806, 0x3e11, 0xf813, 0x3e13, 0xf80e, 0x3e13, 0x4024, /* 328 */ + 0x3e04, 0x7810, 0x449a, 0x0040, 0x0000, 0x0803, 0x2800, 0x7c84, /* 330 */ + 0x30f0, 0x4024, 0x0fff, 0xfec2, 0xa020, 0x0024, 0x0fff, 0xff02, /* 338 */ + 0xa122, 0x0024, 0x4036, 0x0024, 0x0000, 0x1fc2, 0xb326, 0x0024, /* 340 */ + 0x0010, 0x4002, 0x4326, 0x4495, 0x4024, 0x40d2, 0x0000, 0x0180, /* 348 */ + 0xa100, 0x4090, 0x0010, 0x0042, 0x4204, 0x0024, 0xbc82, 0x4091, /* 350 */ + 0x459a, 0x0024, 0x0000, 0x0054, 0x2800, 0x7b84, 0xbd86, 0x4093, /* 358 */ + 0x2400, 0x7b45, 0xfe01, 0x5e0c, 0x5c43, 0x5f2d, 0x5e46, 0x0024, /* 360 */ + 0x5c56, 0x0024, 0x5e53, 0x5e0c, 0x5c43, 0x5f2d, 0x5e46, 0x0024, /* 368 */ + 0x5c56, 0x0024, 0x5e52, 0x0024, 0x4cb2, 0x4405, 0x0010, 0x4004, /* 370 */ + 0x654a, 0x9810, 0x0000, 0x0144, 0xa54a, 0x1bd1, 0x0006, 0x0013, /* 378 */ + 0x3301, 0xc444, 0x687e, 0x2005, 0xad76, 0x8445, 0x4ed6, 0x8784, /* 380 */ + 0x36f3, 0x64c2, 0xac72, 0x8785, 0x4ec2, 0xa443, 0x3009, 0x2440, /* 388 */ + 0x3009, 0x2741, 0x36f3, 0xd80e, 0x36f1, 0xd813, 0x36f1, 0x5806, /* 390 */ + 0x36f0, 0x9803, 0x36f0, 0x1801, 0x2000, 0x0000, 0x36f2, 0x9814, /* 398 */ + 0x0007, 0x0001, 0x8208, 0x0006, 0x000e, 0x4c82, 0x0024, 0x0000, /* 3a0 */ + 0x0024, 0x2000, 0x0005, 0xf5c2, 0x0024, 0x0000, 0x0980, 0x2000, /* 3a8 */ + 0x0000, 0x6010, 0x0024, 0x000a, 0x0001, 0x0050, +#define PLUGIN_SIZE 950 +}; diff --git a/targets/esp32/components/VS1053/include/vs10xx_uc.h b/targets/esp32/components/VS1053/include/vs10xx_uc.h new file mode 100644 index 00000000..b310fca9 --- /dev/null +++ b/targets/esp32/components/VS1053/include/vs10xx_uc.h @@ -0,0 +1,561 @@ +#ifndef VS10XX_MICROCONTROLLER_DEFINITIONS_H +#define VS10XX_MICROCONTROLLER_DEFINITIONS_H + +/* + + VLSI Solution microcontroller definitions for: + VS1063, VS1053 (and VS8053), VS1033, VS1003, VS1103, VS1011. + + v1.01 2012-11-26 HH Added VS1053 recording registers, bug fixes + v1.00 2012-11-23 HH Initial version + +*/ + + + + + +/* SCI registers */ +#define SCI_num_registers 0x0f +#define VS_WRITE_COMMAND 0x02 +#define VS_READ_COMMAND 0x03 + +#define SCI_MODE 0x00 +#define SCI_STATUS 0x01 +#define SCI_BASS 0x02 +#define SCI_CLOCKF 0x03 +#define SCI_DECODE_TIME 0x04 +#define SCI_AUDATA 0x05 +#define SCI_WRAM 0x06 +#define SCI_WRAMADDR 0x07 +#define SCI_HDAT0 0x08 /* VS1063, VS1053, VS1033, VS1003, VS1011 */ +#define SCI_IN0 0x08 /* VS1103 */ +#define SCI_HDAT1 0x09 /* VS1063, VS1053, VS1033, VS1003, VS1011 */ +#define SCI_IN1 0x09 /* VS1103 */ +#define SCI_AIADDR 0x0A +#define SCI_VOL 0x0B +#define SCI_AICTRL0 0x0C /* VS1063, VS1053, VS1033, VS1003, VS1011 */ +#define SCI_MIXERVOL 0x0C /* VS1103 */ +#define SCI_AICTRL1 0x0D /* VS1063, VS1053, VS1033, VS1003, VS1011 */ +#define SCI_ADPCMRECCTL 0x0D /* VS1103 */ +#define SCI_AICTRL2 0x0E +#define SCI_AICTRL3 0x0F + + +/* SCI register recording aliases */ + +#define SCI_RECQUALITY 0x07 /* (WRAMADDR) VS1063 */ +#define SCI_RECDATA 0x08 /* (HDAT0) VS1063 */ +#define SCI_RECWORDS 0x09 /* (HDAT1) VS1063 */ +#define SCI_RECRATE 0x0C /* (AICTRL0) VS1063, VS1053 */ +#define SCI_RECDIV 0x0C /* (AICTRL0) VS1033, VS1003 */ +#define SCI_RECGAIN 0x0D /* (AICTRL1) VS1063, VS1053, VS1033, VS1003 */ +#define SCI_RECMAXAUTO 0x0E /* (AICTRL2) VS1063, VS1053, VS1033 */ +#define SCI_RECMODE 0x0F /* (AICTRL3) VS1063, VS1053 */ + + +/* SCI_MODE bits */ + +#define SM_DIFF_B 0 +#define SM_LAYER12_B 1 /* VS1063, VS1053, VS1033, VS1011 */ +#define SM_RECORD_PATH_B 1 /* VS1103 */ +#define SM_RESET_B 2 +#define SM_CANCEL_B 3 /* VS1063, VS1053 */ +#define SM_OUTOFWAV_B 3 /* VS1033, VS1003, VS1011 */ +#define SM_OUTOFMIDI_B 3 /* VS1103 */ +#define SM_EARSPEAKER_LO_B 4 /* VS1053, VS1033 */ +#define SM_PDOWN_B 4 /* VS1003, VS1103 */ +#define SM_TESTS_B 5 +#define SM_STREAM_B 6 /* VS1053, VS1033, VS1003, VS1011 */ +#define SM_ICONF_B 6 /* VS1103 */ +#define SM_EARSPEAKER_HI_B 7 /* VS1053, VS1033 */ +#define SM_DACT_B 8 +#define SM_SDIORD_B 9 +#define SM_SDISHARE_B 10 +#define SM_SDINEW_B 11 +#define SM_ENCODE_B 12 /* VS1063 */ +#define SM_ADPCM_B 12 /* VS1053, VS1033, VS1003 */ +#define SM_EARSPEAKER_1103_B 12 /* VS1103 */ +#define SM_ADPCM_HP_B 13 /* VS1033, VS1003 */ +#define SM_LINE1_B 14 /* VS1063, VS1053 */ +#define SM_LINE_IN_B 14 /* VS1033, VS1003, VS1103 */ +#define SM_CLK_RANGE_B 15 /* VS1063, VS1053, VS1033 */ +#define SM_ADPCM_1103_B 15 /* VS1103 */ + +#define SM_DIFF (1<< 0) +#define SM_LAYER12 (1<< 1) /* VS1063, VS1053, VS1033, VS1011 */ +#define SM_RECORD_PATH (1<< 1) /* VS1103 */ +#define SM_RESET (1<< 2) +#define SM_CANCEL (1<< 3) /* VS1063, VS1053 */ +#define SM_OUTOFWAV (1<< 3) /* VS1033, VS1003, VS1011 */ +#define SM_OUTOFMIDI (1<< 3) /* VS1103 */ +#define SM_EARSPEAKER_LO (1<< 4) /* VS1053, VS1033 */ +#define SM_PDOWN (1<< 4) /* VS1003, VS1103 */ +#define SM_TESTS (1<< 5) +#define SM_STREAM (1<< 6) /* VS1053, VS1033, VS1003, VS1011 */ +#define SM_ICONF (1<< 6) /* VS1103 */ +#define SM_EARSPEAKER_HI (1<< 7) /* VS1053, VS1033 */ +#define SM_DACT (1<< 8) +#define SM_SDIORD (1<< 9) +#define SM_SDISHARE (1<<10) +#define SM_SDINEW (1<<11) +#define SM_ENCODE (1<<12) /* VS1063 */ +#define SM_ADPCM (1<<12) /* VS1053, VS1033, VS1003 */ +#define SM_EARSPEAKER1103 (1<<12) /* VS1103 */ +#define SM_ADPCM_HP (1<<13) /* VS1033, VS1003 */ +#define SM_LINE1 (1<<14) /* VS1063, VS1053 */ +#define SM_LINE_IN (1<<14) /* VS1033, VS1003, VS1103 */ +#define SM_CLK_RANGE (1<<15) /* VS1063, VS1053, VS1033 */ +#define SM_ADPCM_1103 (1<<15) /* VS1103 */ + +#define SM_ICONF_BITS 2 +#define SM_ICONF_MASK 0x00c0 + +#define SM_EARSPEAKER_1103_BITS 2 +#define SM_EARSPEAKER_1103_MASK 0x3000 + + +/* SCI_STATUS bits */ + +#define SS_REFERENCE_SEL_B 0 /* VS1063, VS1053 */ +#define SS_AVOL_B 0 /* VS1033, VS1003, VS1103, VS1011 */ +#define SS_AD_CLOCK_B 1 /* VS1063, VS1053 */ +#define SS_APDOWN1_B 2 +#define SS_APDOWN2_B 3 +#define SS_VER_B 4 +#define SS_VCM_DISABLE_B 10 /* VS1063, VS1053 */ +#define SS_VCM_OVERLOAD_B 11 /* VS1063, VS1053 */ +#define SS_SWING_B 12 /* VS1063, VS1053 */ +#define SS_DO_NOT_JUMP_B 15 /* VS1063, VS1053 */ + +#define SS_REFERENCE_SEL (1<< 0) /* VS1063, VS1053 */ +#define SS_AVOL (1<< 0) /* VS1033, VS1003, VS1103, VS1011 */ +#define SS_AD_CLOCK (1<< 1) /* VS1063, VS1053 */ +#define SS_APDOWN1 (1<< 2) +#define SS_APDOWN2 (1<< 3) +#define SS_VER (1<< 4) +#define SS_VCM_DISABLE (1<<10) /* VS1063, VS1053 */ +#define SS_VCM_OVERLOAD (1<<11) /* VS1063, VS1053 */ +#define SS_SWING (1<<12) /* VS1063, VS1053 */ +#define SS_DO_NOT_JUMP (1<<15) /* VS1063, VS1053 */ + +#define SS_SWING_BITS 3 +#define SS_SWING_MASK 0x7000 +#define SS_VER_BITS 4 +#define SS_VER_MASK 0x00f0 +#define SS_AVOL_BITS 2 +#define SS_AVOL_MASK 0x0003 + +#define SS_VER_VS1001 0x00 +#define SS_VER_VS1011 0x10 +#define SS_VER_VS1002 0x20 +#define SS_VER_VS1003 0x30 +#define SS_VER_VS1053 0x40 +#define SS_VER_VS8053 0x40 +#define SS_VER_VS1033 0x50 +#define SS_VER_VS1063 0x60 +#define SS_VER_VS1103 0x70 + + +/* SCI_BASS bits */ + +#define ST_AMPLITUDE_B 12 +#define ST_FREQLIMIT_B 8 +#define SB_AMPLITUDE_B 4 +#define SB_FREQLIMIT_B 0 + +#define ST_AMPLITUDE (1<<12) +#define ST_FREQLIMIT (1<< 8) +#define SB_AMPLITUDE (1<< 4) +#define SB_FREQLIMIT (1<< 0) + +#define ST_AMPLITUDE_BITS 4 +#define ST_AMPLITUDE_MASK 0xf000 +#define ST_FREQLIMIT_BITS 4 +#define ST_FREQLIMIT_MASK 0x0f00 +#define SB_AMPLITUDE_BITS 4 +#define SB_AMPLITUDE_MASK 0x00f0 +#define SB_FREQLIMIT_BITS 4 +#define SB_FREQLIMIT_MASK 0x000f + + +/* SCI_CLOCKF bits */ + +#define SC_MULT_B 13 /* VS1063, VS1053, VS1033, VS1103, VS1003 */ +#define SC_ADD_B 11 /* VS1063, VS1053, VS1033, VS1003 */ +#define SC_FREQ_B 0 /* VS1063, VS1053, VS1033, VS1103, VS1003 */ + +#define SC_MULT (1<<13) /* VS1063, VS1053, VS1033, VS1103, VS1003 */ +#define SC_ADD (1<<11) /* VS1063, VS1053, VS1033, VS1003 */ +#define SC_FREQ (1<< 0) /* VS1063, VS1053, VS1033, VS1103, VS1003 */ + +#define SC_MULT_BITS 3 +#define SC_MULT_MASK 0xe000 +#define SC_ADD_BITS 2 +#define SC_ADD_MASK 0x1800 +#define SC_FREQ_BITS 11 +#define SC_FREQ_MASK 0x07ff + +/* The following macro is for VS1063, VS1053, VS1033, VS1003, VS1103. + Divide hz by two when calling if SM_CLK_RANGE = 1 */ +#define HZ_TO_SC_FREQ(hz) (((hz)-8000000+2000)/4000) + +/* The following macro is for VS1011. + The macro will automatically set the clock doubler if XTALI < 16 MHz */ +#define HZ_TO_SCI_CLOCKF(hz) ((((hz)<16000000)?0x8000:0)+((hz)+1000)/2000) + +/* Following are for VS1003 and VS1033 */ +#define SC_MULT_03_10X 0x0000 +#define SC_MULT_03_15X 0x2000 +#define SC_MULT_03_20X 0x4000 +#define SC_MULT_03_25X 0x6000 +#define SC_MULT_03_30X 0x8000 +#define SC_MULT_03_35X 0xa000 +#define SC_MULT_03_40X 0xc000 +#define SC_MULT_03_45X 0xe000 + +/* Following are for VS1053 and VS1063 */ +#define SC_MULT_53_10X 0x0000 +#define SC_MULT_53_20X 0x2000 +#define SC_MULT_53_25X 0x4000 +#define SC_MULT_53_30X 0x6000 +#define SC_MULT_53_35X 0x8000 +#define SC_MULT_53_40X 0xa000 +#define SC_MULT_53_45X 0xc000 +#define SC_MULT_53_50X 0xe000 + +/* Following are for VS1003 and VS1033 */ +#define SC_ADD_03_00X 0x0000 +#define SC_ADD_03_05X 0x0800 +#define SC_ADD_03_10X 0x1000 +#define SC_ADD_03_15X 0x1800 + +/* Following are for VS1053 and VS1063 */ +#define SC_ADD_53_00X 0x0000 +#define SC_ADD_53_10X 0x0800 +#define SC_ADD_53_15X 0x1000 +#define SC_ADD_53_20X 0x1800 + + +/* SCI_WRAMADDR bits */ + +#define SCI_WRAM_X_START 0x0000 +#define SCI_WRAM_Y_START 0x4000 +#define SCI_WRAM_I_START 0x8000 +#define SCI_WRAM_IO_START 0xC000 +#define SCI_WRAM_PARAMETRIC_START 0xC0C0 /* VS1063 */ +#define SCI_WRAM_Y2_START 0xE000 /* VS1063 */ + +#define SCI_WRAM_X_OFFSET 0x0000 +#define SCI_WRAM_Y_OFFSET 0x4000 +#define SCI_WRAM_I_OFFSET 0x8000 +#define SCI_WRAM_IO_OFFSET 0x0000 /* I/O addresses are @0xC000 -> no offset */ +#define SCI_WRAM_PARAMETRIC_OFFSET (0xC0C0-0x1E00) /* VS1063 */ +#define SCI_WRAM_Y2_OFFSET 0x0000 /* VS1063 */ + + +/* SCI_VOL bits */ + +#define SV_LEFT_B 8 +#define SV_RIGHT_B 0 + +#define SV_LEFT (1<<8) +#define SV_RIGHT (1<<0) + +#define SV_LEFT_BITS 8 +#define SV_LEFT_MASK 0xFF00 +#define SV_RIGHT_BITS 8 +#define SV_RIGHT_MASK 0x00FF + + +/* SCI_MIXERVOL bits for VS1103 */ + +#define SMV_ACTIVE_B 15 +#define SMV_GAIN3_B 10 +#define SMV_GAIN2_B 5 +#define SMV_GAIN1_B 0 + +#define SMV_ACTIVE (1<<15) +#define SMV_GAIN3 (1<<10) +#define SMV_GAIN2 (1<< 5) +#define SMV_GAIN1 (1<< 0) + +#define SMV_GAIN3_BITS 5 +#define SMV_GAIN3_MASK 0x7c00 +#define SMV_GAIN2_BITS 5 +#define SMV_GAIN2_MASK 0x04e0 +#define SMV_GAIN1_BITS 5 +#define SMV_GAIN1_MASK 0x001f + + +/* SCI_ADPCMRECCTL bits for VS1103 */ + +#define SARC_DREQ512_B 8 +#define SARC_OUTODADPCM_B 7 +#define SARC_MANUALGAIN_B 6 +#define SARC_GAIN4_B 0 + +#define SARC_DREQ512 (1<<8) +#define SARC_OUTODADPCM (1<<7) +#define SARC_MANUALGAIN (1<<6) +#define SARC_GAIN4 (1<<0) + +#define SARC_GAIN4_BITS 6 +#define SARC_GAIN4_MASK 0x003f + + +/* SCI_RECQUALITY bits for VS1063 */ + +#define RQ_MODE_B 14 +#define RQ_MULT_B 12 +#define RQ_OGG_PAR_SERIAL_NUMBER_B 11 +#define RQ_OGG_LIMIT_FRAME_LENGTH_B 10 +#define RQ_MP3_NO_BIT_RESERVOIR_B 10 +#define RQ_BITRATE_BASE_B 0 + +#define RQ_MODE (1<<14) +#define RQ_MULT (1<<12) +#define RQ_OGG_PAR_SERIAL_NUMBER (1<<11) +#define RQ_OGG_LIMIT_FRAME_LENGTH (1<<10) +#define RQ_MP3_NO_BIT_RESERVOIR (1<<10) +#define RQ_BITRATE_BASE (1<< 0) + +#define RQ_MODE_BITS 2 +#define RQ_MODE_MASK 0xc000 +#define RQ_MULT_BITS 2 +#define RQ_MULT_MASK 0x3000 +#define RQ_BITRATE_BASE_BITS 9 +#define RQ_BITRATE_BASE_MASK 0x01ff + +#define RQ_MODE_QUALITY 0x0000 +#define RQ_MODE_VBR 0x4000 +#define RQ_MODE_ABR 0x8000 +#define RQ_MODE_CBR 0xc000 + +#define RQ_MULT_10 0x0000 +#define RQ_MULT_100 0x1000 +#define RQ_MULT_1000 0x2000 +#define RQ_MULT_10000 0x3000 + + +/* SCI_RECMODE bits for VS1063 */ + +#define RM_63_CODEC_B 15 +#define RM_63_AEC_B 14 +#define RM_63_UART_TX_B 13 +#define RM_63_PAUSE_B 11 +#define RM_63_NO_RIFF_B 10 +#define RM_63_FORMAT_B 4 +#define RM_63_ADC_MODE_B 0 + +#define RM_63_CODEC (1<<15) +#define RM_63_AEC (1<<14) +#define RM_63_UART_TX (1<<13) +#define RM_63_PAUSE (1<<11) +#define RM_63_NO_RIFF (1<<10) +#define RM_63_FORMAT (1<< 4) +#define RM_63_ADC_MODE (1<< 0) + +#define RM_63_FORMAT_BITS 4 +#define RM_63_FORMAT_MASK 0x00f0 +#define RM_63_ADCMODE_BITS 3 +#define RM_63_ADCMODE_MASK 0x0007 + +#define RM_63_FORMAT_IMA_ADPCM 0x0000 +#define RM_63_FORMAT_PCM 0x0010 +#define RM_63_FORMAT_G711_ULAW 0x0020 +#define RM_63_FORMAT_G711_ALAW 0x0030 +#define RM_63_FORMAT_G722_ADPCM 0x0040 +#define RM_63_FORMAT_OGG_VORBIS 0x0050 +#define RM_63_FORMAT_MP3 0x0060 + +#define RM_63_ADC_MODE_JOINT_AGC_STEREO 0x0000 +#define RM_63_ADC_MODE_DUAL_AGC_STEREO 0x0001 +#define RM_63_ADC_MODE_LEFT 0x0002 +#define RM_63_ADC_MODE_RIGHT 0x0003 +#define RM_63_ADC_MODE_MONO 0x0004 + + +/* SCI_RECMODE bits for VS1053 */ + +#define RM_53_FORMAT_B 2 +#define RM_53_ADC_MODE_B 0 + +#define RM_53_FORMAT (1<< 2) +#define RM_53_ADC_MODE (1<< 0) + +#define RM_53_ADCMODE_BITS 2 +#define RM_53_ADCMODE_MASK 0x0003 + +#define RM_53_FORMAT_IMA_ADPCM 0x0000 +#define RM_53_FORMAT_PCM 0x0004 + +#define RM_53_ADC_MODE_JOINT_AGC_STEREO 0x0000 +#define RM_53_ADC_MODE_DUAL_AGC_STEREO 0x0001 +#define RM_53_ADC_MODE_LEFT 0x0002 +#define RM_53_ADC_MODE_RIGHT 0x0003 + + +/* VS1063 definitions */ + +/* VS1063 / VS1053 Parametric */ +#define PAR_CHIP_ID 0x1e00 /* VS1063, VS1053, 32 bits */ +#define PAR_VERSION 0x1e02 /* VS1063, VS1053 */ +#define PAR_CONFIG1 0x1e03 /* VS1063, VS1053 */ +#define PAR_PLAY_SPEED 0x1e04 /* VS1063, VS1053 */ +#define PAR_BITRATE_PER_100 0x1e05 /* VS1063 */ +#define PAR_BYTERATE 0x1e05 /* VS1053 */ +#define PAR_END_FILL_BYTE 0x1e06 /* VS1063, VS1053 */ +#define PAR_RATE_TUNE 0x1e07 /* VS1063, 32 bits */ +#define PAR_PLAY_MODE 0x1e09 /* VS1063 */ +#define PAR_SAMPLE_COUNTER 0x1e0a /* VS1063, 32 bits */ +#define PAR_VU_METER 0x1e0c /* VS1063 */ +#define PAR_AD_MIXER_GAIN 0x1e0d /* VS1063 */ +#define PAR_AD_MIXER_CONFIG 0x1e0e /* VS1063 */ +#define PAR_PCM_MIXER_RATE 0x1e0f /* VS1063 */ +#define PAR_PCM_MIXER_FREE 0x1e10 /* VS1063 */ +#define PAR_PCM_MIXER_VOL 0x1e11 /* VS1063 */ +#define PAR_EQ5_DUMMY 0x1e12 /* VS1063 */ +#define PAR_EQ5_LEVEL1 0x1e13 /* VS1063 */ +#define PAR_EQ5_FREQ1 0x1e14 /* VS1063 */ +#define PAR_EQ5_LEVEL2 0x1e15 /* VS1063 */ +#define PAR_EQ5_FREQ2 0x1e16 /* VS1063 */ +#define PAR_JUMP_POINTS 0x1e16 /* VS1053 */ +#define PAR_EQ5_LEVEL3 0x1e17 /* VS1063 */ +#define PAR_EQ5_FREQ3 0x1e18 /* VS1063 */ +#define PAR_EQ5_LEVEL4 0x1e19 /* VS1063 */ +#define PAR_EQ5_FREQ4 0x1e1a /* VS1063 */ +#define PAR_EQ5_LEVEL5 0x1e1b /* VS1063 */ +#define PAR_EQ5_UPDATED 0x1e1c /* VS1063 */ +#define PAR_SPEED_SHIFTER 0x1e1d /* VS1063 */ +#define PAR_EARSPEAKER_LEVEL 0x1e1e /* VS1063 */ +#define PAR_SDI_FREE 0x1e1f /* VS1063 */ +#define PAR_AUDIO_FILL 0x1e20 /* VS1063 */ +#define PAR_RESERVED0 0x1e21 /* VS1063 */ +#define PAR_RESERVED1 0x1e22 /* VS1063 */ +#define PAR_RESERVED2 0x1e23 /* VS1063 */ +#define PAR_RESERVED3 0x1e24 /* VS1063 */ +#define PAR_LATEST_SOF 0x1e25 /* VS1063, 32 bits */ +#define PAR_LATEST_JUMP 0x1e26 /* VS1053 */ +#define PAR_POSITION_MSEC 0x1e27 /* VS1063, VS1053, 32 bits */ +#define PAR_RESYNC 0x1e29 /* VS1063, VS1053 */ + +/* The following addresses are shared between modes. */ +/* Generic pointer */ +#define PAR_GENERIC 0x1e2a /* VS1063, VS1053 */ + +/* Encoder mode */ +#define PAR_ENC_TX_UART_DIV 0x1e2a /* VS1063 */ +#define PAR_ENC_TX_UART_BYTE_SPEED 0x1e2b /* VS1063 */ +#define PAR_ENC_TX_PAUSE_GPIO 0x1e2c /* VS1063 */ +#define PAR_ENC_AEC_ADAPT_MULTIPLIER 0x1e2d /* VS1063 */ +#define PAR_ENC_RESERVED 0x1e2e /* VS1063 */ +#define PAR_ENC_CHANNEL_MAX 0x1e3c /* VS1063 */ +#define PAR_ENC_SERIAL_NUMBER 0x1e3e /* VS1063 */ + +/* Decoding WMA */ +#define PAR_WMA_CUR_PACKET_SIZE 0x1e2a /* VS1063, VS1053, 32 bits */ +#define PAR_WMA_PACKET_SIZE 0x1e2c /* VS1063, VS1053, 32 bits */ + +/* Decoding AAC */ +#define PAR_AAC_SCE_FOUND_MASK 0x1e2a /* VS1063, VS1053 */ +#define PAR_AAC_CPE_FOUND_MASK 0x1e2b /* VS1063, VS1053 */ +#define PAR_AAC_LFE_FOUND_MASK 0x1e2c /* VS1063, VS1053 */ +#define PAR_AAC_PLAY_SELECT 0x1e2d /* VS1063, VS1053 */ +#define PAR_AAC_DYN_COMPRESS 0x1e2e /* VS1063, VS1053 */ +#define PAR_AAC_DYN_BOOST 0x1e2f /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS 0x1e30 /* VS1063, VS1053 */ +#define PAR_AAC_SBR_PS_FLAGS 0x1e31 /* VS1063 */ + + +/* Decoding MIDI (VS1053) */ +#define PAR_MIDI_BYTES_LEFT 0x1e2a /* VS1053, 32 bits */ + +/* Decoding Vorbis */ +#define PAR_VORBIS_GAIN 0x1e2a 0x1e30 /* VS1063, VS1053 */ + + +/* Bit definitions for parametric registers with bitfields */ +#define PAR_CONFIG1_DIS_WMA_B 15 /* VS1063 */ +#define PAR_CONFIG1_DIS_AAC_B 14 /* VS1063 */ +#define PAR_CONFIG1_DIS_MP3_B 13 /* VS1063 */ +#define PAR_CONFIG1_DIS_FLAC_B 12 /* VS1063 */ +#define PAR_CONFIG1_DIS_CRC_B 8 /* VS1063 */ +#define PAR_CONFIG1_AAC_PS_B 6 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_B 4 /* VS1063, VS1053 */ +#define PAR_CONFIG1_MIDI_REVERB_B 0 /* VS1053 */ + +#define PAR_CONFIG1_DIS_WMA (1<<15) /* VS1063 */ +#define PAR_CONFIG1_DIS_AAC (1<<14) /* VS1063 */ +#define PAR_CONFIG1_DIS_MP3 (1<<13) /* VS1063 */ +#define PAR_CONFIG1_DIS_FLAC (1<<12) /* VS1063 */ +#define PAR_CONFIG1_DIS_CRC (1<< 8) /* VS1063 */ +#define PAR_CONFIG1_AAC_PS (1<< 6) /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR (1<< 4) /* VS1063, VS1053 */ +#define PAR_CONFIG1_MIDI_REVERB (1<< 0) /* VS1053 */ + +#define PAR_CONFIG1_AAC_PS_BITS 2 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_PS_MASK 0x00c0 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_BITS 2 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_MASK 0x0030 /* VS1063, VS1053 */ + +#define PAR_CONFIG1_AAC_SBR_ALWAYS_UPSAMPLE 0x0000 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_SELECTIVE_UPSAMPLE 0x0010 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_NEVER_UPSAMPLE 0x0020 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_DISABLE 0x0030 /* VS1063, VS1053 */ + +#define PAR_CONFIG1_AAC_PS_NORMAL 0x0000 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_PS_DOWNSAMPLED 0x0040 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_PS_DISABLE 0x00c0 /* VS1063, VS1053 */ + +#define PAR_PLAY_MODE_SPEED_SHIFTER_ENA_B 6 /* VS1063 */ +#define PAR_PLAY_MODE_EQ5_ENA_B 5 /* VS1063 */ +#define PAR_PLAY_MODE_PCM_MIXER_ENA_B 4 /* VS1063 */ +#define PAR_PLAY_MODE_AD_MIXER_ENA_B 3 /* VS1063 */ +#define PAR_PLAY_MODE_VU_METER_ENA_B 2 /* VS1063 */ +#define PAR_PLAY_MODE_PAUSE_ENA_B 1 /* VS1063 */ +#define PAR_PLAY_MODE_MONO_ENA_B 0 /* VS1063 */ + +#define PAR_PLAY_MODE_SPEED_SHIFTER_ENA (1<<6) /* VS1063 */ +#define PAR_PLAY_MODE_EQ5_ENA (1<<5) /* VS1063 */ +#define PAR_PLAY_MODE_PCM_MIXER_ENA (1<<4) /* VS1063 */ +#define PAR_PLAY_MODE_AD_MIXER_ENA (1<<3) /* VS1063 */ +#define PAR_PLAY_MODE_VU_METER_ENA (1<<2) /* VS1063 */ +#define PAR_PLAY_MODE_PAUSE_ENA (1<<1) /* VS1063 */ +#define PAR_PLAY_MODE_MONO_ENA (1<<0) /* VS1063 */ + +#define PAR_VU_METER_LEFT_BITS 8 /* VS1063 */ +#define PAR_VU_METER_LEFT_MASK 0xFF00 /* VS1063 */ +#define PAR_VU_METER_RIGHT_BITS 8 /* VS1063 */ +#define PAR_VU_METER_RIGHT_MASK 0x00FF /* VS1063 */ + +#define PAR_AD_MIXER_CONFIG_MODE_B 2 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_B 2 /* VS1063 */ + +#define PAR_AD_MIXER_CONFIG_MODE_BITS 2 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_MODE_MASK 0x000c /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_BITS 2 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_MASK 0x0003 /* VS1063 */ + +#define PAR_AD_MIXER_CONFIG_RATE_192K 0x0000 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_96K 0x0001 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_48K 0x0002 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_24K 0x0003 /* VS1063 */ + +#define PAR_AD_MIXER_CONFIG_MODE_STEREO 0x0000 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_MODE_MONO 0x0040 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_MODE_LEFT 0x0080 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_MODE_RIGHT 0x00c0 /* VS1063 */ + +#define PAR_AAC_SBR_AND_PS_STATUS_SBR_PRESENT_B 0 /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_UPSAMPLING_ACTIVE_B 1 /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_PS_PRESENT_B 2 /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_PS_ACTIVE_B 3 /* VS1063, VS1053 */ + +#define PAR_AAC_SBR_AND_PS_STATUS_SBR_PRESENT (1<<0) /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_UPSAMPLING_ACTIVE (1<<1) /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_PS_PRESENT (1<<2) /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_PS_ACTIVE (1<<3) /* VS1063, VS1053 */ + + +#endif /* !VS10XX_MICROCONTROLLER_DEFINITIONS_H */ diff --git a/targets/esp32/components/VS1053/src/VS1053.cpp b/targets/esp32/components/VS1053/src/VS1053.cpp new file mode 100644 index 00000000..97b0a44f --- /dev/null +++ b/targets/esp32/components/VS1053/src/VS1053.cpp @@ -0,0 +1,666 @@ +#include "VS1053.h" + +#include +#include "esp_log.h" + +static const char* TAG = "VS_SINK"; +void vs_feed(void* track) { + ((VS1053_TRACK*)track)->run_track(1024); +} + +unsigned char pcm_wav_header[44] = { + 0x52, 0x49, 0x46, + 0x46, // RIFF + 0xFF, 0xFF, 0xFF, + 0xFF, // size + 0x57, 0x41, 0x56, + 0x45, // WAVE + 0x66, 0x6d, 0x74, + 0x20, // fmt + 0x10, 0x00, 0x00, + 0x00, // subchunk1size + 0x01, 0x00, // audio format - pcm + 0x02, 0x00, // numof channels + 0x44, 0xac, 0x00, + 0x00, //, //samplerate 44k1: 0x44, 0xac, 0x00, 0x00 48k: 48000: 0x80, 0xbb, 0x00, 0x00, + 0x10, 0xb1, 0x02, + 0x00, // byterate + 0x04, 0x00, // blockalign + 0x10, 0x00, // bits per sample - 16 + 0x64, 0x61, 0x74, + 0x61, // subchunk3id -"data" + 0xFF, 0xFF, 0xFF, + 0xFF // subchunk3size (endless) +}; +const char* afName[] = { + "unknown", "RIFF", "Ogg", "MP1", "MP2", "MP3", "AAC MP4", + "AAC ADTS", "AAC ADIF", "FLAC", "WMA", "MIDI", "DSD64", "LATM/LOAS", +}; +VS1053_SINK::VS1053_SINK() { + // PIN CONFIG + // DREQ + ESP_LOGI(TAG, "VS1053_DREQ=%d", CONFIG_GPIO_VS_DREQ); + gpio_config_t gpio_conf; + gpio_conf.mode = GPIO_MODE_INPUT; + gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE; + gpio_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; + gpio_conf.intr_type = GPIO_INTR_DISABLE; + gpio_conf.pin_bit_mask = ((uint64_t)(((uint64_t)1) << CONFIG_GPIO_VS_DREQ)); + ESP_ERROR_CHECK(gpio_config(&gpio_conf)); + // CS + ESP_LOGI(TAG, "VS1053_CS=%d", CONFIG_GPIO_VS_CS); + gpio_reset_pin((gpio_num_t)CONFIG_GPIO_VS_CS); + gpio_set_direction((gpio_num_t)CONFIG_GPIO_VS_CS, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)CONFIG_GPIO_VS_CS, 1); + // DCS + ESP_LOGI(TAG, "VS1053_DCS=%d", CONFIG_GPIO_VS_DCS); + gpio_reset_pin((gpio_num_t)CONFIG_GPIO_VS_DCS); + gpio_set_direction((gpio_num_t)CONFIG_GPIO_VS_DCS, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)CONFIG_GPIO_VS_DCS, 1); + // RESET + ESP_LOGI(TAG, "VS1053_RESET=%d", CONFIG_GPIO_VS_RESET); + if (CONFIG_GPIO_VS_RESET >= 0) { + gpio_reset_pin((gpio_num_t)CONFIG_GPIO_VS_RESET); + gpio_set_direction((gpio_num_t)CONFIG_GPIO_VS_RESET, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)CONFIG_GPIO_VS_RESET, 0); + vTaskDelay(100 / portTICK_PERIOD_MS); + gpio_set_level((gpio_num_t)CONFIG_GPIO_VS_RESET, 1); + } +} + +esp_err_t VS1053_SINK::init(spi_host_device_t SPI, + SemaphoreHandle_t* SPI_semaphore) { + esp_err_t ret; + this->SPI_semaphore = SPI_semaphore; + // SPI CONFIG + uint32_t freq = spi_get_actual_clock(APB_CLK_FREQ, 1400000, 128); + spi_device_interface_config_t devcfg; + memset(&devcfg, 0, sizeof(spi_device_interface_config_t)); + ESP_LOGI(TAG, "VS1053 LOWFreq: %d", freq); + + devcfg.clock_speed_hz = freq, devcfg.command_bits = 8, + devcfg.address_bits = 8, devcfg.dummy_bits = 0, devcfg.duty_cycle_pos = 0, + devcfg.cs_ena_pretrans = 0, devcfg.cs_ena_posttrans = 1, devcfg.flags = 0, + devcfg.mode = 0, devcfg.spics_io_num = CONFIG_GPIO_VS_CS, + devcfg.queue_size = 1, + devcfg.pre_cb = NULL, // Specify pre-transfer callback to handle D/C line + devcfg.post_cb = NULL; + + ESP_LOGI(TAG, "spi device interface config done, VERSION : %i", VERSION); + ret = spi_bus_add_device(SPI, &devcfg, &this->SPIHandleLow); + ESP_LOGI(TAG, "spi_bus_add_device=%d", ret); + assert(ret == ESP_OK); + // SPI TEST SLOW-/HIGH-SPEED + vTaskDelay(20 / portTICK_PERIOD_MS); + write_register(SCI_MODE, SM_SDINEW | SM_TESTS | SM_RESET); + ret = test_comm("Slow SPI,Testing VS1053 read/write registers...\n"); + if (ret != ESP_OK) + return ret; + { + freq = spi_get_actual_clock(APB_CLK_FREQ, 6670000, 128); + write_register( + SCI_CLOCKF, + HZ_TO_SC_FREQ(12288000) | SC_MULT_53_45X | + SC_ADD_53_00X); // Normal clock settings multiplyer 3.0 = 12.2 MHz + ESP_LOGI(TAG, "VS1053 HighFreq: %d", freq); + devcfg.clock_speed_hz = freq, devcfg.command_bits = 0, + devcfg.address_bits = 0, devcfg.spics_io_num = CONFIG_GPIO_VS_DCS; + ret = spi_bus_add_device(SPI, &devcfg, &this->SPIHandleFast); + ESP_LOGI(TAG, "spi_bus_add_device=%d", ret); + assert(ret == ESP_OK); + ret = test_comm("Slow SPI,Testing VS1053 read/write registers...\n"); + if (ret != ESP_OK) + return ret; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + + write_mem(PAR_CONFIG1, PAR_CONFIG1_AAC_SBR_SELECTIVE_UPSAMPLE); + write_register(SCI_VOL, 0x0c0c); +#ifndef CONFIG_VS1053_NO_PLUGIN + //load_user_code(PLUGIN, PLUGIN_SIZE); +#endif + vTaskDelay(100 / portTICK_PERIOD_MS); + return ESP_OK; +} + +VS1053_SINK::~VS1053_SINK() {} +VS1053_TRACK VS1053_SINK::newTrack(size_t track_id, size_t buffer_size) { + return VS1053_TRACK(this, track_id, buffer_size); +} +// LOOP +VS1053_TRACK::VS1053_TRACK(VS1053_SINK* vsSink, size_t track_id, + size_t buffer_size) { + this->track_id = track_id; + this->audioSink = vsSink; + this->dataBuffer = xStreamBufferCreate(buffer_size, 1); + // this->run_track(); +} +VS1053_TRACK::~VS1053_TRACK() { + if (this->track_state != tsStopped) + this->audioSink->new_state(tsCancel); + while (this->track_handle) + vTaskDelay(10 / portTICK_PERIOD_MS); + if (dataBuffer != NULL) + vStreamBufferDelete(dataBuffer); + dataBuffer = NULL; +} + +void runTrack() {} +void VS1053_SINK::start_track(std::shared_ptr track, + size_t buf_fill) { + this->track = track; + endFillByte = 0; + playMode = read_mem(PAR_PLAY_MODE); + endFillBytes = SDI_END_FILL_BYTES; // How many of those to send + sdi_send_fillers(endFillBytes); + write_register(SCI_DECODE_TIME, 0); // Reset DECODE_TIME + xTaskCreate(vs_feed, "track_feed", 4098, (void*)this->track.get(), 5, + &this->track->track_handle); + new_state(VS1053_TRACK::VS_TRACK_STATE::tsPlaybackStart); +} +void VS1053_SINK::new_track(std::shared_ptr track) { + if (this->track) + this->future_track = track; + else + this->start_track(track, 1024); +} +bool VS1053_SINK::is_seekable(VS1053_TRACK::VS_TRACK_STATE* state) { + if (read_register(SCI_STATUS) >> SS_DO_NOT_JUMP_B == 0) { + new_state(VS1053_TRACK::VS_TRACK_STATE::tsPlaybackSeekable); + return true; + } + return false; +} +size_t VS1053_SINK::track_seekable(size_t track_id) { + if (this->track) + if (this->track->track_id == track_id) + return this->track->header_size; + return 0; +} +void VS1053_SINK::cancel_track(VS1053_TRACK::VS_TRACK_STATE* state) { + unsigned short oldMode; + oldMode = read_register(SCI_MODE); + write_register(SCI_MODE, oldMode | SM_CANCEL); + new_state(VS1053_TRACK::VS_TRACK_STATE::tsCancelAwait); +} +bool VS1053_SINK::is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state) { + if (read_register(SCI_MODE) & SM_CANCEL) + sdi_send_fillers(2); + else { + sdi_send_fillers(endFillBytes); + new_state(VS1053_TRACK::VS_TRACK_STATE::tsStopped); + return true; + } + return false; +} +void VS1053_SINK::delete_track(void) { + if (this->future_track) { + this->track = this->future_track; + this->future_track = nullptr; + this->start_track(this->track, 1024); + } else { + this->remove_track(this->track); + } +} +size_t VS1053_SINK::get_track_info(size_t pos) { +#ifdef CONFIG_REPORT_ON_SCREEN + uint16_t sampleRate; + uint32_t byteRate; +#endif + get_audio_format(&audioFormat, &endFillBytes); + + /* It is important to collect endFillByte while still in normal + playback. If we need to later cancel playback or run into any + trouble with e.g. a broken file, we need to be able to repeatedly + send this byte until the decoder has been able to exit. */ + + endFillByte = read_mem(PAR_END_FILL_BYTE); +#ifdef CONFIG_REPORT_ON_SCREEN + + sampleRate = read_register(SCI_AUDATA); + byteRate = read_mem(PAR_BYTERATE); + /* FLAC: byteRate = bitRate / 32 + Others: byteRate = bitRate / 8 + Here we compensate for that difference. */ + if (audioFormat == afFlac) + byteRate *= 4; + + ESP_LOGI(TAG, + "%dKiB " + "%1ds %1.1f" + "kb/s %dHz %s %s", + pos / (1024 / VS1053_PACKET_SIZE), read_register(SCI_DECODE_TIME), + byteRate * (8.0 / 1000.0), sampleRate & 0xFFFE, + (sampleRate & 1) ? "stereo" : "mono", afName[audioFormat]); +#endif + return (audioFormat == afMidi || audioFormat == afUnknown) + ? REPORT_INTERVAL_MIDI + : REPORT_INTERVAL; +} + +size_t VS1053_TRACK::feed_data(uint8_t* data, size_t len, + bool STORAGE_VOLATILE) { + if (!len || xStreamBufferSpacesAvailable(this->dataBuffer) < len) + return 0; + if (STORAGE_VOLATILE) + if (this->header_size) + xStreamBufferReset(this->dataBuffer); + size_t res = + xStreamBufferSend(this->dataBuffer, (void*)data, len, pdMS_TO_TICKS(100)); + return res; +} +size_t VS1053_SINK::spaces_available(size_t track_id) { + if (this->track == nullptr) + return 0; + if (this->track->track_id == track_id) + return xStreamBufferSpacesAvailable(this->track->dataBuffer); + else + return xStreamBufferSpacesAvailable(this->future_track->dataBuffer); +} +void VS1053_TRACK::empty_feed() { + if (this->dataBuffer != NULL) + xStreamBufferReset(this->dataBuffer); +} +void VS1053_SINK::new_state(VS1053_TRACK::VS_TRACK_STATE state) { + this->track->track_state = state; + if (state_callback != NULL) { + state_callback(state); + } +} + +void VS1053_TRACK::run_track(size_t FILL_BUFFER_BEFORE_PLAYBACK) { + uint32_t pos = 0; + long nextReportPos = 0; // File pointer where to next collect/report + size_t itemSize = 0; + uint8_t* item = (uint8_t*)malloc(VS1053_PACKET_SIZE); + + if (FILL_BUFFER_BEFORE_PLAYBACK < + xStreamBufferBytesAvailable(this->dataBuffer)) + vTaskDelay(10 / portTICK_PERIOD_MS); + while (this->track_state != tsStopped) { + if (this->audioSink->command_callbacks.size()) { + this->audioSink->command_callbacks[0](track_id); + this->audioSink->command_callbacks.pop_front(); + } + switch (this->track_state) { + case tsPlaybackStart: + this->audioSink->new_state(tsPlayback); + goto tsPlaybackSeekable; + case tsPlayback: + if (this->audioSink->is_seekable(&this->track_state)) + if (!this->header_size) + this->header_size = VS1053_PACKET_SIZE * pos; + goto tsPlaybackSeekable; + case tsPlaybackSeekable: + + tsPlaybackSeekable: + itemSize = xStreamBufferReceive(this->dataBuffer, (void*)item, + VS1053_PACKET_SIZE, 10); + if (itemSize) { + this->audioSink->sdi_send_buffer(item, itemSize); + pos++; + } + break; + case tsSoftCancel: + if (xStreamBufferBytesAvailable(this->dataBuffer)) + goto tsPlaybackSeekable; + this->audioSink->new_state(tsCancel); + [[fallthrough]]; + case tsCancel: + free(item); + this->empty_feed(); + this->audioSink->cancel_track(&this->track_state); + [[fallthrough]]; + case tsCancelAwait: + if (this->audioSink->is_cancelled(&this->track_state)) {} + break; + default: + vTaskDelay(20 / portTICK_PERIOD_MS); + break; + } + if (pos >= nextReportPos) { + nextReportPos += this->audioSink->get_track_info(pos); + } + } + this->track_handle = NULL; + this->audioSink->delete_track(); + vTaskDelete(NULL); +} +// FEED FUNCTIONS + +size_t VS1053_SINK::data_request() { + return xStreamBufferSpacesAvailable(track->dataBuffer); +} + +void VS1053_SINK::stop_feed() { + if (this->future_track != nullptr) + this->future_track.reset(); // + if ((uint8_t)this->track->track_state < 3) + new_state(VS1053_TRACK::VS_TRACK_STATE::tsCancel); +} +void VS1053_SINK::soft_stop_feed() { + if (this->future_track != nullptr) + this->future_track.reset(); // + if ((uint8_t)this->track->track_state < 3) + new_state(VS1053_TRACK::VS_TRACK_STATE::tsSoftCancel); +} + +// COMMAND FUCNTIONS +/* The command pipeline recieves command in a structure of uint8_t[]. + */ +uint8_t VS1053_SINK::feed_command(command_callback commandCallback) { + if (this->track) { + command_callbacks.push_back(commandCallback); + } else + commandCallback(0); + return 0; +} +void VS1053_SINK::set_volume_logarithmic(size_t vol) { + float value = log10((float)vol / 0xFFFF * 100 + 1); + if (value >= 2.0) + value = 2.0; + size_t logVolume = value / 2 * 100; // *100 + + this->set_volume(logVolume); +} +/** + * set_volume accepts values from 0 to 100 + */ +void VS1053_SINK::set_volume(uint8_t vol) { + vol = vol > 100 ? 0 : 100 - vol; + uint16_t value = (vol << 8) | vol; + write_register(SCI_VOL, value); // Volume left and right +} + +void VS1053_SINK::set_volume(uint8_t left, uint8_t right) { + left = left > 100 ? 0 : 100 - left; + right = right > 100 ? 0 : 100 - right; + uint16_t value = (left << 8) | right; + write_register(SCI_VOL, value); // Volume left and right +} + +void VS1053_SINK::get_audio_format(Audio_Format* audioFormat, + size_t* endFillBytes) { + uint16_t h1 = read_register(SCI_HDAT1); + *audioFormat = afUnknown; + switch (h1) { + case 0x7665: + *audioFormat = afRiff; + goto sdi_end_fill_bytes; + case 0x4444: + *audioFormat = afDsd64; + goto sdi_end_fill_bytes_flac; + case 0x4c41: + *audioFormat = afLatm; + // set OUT_OF_WAV bit of SCI_MODE; + goto sdi_end_fill_bytes_flac; + case 0x4154: + *audioFormat = afAacAdts; + goto sdi_end_fill_bytes; + case 0x4144: + *audioFormat = afAacAdif; + goto sdi_end_fill_bytes; + case 0x574d: + *audioFormat = afWma; + goto sdi_end_fill_bytes; + case 0x4f67: + *audioFormat = afOggVorbis; + goto sdi_end_fill_bytes; + case 0x664c: + *audioFormat = afFlac; + goto sdi_end_fill_bytes_flac; + case 0x4d34: + *audioFormat = afAacMp4; + goto sdi_end_fill_bytes; + case 0x4d54: + *audioFormat = afMidi; + goto sdi_end_fill_bytes; + default: + h1 &= 0xffe6; + if (h1 == 0xffe2) + *audioFormat = afMp2; + else if (h1 == 0xffe4) + *audioFormat = afMp2; + else if (h1 == 0xffe6) + *audioFormat = afMp1; + if (*audioFormat == afUnknown) + goto sdi_end_fill_bytes_flac; + sdi_end_fill_bytes: + *endFillBytes = SDI_END_FILL_BYTES; + break; + sdi_end_fill_bytes_flac: + *endFillBytes = SDI_END_FILL_BYTES_FLAC; + break; + } +} + +// SPI COMMUNICATION TEST +const uint16_t chipNumber[16] = {1001, 1011, 1011, 1003, 1053, 1033, 1063, 1103, + 0, 0, 0, 0, 0, 0, 0, 0}; + +esp_err_t VS1053_SINK::test_comm(const char* header) { + // Test the communication with the VS1053 module. The result wille be returned. + // If DREQ is low, there is problably no VS1053 connected. Pull the line HIGH + // in order to prevent an endless loop waiting for this signal. The rest of the + // software will still work, but readbacks from VS1053 will fail. + + write_register(SCI_AICTRL1, 0xABAD); + write_register(SCI_AICTRL2, 0x7E57); + if (read_register(SCI_AICTRL1) != 0xABAD || + read_register(SCI_AICTRL2) != 0x7E57) { + ESP_LOGI(TAG, "There is something wrong with VS10xx SCI registers\n"); + return ESP_ERR_INVALID_RESPONSE; + } + write_register(SCI_AICTRL1, 0); + write_register(SCI_AICTRL2, 0); + uint16_t ssVer = ((read_register(SCI_STATUS) >> 4) & 15); + if (chipNumber[ssVer]) { + ESP_LOGI(TAG, "Chip is VS%d\n", chipNumber[ssVer]); + if (chipNumber[ssVer] != 1053) { + ESP_LOGI(TAG, "Incorrect chip\n"); + return ESP_ERR_NOT_SUPPORTED; + } + } else { + ESP_LOGI(TAG, "Unknown VS10xx SCI_MODE field SS_VER = %d\n", ssVer); + return ESP_ERR_NOT_FOUND; + } + + return ESP_OK; +} + +// PLUGIN FUNCTION + +void VS1053_SINK::load_user_code(const unsigned short* plugin, + uint16_t sizeofpatch) { + ESP_LOGI(TAG, "Loading patch"); + await_data_request(); + int i = 0; + while (i < sizeofpatch) { + unsigned short addr, n, val; + addr = plugin[i++]; + n = plugin[i++]; + if (n & 0x8000U) { /* RLE run, replicate n samples */ + n &= 0x7FFF; + val = plugin[i++]; + while (n--) { + write_register(addr, val); + } + } else { /* Copy run, copy n samples */ + while (n--) { + val = plugin[i++]; + write_register(addr, val); + } + } + } +} + +// GPIO FUNCTIONS + +void VS1053_SINK::await_data_request() { + while (!gpio_get_level((gpio_num_t)CONFIG_GPIO_VS_DREQ)) + vTaskDelay(1); +} +// WRITE/READ FUNCTIONS + +uint16_t VS1053_SINK::read_register(uint8_t _reg) { + spi_transaction_t SPITransaction; + esp_err_t ret; + await_data_request(); // Wait for DREQ to be HIGH + memset(&SPITransaction, 0, sizeof(spi_transaction_t)); + SPITransaction.length = 16; + SPITransaction.flags |= SPI_TRANS_USE_RXDATA; + SPITransaction.cmd = VS_READ_COMMAND; + SPITransaction.addr = _reg; + if (SPI_semaphore != NULL) + while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) + vTaskDelay(1); + ret = spi_device_transmit(this->SPIHandleLow, &SPITransaction); + assert(ret == ESP_OK); + uint16_t result = (((SPITransaction.rx_data[0] & 0xFF) << 8) | + ((SPITransaction.rx_data[1]) & 0xFF)); + await_data_request(); // Wait for DREQ to be HIGH again + if (SPI_semaphore != NULL) + xSemaphoreGive(*SPI_semaphore); + return result; +} + +bool VS1053_SINK::write_register(uint8_t _reg, uint16_t _value) { + spi_transaction_t SPITransaction; + esp_err_t ret; + + await_data_request(); // Wait for DREQ to be HIGH + memset(&SPITransaction, 0, sizeof(spi_transaction_t)); + SPITransaction.flags |= SPI_TRANS_USE_TXDATA; + SPITransaction.cmd = VS_WRITE_COMMAND; + SPITransaction.addr = _reg; + SPITransaction.tx_data[0] = (_value >> 8) & 0xFF; + SPITransaction.tx_data[1] = (_value & 0xFF); + SPITransaction.length = 16; + if (SPI_semaphore != NULL) + while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) + vTaskDelay(1); + ret = spi_device_transmit(this->SPIHandleLow, &SPITransaction); + assert(ret == ESP_OK); + await_data_request(); // Wait for DREQ to be HIGH again + if (SPI_semaphore != NULL) + xSemaphoreGive(*SPI_semaphore); + return true; +} + +uint32_t VS1053_SINK::read_mem32(uint16_t addr) { + uint16_t result; + + write_register(SCI_WRAMADDR, addr); + // Note: transfer16 does not seem to work + result = read_register(SCI_WRAM); + return result | ((uint32_t)read_register(SCI_WRAM) << 16); +} + +uint32_t VS1053_SINK::read_mem32_counter(uint16_t addr) { + uint16_t msbV1, lsb, msbV2; + uint32_t res; + write_register(SCI_WRAMADDR, addr); + msbV1 = read_register(SCI_WRAM); + write_register(SCI_WRAMADDR, addr); + lsb = read_register(SCI_WRAM); + msbV2 = read_register(SCI_WRAM); + if (lsb < 0x8000U) { + msbV1 = msbV2; + } + res = ((uint32_t)msbV1 << 16) | lsb; + + return res; +} + +uint16_t VS1053_SINK::read_mem(uint16_t addr) { + write_register(SCI_WRAMADDR, addr); + return read_register(SCI_WRAM); +} + +/* + Write 16-bit value to given VS10xx address +*/ +void VS1053_SINK::write_mem(uint16_t addr, uint16_t data) { + write_register(SCI_WRAMADDR, addr); + write_register(SCI_WRAM, data); +} + +/* + Write 32-bit value to given VS10xx address +*/ +void VS1053_SINK::write_mem32(uint16_t addr, uint32_t data) { + write_register(SCI_WRAMADDR, addr); + write_register(SCI_WRAM, (uint16_t)data); + write_register(SCI_WRAM, (uint16_t)(data >> 16)); +} +bool VS1053_SINK::sdi_send_buffer(uint8_t* data, size_t len) { + size_t chunk_length; // Length of chunk 32 byte or shorter + spi_transaction_t SPITransaction; + esp_err_t ret; + if (SPI_semaphore != NULL) + while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) + vTaskDelay(1); + while (len) // More to do? + { + await_data_request(); // Wait for space available + chunk_length = len; + if (len > VS1053_CHUNK_SIZE) { + chunk_length = VS1053_CHUNK_SIZE; + } + len -= chunk_length; + memset(&SPITransaction, 0, sizeof(spi_transaction_t)); + SPITransaction.length = chunk_length * 8; + SPITransaction.tx_buffer = data; + // while(spi_device_acquire_bus(this->SPIHandleFast,portMAX_DELAY)!=ESP_OK){}; + ret = spi_device_transmit(this->SPIHandleFast, &SPITransaction); + // spi_device_release_bus(this->SPIHandleFast); + assert(ret == ESP_OK); + data += chunk_length; + } + if (SPI_semaphore != NULL) + xSemaphoreGive(*SPI_semaphore); + + return true; +} + +bool VS1053_SINK::sdi_send_fillers(size_t len) { + size_t chunk_length; // Length of chunk 32 byte or shorter + spi_transaction_t SPITransaction; + esp_err_t ret; + uint8_t data[VS1053_CHUNK_SIZE]; + for (int i = 0; i < VS1053_CHUNK_SIZE; i++) + data[i] = this->endFillByte; + if (SPI_semaphore != NULL) + while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) + vTaskDelay(1); + while (len) // More to do? + { + await_data_request(); // Wait for space available + chunk_length = len; + if (len > VS1053_CHUNK_SIZE) { + chunk_length = VS1053_CHUNK_SIZE; + } + len -= chunk_length; + + memset(&SPITransaction, 0, sizeof(spi_transaction_t)); + SPITransaction.length = chunk_length * 8; + SPITransaction.tx_buffer = data; + spi_device_acquire_bus(this->SPIHandleFast, portMAX_DELAY); + ret = spi_device_transmit(this->SPIHandleFast, &SPITransaction); + spi_device_release_bus(this->SPIHandleFast); + assert(ret == ESP_OK); + } + if (SPI_semaphore != NULL) + xSemaphoreGive(*SPI_semaphore); + return true; +} + +void VS1053_SINK::wram_write(uint16_t address, uint16_t data) { + write_register(SCI_WRAMADDR, address); + write_register(SCI_WRAM, data); +} + +uint16_t VS1053_SINK::wram_read(uint16_t address) { + write_register(SCI_WRAMADDR, address); // Start reading from WRAM + return read_register(SCI_WRAM); // Read back result +} diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp index 4fdc2330..8a601ef5 100644 --- a/targets/esp32/main/EspPlayer.cpp +++ b/targets/esp32/main/EspPlayer.cpp @@ -26,17 +26,20 @@ EspPlayer::EspPlayer(std::unique_ptr sink, this->circularBuffer = std::make_shared(1024 * 128); - this->handler->getTrackPlayer()->setDataCallback( - [this](uint8_t* data, size_t bytes, size_t trackId) { - this->feedData(data, bytes, trackId); - return bytes; - }); + this->handler->getTrackPlayer()->setDataCallback([this](uint8_t* data, + size_t bytes, +#ifdef CONFIG_BELL_NOCODEC + bool STORAGE_VOLATILE, +#endif + size_t trackId) { + this->feedData(data, bytes, trackId); + return bytes; + }); this->isPaused = false; this->handler->setEventHandler( [this](std::unique_ptr event) { - switch (event->eventType) { case cspot::SpircHandler::EventType::PLAY_PAUSE: if (std::get(event->data)) { @@ -77,16 +80,19 @@ EspPlayer::EspPlayer(std::unique_ptr sink, void EspPlayer::feedData(uint8_t* data, size_t len, size_t trackId) { size_t toWrite = len; - while (toWrite > 0) { - this->current_hash = trackId; - size_t written = - this->circularBuffer->write(data + (len - toWrite), toWrite); - if (written == 0) { - BELL_SLEEP_MS(10); - } + if (!len) + this->handler->notifyAudioReachedPlaybackEnd(); + else + while (toWrite > 0) { + this->current_hash = trackId; + size_t written = + this->circularBuffer->write(data + (len - toWrite), toWrite); + if (written == 0) { + BELL_SLEEP_MS(10); + } - toWrite -= written; - } + toWrite -= written; + } } void EspPlayer::runTask() { diff --git a/targets/esp32/main/Kconfig.projbuild b/targets/esp32/main/Kconfig.projbuild index 64e164cb..54d700a6 100644 --- a/targets/esp32/main/Kconfig.projbuild +++ b/targets/esp32/main/Kconfig.projbuild @@ -8,10 +8,12 @@ menu "CSPOT Configuration" choice CSPOT_SINK prompt "Sink Device" - default CSPOT_SINK_AC101 + default CSPOT_SINK_INTERNAL help Select audio sink device + config BELL_NOCODEC + bool "VS1053" config CSPOT_SINK_INTERNAL bool "Built-in DAC" config CSPOT_SINK_AC101 @@ -28,17 +30,30 @@ menu "CSPOT Configuration" choice CSPOT_QUALITY prompt "Audio Quality (BPS)" - default CSPOT_QUALITY_320 + default VORBIS_160 help Audio quality (not used currently) - config CSPOT_QUALITY_320 + config VORBIS_320 bool "320 bps" - config CSPOT_QUALITY_160 + config VORBIS_160 bool "160 bps" - config CSPOT_QUALITY_96 + config VORBIS_96 bool "96 bps" endchoice + config CSPOT_AUDIO_FORMAT + int + default 0 if VORBIS_96 + default 1 if VORBIS_160 + default 2 if VORBIS_320 + default 3 if MP3_256 + default 4 if MP3_320 + default 5 if MP3_160 + default 6 if MP3_96 + default 7 if MP3_160_ENC + default 8 if AAC_24 + default 9 if AAC_48 + choice CSPOT_STATUS_LED_TYPE prompt "Status LED type" default CSPOT_STATUS_LED_TYPE_NONE diff --git a/targets/esp32/main/VSPlayer.cpp b/targets/esp32/main/VSPlayer.cpp new file mode 100644 index 00000000..f8836d49 --- /dev/null +++ b/targets/esp32/main/VSPlayer.cpp @@ -0,0 +1,100 @@ +#include "VSPlayer.h" + +#include // for uint8_t +#include // for operator<<, basic_ostream, endl, cout +#include // for shared_ptr, make_shared, make_unique +#include // for scoped_lock +#include // for get + +#include "TrackPlayer.h" // for TrackPlayer + +VSPlayer::VSPlayer(std::shared_ptr handler, + std::shared_ptr vsSink) { + this->handler = handler; + this->vsSink = vsSink; + this->vsSink->state_callback = [this](uint8_t state) { + this->state_callback(state); + }; + + this->handler->getTrackPlayer()->setDataCallback( + [this](uint8_t* data, size_t bytes, size_t trackId, + bool STORAGE_VOLATILE) { + if (!this->track) { + this->track = std::make_shared(this->vsSink.get(), + trackId, 4098 * 16); + this->vsSink->new_track(this->track); + } + if (trackId != this->track->track_id) { + this->vsSink->soft_stop_feed(); + this->track = std::make_shared(this->vsSink.get(), + trackId, 4098 * 16); + this->vsSink->new_track(this->track); + } + return this->track->feed_data(data, bytes, STORAGE_VOLATILE); + }, + [this](size_t trackId) { return this->vsSink->track_seekable(trackId); }, + [this](size_t trackId) { + return this->vsSink->spaces_available(trackId); + }); + + this->isPaused = false; + + this->handler->setEventHandler( + [this](std::unique_ptr event) { + switch (event->eventType) { + case cspot::SpircHandler::EventType::PLAY_PAUSE: + if (std::get(event->data)) { + if (this->track) + this->vsSink->new_state(VS1053_TRACK::tsPlaybackPaused); + } else { + if (this->track) + this->vsSink->new_state(VS1053_TRACK::tsPlaybackSeekable); + } + break; + case cspot::SpircHandler::EventType::DISC: + this->track = nullptr; + this->vsSink->stop_feed(); + break; + case cspot::SpircHandler::EventType::FLUSH: + this->track->empty_feed(); + break; + case cspot::SpircHandler::EventType::SEEK: + break; + case cspot::SpircHandler::EventType::PLAYBACK_START: + this->isPaused = true; + this->playlistEnd = false; + break; + case cspot::SpircHandler::EventType::DEPLETED: + this->playlistEnd = true; + this->track = nullptr; + this->vsSink->stop_feed(); + break; + case cspot::SpircHandler::EventType::VOLUME: { + this->volume = std::get(event->data); + this->vsSink->feed_command([this](uint8_t) { + this->vsSink->set_volume_logarithmic(this->volume); + }); + break; + } + default: + break; + } + }); +} + +void VSPlayer::state_callback(uint8_t state) { + if (state == 1) { + this->handler->notifyAudioReachedPlayback(); + } + if (state == 7) { + if (this->playlistEnd) + this->handler->notifyAudioEnded(); + else + this->handler->notifyAudioReachedPlaybackEnd(); + } +} + +void VSPlayer::disconnect() { + isRunning = false; + std::scoped_lock lock(runningMutex); +} diff --git a/targets/esp32/main/VSPlayer.h b/targets/esp32/main/VSPlayer.h new file mode 100644 index 00000000..c8db9a36 --- /dev/null +++ b/targets/esp32/main/VSPlayer.h @@ -0,0 +1,36 @@ +#pragma once + +#include // for size_t +#include // for uint8_t +#include // for atomic +#include // for shared_ptr, unique_ptr +#include // for mutex +#include // for string + +#include "SpircHandler.h" // for SpircHandler, SpircHandler::EventType +#include "VS1053.h" +namespace cspot { +class SpircHandler; +} // namespace cspot + +class VSPlayer { + public: + VSPlayer(std::shared_ptr spircHandler, + std::shared_ptr vsSink = NULL); + void disconnect(); + size_t volume = 0; + + private: + std::string currentTrackId; + std::shared_ptr vsSink; + std::shared_ptr handler; + std::shared_ptr track = nullptr; + VS1053_TRACK* futureTrack = NULL; + void state_callback(uint8_t state); + + std::atomic pauseRequested = false; + std::atomic isPaused = true; + std::atomic isRunning = true; + std::mutex runningMutex; + std::atomic playlistEnd = false; +}; diff --git a/targets/esp32/main/VSinit.h b/targets/esp32/main/VSinit.h new file mode 100644 index 00000000..cf438f18 --- /dev/null +++ b/targets/esp32/main/VSinit.h @@ -0,0 +1,30 @@ + +#include +#include +#include "esp_log.h" + +#include "VS1053.h" + +#define MOUNT_POINT "/sdcard" + +SemaphoreHandle_t SPI_semaphore; +#define TAG "INIT" +void initAudioSink(std::shared_ptr VS1053) { + esp_err_t ret; + // SPI SETUP + spi_bus_config_t bus_cfg; + memset(&bus_cfg, 0, sizeof(spi_bus_config_t)); + bus_cfg.sclk_io_num = CONFIG_GPIO_CLK; + bus_cfg.mosi_io_num = CONFIG_GPIO_MOSI; + bus_cfg.miso_io_num = CONFIG_GPIO_MISO; + bus_cfg.quadwp_io_num = -1; + bus_cfg.quadhd_io_num = -1; + ESP_LOGI("vsInit", "spi config done"); + ret = spi_bus_initialize(HSPI_HOST, &bus_cfg, 1); + assert(ret == ESP_OK); + SPI_semaphore = xSemaphoreCreateMutex(); + + // VS1053 SETUP + VS1053->init(HSPI_HOST, &SPI_semaphore); + VS1053->write_register(SCI_VOL, 10 | 10 << 8); +} \ No newline at end of file diff --git a/targets/esp32/main/main.cpp b/targets/esp32/main/main.cpp index d0ba2ba5..12e0f29d 100644 --- a/targets/esp32/main/main.cpp +++ b/targets/esp32/main/main.cpp @@ -7,11 +7,10 @@ #include #include #include "BellHTTPServer.h" -#include "BellLogger.h" // for setDefaultLogger, AbstractLogger +#include "BellLogger.h" // for setDefaultLogger, AbstractLogger #include "BellTask.h" #include "civetweb.h" #include "esp_event.h" -#include "esp_log.h" #include "esp_spiffs.h" #include "esp_system.h" #include "esp_wifi.h" @@ -22,8 +21,6 @@ #include "protocol_examples_common.h" #include "sdkconfig.h" -#include "EspPlayer.h" - #include #include #include @@ -37,6 +34,11 @@ #define DEVICE_NAME CONFIG_CSPOT_DEVICE_NAME +#ifdef CONFIG_BELL_NOCODEC +#include "VSPlayer.h" +#include "VSinit.h" +#else +#include "EspPlayer.h" #ifdef CONFIG_CSPOT_SINK_INTERNAL #include #endif @@ -55,18 +57,16 @@ #ifdef CONFIG_CSPOT_SINK_TAS5711 #include #endif - -static const char* TAG = "cspot"; - +#endif extern "C" { - void app_main(void); +void app_main(void); } class ZeroconfAuthenticator { -public: - ZeroconfAuthenticator() {}; - ~ZeroconfAuthenticator() {}; + public: + ZeroconfAuthenticator(){}; + ~ZeroconfAuthenticator(){}; // Authenticator state int serverPort = 7864; @@ -83,14 +83,12 @@ class ZeroconfAuthenticator { server->registerGet("/spotify_info", [this](struct mg_connection* conn) { return this->server->makeJsonResponse(this->blob->buildZeroconfInfo()); - }); - + }); server->registerGet("/close", [this](struct mg_connection* conn) { this->onClose(); return this->server->makeEmptyResponse(); - }); - + }); server->registerPost("/spotify_info", [this](struct mg_connection* conn) { nlohmann::json obj; @@ -124,48 +122,57 @@ class ZeroconfAuthenticator { } return server->makeJsonResponse(obj.dump()); - }); - + }); // Register mdns service, for spotify to find us bell::MDNSService::registerService( - blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort, - { {"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"} }); + blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort, + {{"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"}}); std::cout << "Waiting for spotify app to connect..." << std::endl; } }; class CSpotTask : public bell::Task { -private: + private: std::unique_ptr handler; +#ifndef CONFIG_BELL_NOCODEC std::unique_ptr audioSink; +#endif -public: - CSpotTask() : bell::Task("cspot", 8 * 1024, 0, 0) { startTask(); } + public: + CSpotTask() : bell::Task("cspot", 8 * 1024, 0, 0) { + startTask(); + } void runTask() { mdns_init(); mdns_hostname_set("cspot"); +#ifdef CONFIG_BELL_NOCODEC + std::shared_ptr audioSink; + audioSink = std::make_shared(); + initAudioSink(audioSink); +#else #ifdef CONFIG_CSPOT_SINK_INTERNAL -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_AC101 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_ES8388 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_ES9018 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_PCM5102 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_TAS5711 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif audioSink->setParams(44100, 2, 16); audioSink->volumeChanged(160); +#endif auto loggedInSemaphore = std::make_shared(1); @@ -174,18 +181,19 @@ auto audioSink = std::make_unique(); zeroconfServer->onClose = [&isRunning]() { isRunning = false; - }; + }; auto loginBlob = std::make_shared(DEVICE_NAME); #ifdef CONFIG_CSPOT_LOGIN_PASS - loginBlob->loadUserPass(CONFIG_CSPOT_LOGIN_USERNAME, CONFIG_CSPOT_LOGIN_PASSWORD); + loginBlob->loadUserPass(CONFIG_CSPOT_LOGIN_USERNAME, + CONFIG_CSPOT_LOGIN_PASSWORD); loggedInSemaphore->give(); #else zeroconfServer->blob = loginBlob; zeroconfServer->onAuthSuccess = [loggedInSemaphore]() { loggedInSemaphore->give(); - }; + }; zeroconfServer->registerHandlers(); #endif loggedInSemaphore->wait(); @@ -202,8 +210,13 @@ auto audioSink = std::make_unique(); ctx->session->startTask(); // Create a player, pass the handler - auto player = std::make_shared(std::move(audioSink), std::move(handler)); - +#ifndef CONFIG_BELL_NOCODEC + auto player = + std::make_shared(std::move(audioSink), std::move(handler)); +#else + auto player = + std::make_shared(std::move(handler), std::move(audioSink)); +#endif // If we wanted to handle multiple devices, we would halt this loop // when a new zeroconf login is requested, and reinitialize the session while (isRunning) { @@ -213,28 +226,26 @@ auto audioSink = std::make_unique(); // Never happens, but required for above case handler->disconnect(); player->disconnect(); - } } }; void init_spiffs() { - esp_vfs_spiffs_conf_t conf = { .base_path = "/spiffs", + esp_vfs_spiffs_conf_t conf = {.base_path = "/spiffs", .partition_label = NULL, .max_files = 5, - .format_if_mount_failed = true }; + .format_if_mount_failed = true}; esp_err_t ret = esp_vfs_spiffs_register(&conf); if (ret != ESP_OK) { if (ret == ESP_FAIL) { - ESP_LOGE(TAG, "Failed to mount or format filesystem"); - } - else if (ret == ESP_ERR_NOT_FOUND) { - ESP_LOGE(TAG, "Failed to find SPIFFS partition"); - } - else { - ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); + CSPOT_LOG(error, "Failed to mount or format filesystem"); + } else if (ret == ESP_ERR_NOT_FOUND) { + CSPOT_LOG(error, "Failed to find SPIFFS partition"); + } else { + CSPOT_LOG(error, "Failed to initialize SPIFFS (%s)", + esp_err_to_name(ret)); } return; } @@ -242,11 +253,10 @@ void init_spiffs() { size_t total = 0, used = 0; ret = esp_spiffs_info(conf.partition_label, &total, &used); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", - esp_err_to_name(ret)); - } - else { - ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); + CSPOT_LOG(error, "Failed to get SPIFFS partition information (%s)", + esp_err_to_name(ret)); + } else { + CSPOT_LOG(info, "Partition size: total: %d, used: %d", total, used); } } @@ -256,7 +266,7 @@ void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || - ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } @@ -273,7 +283,7 @@ void app_main(void) { // statusLed->setStatus(StatusLed::WIFI_CONNECTED); - ESP_LOGI(TAG, "Connected to AP, start spotify receiver"); + CSPOT_LOG(info, "Connected to AP, start spotify receiver"); //auto taskHandle = xTaskCreatePinnedToCore(&cspotTask, "cspot", 12*1024, NULL, 5, NULL, 1); /*auto taskHandle = */ bell::setDefaultLogger(); From ef5a6145b019fcf80343e437fac61de3851bf1e9 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 16 Jul 2024 23:29:48 +0200 Subject: [PATCH 23/41] currentTracksIndex is pointing to the currentlyPlaying song, VS1053 support --- cspot/include/SpircHandler.h | 1 + cspot/src/SpircHandler.cpp | 23 +- cspot/src/TrackPlayer.cpp | 13 +- cspot/src/TrackQueue.cpp | 4 +- targets/cli/CliPlayer.cpp | 7 +- .../esp32/components/VS1053/CMakeLists.txt | 4 + targets/esp32/components/VS1053/Kconfig | 69 ++ targets/esp32/components/VS1053/component.mk | 0 .../esp32/components/VS1053/include/VS1053.h | 239 +++++ .../components/VS1053/include/patches_dsd.h | 983 ++++++++++++++++++ .../components/VS1053/include/patches_flac.h | 961 +++++++++++++++++ .../VS1053/include/patches_flac_latm.h | 980 +++++++++++++++++ .../components/VS1053/include/patches_latm.h | 644 ++++++++++++ .../components/VS1053/include/patches_pitch.h | 688 ++++++++++++ .../VS1053/include/spectrum_analyzer.h | 124 +++ .../components/VS1053/include/vs10xx_uc.h | 561 ++++++++++ .../esp32/components/VS1053/src/VS1053.cpp | 666 ++++++++++++ targets/esp32/main/EspPlayer.cpp | 36 +- targets/esp32/main/Kconfig.projbuild | 25 +- targets/esp32/main/VSPlayer.cpp | 100 ++ targets/esp32/main/VSPlayer.h | 36 + targets/esp32/main/VSinit.h | 30 + targets/esp32/main/main.cpp | 96 +- 23 files changed, 6210 insertions(+), 80 deletions(-) create mode 100644 targets/esp32/components/VS1053/CMakeLists.txt create mode 100644 targets/esp32/components/VS1053/Kconfig create mode 100644 targets/esp32/components/VS1053/component.mk create mode 100644 targets/esp32/components/VS1053/include/VS1053.h create mode 100644 targets/esp32/components/VS1053/include/patches_dsd.h create mode 100644 targets/esp32/components/VS1053/include/patches_flac.h create mode 100644 targets/esp32/components/VS1053/include/patches_flac_latm.h create mode 100644 targets/esp32/components/VS1053/include/patches_latm.h create mode 100644 targets/esp32/components/VS1053/include/patches_pitch.h create mode 100644 targets/esp32/components/VS1053/include/spectrum_analyzer.h create mode 100644 targets/esp32/components/VS1053/include/vs10xx_uc.h create mode 100644 targets/esp32/components/VS1053/src/VS1053.cpp create mode 100644 targets/esp32/main/VSPlayer.cpp create mode 100644 targets/esp32/main/VSPlayer.h create mode 100644 targets/esp32/main/VSinit.h diff --git a/cspot/include/SpircHandler.h b/cspot/include/SpircHandler.h index 3464450f..9baa7658 100644 --- a/cspot/include/SpircHandler.h +++ b/cspot/include/SpircHandler.h @@ -52,6 +52,7 @@ class SpircHandler { bool nextSong(); + void notifyAudioReachedPlaybackEnd(); void notifyAudioReachedPlayback(); void notifyAudioEnded(); void updatePositionMs(uint32_t position); diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index dbf09877..894809e0 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -82,23 +82,34 @@ void SpircHandler::loadTrackFromURI(const std::string& uri) {} void SpircHandler::notifyAudioEnded() { playbackState->updatePositionMs(0); notify(); -#ifndef CONFIG_BELL_NOCODEC trackPlayer->resetState(true); -#endif } - -void SpircHandler::notifyAudioReachedPlayback() { +void SpircHandler::notifyAudioReachedPlaybackEnd() { int offset = 0; // get HEAD track auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - if (!playbackState->innerFrame.state.repeat) { - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT); + if (trackQueue->notifyPending) { + trackQueue->notifyPending = false; + + playbackState->updatePositionMs(currentTrack->requestedPosition); + + // Reset position in queued track + currentTrack->requestedPosition = 0; + } else if (!playbackState->innerFrame.state.repeat) { + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); // we moved to next track, re-acquire currentTrack again currentTrack = trackQueue->consumeTrack(nullptr, offset); } + playbackState->updatePositionMs(0); +} +void SpircHandler::notifyAudioReachedPlayback() { + int offset = 0; + + // get HEAD track + auto currentTrack = trackQueue->consumeTrack(nullptr, offset); this->notify(); sendEvent(EventType::TRACK_INFO, currentTrack->trackInfo); diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index b65f3cc7..ff7a4b6f 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -127,7 +127,7 @@ void TrackPlayer::runTask() { std::shared_ptr track = nullptr, newTrack = nullptr; int trackOffset = 0; - size_t tracksPlayed = 0; + size_t tracksPlayed = 1; bool eof = false; bool endOfQueueReached = false; @@ -295,14 +295,15 @@ void TrackPlayer::runTask() { ¤tSection); #endif - if (ret == 0) { - CSPOT_LOG(info, "EOF"); - // and done :) - eof = true; - } else if (ret < 0) { + if (ret < 0) { CSPOT_LOG(error, "An error has occured in the stream %d", ret); currentSongPlaying = false; } else { + if (ret == 0) { + CSPOT_LOG(info, "EOF"); + // and done :) + eof = true; + } if (this->dataCallback != nullptr) { auto toWrite = ret; diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 5621b279..5265418a 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -712,8 +712,8 @@ bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { } void TrackQueue::prepareRepeat() { - if (currentTracksIndex) - currentTracksIndex--; + if (currentTracksIndex > 0) + preloadedTracks.clear(); preloadedTracks.push_front( std::make_shared(currentTracks[currentTracksIndex], ctx, 0)); } diff --git a/targets/cli/CliPlayer.cpp b/targets/cli/CliPlayer.cpp index 0dc469ef..766574cf 100644 --- a/targets/cli/CliPlayer.cpp +++ b/targets/cli/CliPlayer.cpp @@ -34,7 +34,8 @@ CliPlayer::CliPlayer(std::unique_ptr sink, this->handler->getTrackPlayer()->setDataCallback( [this](uint8_t* data, size_t bytes, size_t trackId) { - + if (!bytes) + this->handler->notifyAudioReachedPlaybackEnd(); return this->centralAudioBuffer->writePCM(data, bytes, trackId); }); @@ -108,8 +109,8 @@ void CliPlayer::runTask() { if (!chunk || chunk->pcmSize == 0) { if (this->playlistEnd) { - this->handler->notifyAudioEnded(); - this->playlistEnd = false; + this->handler->notifyAudioEnded(); + this->playlistEnd = false; } BELL_SLEEP_MS(10); continue; diff --git a/targets/esp32/components/VS1053/CMakeLists.txt b/targets/esp32/components/VS1053/CMakeLists.txt new file mode 100644 index 00000000..2d42d503 --- /dev/null +++ b/targets/esp32/components/VS1053/CMakeLists.txt @@ -0,0 +1,4 @@ +set(CMAKE_CXX_STANDARD 17) + idf_component_register(SRCS "src/VS1053.cpp" INCLUDE_DIRS + "include" + "src" PRIV_REQUIRES fatfs) diff --git a/targets/esp32/components/VS1053/Kconfig b/targets/esp32/components/VS1053/Kconfig new file mode 100644 index 00000000..9b45b46c --- /dev/null +++ b/targets/esp32/components/VS1053/Kconfig @@ -0,0 +1,69 @@ +menu "VS1053 Configuration" + + menu "VS1053 PIN Configuration" + + config GPIO_MISO + int "GPIO pin MISO" + range -1 39 + default 19 + + config GPIO_MOSI + int "GPIO pin MOSI" + range -1 39 + default 23 + + config GPIO_CLK + int "GPIO pin CLK" + range -1 39 + default 18 + + config GPIO_VS_CS + int "GPIO pin VS CS" + range -1 39 + default 4 + + config GPIO_VS_DCS + int "GPIO pin VS DCS" + range -1 39 + default 21 + + config GPIO_VS_RESET + int "GPIO pin VS RESET" + range -1 39 + default 0 + + config GPIO_VS_DREQ + int "GPIO pin VS DREQ" + range -1 39 + default 22 + + config GPIO_SD_CS + int "GPIO pin SD CS" + range -1 39 + default 5 + endmenu + +choice VS_PLUGIN + prompt "VS1053 plugin" + default VS_FLAC + help + you have to choose between special audio compability or a spectrum analyzer + config VS_DSD64 + bool "with dsd patch" + config VS_FLAC + bool "with flac patch" + config VS_FLAC_LATM + bool "with flac & latm/loas patch" + config VS_LATM + bool "with latm/loas patch" + config VS_PITCH + bool "with pitch plugin" + config VS_SPECTRUM_ANALYZER + bool "with spectrum analyzer plugin" +endchoice + + +config REPORT_ON_SCREEN + bool "REPORT_ON_SCREEN" + +endmenu diff --git a/targets/esp32/components/VS1053/component.mk b/targets/esp32/components/VS1053/component.mk new file mode 100644 index 00000000..e69de29b diff --git a/targets/esp32/components/VS1053/include/VS1053.h b/targets/esp32/components/VS1053/include/VS1053.h new file mode 100644 index 00000000..35bcbc71 --- /dev/null +++ b/targets/esp32/components/VS1053/include/VS1053.h @@ -0,0 +1,239 @@ +#ifndef VS1053_H +#define VS1053_H + +#include //for memset +#include //for dequeue +#include //for function +#include +#include + +#include "esp_err.h" + +#include +#include + +#include "freertos/semphr.h" +#include "freertos/stream_buffer.h" +#include "freertos/task.h" + +#include "vs10xx_uc.h" +#ifdef CONFIG_VS_DSD64 +#include "patches_dsd.h" +#endif +#ifdef CONFIG_VS_FLAC +#include "patches_flac.h" +#endif +#ifdef CONFIG_VS_FLAC_LATM +#include "patches_flac_latm.h" +#endif +#ifdef CONFIG_VS_LATM +#include "patches_latm.h" +#endif +#ifdef CONFIG_VS_PITCH +#include "patches_pitch.h" +#endif +#ifdef CONFIG_VS_SPECTRUM_ANALYZER +#include "spectrum_analyzer.h" +#endif + +#define VERSION 1 +#define VS1053_CHUNK_SIZE 16 // chunck size +#define VS1053_PACKET_SIZE 8 +#define BUF_SIZE_CMD 1028 +#define BUF_SIZE_FEED 4096 * 4 + +#define SDI_END_FILL_BYTES_FLAC 12288 +#define SDI_END_FILL_BYTES 2050 + +#define REPORT_INTERVAL 4096 +#define REPORT_INTERVAL_MIDI 512 +/** + * + * callback for the command_pipeline + * + */ +class VS1053_SINK; +class VS1053_TRACK { + public: + VS1053_TRACK(VS1053_SINK* vsSink, size_t track_id = 0, + size_t buffer_size = BUF_SIZE_FEED); + ~VS1053_TRACK(); + /** + * feed data to dataBuffer + * @param data pointer to byte array + * @param len length of the byte array + * @warning always call data_request, before feeding data, + * to get available space in dataBuffer + */ + size_t feed_data(uint8_t* data, size_t len, bool STORAGE_VOLATILE = 0); + void empty_feed(); + void run_track(size_t FILL_BUFFER_BEFORE_PLAYSTART = 0); + VS1053_SINK* audioSink; + TaskHandle_t track_handle = NULL; + enum VS_TRACK_STATE { + tsPlaybackStart = 0, + tsPlayback = 1, + tsPlaybackSeekable = 2, + tsPlaybackPaused = 3, + tsSoftCancel = 4, + tsCancel = 5, + tsCancelAwait = 6, + tsStopped = 7 + } track_state = tsStopped; + size_t header_size = 0; + size_t track_id; + StreamBufferHandle_t dataBuffer; + + private: +}; +class VS1053_SINK { + public: + /** + * `CONSTRUCTOR` + * + * PULLS CS and DCS HIGH. + * If RESET >= 0, VS1053 gets hardreset. + * For sharing the SPI_BUS with a SD-Card, the CS-pins + * of the other devices are needed to be pulled high + * before mounting the SD-card. + * After mounting the SD-card, you can add the other devices + * + * @param RESET GPIO_PIN_NUM, if + */ + VS1053_SINK(); + + /** + * DECONSTRUCTOR + */ + ~VS1053_SINK(); + typedef std::function command_callback; + //typedef std::function command_callback; + /** + * `init feed` + * add the VS 1053 to the SPI_BUS, test the device and + * add vs_loop to freertosTask + * + * @param SPI pointer to the used SPI peripheral + * @param SPI_semaphore semaphore for the SPI_BUS, NULL if uninitiallized + * + * @return `ESP_OK` if setup worked. + * @return `ESP_ERR_INVALID_RESPONSE` if the register response is wrong. + * @return `ESP_ERR_NOT_SUPPORTED` if the chip is not a VS1053. + * @return `ESP_ERR_NOT_FOUND` if the chipNumber is not recognized. + */ + esp_err_t init(spi_host_device_t SPI, + SemaphoreHandle_t* SPI_semaphore = NULL); + /** + * stops data feed imeaditly + */ + void stop_feed(); + /** + * stops data feed if dataBuffer contains no more + */ + void soft_stop_feed(); + /** + * feed data to commandBuffer + * @param command_callback callback function + * + */ + uint8_t feed_command(command_callback commandCallback); + void set_volume_logarithmic(size_t vol); + /** + * set volume through cmd_pipeline, sets left and right volume to vol + * @param vol 0...100, gets capped if bigger + */ + void set_volume(uint8_t vol); + /** + * set volume through cmd_pipeline, sets separate volume for left and right channel + * @param left 0...100, gets capped if bigger + * @param right 0...100, gets capped if bigger + */ + void set_volume(uint8_t left, uint8_t right); + /** + * get available Space in dataBuffer + * @return free space available in dataBuffer + */ + size_t data_request(); + /** + * loads Usercode(PATCH) + * @param plugin uint8_t * to plugin array + * @param sizeofpatch length of the array + */ + void load_user_code(const unsigned short* plugin, uint16_t sizeofpatch); + /** + * test SPI communication and if the board is a VS1053 + * @return `ESP_OK` if setup worked. + * @return `ESP_ERR_INVALID_RESPONSE` if the register response is wrong. + * @return `ESP_ERR_NOT_SUPPORTED` if the chip is not a VS1053. + * @return `ESP_ERR_NOT_FOUND` if the chipNumber is not recognized. + */ + esp_err_t test_comm(const char* header); + std::function state_callback = nullptr; + enum Audio_Format { + afUnknown, + afRiff, + afOggVorbis, + afMp1, + afMp2, + afMp3, + afAacMp4, + afAacAdts, + afAacAdif, + afFlac, + afWma, + afMidi, + afDsd64, + afLatm + } audioFormat = afUnknown; + void get_audio_format(Audio_Format* audioFormat, size_t* endFillBytes); + void control_mode_on(); + void control_mode_off(); + void data_mode_on(); + void data_mode_off(); + uint16_t read_register(uint8_t _reg); + bool write_register(uint8_t _reg, uint16_t _value); + uint32_t read_mem32(uint16_t addr); + uint32_t read_mem32_counter(uint16_t addr); + uint16_t read_mem(uint16_t addr); + void write_mem(uint16_t addr, uint16_t data); + void write_mem32(uint16_t addr, uint32_t data); + bool sdi_send_buffer(uint8_t* data, size_t len); + void remove_track(std::shared_ptr track) { + if (this->track->track_id == track->track_id) + this->track = nullptr; + }; + void start_track(std::shared_ptr, size_t); + bool is_seekable(VS1053_TRACK::VS_TRACK_STATE* state); + size_t track_seekable(size_t); + void cancel_track(VS1053_TRACK::VS_TRACK_STATE* state); + bool is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state); + size_t get_track_info(size_t); + void new_state(VS1053_TRACK::VS_TRACK_STATE); + void new_track(std::shared_ptr track); + VS1053_TRACK newTrack(size_t track_id, size_t buffer_size = BUF_SIZE_FEED); + + void delete_track(void); + size_t spaces_available(size_t); + std::shared_ptr track = nullptr; + std::shared_ptr future_track = nullptr; + size_t command_pointer = 0, command_reader = 0; + std::deque command_callbacks; + + private: + spi_device_handle_t SPIHandleLow; + spi_device_handle_t SPIHandleFast; + uint8_t curvol; // Current volume setting 0..100% + uint8_t endFillByte = 0; // Byte to send when stopping song + size_t endFillBytes = SDI_END_FILL_BYTES; + int playMode = 0; + uint8_t chipVersion; // Version of hardware + SemaphoreHandle_t* SPI_semaphore = NULL; + TaskHandle_t VS_TASK; + void await_data_request(); + bool sdi_send_fillers(size_t len); + void wram_write(uint16_t address, uint16_t data); + uint16_t wram_read(uint16_t address); + size_t (*data_callback)(uint8_t*, size_t) = NULL; +}; + +#endif \ No newline at end of file diff --git a/targets/esp32/components/VS1053/include/patches_dsd.h b/targets/esp32/components/VS1053/include/patches_dsd.h new file mode 100644 index 00000000..d9ac29d9 --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_dsd.h @@ -0,0 +1,983 @@ + +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x001e, /*copy 30*/ + 0x2a00, 0xc000, 0x3e12, 0xb817, 0x3e14, 0xf812, 0x3e01, 0xb811, 0x0007, + 0x9717, 0x0020, 0xffd2, 0x0030, 0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, + 0x3b81, 0x8024, 0x3101, 0x8024, 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, + 0x4800, 0x36f1, 0x9811, 0x0007, 0x0001, /*copy 1*/ + 0x8060, 0x0006, 0x053e, /*copy 1342*/ + 0xf400, 0x4095, 0x0000, 0x02c2, 0x6124, 0x0024, 0x0000, 0x0024, 0x2800, + 0x1ac5, 0x4192, 0x4542, 0x0000, 0x0041, 0x2000, 0x0015, 0x0030, 0x0317, + 0x2000, 0x0000, 0x3f00, 0x4024, 0x2000, 0x0000, 0x0000, 0x0000, 0x3e12, + 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, 0x8257, 0x3700, 0x984c, + 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, 0x2910, 0x0181, 0x0000, + 0x1bc8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, 0x0195, 0x0000, 0x1bc8, + 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2945, 0x3e13, 0x780e, 0x3e11, + 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, 0xb808, 0x003f, 0xe004, + 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, 0x48be, 0x4497, 0x4090, + 0x1c46, 0xf06c, 0x0024, 0x2400, 0x2580, 0x6090, 0x41c3, 0x6628, 0x1c47, + 0x0000, 0x0024, 0x2800, 0x2449, 0xf07e, 0x0024, 0xf400, 0x4182, 0x673a, + 0x1c46, 0x0000, 0x0024, 0x2800, 0x2589, 0xf06c, 0x0024, 0xf400, 0x41c3, + 0x0000, 0x0024, 0x4224, 0x3442, 0x2903, 0xdc80, 0x4336, 0x37c3, 0x0000, + 0x1805, 0x2903, 0xdc80, 0x4508, 0x40c2, 0x450a, 0x9808, 0x0000, 0x0207, + 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, 0x3d01, 0x5bc1, 0x36f3, + 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, 0x580e, 0x0007, 0x8257, + 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, 0xd428, 0x3c02, 0x0006, + 0xc717, 0x2800, 0x2d05, 0x4284, 0x0024, 0x3613, 0x3c02, 0x0006, 0xc357, + 0x2901, 0x6a00, 0x3e11, 0x5c05, 0x4284, 0x1bc5, 0x0007, 0x8257, 0x2800, + 0x3285, 0x0002, 0x0001, 0x3701, 0x0024, 0x0006, 0xc357, 0xb412, 0x9c02, + 0x002e, 0xe001, 0x2800, 0x3005, 0x6212, 0x0024, 0x0000, 0x0024, 0x2800, + 0x3295, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, 0x0024, 0x3613, 0x0024, + 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, 0x2900, 0x4b40, 0x0006, + 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, 0x8257, 0x3700, 0x8024, + 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x3491, 0x3600, 0x9844, 0x2900, + 0x3a40, 0x0000, 0x3508, 0x2911, 0xf140, 0x0000, 0x0024, 0x0030, 0x0057, + 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, 0xa024, 0x164c, 0x8000, + 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, 0x6d82, 0xd024, 0x44c0, + 0x0006, 0xa402, 0x2800, 0x3955, 0xd024, 0x0024, 0x0000, 0x0000, 0x2800, + 0x3955, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, 0x8024, 0x36f2, 0x1800, + 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, 0x3e13, 0xb80d, 0x3e13, + 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0xf801, + 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, 0xbf8e, 0x9c42, 0x3e01, + 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, 0x8250, 0x0fff, 0xfd85, + 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, 0x2800, 0x4091, 0xf25a, + 0x104c, 0x34f3, 0x0024, 0x2800, 0x4091, 0x0000, 0x0024, 0x3413, 0x084c, + 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, 0x2400, 0x42c0, 0x4efa, + 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, 0x4d64, 0x48b2, 0xa201, + 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, 0x36f4, 0xd801, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0xd80a, 0x36f3, 0x980d, + 0x2000, 0x0000, 0x36f4, 0x5810, 0x36f3, 0x0024, 0x3009, 0x3848, 0x3e14, + 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, + 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, 0x9e40, 0x3604, 0x1811, 0x3613, + 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, + 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x36f4, 0x1811, 0x3009, + 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e13, 0x7801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, + 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, 0x34e5, 0xc024, 0x3524, + 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, 0x4a0c, 0x3d44, 0x8024, + 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, 0x6010, 0x3400, 0x3710, + 0x8024, 0x2800, 0x5704, 0x3af0, 0x8024, 0x3df0, 0x0024, 0x3591, 0x4024, + 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, 0x4020, 0x1753, 0xbf8e, + 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, 0x550e, 0xfe6d, 0x2819, + 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, 0xad56, 0x904c, 0xaf5e, + 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, 0x2046, 0x3cf4, 0x0024, + 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, 0x2800, 0x4f95, 0x3c00, + 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0x5801, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x0000, 0x0200, + 0xb386, 0x3803, 0xad06, 0x0024, 0x2000, 0x0000, 0xc320, 0x1bc3, 0x2814, + 0x9c91, 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, 0x3e12, 0xb817, + 0x3e12, 0x7808, 0x3e11, 0xb811, 0x3e15, 0x7810, 0x3e18, 0xb823, 0x3e18, + 0x3821, 0x3e10, 0x3801, 0x48b2, 0x0024, 0x3e10, 0x3801, 0x3e11, 0x3802, + 0x3009, 0x3814, 0x0030, 0x0717, 0x3f05, 0xc024, 0x0030, 0x0351, 0x3100, + 0x0024, 0x4080, 0x0024, 0x0030, 0x10d1, 0x2800, 0x6885, 0x0001, 0x800a, + 0x0006, 0x6514, 0x3111, 0x8024, 0x6894, 0x13c1, 0x6618, 0x0024, 0xfe44, + 0x1000, 0x4cb2, 0x0406, 0x3c10, 0x0024, 0x3c50, 0x4024, 0x34f0, 0x4024, + 0x661c, 0x1040, 0xfe64, 0x0024, 0x4cb2, 0x0024, 0x3cf0, 0x4024, 0xbc82, + 0x3080, 0x0030, 0x0351, 0x3100, 0x8024, 0xfea8, 0x0024, 0x5ca2, 0x0024, + 0x0000, 0x0182, 0xac22, 0x0024, 0xf7c8, 0x0024, 0x48b2, 0x0024, 0xac22, + 0x0024, 0x2800, 0x6c00, 0xf7cc, 0x1002, 0x0030, 0x0394, 0x3400, 0x4024, + 0x3100, 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, 0x6410, 0x4088, + 0x1001, 0x0030, 0x1111, 0x3100, 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, + 0x0006, 0x6550, 0x0006, 0x6694, 0x408c, 0x1002, 0xf224, 0x0024, 0x0006, + 0xa017, 0x2800, 0x7015, 0x0000, 0x0024, 0x2808, 0x3f41, 0x0006, 0x6410, + 0x3050, 0x0024, 0x3000, 0x4024, 0x6014, 0x0024, 0x0000, 0x0024, 0x2800, + 0x6f59, 0x0000, 0x0024, 0xf400, 0x4040, 0x38b0, 0x0024, 0x2808, 0x3f40, + 0x3800, 0x0024, 0x2800, 0x7201, 0xf224, 0x0024, 0x0000, 0x0024, 0x2808, + 0x3f45, 0x4684, 0x4106, 0xf12c, 0x0024, 0xf148, 0x0024, 0x846c, 0x0024, + 0x2808, 0x3f40, 0xf400, 0x4184, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0xa090, 0x2912, + 0x0d00, 0x3e14, 0xc024, 0x4088, 0x8000, 0x4080, 0x0024, 0x0007, 0x90d1, + 0x2800, 0x7845, 0x0000, 0x0024, 0x0007, 0x9051, 0x3100, 0x4024, 0x4100, + 0x0024, 0x3900, 0x0024, 0x0007, 0x90d1, 0x0004, 0x0000, 0x31f0, 0x4024, + 0x6014, 0x0400, 0x0000, 0x0024, 0x2800, 0x7c91, 0x4080, 0x0024, 0x0000, + 0x0000, 0x2800, 0x7c05, 0x0000, 0x0024, 0x0007, 0x9053, 0x3300, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0000, 0x2800, 0x7c98, 0x0000, 0x0024, 0x0007, + 0x9051, 0x3900, 0x0024, 0x3200, 0x504c, 0x6410, 0x0024, 0x3cf0, 0x0000, + 0x4080, 0x0024, 0x0006, 0xc691, 0x2800, 0x9545, 0x3009, 0x0400, 0x0000, + 0x1001, 0x0007, 0x9051, 0x3100, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, + 0x2800, 0x8989, 0x003f, 0xe000, 0x0006, 0xc693, 0x3900, 0x0c00, 0x3009, + 0x0001, 0x6014, 0x0024, 0x0007, 0x1ad0, 0x2800, 0x8995, 0x3009, 0x0000, + 0x4080, 0x0024, 0x0000, 0x0301, 0x2800, 0x8385, 0x4090, 0x0024, 0x0000, + 0x0024, 0x2800, 0x8495, 0x0000, 0x0024, 0x3009, 0x0000, 0xc012, 0x0024, + 0x2800, 0x8980, 0x3009, 0x2001, 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, + 0x0341, 0x2800, 0x8695, 0x0000, 0x0024, 0x6190, 0x0024, 0x2800, 0x8980, + 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, 0x0381, 0x2800, 0x8855, 0x0000, + 0x0024, 0x6190, 0x0024, 0x2800, 0x8980, 0x3009, 0x2000, 0x6012, 0x0024, + 0x0000, 0x00c0, 0x2800, 0x8995, 0x0000, 0x0024, 0x3009, 0x2000, 0x0006, + 0xa090, 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0081, 0x2800, 0x8e55, + 0x0007, 0x8c13, 0x3300, 0x104c, 0xb010, 0x0024, 0x0002, 0x8001, 0x2800, + 0x90c5, 0x34f0, 0x0024, 0x2800, 0x8e40, 0x0000, 0x0024, 0x0006, 0xc351, + 0x3009, 0x0000, 0x6090, 0x0024, 0x3009, 0x2000, 0x2900, 0x0b80, 0x3009, + 0x0405, 0x0006, 0xc6d1, 0x0006, 0xc690, 0x3009, 0x0000, 0x3009, 0x0401, + 0x6014, 0x0024, 0x0006, 0xa093, 0x2800, 0x8cd1, 0xb880, 0x0024, 0x2800, + 0x9e00, 0x3009, 0x2c00, 0x4040, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, + 0x2800, 0x9e18, 0x0000, 0x0024, 0x0006, 0xc693, 0x3009, 0x0c00, 0x3009, + 0x0001, 0x6014, 0x0024, 0x0006, 0xc350, 0x2800, 0x9e01, 0x0000, 0x0024, + 0x6090, 0x0024, 0x3009, 0x2c00, 0x3009, 0x0005, 0x2900, 0x0b80, 0x0000, + 0x9e08, 0x3009, 0x0400, 0x4080, 0x0024, 0x0003, 0x8000, 0x2800, 0x9e05, + 0x0000, 0x0024, 0x6400, 0x0024, 0x0000, 0x0081, 0x2800, 0x9e09, 0x0000, + 0x0024, 0x0007, 0x8c13, 0x3300, 0x0024, 0xb010, 0x0024, 0x0006, 0xc650, + 0x2800, 0x9e15, 0x0000, 0x0024, 0x0001, 0x0002, 0x3413, 0x0000, 0x3009, + 0x0401, 0x4010, 0x8406, 0x0000, 0x0281, 0xa010, 0x13c1, 0x4122, 0x0024, + 0x0000, 0x03c2, 0x6122, 0x8002, 0x462c, 0x0024, 0x469c, 0x0024, 0xfee2, + 0x0024, 0x48be, 0x0024, 0x6066, 0x8400, 0x0006, 0xc350, 0x2800, 0x9e01, + 0x0000, 0x0024, 0x4090, 0x0024, 0x3009, 0x2400, 0x2900, 0x0b80, 0x3009, + 0x0005, 0x0007, 0x1b50, 0x2912, 0x0d00, 0x3613, 0x0024, 0x3a00, 0x0380, + 0x4080, 0x0024, 0x0000, 0x00c1, 0x2800, 0xa6c5, 0x3009, 0x0000, 0xb010, + 0x008c, 0x4192, 0x0024, 0x6012, 0x0024, 0x0006, 0xf051, 0x2800, 0xa4d8, + 0x3009, 0x0400, 0x0007, 0x1fd1, 0x30e3, 0x0400, 0x4080, 0x0024, 0x0000, + 0x0301, 0x2800, 0xa6c5, 0x3009, 0x0000, 0xb010, 0x0024, 0x0000, 0x0101, + 0x6012, 0x0024, 0x0006, 0xf051, 0x2800, 0xa6d5, 0x0000, 0x0024, 0x3023, + 0x0400, 0xf200, 0x184c, 0xb880, 0xa400, 0x3009, 0x2000, 0x3009, 0x0441, + 0x3e10, 0x4402, 0x2909, 0xa9c0, 0x3e10, 0x8024, 0x36e3, 0x0024, 0x36f4, + 0xc024, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e14, 0x3811, 0x3e14, 0x92cc, 0x3400, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0590, 0x2800, 0xb058, 0x0000, 0x0024, 0x6800, 0x9bcc, 0x3c20, + 0x0024, 0x34e4, 0x4024, 0x3410, 0x860c, 0x3100, 0x0024, 0xff20, 0x1012, + 0x48b6, 0x084c, 0x4280, 0x1110, 0x6898, 0x0024, 0x2900, 0xb480, 0x0000, + 0x0085, 0x34b3, 0x184c, 0x3410, 0x0024, 0x3e10, 0x0024, 0x3410, 0x0024, + 0x3e10, 0x0024, 0x3430, 0x0024, 0x2920, 0x1340, 0x3e00, 0x0024, 0x36d3, + 0x0024, 0x36f4, 0x8024, 0x36f4, 0x1811, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, + 0x9817, 0x4090, 0x184c, 0x3e14, 0xf811, 0x3e13, 0xf80e, 0x2800, 0xb6c4, + 0x3e03, 0x4024, 0x2400, 0xb680, 0x2b11, 0x1153, 0x3280, 0x0024, 0x3880, + 0x0024, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x36f4, 0xd811, + 0x4090, 0x184c, 0x3e14, 0xf811, 0x3e13, 0xf80e, 0x2800, 0xbac4, 0x4498, + 0x380d, 0x459a, 0x0024, 0x2400, 0xba80, 0x2b11, 0x1153, 0x3210, 0x0024, + 0x3810, 0x0024, 0x3280, 0x0024, 0x3880, 0x0024, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x2000, 0x0000, 0x36f4, 0xd811, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0xb880, 0x1854, 0x3405, 0x9014, 0x36e3, 0x0024, 0x2000, + 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, + 0x3615, 0x0024, 0x3405, 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, + 0x9815, 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x191c, /*copy 6428*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x69d7, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x5c8e, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x4d86, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdd55, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xdc0e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x10c8, 0x0039, + 0x324f, 0x0001, 0x3dce, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x0014, 0x1b01, 0x0015, 0x59c0, + 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, 0xe795, 0x0000, 0x0024, 0x290c, + 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, 0x4086, 0x184c, 0x0000, 0x18c2, + 0x6234, 0x0024, 0x0000, 0x1d02, 0x2800, 0xe395, 0x6234, 0x0024, 0x0030, + 0x0317, 0x2800, 0xe780, 0x3f00, 0x0024, 0x0000, 0x1d82, 0x2800, 0xe615, + 0x6234, 0x0024, 0x2912, 0x0d00, 0x4084, 0x184c, 0xf200, 0x0024, 0x6200, + 0x0024, 0x0006, 0x0017, 0x2800, 0xe300, 0xb080, 0x3c40, 0x0000, 0x0202, + 0x2800, 0xe795, 0xa024, 0x0024, 0xc020, 0x0024, 0x2800, 0xe300, 0x0030, + 0x02d7, 0x0011, 0x14c1, 0x0011, 0x0800, 0x6fc2, 0x0024, 0x0011, 0x9481, + 0x2800, 0xea05, 0x0013, 0x4e00, 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, + 0xea95, 0x0000, 0x0024, 0x2801, 0x8ec0, 0x000a, 0xcac8, 0x000a, 0x8c8f, + 0x0000, 0xebce, 0x000c, 0x0981, 0x280a, 0x71c0, 0x002c, 0x9d40, 0x000a, + 0x708f, 0x0000, 0xd7ce, 0x280a, 0xc0d5, 0x0012, 0x5182, 0x6fd6, 0x0024, + 0x003f, 0xfd81, 0x280a, 0x8e45, 0xb710, 0x0024, 0xb710, 0x0024, 0x003f, + 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x0795, 0xffd2, 0x0024, + 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x190d, 0x2801, 0x0795, 0x0030, + 0x0250, 0xb880, 0x104c, 0x3cf0, 0x0024, 0x0010, 0x5500, 0xb880, 0x23c0, + 0xb882, 0x2000, 0x0007, 0x8590, 0x2914, 0xbec0, 0x0000, 0x0440, 0x0007, + 0x8b50, 0xb880, 0x0024, 0x2920, 0x0100, 0x3800, 0x0024, 0x2920, 0x0000, + 0x0006, 0x8a91, 0x0000, 0x0800, 0xb880, 0xa440, 0x003f, 0xfd81, 0xb710, + 0xa7c0, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x10d5, + 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, + 0x0024, 0x2801, 0x10d5, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, + 0x4080, 0x0024, 0x0006, 0x8a90, 0x2801, 0x10d5, 0x0000, 0x01c2, 0xb886, + 0x8040, 0x3613, 0x03c1, 0xbcd2, 0x0024, 0x0030, 0x0011, 0x2800, 0xfd55, + 0x003f, 0xff42, 0xb886, 0x8040, 0x3009, 0x03c1, 0x0000, 0x0020, 0xac22, + 0x0024, 0x0000, 0x0102, 0x6cd2, 0x0024, 0x3e10, 0x0024, 0x2909, 0x8c80, + 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3e11, 0x8024, 0x3e01, 0xc024, 0x2901, + 0x3480, 0x0000, 0x0201, 0xf400, 0x4512, 0x2900, 0x0c80, 0x3213, 0x1b8c, + 0x3100, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, 0x10d5, 0x0000, + 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2920, 0x0200, 0x3633, 0x0024, + 0x2920, 0x0280, 0x0000, 0x0401, 0x408e, 0x0024, 0x2920, 0x0280, 0x0000, + 0x0401, 0x003f, 0xfd81, 0xb710, 0x4006, 0x003f, 0xfc01, 0x6012, 0x0024, + 0x0000, 0x0101, 0x2801, 0x10d5, 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, + 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x10d5, 0x0000, 0x0024, + 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0000, 0x01c2, 0x2800, + 0xf945, 0x0006, 0x8a90, 0x2a01, 0x10c0, 0x2920, 0x0100, 0x0000, 0x0401, + 0x0000, 0x0180, 0x2920, 0x0200, 0x3613, 0x0024, 0x2920, 0x0280, 0x3613, + 0x0024, 0x0000, 0x0401, 0x2920, 0x0280, 0x4084, 0x984c, 0x0019, 0x9d01, + 0x6212, 0x0024, 0x001e, 0x5c01, 0x2801, 0x0c15, 0x6012, 0x0024, 0x0000, + 0x0024, 0x2801, 0x0e05, 0x0000, 0x0024, 0x001b, 0x5bc1, 0x6212, 0x0024, + 0x001b, 0xdd81, 0x2801, 0x11d5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, + 0x11d5, 0x0000, 0x0024, 0x0000, 0x004d, 0x000a, 0xbf4f, 0x280a, 0xb880, + 0x0001, 0x0f0e, 0x0020, 0xfb4f, 0x0000, 0x190d, 0x0001, 0x160e, 0x2920, + 0xf440, 0x3009, 0x2bc1, 0x291a, 0x8a40, 0x36e3, 0x0024, 0x0000, 0x190d, + 0x000a, 0x708f, 0x280a, 0xcac0, 0x0000, 0xd7ce, 0x0030, 0x0017, 0x3700, + 0x4024, 0x0000, 0x0200, 0xb102, 0x0024, 0x0000, 0x00c0, 0x2801, 0x1505, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0000, 0x190d, 0x000a, 0x708f, + 0x280a, 0xc0c0, 0x0000, 0xd7ce, 0x0000, 0x004d, 0x0020, 0xfe0f, 0x2820, + 0xfb40, 0x0001, 0x170e, 0x2801, 0x18d5, 0x3009, 0x1000, 0x6012, 0x93cc, + 0x0000, 0x0024, 0x2801, 0x3385, 0x0000, 0x0024, 0x3413, 0x0024, 0x34b0, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, 0x1bd5, 0xb882, 0x0024, + 0x3453, 0x0024, 0x3009, 0x13c0, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, + 0x3385, 0x0000, 0x0024, 0xb882, 0x130c, 0x0000, 0x004d, 0x0021, 0x058f, + 0x2821, 0x0340, 0x0001, 0x1cce, 0x2801, 0x2d15, 0x6012, 0x0024, 0x0000, + 0x0024, 0x2801, 0x2d15, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3e13, 0xb80f, + 0xf400, 0x4500, 0x0026, 0x9dcf, 0x0001, 0x20ce, 0x0000, 0xfa0d, 0x2926, + 0x8e80, 0x3e10, 0x110c, 0x36f3, 0x0024, 0x2801, 0x2d00, 0x36f3, 0x980f, + 0x001c, 0xdd00, 0x001c, 0xd901, 0x6ec2, 0x0024, 0x001c, 0xdd00, 0x2801, + 0x23d5, 0x0018, 0xdbc1, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0xc640, + 0x3e00, 0x13cc, 0x2801, 0x2ac0, 0x36f3, 0x0024, 0x6ec2, 0x0024, 0x003f, + 0xc000, 0x2801, 0x2655, 0x002a, 0x4001, 0x3413, 0x184c, 0xf400, 0x4500, + 0x2926, 0xafc0, 0x3e00, 0x13cc, 0x2801, 0x2ac0, 0x36f3, 0x0024, 0xb400, + 0x0024, 0xd100, 0x0024, 0x0000, 0x0024, 0x2801, 0x2ac5, 0x0000, 0x0024, + 0x3613, 0x0024, 0x3e11, 0x4024, 0x2926, 0x8540, 0x3e01, 0x0024, 0x4080, + 0x1b8c, 0x0000, 0x0024, 0x2801, 0x2ac5, 0x0000, 0x0024, 0x3413, 0x184c, + 0xf400, 0x4500, 0x2926, 0x8e80, 0x3e10, 0x13cc, 0x36f3, 0x0024, 0x3110, + 0x8024, 0x31f0, 0xc024, 0x0000, 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, + 0x3110, 0x8024, 0x2826, 0xa8c4, 0x31f0, 0xc024, 0x2a26, 0xad00, 0x34c3, + 0x184c, 0x3410, 0x8024, 0x3430, 0xc024, 0x0000, 0x4000, 0x0000, 0x0021, + 0x6d06, 0x0024, 0x0000, 0x0024, 0x2801, 0x3394, 0x4d06, 0x0024, 0x0000, + 0x0200, 0x2922, 0x1885, 0x0001, 0x3208, 0x0000, 0x0200, 0x3e10, 0x8024, + 0x2921, 0xca80, 0x3e00, 0xc024, 0x291a, 0x8a40, 0x0000, 0x0024, 0x2922, + 0x1880, 0x36f3, 0x0024, 0x0000, 0x004d, 0x0021, 0x0ecf, 0x2821, 0x0bc0, + 0x0001, 0x330e, 0x2801, 0x1600, 0x3c30, 0x4024, 0x0000, 0x190d, 0x0000, + 0x458e, 0x2821, 0x0f80, 0x0027, 0x9e0f, 0x0020, 0xcd4f, 0x2820, 0xc780, + 0x0001, 0x354e, 0x0006, 0xf017, 0x0000, 0x0015, 0xb070, 0xbc15, 0x0000, + 0x458e, 0x0027, 0x9e0f, 0x2820, 0xcd80, 0x0000, 0x190d, 0x3613, 0x0024, + 0x3e10, 0xb803, 0x3e14, 0x3811, 0x3e11, 0x3805, 0x3e00, 0x3801, 0x0007, + 0xc390, 0x0006, 0xa011, 0x3010, 0x0444, 0x3050, 0x4405, 0x6458, 0x0302, + 0xff94, 0x4081, 0x0003, 0xffc5, 0x48b6, 0x0024, 0xff82, 0x0024, 0x42b2, + 0x0042, 0xb458, 0x0003, 0x4cd6, 0x9801, 0xf248, 0x1bc0, 0xb58a, 0x0024, + 0x6de6, 0x1804, 0x0006, 0x0010, 0x3810, 0x9bc5, 0x3800, 0xc024, 0x36f4, + 0x1811, 0x36f0, 0x9803, 0x283e, 0x2d80, 0x0fff, 0xffc3, 0x2801, 0x4b80, + 0x0000, 0x0024, 0x3413, 0x0024, 0x2801, 0x3f85, 0xf400, 0x4517, 0x2801, + 0x4380, 0x6894, 0x13cc, 0x37b0, 0x184c, 0x6090, 0x1d51, 0x0000, 0x0910, + 0x3f00, 0x060c, 0x3100, 0x4024, 0x6016, 0xb812, 0x000c, 0x8012, 0x2801, + 0x4211, 0xb884, 0x0024, 0x6894, 0x3002, 0x0000, 0x028d, 0x003a, 0x5e0f, + 0x0001, 0x538e, 0x2939, 0xb0c0, 0x3e10, 0x93cc, 0x4084, 0x9bd2, 0x4282, + 0x0024, 0x0000, 0x0040, 0x2801, 0x4585, 0x4292, 0x130c, 0x3443, 0x0024, + 0x2801, 0x46c5, 0x000c, 0x8390, 0x2a01, 0x4a40, 0x3444, 0x0024, 0x3073, + 0x0024, 0xc090, 0x014c, 0x2801, 0x4a40, 0x3800, 0x0024, 0x000c, 0x4113, + 0xb880, 0x2380, 0x3304, 0x4024, 0x3800, 0x05cc, 0xcc92, 0x05cc, 0x3910, + 0x0024, 0x3910, 0x4024, 0x000c, 0x8110, 0x3910, 0x0024, 0x39f0, 0x4024, + 0x3810, 0x0024, 0x38d0, 0x4024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x34c3, + 0x0024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x3613, + 0x0024, 0x2801, 0x4d85, 0x6898, 0xb804, 0x0000, 0x0084, 0x293b, 0x1cc0, + 0x3613, 0x0024, 0x000c, 0x8117, 0x3711, 0x0024, 0x37d1, 0x4024, 0x4e8a, + 0x0024, 0x0000, 0x0015, 0x2801, 0x5045, 0xce9a, 0x0024, 0x3f11, 0x0024, + 0x3f01, 0x4024, 0x000c, 0x8197, 0x408a, 0x9bc4, 0x3f15, 0x4024, 0x2801, + 0x5285, 0x4284, 0x3c15, 0x6590, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, + 0x4284, 0x0024, 0x0000, 0x0024, 0x2801, 0x3e58, 0x458a, 0x0024, 0x2a39, + 0x53c0, 0x003e, 0x2d4f, 0x283a, 0x5ed5, 0x0001, 0x370e, 0x000c, 0x4653, + 0x0000, 0x0246, 0xffac, 0x0c01, 0x48be, 0x0024, 0x4162, 0x4546, 0x6642, + 0x4055, 0x3501, 0x8024, 0x0000, 0x0087, 0x667c, 0x4057, 0x000c, 0x41d5, + 0x283a, 0x62d5, 0x3501, 0x8024, 0x667c, 0x1c47, 0x3701, 0x8024, 0x283a, + 0x62d5, 0xc67c, 0x0024, 0x0000, 0x0024, 0x283a, 0x62c5, 0x0000, 0x0024, + 0x2a3a, 0x5ec0, 0x3009, 0x3851, 0x3e14, 0xf812, 0x3e12, 0xb817, 0x3e11, + 0x8024, 0x0006, 0x0293, 0x3301, 0x8024, 0x468c, 0x3804, 0x0006, 0xa057, + 0x2801, 0x5f84, 0x0006, 0x0011, 0x469c, 0x0024, 0x3be1, 0x8024, 0x2801, + 0x5f95, 0x0006, 0xc392, 0x3311, 0x0024, 0x33f1, 0x2844, 0x3009, 0x2bc4, + 0x0030, 0x04d2, 0x3311, 0x0024, 0x3a11, 0x0024, 0x3201, 0x8024, 0x003f, + 0xfc04, 0xb64c, 0x0fc4, 0xc648, 0x0024, 0x3a01, 0x0024, 0x3111, 0x1fd3, + 0x6498, 0x07c6, 0x868c, 0x2444, 0x0023, 0xffd2, 0x3901, 0x8e06, 0x0030, + 0x0551, 0x3911, 0x8e06, 0x3961, 0x9c44, 0xf400, 0x44c6, 0xd46c, 0x1bc4, + 0x36f1, 0xbc13, 0x2801, 0x6915, 0x36f2, 0x9817, 0x002b, 0xffd2, 0x3383, + 0x188c, 0x3e01, 0x8c06, 0x0006, 0xa097, 0x3009, 0x1c12, 0x3213, 0x0024, + 0x468c, 0xbc12, 0x002b, 0xffd2, 0xf400, 0x4197, 0x2801, 0x6604, 0x3713, + 0x0024, 0x2801, 0x6645, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x3383, 0x0024, + 0x3009, 0x0c06, 0x468c, 0x4197, 0x0006, 0xa052, 0x2801, 0x6844, 0x3713, + 0x2813, 0x2801, 0x6885, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x36f1, 0x8024, + 0x36f2, 0x9817, 0x36f4, 0xd812, 0x2100, 0x0000, 0x3904, 0x5bd1, 0x2a01, + 0x594e, 0x3e11, 0x7804, 0x0030, 0x0257, 0x3701, 0x0024, 0x0013, 0x4d05, + 0xd45b, 0xe0e1, 0x0007, 0xc795, 0x2801, 0x7095, 0x0fff, 0xff45, 0x3511, + 0x184c, 0x4488, 0xb808, 0x0006, 0x8a97, 0x2801, 0x7045, 0x3009, 0x1c40, + 0x3511, 0x1fc1, 0x0000, 0x0020, 0xac52, 0x1405, 0x6ce2, 0x0024, 0x0000, + 0x0024, 0x2801, 0x7041, 0x68c2, 0x0024, 0x291a, 0x8a40, 0x3e10, 0x0024, + 0x2921, 0xca80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3009, 0x1bc8, 0x36f0, + 0x1801, 0x3601, 0x5804, 0x3e13, 0x780f, 0x3e13, 0xb808, 0x0008, 0x9b0f, + 0x0001, 0x734e, 0x2908, 0x9300, 0x0000, 0x004d, 0x36f3, 0x9808, 0x2000, + 0x0000, 0x36f3, 0x580f, 0x0007, 0x81d7, 0x3711, 0x8024, 0x3711, 0xc024, + 0x3700, 0x0024, 0x0000, 0x2001, 0xb012, 0x0024, 0x0034, 0x0000, 0x2801, + 0x78c5, 0x0000, 0x01c1, 0x3700, 0x0024, 0x0002, 0x0001, 0xb012, 0x0024, + 0x002e, 0xe001, 0x2801, 0x77c5, 0x6512, 0x0024, 0x0034, 0x0000, 0x2801, + 0x78d5, 0x0000, 0x01c1, 0x0030, 0x0117, 0x3f00, 0x0024, 0x0014, 0xc000, + 0x0000, 0x01c1, 0x4fce, 0x0024, 0xffea, 0x0024, 0x48b6, 0x0024, 0x4384, + 0x4097, 0xb886, 0x45c6, 0xfede, 0x0024, 0x4db6, 0x0024, 0x466c, 0x0024, + 0x0006, 0xc610, 0x8dd6, 0x8007, 0x0000, 0x00c6, 0xff6e, 0x0024, 0x48b2, + 0x0024, 0x0034, 0x2406, 0xffee, 0x0024, 0x2914, 0xaa80, 0x40b2, 0x0024, + 0xf1c6, 0x0024, 0xf1d6, 0x0024, 0x0000, 0x0201, 0x8d86, 0x0024, 0x61de, + 0x0024, 0x0006, 0xc612, 0x2801, 0x7f41, 0x0006, 0xc713, 0x4c86, 0x0024, + 0x2912, 0x1180, 0x0006, 0xc351, 0x0006, 0x0210, 0x2912, 0x0d00, 0x3810, + 0x984c, 0xf200, 0x2043, 0x2808, 0xa000, 0x3800, 0x0024, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x7802, 0x3e04, 0x3811, 0x34a3, 0x0024, 0x3470, 0x0024, + 0x2801, 0x88c0, 0x3cf0, 0x0024, 0x0000, 0xfa01, 0x3e10, 0x0024, 0x3410, + 0x0024, 0x3e10, 0x0024, 0x3410, 0x0024, 0x3e10, 0x0024, 0x3430, 0x0024, + 0x2920, 0x0600, 0x3e00, 0x0024, 0x36c3, 0x128c, 0xf400, 0x4510, 0x3420, + 0x0024, 0x6012, 0x4511, 0x3800, 0x4024, 0x0000, 0x7d01, 0x3440, 0x0024, + 0x4012, 0x0024, 0x3900, 0x4024, 0x0000, 0xfa00, 0x34a3, 0x184c, 0x3410, + 0x4024, 0x6014, 0x0024, 0x0000, 0x0024, 0x2801, 0x8451, 0x0000, 0x0024, + 0x3e10, 0x4024, 0x3410, 0x0024, 0x3e10, 0x0024, 0x3410, 0x0024, 0x3e10, + 0x0024, 0x3430, 0x0024, 0x2920, 0x0600, 0x3e00, 0x0024, 0x36c3, 0x104c, + 0x34f0, 0x1811, 0x36f4, 0x0024, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x0000, 0x0081, 0x3e10, 0xb804, 0x3e14, 0x3811, + 0x0006, 0x9f90, 0x3e04, 0xb813, 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, + 0x0000, 0x6104, 0xa001, 0x0000, 0x0940, 0x2801, 0x94c1, 0xb882, 0x0024, + 0x0001, 0x0001, 0x3009, 0x0000, 0x4012, 0x0024, 0x0000, 0x0940, 0xb882, + 0xa001, 0x0000, 0xa992, 0x0007, 0xc051, 0x2914, 0xbec0, 0x0007, 0xc010, + 0x0001, 0x8150, 0x003f, 0xffc0, 0x001f, 0xffc1, 0x3944, 0x0024, 0x0007, + 0xd010, 0x3974, 0x8024, 0x0030, 0x0252, 0x4890, 0x2780, 0x3910, 0x0024, + 0x39d0, 0x4024, 0x3910, 0x0024, 0x2902, 0x0600, 0x39f0, 0x4024, 0x3800, + 0x0024, 0x0011, 0x14c0, 0x3a00, 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0024, 0x2801, 0x9d85, 0x0000, 0x0024, 0x3413, 0x184c, 0x2b50, + 0x4013, 0x3e11, 0x0c8c, 0x0007, 0xc004, 0x3e11, 0x13cc, 0x3e00, 0x0024, + 0x3302, 0x0024, 0x2000, 0x0000, 0x0001, 0x9d48, 0x36d3, 0x0024, 0x36f4, + 0x9813, 0x36f4, 0x1811, 0x36f0, 0x9804, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb813, 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, + 0x3e11, 0x7806, 0x3e11, 0xf80d, 0x3e13, 0xf80e, 0xf400, 0x4455, 0x6804, + 0x1444, 0xf400, 0x4417, 0x2801, 0xb458, 0x4094, 0x1453, 0x0000, 0x0051, + 0x0fff, 0xff01, 0x2401, 0xb402, 0x3700, 0x8024, 0x003f, 0xc007, 0xb274, + 0x0024, 0xc428, 0x3812, 0x0020, 0x07d2, 0x0003, 0xffc7, 0xb47c, 0x0e0c, + 0x0008, 0x0003, 0x4360, 0x0024, 0xa41c, 0x4010, 0xb67c, 0x0002, 0x4360, + 0x2e02, 0x0000, 0x0206, 0xb58a, 0x1c04, 0xae6a, 0x4010, 0xc548, 0x0002, + 0xb47c, 0x2e02, 0x4360, 0x148c, 0xa41c, 0x4010, 0xb67c, 0x0002, 0x4360, + 0x2e02, 0xf400, 0x4010, 0x3711, 0x3813, 0x0000, 0x3fc6, 0xb468, 0x0000, + 0xb78e, 0x1786, 0x0028, 0x07d2, 0x4ffe, 0x0024, 0x4ffe, 0x1490, 0xbd87, + 0xb80d, 0xfe51, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, + 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, + 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, + 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, + 0x380d, 0x505f, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, + 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, + 0x3005, 0x5056, 0x1812, 0x4db6, 0x9813, 0x0fff, 0xff40, 0xad06, 0x0024, + 0x4fde, 0x0024, 0xf1fe, 0x1c02, 0xf1fe, 0x0024, 0xf6fe, 0x3786, 0x3009, + 0x2847, 0x35f3, 0x0024, 0x3df4, 0xc024, 0x3d01, 0x1bcc, 0x36f3, 0xd80e, + 0x36f1, 0xd80d, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x2000, + 0x0000, 0x36f2, 0x9813, 0x3613, 0x0024, 0x3e12, 0xb813, 0x0000, 0x800a, + 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7806, 0x3e11, 0xf80d, 0x3e13, + 0xf80e, 0x3009, 0x3854, 0xf400, 0x4455, 0x6804, 0x1444, 0xf400, 0x4417, + 0x2801, 0xcc18, 0x4094, 0x1453, 0x0fff, 0xff01, 0x0000, 0x0051, 0x2401, + 0xcbc2, 0x3700, 0x8024, 0x0fff, 0xfe07, 0xa274, 0x3812, 0x0000, 0x3fc7, + 0xb274, 0x0024, 0x0020, 0x07d2, 0xc428, 0x0e0c, 0xa41c, 0x0024, 0x0003, + 0xffc7, 0xb67c, 0x0024, 0x0008, 0x0003, 0x4360, 0x0024, 0xf400, 0x4010, + 0xb47c, 0x0002, 0x4360, 0x2e02, 0x3701, 0x0024, 0xa41c, 0x4010, 0x3000, + 0x8024, 0xb67c, 0x2e02, 0x4360, 0x948c, 0xf400, 0x4010, 0xb47c, 0x0002, + 0x4360, 0x2e02, 0xf400, 0x4010, 0x3711, 0x3813, 0x0000, 0x0206, 0xa468, + 0x0000, 0xb78e, 0x1786, 0x0028, 0x07d2, 0x4ffe, 0x0024, 0x4ffe, 0x1490, + 0xbd87, 0xb80d, 0xfe51, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, + 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, + 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x505f, 0x380d, 0x505f, + 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, 0x505f, 0x380d, + 0x505f, 0x380d, 0x505f, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, + 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, 0x5057, 0x380d, + 0x5057, 0x3005, 0x5056, 0x1812, 0x4db6, 0x9813, 0x0fff, 0xff40, 0xad06, + 0x0024, 0x4fde, 0x0024, 0xf1fe, 0x1c02, 0xf1fe, 0x0024, 0xf6fe, 0x3786, + 0x3009, 0x2847, 0x35f3, 0x0024, 0x3df4, 0xdbcc, 0x3d01, 0x1bd4, 0x36f3, + 0xd80e, 0x36f1, 0xd80d, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, + 0x2000, 0x0000, 0x36f2, 0x9813, 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, + 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7806, 0x3e11, 0xf813, + 0x3e13, 0xf80e, 0x3e03, 0x7814, 0xf400, 0x4497, 0x6804, 0x044c, 0x0000, + 0x0024, 0x2801, 0xdb18, 0x4094, 0x0024, 0xf224, 0x0024, 0x2401, 0xdac2, + 0x0000, 0x0055, 0x0028, 0x07d3, 0x3114, 0x8024, 0x31f5, 0x0024, 0x3283, + 0x0040, 0x3a80, 0x0040, 0x3a00, 0x0024, 0xbe8a, 0x2412, 0x0020, 0x07d3, + 0xbd87, 0x2849, 0xfe11, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x501b, 0x2849, 0x501b, 0x2849, + 0x501b, 0x2849, 0x501b, 0x2849, 0x501b, 0x2849, 0x501b, 0x2849, 0x501b, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5016, 0x0024, + 0x4db6, 0x0024, 0x0fff, 0xff40, 0xad06, 0x0024, 0x4eda, 0x0024, 0xf7ea, + 0x0024, 0x3f11, 0x4024, 0x3f18, 0x8024, 0x36f3, 0x5814, 0x36f3, 0xd80e, + 0x36f1, 0xd813, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x2000, + 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, 0xb814, 0x0000, 0x800a, + 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7806, 0x3e11, 0xf813, 0x3e13, + 0xf80e, 0x3e03, 0x4024, 0x6804, 0x044c, 0x0000, 0x0024, 0x2801, 0xf758, + 0x4094, 0x4497, 0xf224, 0x0024, 0x2401, 0xf702, 0x0000, 0x0095, 0x0028, + 0x7fd3, 0xbe8a, 0x0452, 0x31f5, 0x0a0c, 0x3010, 0x0024, 0x3010, 0x4024, + 0x3a80, 0x4024, 0x3a80, 0x0024, 0x3010, 0x0024, 0x3010, 0x4024, 0x3a80, + 0x4024, 0x3a00, 0x3812, 0x0010, 0x41d3, 0xbd87, 0x2849, 0xfe11, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2041, 0x3223, + 0x104c, 0x501b, 0x2041, 0x32e3, 0x13cc, 0x3283, 0x120c, 0x501b, 0x2849, + 0x501b, 0x2849, 0x501b, 0x2849, 0x501b, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, + 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, 0x2849, 0x5017, + 0x2849, 0x5016, 0x9812, 0x4db6, 0x2452, 0x0fff, 0xff40, 0xad06, 0x07d4, + 0x4dee, 0x084c, 0x3f11, 0x8024, 0x3f31, 0xc024, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x36f1, 0xd813, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, + 0x2000, 0x0000, 0x36f2, 0x9814, 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x780d, 0x6840, 0xb80e, + 0x0000, 0x0024, 0x2801, 0xfe18, 0x4490, 0x380f, 0xf200, 0x0024, 0x003f, + 0xc001, 0x2401, 0xfdc0, 0x0000, 0x0200, 0xb386, 0x0445, 0xb51a, 0x0442, + 0xad06, 0x0024, 0xc356, 0x0024, 0x3810, 0xc024, 0x36f3, 0xd80e, 0x36f1, + 0x580d, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x2000, 0x0000, 0x36f2, 0x9815, + 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, + 0xb805, 0x3e13, 0xf80e, 0x3e03, 0x4024, 0x6840, 0x0024, 0x0000, 0x0024, + 0x2802, 0x0498, 0x4490, 0x0024, 0x0000, 0x0201, 0xf200, 0x0024, 0x2402, + 0x0440, 0x0000, 0x3fc2, 0x3110, 0x0024, 0xa010, 0x0445, 0xb52a, 0x0024, + 0xc050, 0x0024, 0x3810, 0x0024, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f0, + 0x9805, 0x36f0, 0x1801, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x3e10, + 0x7810, 0x0003, 0xf410, 0xb882, 0x3811, 0x0002, 0x0611, 0x3009, 0x3812, + 0x0002, 0x0d12, 0x2914, 0xbec0, 0x0000, 0x0700, 0x0003, 0xf410, 0x0000, + 0x4140, 0x3810, 0x0024, 0x0003, 0xf400, 0x3824, 0x4024, 0x0002, 0x70d1, + 0x38f4, 0x9812, 0x3804, 0x4024, 0x36f4, 0x4024, 0x36f0, 0x5810, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x0000, 0x0200, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3655, + 0x0024, 0x0000, 0x800a, 0x3e10, 0xb804, 0x3e11, 0x7810, 0x3e14, 0x504c, + 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x130c, 0x3430, + 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, + 0x0002, 0x1408, 0x0000, 0x0201, 0x6012, 0x9b4c, 0x3413, 0x0024, 0x2802, + 0x1601, 0xf400, 0x4511, 0x34f3, 0x1bcc, 0x2802, 0x1880, 0xbc82, 0x0024, + 0x2900, 0x5b40, 0x3100, 0x93cc, 0xb182, 0x184c, 0x3113, 0x3840, 0x2900, + 0x5b40, 0x3100, 0x8024, 0x4088, 0x9bc0, 0xf400, 0x4105, 0x0000, 0x0004, + 0xcce2, 0x0024, 0x36f4, 0x4024, 0x36f1, 0x5810, 0x36f0, 0x9804, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x0000, 0x0200, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3655, 0x0024, 0x0000, 0x800a, 0x3e11, 0x3805, 0x3e14, 0x3811, + 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, + 0x130c, 0x3430, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, + 0x2000, 0x0000, 0x0002, 0x1f88, 0x0000, 0x0201, 0x6012, 0x9b0c, 0x3443, + 0x0024, 0x2802, 0x2141, 0xf400, 0x4511, 0x2802, 0x2280, 0xbc82, 0x130c, + 0x31f0, 0x130c, 0xb182, 0x0404, 0xf400, 0x4105, 0x0000, 0x0004, 0xcce2, + 0x0024, 0x36f4, 0x1811, 0x36f1, 0x1805, 0x3405, 0x9014, 0x36f3, 0x0024, + 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x0000, 0x0100, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, + 0x0000, 0x800a, 0x3e10, 0xb804, 0x3e11, 0x7810, 0x3e14, 0x504c, 0xb880, + 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x130c, 0x3430, 0x0024, + 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, 0x0002, + 0x2948, 0x0000, 0x0101, 0x6012, 0x9b4c, 0x3413, 0x0024, 0x2802, 0x2b41, + 0xf400, 0x4511, 0x34f3, 0x1bcc, 0x2802, 0x2dc0, 0xbc82, 0x0024, 0x2900, + 0x5b40, 0x3100, 0x93cc, 0xb182, 0x184c, 0x3113, 0x3840, 0x2900, 0x5b40, + 0x3100, 0x8024, 0x4088, 0x9bc0, 0xf400, 0x4105, 0x0000, 0x0004, 0xcce2, + 0x0024, 0x36f4, 0x4024, 0x36f1, 0x5810, 0x36f0, 0x9804, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x0000, + 0x0100, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3635, 0x0024, 0x0000, 0x800a, 0x3e11, 0x3805, 0x3e14, 0x3811, 0x3e10, + 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x130c, + 0x3430, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, + 0x0000, 0x0002, 0x34c8, 0x0000, 0x0101, 0x6012, 0x9b0c, 0x3423, 0x0024, + 0x2802, 0x3681, 0xf400, 0x4511, 0x2802, 0x37c0, 0xbc82, 0x138c, 0x31f0, + 0x138c, 0xb182, 0x0404, 0xf400, 0x4105, 0x0000, 0x0004, 0xcce2, 0x0024, + 0x36f4, 0x1811, 0x36f1, 0x1805, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x0000, 0x0080, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, + 0x800a, 0x3e14, 0x3811, 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, + 0xf400, 0x4500, 0x3e10, 0x130c, 0x3430, 0x0024, 0xf400, 0x4010, 0x3e00, + 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, 0x0002, 0x3e48, 0x0000, 0x0081, + 0x6012, 0x1b0c, 0x0000, 0x0024, 0x2802, 0x4001, 0xb182, 0x104c, 0x2802, + 0x4040, 0xbc82, 0x13cc, 0x34f0, 0x0024, 0x36f4, 0x1811, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3645, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb804, 0x3e11, 0x7806, 0x3e11, 0xf810, 0x3e14, + 0x780d, 0x3e03, 0xf80e, 0x0003, 0xffce, 0xb880, 0x108c, 0x3c10, 0x0024, + 0x3ce0, 0x0024, 0x2402, 0x6e0e, 0x3cf0, 0x0024, 0x0006, 0x18d0, 0xbe8a, + 0x104c, 0x6892, 0x13c0, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, + 0x2802, 0x4885, 0xfe02, 0x0024, 0x2802, 0x48c0, 0x4eba, 0x0024, 0x6eba, + 0x0024, 0x0000, 0x0081, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0024, 0x2802, 0x4b45, 0x4192, 0x0000, 0xfe02, 0x0024, 0x2802, + 0x4bc0, 0x4eba, 0x0024, 0xfe02, 0x0024, 0x6eba, 0x0024, 0x0000, 0x0101, + 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, + 0x0024, 0x2802, 0x4e45, 0xfe02, 0x0024, 0x2802, 0x4e80, 0x4eba, 0x0024, + 0x6eba, 0x0024, 0x0000, 0x0201, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, 0x5105, 0xfe02, 0x0024, + 0x2802, 0x5140, 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0000, 0x0401, 0x3413, + 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, + 0x2802, 0x53c5, 0xfe02, 0x0024, 0x2802, 0x5400, 0x4eba, 0x0024, 0x6eba, + 0x0024, 0x0000, 0x0801, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, 0x5685, 0xfe02, 0x0024, 0x2802, + 0x56c0, 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0000, 0x1001, 0x3413, 0x004c, + 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, + 0x5945, 0xfe02, 0x0024, 0x2802, 0x5980, 0x4eba, 0x0024, 0x6eba, 0x0024, + 0x0000, 0x2001, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, + 0x0041, 0x3000, 0x0024, 0x2802, 0x5c05, 0xfe02, 0x0024, 0x2802, 0x5c40, + 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0000, 0x4001, 0x3413, 0x004c, 0x34f0, + 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, 0x5ec5, + 0xfe02, 0x0024, 0x2802, 0x5f00, 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0000, + 0x8001, 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, + 0x3000, 0x0024, 0x2802, 0x6185, 0xfe02, 0x0024, 0x2802, 0x61c0, 0x4eba, + 0x0024, 0x6eba, 0x0024, 0x0001, 0x0001, 0x3413, 0x004c, 0x34f0, 0x0024, + 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, 0x0024, 0x2802, 0x6445, 0xfe02, + 0x0024, 0x2802, 0x6480, 0x4eba, 0x0024, 0x6eba, 0x0024, 0x0002, 0x0001, + 0x3413, 0x004c, 0x34f0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0041, 0x3000, + 0x0024, 0x2802, 0x6705, 0xfe02, 0x0024, 0x2802, 0x6740, 0x4eba, 0x0024, + 0x6eba, 0x0024, 0xf1ea, 0x104c, 0x4e82, 0x1042, 0x0008, 0x0001, 0x4122, + 0x0024, 0xf400, 0x4055, 0x0000, 0x0041, 0x3d00, 0x0024, 0x3410, 0x0024, + 0xfe02, 0x0024, 0x48b2, 0x0024, 0x6cee, 0x1380, 0x0000, 0x0041, 0x2802, + 0x6bc9, 0xfe02, 0x4511, 0x3413, 0x0024, 0x3c11, 0x0024, 0x34e0, 0x0024, + 0xfe02, 0x4511, 0x48b2, 0x0024, 0x6cee, 0x1080, 0x0000, 0x0024, 0x2802, + 0x6dd8, 0x0000, 0x0024, 0x3ce1, 0x0024, 0xf400, 0x4511, 0x3420, 0x0024, + 0x6090, 0x934c, 0x3900, 0x0024, 0x36f3, 0xd80e, 0x36f4, 0x580d, 0x36f1, + 0xd810, 0x36f1, 0x5806, 0x36f0, 0x9804, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x0000, 0x0657, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3685, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7806, 0x3e11, + 0xf810, 0x3e14, 0x7812, 0x3e04, 0xd34c, 0x2902, 0x41c0, 0x6898, 0x10d2, + 0xf400, 0x4490, 0x34c3, 0x010c, 0x34f0, 0x184c, 0x3800, 0x0024, 0x3460, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0100, 0x2802, 0x7805, 0x0000, 0x0024, + 0x0006, 0x0580, 0x3009, 0x128c, 0x3464, 0x4024, 0x3900, 0x0024, 0x0000, + 0x0100, 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, + 0x3440, 0x0024, 0xf400, 0x4011, 0x3e00, 0x044c, 0x3102, 0x0024, 0x2000, + 0x0000, 0x0002, 0x7a88, 0x0000, 0x0101, 0x6012, 0x9b0c, 0x0012, 0x5101, + 0x2802, 0x7c41, 0x3413, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x13cc, 0xf400, + 0x4510, 0x34f0, 0x004c, 0x6012, 0x0000, 0x003f, 0xc001, 0x2802, 0x9515, + 0xb010, 0x0024, 0x000c, 0xc001, 0x6012, 0x0024, 0x0000, 0x0024, 0x2802, + 0x9515, 0x0000, 0x0024, 0xb880, 0x110c, 0x3cd0, 0x184c, 0x0000, 0x0080, + 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, 0x3440, + 0x0024, 0x3e00, 0x0024, 0x3102, 0x0024, 0x2000, 0x0000, 0x0002, 0x8208, + 0x0000, 0x0100, 0x36d3, 0x104c, 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, + 0x4500, 0x3e10, 0x12cc, 0x3440, 0x0024, 0x3e00, 0x0024, 0x3102, 0x0024, + 0x2000, 0x0000, 0x0002, 0x84c8, 0x001f, 0xc001, 0x0000, 0x1fc2, 0x3123, + 0x108c, 0xf400, 0x4510, 0x34e0, 0x1b0c, 0xb010, 0x0081, 0xf200, 0x0024, + 0xb122, 0x0024, 0x4010, 0x0024, 0x3800, 0x0024, 0x31f0, 0x0024, 0x4080, + 0x0024, 0x3100, 0x0024, 0x2802, 0x8c85, 0x4080, 0x0024, 0x0000, 0x0043, + 0x34c3, 0x184c, 0x6890, 0x844c, 0x3e10, 0x0024, 0x3000, 0x8024, 0xfe26, + 0x0024, 0x48b6, 0x0024, 0x3e10, 0x8024, 0x3e10, 0xc024, 0x3440, 0x0024, + 0x3e00, 0x0024, 0x3102, 0x0024, 0x2000, 0x0000, 0x0002, 0x8c08, 0x2802, + 0x9040, 0x36c3, 0x0024, 0x0000, 0x0024, 0x2802, 0x9045, 0x0000, 0x0024, + 0x0000, 0x0041, 0x3000, 0x184c, 0xfe02, 0x930c, 0x48b2, 0x0024, 0x3e10, + 0x0024, 0x3e10, 0x4024, 0x3440, 0xc024, 0x3e00, 0xc024, 0x3102, 0x0024, + 0x2000, 0x0000, 0x0002, 0x9008, 0x36d3, 0x0024, 0x0000, 0x0100, 0x3613, + 0x104c, 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, + 0x3440, 0x0024, 0xf400, 0x4011, 0x3e00, 0x044c, 0x3102, 0x0024, 0x2000, + 0x0000, 0x0002, 0x9348, 0x0000, 0x0101, 0x6012, 0x1b0c, 0x0000, 0x0024, + 0x2802, 0x9501, 0x0000, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x0024, 0x0011, + 0x9481, 0x3413, 0x0024, 0xf400, 0x4510, 0x34f0, 0x004c, 0x6012, 0x0000, + 0x0013, 0x4e01, 0x2803, 0x1fd5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2803, + 0x1fd5, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3470, 0x8024, 0x2902, 0x1a80, + 0x3e00, 0x8024, 0x3c10, 0x0024, 0x0000, 0x0100, 0x3cd0, 0x4024, 0xb880, + 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x13cc, 0x3e00, 0x8024, + 0x3102, 0x0024, 0x2000, 0x0000, 0x0002, 0x9b88, 0x0000, 0x0101, 0x6012, + 0x9b0c, 0x0011, 0x14c1, 0x2802, 0x9d41, 0x3413, 0x0024, 0x2803, 0xd9c0, + 0x4480, 0x13cc, 0xf400, 0x4510, 0x34f0, 0x004c, 0x6012, 0x0000, 0x0011, + 0x0801, 0x2803, 0x1fd5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2803, 0x1fd5, + 0x0000, 0x0024, 0xb880, 0x11cc, 0xb882, 0x3040, 0x002b, 0x1100, 0xb888, + 0x3040, 0x3c90, 0x4024, 0x3493, 0x0024, 0x3450, 0x0024, 0x4080, 0x0024, + 0x0006, 0x0a40, 0x2803, 0x1b45, 0x0000, 0x0024, 0x34b3, 0x0024, 0x3454, + 0x0024, 0x2803, 0x1b40, 0x3800, 0x0024, 0xb880, 0x3840, 0x3e10, 0x0024, + 0xf400, 0x4500, 0x3e10, 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, + 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, 0x0002, 0xa5c8, 0x0000, 0x0101, + 0x6012, 0x130c, 0x3440, 0x9b4c, 0x2802, 0xa781, 0xf400, 0x4100, 0x2803, + 0xd9c0, 0x3009, 0x1bcc, 0x2902, 0x1a80, 0x3e00, 0x8024, 0x36f3, 0x114c, + 0x3c10, 0x0024, 0x3cb0, 0x4024, 0xf400, 0x4511, 0x0014, 0x1481, 0x34f0, + 0x0024, 0x6012, 0x0024, 0x0013, 0xd401, 0x2803, 0x1715, 0x0000, 0x0024, + 0x3113, 0x0024, 0x3100, 0x0024, 0x6012, 0x0024, 0x0000, 0x0024, 0x2803, + 0x1715, 0x0000, 0x0024, 0x3613, 0x0024, 0x2902, 0x2440, 0x3e00, 0x8024, + 0x36f3, 0x11cc, 0x3433, 0x0024, 0x3c10, 0x0024, 0x3c90, 0x4024, 0x2803, + 0x1000, 0x34c3, 0x0024, 0xb880, 0x3840, 0x3e10, 0x0024, 0xf400, 0x4500, + 0x3e10, 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0002, 0xb0c8, 0x0000, 0x0101, 0x6012, 0x130c, + 0x3440, 0x9b4c, 0x2802, 0xb281, 0xf400, 0x4100, 0x2803, 0xd9c0, 0x3009, + 0x1bcc, 0x2902, 0x1a80, 0x3e00, 0x8024, 0x36f3, 0x11cc, 0x3453, 0x0024, + 0x3c10, 0x0024, 0x0000, 0x0300, 0xb882, 0x33c1, 0x3411, 0x8024, 0x3491, + 0xc024, 0x6cf2, 0x13cc, 0xf400, 0x4511, 0x3110, 0x92cc, 0x31f0, 0xc024, + 0x6dc2, 0x0024, 0x3910, 0x0024, 0x39b0, 0x4024, 0x0011, 0x94c1, 0x3110, + 0x0024, 0x6012, 0x0400, 0x0008, 0x0801, 0x2802, 0xbd95, 0x6012, 0x0024, + 0x0000, 0x0024, 0x2802, 0xbd95, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3440, + 0x8024, 0x2902, 0x2fc0, 0x3e00, 0x8024, 0x0000, 0x0102, 0x36f3, 0x11cc, + 0xb886, 0x104c, 0x3c10, 0x0024, 0x3c90, 0x4024, 0x34e3, 0x0024, 0xf400, + 0x4511, 0x3173, 0x0024, 0x3153, 0x0024, 0x3110, 0x0024, 0x31f0, 0x4024, + 0x6cd6, 0x0024, 0x3910, 0x8024, 0x2803, 0x0b80, 0x39f0, 0xc024, 0x0010, + 0xd201, 0x3413, 0x0024, 0xf400, 0x4511, 0x34f0, 0x044c, 0x6012, 0x0400, + 0x0013, 0x9301, 0x2802, 0xc455, 0x6012, 0x0024, 0x0000, 0x0024, 0x2802, + 0xc455, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3440, 0x8024, 0x2902, 0x3980, + 0x3e00, 0x8024, 0x36f3, 0x11cc, 0xb882, 0x3240, 0xf400, 0x4511, 0x0000, + 0x0080, 0x3173, 0x0024, 0x3153, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, + 0x6dc2, 0x0024, 0x3910, 0x0024, 0x2803, 0x0b80, 0x39f0, 0x4024, 0x0011, + 0x14c1, 0x3413, 0x0024, 0xf400, 0x4511, 0x34f0, 0x0024, 0x6012, 0x0024, + 0x0011, 0x0801, 0x2803, 0x0b95, 0x0000, 0x0024, 0x3113, 0x0024, 0x3100, + 0x0024, 0x6012, 0x0024, 0x0000, 0x0024, 0x2803, 0x0b95, 0x0000, 0x0024, + 0x003f, 0xfe82, 0x0000, 0x04d1, 0x3473, 0x020c, 0x3413, 0x04cc, 0x3410, + 0x0024, 0x34e0, 0x4024, 0xac22, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, + 0x0000, 0x0081, 0x3490, 0x0024, 0x34c3, 0x0024, 0x3474, 0x0024, 0x3083, + 0x110c, 0x3800, 0x0024, 0x3490, 0x0024, 0x6012, 0x130c, 0x3444, 0x0024, + 0x2802, 0xcf85, 0x3043, 0x0024, 0x34b3, 0x0024, 0x3450, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0184, 0x2802, 0xcf05, 0x0006, 0x0b00, 0x34b3, 0x0024, + 0x3454, 0x0024, 0x3800, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x0024, 0x30f0, + 0x0024, 0x4080, 0x0024, 0x3000, 0x0024, 0x2803, 0x01c5, 0x4080, 0x0024, + 0x0000, 0x0024, 0x2803, 0x01c5, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3440, + 0x8024, 0xf400, 0x4090, 0x3e00, 0x810c, 0x3002, 0x0024, 0x2000, 0x0000, + 0x0002, 0xd348, 0xf400, 0x4491, 0x0000, 0x0610, 0x3473, 0x060c, 0x3910, + 0x114c, 0x3910, 0x5bcc, 0x3410, 0x0024, 0x3490, 0x4024, 0x3910, 0x128c, + 0x2803, 0x01c0, 0x39f0, 0x4024, 0x3053, 0x0024, 0x3090, 0x0024, 0x6012, + 0x038c, 0x3000, 0x0024, 0x2802, 0xecc5, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2802, 0xecc5, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3444, 0x0024, 0x3073, + 0x0024, 0x3053, 0x0024, 0x3070, 0x0024, 0x4080, 0x00cc, 0x0000, 0x0024, + 0x2802, 0xe095, 0x0000, 0x0024, 0x0000, 0x0610, 0xb880, 0x4491, 0x3e10, + 0x060c, 0x3110, 0x930c, 0x31f0, 0xc024, 0x3e10, 0x8024, 0x3e10, 0xc024, + 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x00cc, 0x3002, 0x0024, 0x2000, + 0x0000, 0x0002, 0xdd88, 0x3473, 0x048c, 0x3110, 0x114c, 0x31f0, 0x41cc, + 0x0000, 0x0411, 0x3c10, 0x010c, 0x3c90, 0x5b0c, 0xbc82, 0x124c, 0x3810, + 0x134c, 0x38f0, 0x4024, 0x3444, 0x0024, 0x2802, 0xeb00, 0x3083, 0x0024, + 0xb78e, 0x4511, 0x3090, 0x3804, 0x30d3, 0x130c, 0x3021, 0x8024, 0x3010, + 0x8024, 0x3050, 0xc024, 0x6fde, 0x0042, 0xfeae, 0x03c3, 0x0000, 0x03d0, + 0x3e00, 0xc60c, 0x48ba, 0x0024, 0xffe6, 0x0024, 0x5daa, 0x0024, 0x0000, + 0x00c2, 0x44be, 0x9804, 0xaf2e, 0x0024, 0xfff0, 0x4007, 0x48b2, 0x0024, + 0xffee, 0x0024, 0x40b2, 0x0024, 0x6890, 0x2440, 0x39f0, 0x4024, 0x3e10, + 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x3e10, 0x8024, 0x3e10, 0xc024, + 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x00cc, 0x3002, 0x0024, 0x2000, + 0x0000, 0x0002, 0xe8c8, 0xf400, 0x4513, 0x3073, 0x0dcc, 0x3353, 0x008c, + 0x3310, 0x1b0c, 0x33f0, 0x4024, 0x6cd6, 0x0024, 0xb182, 0x2c42, 0x3bf0, + 0xc024, 0x3020, 0x0024, 0x3810, 0x130c, 0x003f, 0xffc0, 0x38f0, 0x4024, + 0x3444, 0x0024, 0x3073, 0x0024, 0x3053, 0x0024, 0x3800, 0x0024, 0x0004, + 0x0000, 0x3613, 0x130c, 0xb880, 0x3840, 0x3e10, 0x0024, 0x000d, 0x0000, + 0x3e10, 0x0024, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0002, 0xefc8, 0x0004, 0x0001, 0x6012, 0x1b0c, + 0x0004, 0x0000, 0x2803, 0x0b91, 0x0004, 0x0010, 0xb882, 0x4511, 0x3173, + 0x184c, 0x3153, 0x3804, 0x3110, 0x8024, 0x31f0, 0xc024, 0x6dc2, 0x0024, + 0x3910, 0x0024, 0x39f0, 0x4024, 0x000d, 0x0011, 0x2901, 0xf940, 0x0002, + 0x0004, 0x0005, 0x0010, 0x000d, 0x0011, 0x0000, 0x4001, 0x2901, 0xff80, + 0x0002, 0x0004, 0x0004, 0x0010, 0x0001, 0x0000, 0x0006, 0x8091, 0x3009, + 0x1804, 0x3009, 0x3812, 0x2901, 0xb6c0, 0x0008, 0x0012, 0x0001, 0x0000, + 0x0006, 0x8311, 0x0008, 0x0010, 0x2901, 0xce80, 0x000d, 0x0012, 0x0000, + 0x8000, 0x000d, 0x0010, 0x0006, 0x8591, 0x2901, 0xdd00, 0x0002, 0x0012, + 0x0005, 0x0010, 0x0001, 0x0000, 0x0006, 0x81d1, 0x2901, 0xb6c0, 0x0008, + 0x0012, 0x0001, 0x0000, 0x0006, 0x8451, 0x0008, 0x0010, 0x2901, 0xce80, + 0x000d, 0x0012, 0x0000, 0x8000, 0x000d, 0x0010, 0x0006, 0x86d1, 0x2901, + 0xdd00, 0x0002, 0x0092, 0x0006, 0x8010, 0x3000, 0x9812, 0x6122, 0x930c, + 0x6810, 0x0024, 0x3e10, 0x0024, 0x0002, 0x0000, 0x4020, 0x0024, 0x4020, + 0x0024, 0x4020, 0x0024, 0x4020, 0x0024, 0x3e10, 0x0024, 0x3440, 0x0024, + 0xf400, 0x4011, 0x3e00, 0x054c, 0x3102, 0x0024, 0x2000, 0x0000, 0x0003, + 0x0148, 0xb880, 0x9b4c, 0x3800, 0x0024, 0x0004, 0x0000, 0xb882, 0x11cc, + 0x3453, 0x0024, 0x3410, 0x8024, 0x3490, 0xc024, 0x6dc2, 0x128c, 0x0000, + 0x0024, 0x2803, 0x0b88, 0x0000, 0x0024, 0x34c3, 0x0024, 0x3404, 0x0024, + 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, 0x1110, 0x003f, + 0xffc1, 0x2802, 0xd5c5, 0x3073, 0x0024, 0x2803, 0x0b80, 0x0000, 0x0024, + 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, + 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, + 0x2000, 0x0000, 0x0003, 0x0988, 0xf400, 0x4511, 0x36c3, 0x05cc, 0x3153, + 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x4d96, 0x0024, 0x3910, 0x8024, + 0x39f0, 0xc024, 0x3473, 0x0024, 0x3453, 0x0024, 0x3410, 0x0024, 0x3490, + 0x4024, 0x4c82, 0x128c, 0x0000, 0x0024, 0x2803, 0x1009, 0x0000, 0x0024, + 0x34c3, 0x184c, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0040, 0x2803, 0x06c5, 0x0000, 0x0024, + 0x36f3, 0x0024, 0x0000, 0x0300, 0xb882, 0x114c, 0x3410, 0x984c, 0x34b0, + 0xc024, 0x6dc2, 0x0024, 0x0000, 0x0100, 0x2802, 0xae58, 0x0000, 0x0024, + 0x2803, 0x1700, 0x36f3, 0x13cc, 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, + 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, + 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, 0x0000, 0x0003, 0x1548, 0x36c3, + 0x114c, 0xf400, 0x4511, 0x3110, 0x92cc, 0x31f0, 0xc024, 0x4d96, 0x0024, + 0x3910, 0x8024, 0x39f0, 0xc024, 0x3453, 0x0024, 0x3410, 0x0024, 0x34a0, + 0x4024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2803, 0x1b45, 0x0000, 0x0024, + 0x34c3, 0x184c, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0040, 0x2803, 0x1285, 0x0000, 0x0024, + 0x36f3, 0x0024, 0x3433, 0x0024, 0x3410, 0x8024, 0x3490, 0xc024, 0x4d86, + 0x13cc, 0x0000, 0x0024, 0x2803, 0x1f45, 0x0000, 0x0024, 0x3454, 0x184c, + 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0100, 0x2802, 0xa345, 0x0000, 0x0024, 0x36f3, 0x12cc, 0x2803, 0xd9c0, + 0x4480, 0x110c, 0x0011, 0x14c1, 0x3413, 0x0024, 0xf400, 0x4510, 0x34f0, + 0x004c, 0x6012, 0x0000, 0x0011, 0x0801, 0x2803, 0xd3d5, 0x6012, 0x0024, + 0x0000, 0x0024, 0x2803, 0xd3d5, 0x0000, 0x0024, 0xb888, 0x12cc, 0x3410, + 0x184c, 0x4080, 0x13c2, 0x0006, 0x0a40, 0x2803, 0x2485, 0x3414, 0x0024, + 0x3800, 0x0024, 0x3400, 0x8024, 0x2902, 0x0f00, 0x3e00, 0x91cc, 0x3c10, + 0x0024, 0x3cc0, 0x4024, 0x2902, 0x0f00, 0x3e00, 0x8024, 0x2902, 0x0f00, + 0x3e00, 0x8024, 0x0000, 0x0702, 0x36f3, 0x10cc, 0xb886, 0x4510, 0x3010, + 0x134c, 0x30f0, 0x494c, 0x6cd6, 0x0024, 0x3810, 0x8024, 0x38f0, 0xc024, + 0x0019, 0x9b41, 0x32b3, 0x104c, 0xf400, 0x4510, 0x34f0, 0x004c, 0x6012, + 0x0000, 0x001d, 0x0801, 0x2803, 0x42d5, 0x6012, 0x0024, 0x0000, 0x0024, + 0x2803, 0x42d5, 0x0000, 0x0024, 0x0000, 0x0511, 0x34c3, 0x184c, 0x3470, + 0x8024, 0x2902, 0x0f00, 0x3e00, 0x8024, 0x3c10, 0x0024, 0x3cc0, 0x4024, + 0x2902, 0x2440, 0x3e00, 0x8024, 0x2902, 0x2440, 0x3e00, 0x91cc, 0x3c10, + 0x0024, 0x3c10, 0x4024, 0x2902, 0x2440, 0x3e00, 0x8024, 0x3c10, 0x0024, + 0x3c10, 0x4024, 0x2902, 0x2440, 0x3e00, 0x8024, 0x3c10, 0x0024, 0x3c90, + 0x4024, 0x2902, 0x2440, 0x3e00, 0x92cc, 0x003f, 0xfe82, 0x3009, 0x11cc, + 0x3463, 0x0024, 0x3c10, 0x0024, 0x3cf0, 0x4024, 0x3410, 0x0024, 0x3490, + 0x4024, 0x3493, 0x0024, 0xac22, 0x130c, 0x3474, 0x0024, 0x3083, 0x11cc, + 0x3810, 0x104c, 0x38f0, 0x448c, 0x3490, 0x0024, 0x3493, 0x0024, 0x34f3, + 0x0024, 0x3404, 0x0024, 0x3083, 0x0024, 0x3800, 0x0024, 0x3440, 0x8024, + 0x2902, 0x2440, 0x3e00, 0x8024, 0xf400, 0x4510, 0x0000, 0x03d1, 0x3009, + 0x020c, 0x3810, 0x0024, 0x3830, 0x4024, 0x2902, 0x0f00, 0x3e00, 0x8024, + 0x3810, 0x0024, 0x38f0, 0x4024, 0x2902, 0x2440, 0x3e00, 0x8024, 0x36f3, + 0x038c, 0x3810, 0x0024, 0x38d0, 0x4024, 0x3010, 0x0024, 0x30b0, 0x4024, + 0x4c92, 0x0024, 0x0000, 0x0080, 0x2803, 0x3c85, 0xb882, 0x0024, 0x6890, + 0x4491, 0xb882, 0x054c, 0x3900, 0x0024, 0x0000, 0x0080, 0x3010, 0x90cc, + 0x30f0, 0xc024, 0x6dc2, 0x0024, 0x0000, 0x0c00, 0x2803, 0x4105, 0xb882, + 0x0024, 0x3493, 0x0024, 0x34f3, 0x0024, 0x3450, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0184, 0x2803, 0x4085, 0x0006, 0x0b00, 0x34b3, 0x0024, 0x3454, + 0x4024, 0x3900, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x0024, 0xf400, 0x4511, + 0x3110, 0x934c, 0x31f0, 0xc024, 0x6dc2, 0x0024, 0x3910, 0x0024, 0x2803, + 0xc740, 0x39f0, 0x4024, 0x0019, 0x1841, 0x3413, 0x0024, 0xf400, 0x4510, + 0x34f0, 0x004c, 0x6012, 0x0000, 0x001d, 0x1841, 0x2803, 0xc755, 0x6012, + 0x0024, 0x0000, 0x0024, 0x2803, 0xc755, 0x0000, 0x0024, 0x34c3, 0x184c, + 0x3440, 0x8024, 0x2902, 0x0f00, 0x3e00, 0x8024, 0x0000, 0x0302, 0x36f3, + 0x10cc, 0xb886, 0x3040, 0x3cf0, 0x4024, 0xf400, 0x4510, 0x3010, 0x134c, + 0x30f0, 0x4024, 0x6cd6, 0x0024, 0x3810, 0x8024, 0x3890, 0xc024, 0x30f3, + 0x0024, 0x3004, 0x4024, 0x3143, 0x0024, 0x3100, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0024, 0x2803, 0xbbc5, 0x0000, 0x0024, 0x31f3, 0x0024, 0x3100, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0xbbc5, 0x0000, 0x0024, + 0x3000, 0x984c, 0xf400, 0x4091, 0x3e00, 0x850c, 0x3102, 0x0024, 0x2000, + 0x0000, 0x0003, 0x4e08, 0xf400, 0x4493, 0x3073, 0x3812, 0x0000, 0x0612, + 0x3383, 0x1bd2, 0x3b10, 0x0024, 0x3b10, 0x4024, 0x3010, 0x0024, 0x30f0, + 0x4024, 0x3b10, 0x0024, 0x2803, 0xbbc0, 0x3bf0, 0x4024, 0x3483, 0x0024, + 0x1fff, 0xfb95, 0x3410, 0x0024, 0x3480, 0x4024, 0xf1c2, 0x4510, 0x003f, + 0xffc1, 0x3083, 0x130c, 0x3800, 0x0024, 0x3444, 0x4024, 0x3173, 0x0024, + 0x3153, 0x0024, 0x3190, 0x0024, 0x6012, 0x078c, 0x3100, 0x0024, 0x2803, + 0x8d05, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0x8d05, 0x0000, 0x0024, + 0x34c3, 0x0024, 0x3444, 0x4024, 0x3173, 0x0024, 0x3153, 0x0024, 0x3100, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0x6095, 0x0000, 0x0024, + 0xb880, 0x4493, 0x3613, 0x130c, 0x3e20, 0x0024, 0x3009, 0x3812, 0x0000, + 0x0612, 0x3383, 0x1bd2, 0x3310, 0x8024, 0x33f0, 0xc024, 0x3e10, 0x8024, + 0x3e10, 0xc024, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x00cc, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0003, 0x5bc8, 0xf400, 0x4490, 0x0000, 0x0691, + 0x3433, 0x020c, 0x3010, 0x1b0c, 0x30f0, 0x4024, 0x0000, 0x0410, 0x3c10, + 0x0024, 0xbc82, 0x3241, 0x34f3, 0x0024, 0x3404, 0x4024, 0x3183, 0x0024, + 0x3910, 0x0024, 0x39f0, 0x4024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3073, + 0x0024, 0x3810, 0x0024, 0x2803, 0x8b80, 0x38f0, 0x4024, 0xb182, 0x048c, + 0x3111, 0x804c, 0x3151, 0xd84c, 0x6cf2, 0x0442, 0x3110, 0xd30c, 0xfea2, + 0x0024, 0x48be, 0x0024, 0xff86, 0x0024, 0x51ae, 0x0024, 0x003f, 0xfdc2, + 0x46b2, 0x0024, 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0302, 0xac22, + 0x0024, 0x6890, 0x2040, 0x38f0, 0x4024, 0x3e10, 0x0024, 0x3100, 0x8024, + 0x3011, 0x8024, 0x30f1, 0xc024, 0xff74, 0x4087, 0x48b6, 0x0024, 0xffee, + 0x0024, 0x42b6, 0x0024, 0x3e10, 0x8024, 0x3e10, 0xc024, 0x3440, 0x0024, + 0xf400, 0x4013, 0x3e00, 0x0ccc, 0x3302, 0x0024, 0x2000, 0x0000, 0x0003, + 0x68c8, 0x0000, 0x05d5, 0x3100, 0x10cc, 0x0000, 0x05d1, 0x3011, 0x9b0c, + 0x30f1, 0xc024, 0xff70, 0x4007, 0x48b2, 0x4510, 0xffee, 0x934c, 0x40b2, + 0x0042, 0x30f0, 0xd20c, 0x1fff, 0xfa15, 0x4dc2, 0x0024, 0x003f, 0xff42, + 0x3810, 0x0024, 0x38f0, 0x4024, 0x3410, 0x0024, 0x3480, 0x4024, 0xac22, + 0x4510, 0x3083, 0x130c, 0x3810, 0x0024, 0x4c82, 0x23c1, 0x0000, 0x0510, + 0x2803, 0x7658, 0x4c86, 0x1111, 0x68c6, 0x060c, 0x3110, 0x0024, 0x2914, + 0xa580, 0x31f0, 0x4024, 0x0000, 0x0411, 0x0000, 0x05d5, 0x4d82, 0x130c, + 0x3444, 0x0024, 0x3083, 0x120c, 0x1fff, 0xfa15, 0x3010, 0x850c, 0x30f0, + 0xc024, 0x6dc2, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x3411, 0x8024, + 0x3481, 0xc024, 0x68f6, 0x130c, 0x3404, 0x0024, 0x3083, 0x0024, 0x3010, + 0x0024, 0x2914, 0xa580, 0x30f0, 0x4024, 0x3444, 0x0024, 0x3073, 0x0024, + 0x3073, 0x0024, 0x3010, 0x8024, 0x30f0, 0xc024, 0x2803, 0x7d80, 0x6dc2, + 0x0024, 0x3183, 0x0024, 0x3110, 0x0024, 0x2914, 0xa580, 0x31f0, 0x4024, + 0x0000, 0x0411, 0x0000, 0x05d5, 0x4d82, 0x130c, 0x3444, 0x0024, 0x3083, + 0x120c, 0x1fff, 0xfa15, 0x3010, 0x850c, 0x30f0, 0xc024, 0x4dc2, 0x0024, + 0x3810, 0x0024, 0x38f0, 0x4024, 0x3410, 0x8024, 0x3480, 0xc024, 0x34c3, + 0x0024, 0x3404, 0x0024, 0x3083, 0x0024, 0x3010, 0x0024, 0x2914, 0xa580, + 0x30f0, 0x4024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3073, 0x0024, 0x3010, + 0x8024, 0x30f0, 0xc024, 0x4dc2, 0x0024, 0x0000, 0x0411, 0x3810, 0x130c, + 0x38f0, 0x4024, 0x3404, 0x0024, 0x3083, 0x0024, 0x3010, 0x0024, 0x30f0, + 0x4024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2803, 0x8518, 0x0000, 0x0024, + 0x3404, 0x410c, 0x3010, 0x0024, 0x30f0, 0x4024, 0x0000, 0x0410, 0x3183, + 0x0024, 0x3111, 0x8024, 0x31f1, 0xc024, 0x4fc2, 0x0024, 0x3910, 0x0024, + 0x39f0, 0x4024, 0x0000, 0x0411, 0x3404, 0x0024, 0x3073, 0x0024, 0x3073, + 0x0024, 0x3010, 0x8024, 0x30f0, 0xc024, 0x4d96, 0x0024, 0x3810, 0x8024, + 0x38f0, 0xc024, 0x3444, 0x0024, 0x3083, 0x0024, 0x3010, 0x0024, 0x3030, + 0x4024, 0x3010, 0x8024, 0x30f0, 0xc024, 0x6cde, 0x0024, 0x0000, 0x0410, + 0x2803, 0x8b91, 0x0000, 0x0024, 0x34c3, 0x0024, 0x3404, 0x4024, 0x3183, + 0x0024, 0x3111, 0x8024, 0x31f1, 0xc024, 0x6fd6, 0x0024, 0x3910, 0x8024, + 0x39f0, 0xc024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3073, 0x0024, 0x3010, + 0x0024, 0x30f0, 0x4024, 0x6c92, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, + 0x003f, 0xffc0, 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3053, + 0x0024, 0x3800, 0x0024, 0x0000, 0x0551, 0xb880, 0x4510, 0x2803, 0xb040, + 0x3083, 0x0024, 0x0000, 0x0455, 0x3483, 0x184c, 0x1fff, 0xfb95, 0xb880, + 0x1046, 0x3481, 0xc024, 0x3e11, 0x930c, 0x3e10, 0x0024, 0x0004, 0x0000, + 0x3e10, 0x0024, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0003, 0x91c8, 0xb182, 0x1b0c, 0x6cf6, 0x0024, + 0x0000, 0x0555, 0x2803, 0xc208, 0x0000, 0x0024, 0x3433, 0x0024, 0xf400, + 0x4511, 0x3110, 0x934c, 0x31f0, 0xd20c, 0x1fff, 0xfad5, 0x6dfe, 0x0024, + 0x3911, 0x8024, 0x39f1, 0xc024, 0x3480, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0455, 0x2803, 0xa115, 0x0000, 0x0024, 0x3483, 0x184c, 0x1fff, 0xfb95, + 0x3410, 0x3804, 0x3480, 0x4024, 0x3473, 0x0024, 0x3443, 0x0024, 0x3410, + 0x8024, 0xfea2, 0x1243, 0x48ba, 0x3803, 0xfe86, 0x92cc, 0x51aa, 0x0024, + 0x44b2, 0x9bc4, 0x6fc6, 0x0024, 0x0000, 0x0595, 0x2803, 0xa118, 0x0000, + 0x0024, 0x3483, 0x0024, 0x1fff, 0xfa95, 0x3480, 0x0024, 0x4080, 0x0024, + 0x0005, 0xffd1, 0x2803, 0xa105, 0x3100, 0x0024, 0x4080, 0x4510, 0x0000, + 0x0595, 0x2803, 0xa115, 0x0000, 0x0024, 0x3613, 0x120c, 0x1fff, 0xfa95, + 0x3009, 0x3811, 0x0000, 0x0591, 0x3083, 0x1bd1, 0x3000, 0x07cc, 0x4090, + 0x0024, 0x3800, 0x0024, 0x3480, 0x0024, 0x4080, 0x4510, 0x3100, 0x0024, + 0x2803, 0xa105, 0x4080, 0x0024, 0x0000, 0x0595, 0x2803, 0x9d05, 0x0000, + 0x0024, 0x0000, 0x0455, 0x0000, 0x0142, 0x0004, 0x0010, 0x3613, 0x120c, + 0x1fff, 0xfb95, 0x3410, 0x3812, 0x0008, 0x0012, 0x3480, 0x4024, 0x0000, + 0x0555, 0xf1c2, 0x120c, 0x1fff, 0xfad5, 0x0006, 0x8081, 0x3480, 0xc024, + 0xff34, 0x0024, 0x48b6, 0x0024, 0x4122, 0x0024, 0x0000, 0x0142, 0x2901, + 0x9fc0, 0xf400, 0x4051, 0x000d, 0x0012, 0x0008, 0x0010, 0x0000, 0x0455, + 0x3483, 0x0024, 0x1fff, 0xfb95, 0x3410, 0x0024, 0x3480, 0x4024, 0x0000, + 0x0555, 0xf1c2, 0x120c, 0x1fff, 0xfad5, 0x0006, 0x8301, 0x3480, 0xc024, + 0xff34, 0x0024, 0x48b6, 0x0024, 0x4122, 0x0024, 0x2901, 0xce80, 0xf400, + 0x4051, 0x000d, 0x0010, 0x0000, 0x0143, 0x0000, 0x0455, 0x3483, 0x0024, + 0x1fff, 0xfb95, 0x3410, 0x0024, 0x3480, 0x4024, 0x0000, 0x0555, 0xf1c2, + 0x120c, 0x1fff, 0xfad5, 0xf1c2, 0x1202, 0x0002, 0x0001, 0x4122, 0x0024, + 0x4122, 0x0024, 0xff26, 0x4052, 0x0006, 0x8581, 0x48b6, 0x0024, 0x4122, + 0x0024, 0x2901, 0xdd00, 0xf400, 0x4051, 0xf400, 0x4510, 0x0000, 0x0551, + 0x3083, 0x1bd2, 0x3000, 0x0024, 0x6090, 0x0024, 0x0000, 0x0555, 0x0000, + 0x0041, 0x3800, 0x120c, 0x1fff, 0xfad5, 0x3480, 0x0024, 0xfe02, 0x11cc, + 0x48b2, 0x110c, 0x3411, 0x8024, 0x3491, 0xc024, 0x6cf6, 0x12cc, 0x0006, + 0x8050, 0x2803, 0x8e08, 0x0000, 0x0024, 0x0000, 0x8001, 0x3000, 0x984c, + 0x6122, 0x930c, 0x6810, 0x0024, 0x3e10, 0x0024, 0x0002, 0x0000, 0x4020, + 0x0024, 0x4020, 0x0024, 0x4020, 0x0024, 0x4020, 0x0024, 0x3e10, 0x0024, + 0x3440, 0x0024, 0xf400, 0x4011, 0x3e00, 0x054c, 0x3102, 0x0024, 0x2000, + 0x0000, 0x0003, 0xb7c8, 0x0000, 0x0455, 0x0000, 0x00c2, 0xb880, 0x920c, + 0x1fff, 0xfb95, 0x3800, 0x1b4c, 0x3410, 0x0024, 0x3480, 0x4024, 0xac22, + 0x4513, 0x3373, 0x0024, 0x3373, 0x0024, 0x3353, 0x0024, 0x3310, 0x8024, + 0x33f0, 0xc024, 0x6dc2, 0x0024, 0x3b10, 0x0024, 0x3bf0, 0x4024, 0x0000, + 0x04d5, 0x3483, 0x0024, 0x1fff, 0xfb15, 0x3410, 0x0024, 0x3480, 0x4024, + 0x4c82, 0x0024, 0x0000, 0x0024, 0x2803, 0xc209, 0x0000, 0x0024, 0x3433, + 0x0024, 0x3410, 0x0024, 0x34c0, 0x4024, 0x4c82, 0x0024, 0x0000, 0x0024, + 0x2803, 0xc209, 0x0000, 0x0024, 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, + 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, 0x0591, + 0x2803, 0x50c5, 0x0000, 0x0455, 0x2803, 0xd9c0, 0xb880, 0x0024, 0x6890, + 0x184c, 0x3e10, 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, + 0x3e10, 0x12cc, 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, + 0x0024, 0x2000, 0x0000, 0x0003, 0xc588, 0x36c3, 0x10cc, 0xf400, 0x4511, + 0x3110, 0x934c, 0x31f0, 0xc024, 0x4d96, 0x0024, 0x3910, 0x8024, 0x39f0, + 0xc024, 0x3433, 0x184c, 0x3410, 0x0024, 0x34c0, 0x4024, 0x4c82, 0x0024, + 0x0000, 0x0040, 0x2803, 0xc2d5, 0x0000, 0x0024, 0x0000, 0x0100, 0x3e10, + 0x104c, 0xb880, 0x0024, 0x3e10, 0x0024, 0xf400, 0x4500, 0x3e10, 0x12cc, + 0x3440, 0x0024, 0xf400, 0x4010, 0x3e00, 0x004c, 0x3002, 0x0024, 0x2000, + 0x0000, 0x0003, 0xcc08, 0x0000, 0x0101, 0x6012, 0x094c, 0x3200, 0x1b0c, + 0x2803, 0xcdc1, 0x3073, 0x0024, 0x2803, 0xd9c0, 0x4480, 0x0024, 0x4080, + 0x014c, 0x3070, 0x0024, 0x2803, 0xcfd5, 0x0000, 0x0024, 0x4080, 0x01cc, + 0x0000, 0x0024, 0x2803, 0x2885, 0x3053, 0x0024, 0x32b0, 0x024c, 0x3009, + 0x024c, 0x4080, 0x02cc, 0x0000, 0x0024, 0x2803, 0xd605, 0x0000, 0x0024, + 0x34b3, 0x0024, 0x3450, 0x0024, 0x4080, 0x0024, 0x0000, 0x0184, 0x2803, + 0xd605, 0x0006, 0x0ec0, 0x34b3, 0x0024, 0x3454, 0x0024, 0x2803, 0xd600, + 0x3800, 0x0024, 0x6898, 0x12cc, 0x3450, 0x0024, 0x4080, 0x0024, 0x0006, + 0x1440, 0x2803, 0xd605, 0x0000, 0x0024, 0x34b3, 0x0024, 0x3454, 0x0024, + 0x3800, 0x0024, 0x34c3, 0x0024, 0x3404, 0x0024, 0x3073, 0x0024, 0x3063, + 0x0024, 0x3000, 0x0024, 0x4080, 0x1110, 0x0000, 0x0000, 0x2803, 0xd945, + 0x3073, 0x0024, 0x0000, 0x0144, 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, + 0x0024, 0x3063, 0x0024, 0x4480, 0x2000, 0x36f4, 0xc024, 0x36f4, 0x5812, + 0x36f1, 0xd810, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0xb386, 0x40d7, 0x4284, 0x184c, 0x0000, 0x05c0, 0x2803, 0xde15, 0xf5d8, + 0x3804, 0x0000, 0x0984, 0x6400, 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, + 0x0000, 0x800a, 0x0000, 0x00ce, 0x2403, 0xe14e, 0xffa4, 0x0024, 0x48b6, + 0x0024, 0x0000, 0x0024, 0x2803, 0xe144, 0x4000, 0x40c2, 0x4224, 0x0024, + 0x6090, 0x0024, 0xffa4, 0x0024, 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, + 0xd80d, 0x48b6, 0x0024, 0x0fff, 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, + 0x36f1, 0x180a, 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6a00, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1b40, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x144e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x7280, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x0254, /*copy 596*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0164, 0x04b9, 0x09a5, + 0x0d57, 0x045f, 0xe8cd, 0xbc5c, 0x9380, 0xa08d, 0x0c3f, 0x1d7a, 0x43d9, + 0x68b4, 0x7fff, 0x7fff, 0x68b4, 0x43d9, 0x1d7a, 0x0c3f, 0xa08d, 0x9380, + 0xbc5c, 0xe8cd, 0x045f, 0x0d57, 0x09a5, 0x04b9, 0x0164, 0xfd25, 0xfb12, + 0x1042, 0x253f, 0xd5bc, 0xed41, 0x08de, 0x53f7, 0x7fff, 0x53f7, 0x08de, + 0xed41, 0xd5bc, 0x253f, 0x1042, 0xfb12, 0xfd25, 0x0006, 0x0000, 0xfff7, + 0x0000, 0x0012, 0x0000, 0xffe4, 0x0000, 0x002e, 0x0000, 0xffbb, 0x0000, + 0x0067, 0x0000, 0xff6f, 0x0000, 0x00cb, 0x0000, 0xfeed, 0x0000, 0x0170, + 0x0000, 0xfe1d, 0x0000, 0x0274, 0x0000, 0xfcde, 0x0000, 0x03f8, 0x0000, + 0xfb0a, 0x0000, 0x0629, 0x0000, 0xf86c, 0x0000, 0x0943, 0x0000, 0xf4c1, + 0x0000, 0x0d9a, 0x0000, 0xef9e, 0x0000, 0x13b4, 0x0000, 0xe851, 0x0000, + 0x1c8a, 0x0000, 0xdd72, 0x0000, 0x2a3c, 0x0000, 0xcb94, 0x0000, 0x42bd, + 0x0000, 0xa75f, 0x0000, 0x7f22, 0x0000, 0xe516, 0x0000, 0x5168, 0x7fff, + 0x5168, 0x0000, 0xe516, 0x0000, 0x7f22, 0x0000, 0xa75f, 0x0000, 0x42bd, + 0x0000, 0xcb94, 0x0000, 0x2a3c, 0x0000, 0xdd72, 0x0000, 0x1c8a, 0x0000, + 0xe851, 0x0000, 0x13b4, 0x0000, 0xef9e, 0x0000, 0x0d9a, 0x0000, 0xf4c1, + 0x0000, 0x0943, 0x0000, 0xf86c, 0x0000, 0x0629, 0x0000, 0xfb0a, 0x0000, + 0x03f8, 0x0000, 0xfcde, 0x0000, 0x0274, 0x0000, 0xfe1d, 0x0000, 0x0170, + 0x0000, 0xfeed, 0x0000, 0x00cb, 0x0000, 0xff6f, 0x0000, 0x0067, 0x0000, + 0xffbb, 0x0000, 0x002e, 0x0000, 0xffe4, 0x0000, 0x0012, 0x0000, 0xfff7, + 0x0000, 0x0006, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x0064, /*copy 100*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x0046, 0x006f, 0x0072, 0x006d, 0x0061, 0x0074, 0x0020, + 0x004e, 0x006f, 0x0074, 0x0020, 0x0044, 0x0053, 0x0046, 0x002f, 0x0044, + 0x0046, 0x0046, 0x0000, 0x004f, 0x006b, 0x0000, 0x004e, 0x006f, 0x0074, + 0x0020, 0x0032, 0x0020, 0x0063, 0x0068, 0x0061, 0x006e, 0x006e, 0x0065, + 0x006c, 0x0073, 0x0000, 0x0049, 0x006e, 0x0076, 0x0061, 0x006c, 0x0069, + 0x0064, 0x0020, 0x0044, 0x0053, 0x0044, 0x0020, 0x0062, 0x0069, 0x0074, + 0x0073, 0x0074, 0x0072, 0x0065, 0x0061, 0x006d, 0x0000, 0x004e, 0x006f, + 0x0074, 0x0020, 0x0044, 0x0053, 0x0044, 0x0020, 0x0062, 0x0069, 0x0074, + 0x0073, 0x0074, 0x0072, 0x0065, 0x0061, 0x006d, 0x0000, 0xff2f, 0x0295, + 0x0a83, 0x16ef, 0x2912, 0x3215, 0x3215, 0x2912, 0x16ef, 0x0a83, 0x0295, + 0xff2f, 0x0007, 0x0001, /*copy 1*/ + 0x8025, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x5d8e, 0x0007, 0x0001, /*copy 1*/ + 0x1a00, 0x0006, 0x0020, /*copy 32*/ + 0x0046, 0x0046, 0x0055, 0x1a40, 0xfc57, 0x0000, 0x0000, 0x0055, 0x1a60, + 0xfc57, 0x0000, 0x0000, 0x0000, 0x1a80, 0xfc73, 0x0000, 0x0000, 0x0000, + 0x1aa0, 0xfc73, 0x0000, 0x0000, 0x0000, 0x3000, 0xfc84, 0x0000, 0x0000, + 0x0000, 0x3200, 0xfc84, 0x0000, 0x0000, 0x0007, 0x0001, /*copy 1*/ + 0x1a40, 0x0006, 0x8080, 0x0000, /*Rle(128)*/ + 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 8608 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/patches_flac.h b/targets/esp32/components/VS1053/include/patches_flac.h new file mode 100644 index 00000000..c74a87d1 --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_flac.h @@ -0,0 +1,961 @@ +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x001e, /*copy 30*/ + 0x2a00, 0xc000, 0x3e12, 0xb817, 0x3e14, 0xf812, 0x3e01, 0xb811, 0x0007, + 0x9717, 0x0020, 0xffd2, 0x0030, 0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, + 0x3b81, 0x8024, 0x3101, 0x8024, 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, + 0x4800, 0x36f1, 0x9811, 0x0007, 0x0001, /*copy 1*/ + 0x8060, 0x0006, 0x0540, /*copy 1344*/ + 0xf400, 0x4095, 0x0000, 0x02c2, 0x6124, 0x0024, 0x0000, 0x0024, 0x2800, + 0x1ac5, 0x4192, 0x4542, 0x0000, 0x0041, 0x2000, 0x0015, 0x0030, 0x0317, + 0x2000, 0x0000, 0x3f00, 0x4024, 0x2000, 0x0000, 0x0000, 0x0000, 0x3e12, + 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, 0x8257, 0x3700, 0x984c, + 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, 0x2910, 0x0181, 0x0000, + 0x1bc8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, 0x0195, 0x0000, 0x1bc8, + 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2945, 0x3e13, 0x780e, 0x3e11, + 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, 0xb808, 0x003f, 0xe004, + 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, 0x48be, 0x4497, 0x4090, + 0x1c46, 0xf06c, 0x0024, 0x2400, 0x2580, 0x6090, 0x41c3, 0x6628, 0x1c47, + 0x0000, 0x0024, 0x2800, 0x2449, 0xf07e, 0x0024, 0xf400, 0x4182, 0x673a, + 0x1c46, 0x0000, 0x0024, 0x2800, 0x2589, 0xf06c, 0x0024, 0xf400, 0x41c3, + 0x0000, 0x0024, 0x4224, 0x3442, 0x2903, 0xd9c0, 0x4336, 0x37c3, 0x0000, + 0x1805, 0x2903, 0xd9c0, 0x4508, 0x40c2, 0x450a, 0x9808, 0x0000, 0x0207, + 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, 0x3d01, 0x5bc1, 0x36f3, + 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, 0x580e, 0x0007, 0x8257, + 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, 0xd428, 0x3c02, 0x0006, + 0xc717, 0x2800, 0x2d05, 0x4284, 0x0024, 0x3613, 0x3c02, 0x0006, 0xc357, + 0x2901, 0x6ac0, 0x3e11, 0x5c05, 0x4284, 0x1bc5, 0x0007, 0x8257, 0x2800, + 0x3285, 0x0002, 0x0001, 0x3701, 0x0024, 0x0006, 0xc357, 0xb412, 0x9c02, + 0x002e, 0xe001, 0x2800, 0x3005, 0x6212, 0x0024, 0x0000, 0x0024, 0x2800, + 0x3295, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, 0x0024, 0x3613, 0x0024, + 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, 0x2900, 0x4b40, 0x0006, + 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, 0x8257, 0x3700, 0x8024, + 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x3491, 0x3600, 0x9844, 0x2900, + 0x3a40, 0x0000, 0x3508, 0x2911, 0xf140, 0x0000, 0x0024, 0x0030, 0x0057, + 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, 0xa024, 0x164c, 0x8000, + 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, 0x6d82, 0xd024, 0x44c0, + 0x0006, 0xa402, 0x2800, 0x3955, 0xd024, 0x0024, 0x0000, 0x0000, 0x2800, + 0x3955, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, 0x8024, 0x36f2, 0x1800, + 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, 0x3e13, 0xb80d, 0x3e13, + 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0xf801, + 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, 0xbf8e, 0x9c42, 0x3e01, + 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, 0x8250, 0x0fff, 0xfd85, + 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, 0x2800, 0x4091, 0xf25a, + 0x104c, 0x34f3, 0x0024, 0x2800, 0x4091, 0x0000, 0x0024, 0x3413, 0x084c, + 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, 0x2400, 0x42c0, 0x4efa, + 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, 0x4d64, 0x48b2, 0xa201, + 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, 0x36f4, 0xd801, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0xd80a, 0x36f3, 0x980d, + 0x2000, 0x0000, 0x36f4, 0x5810, 0x36f3, 0x0024, 0x3009, 0x3848, 0x3e14, + 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, + 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, 0x9e40, 0x3604, 0x1811, 0x3613, + 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, + 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x36f4, 0x1811, 0x3009, + 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e13, 0x7801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, + 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, 0x34e5, 0xc024, 0x3524, + 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, 0x4a0c, 0x3d44, 0x8024, + 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, 0x6010, 0x3400, 0x3710, + 0x8024, 0x2800, 0x5704, 0x3af0, 0x8024, 0x3df0, 0x0024, 0x3591, 0x4024, + 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, 0x4020, 0x1753, 0xbf8e, + 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, 0x550e, 0xfe6d, 0x2819, + 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, 0xad56, 0x904c, 0xaf5e, + 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, 0x2046, 0x3cf4, 0x0024, + 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, 0x2800, 0x4f95, 0x3c00, + 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0x5801, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x2814, 0x9c91, + 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, 0x3e12, 0xb817, 0x3e12, + 0x7808, 0x3e11, 0xb811, 0x3e15, 0x7810, 0x3e18, 0xb823, 0x3e18, 0x3821, + 0x3e10, 0x3801, 0x48b2, 0x0024, 0x3e10, 0x3801, 0x3e11, 0x3802, 0x3009, + 0x3814, 0x0030, 0x0717, 0x3f05, 0xc024, 0x0030, 0x0351, 0x3100, 0x0024, + 0x4080, 0x0024, 0x0030, 0x10d1, 0x2800, 0x6745, 0x0001, 0x800a, 0x0006, + 0x6514, 0x3111, 0x8024, 0x6894, 0x13c1, 0x6618, 0x0024, 0xfe44, 0x1000, + 0x4cb2, 0x0406, 0x3c10, 0x0024, 0x3c50, 0x4024, 0x34f0, 0x4024, 0x661c, + 0x1040, 0xfe64, 0x0024, 0x4cb2, 0x0024, 0x3cf0, 0x4024, 0xbc82, 0x3080, + 0x0030, 0x0351, 0x3100, 0x8024, 0xfea8, 0x0024, 0x5ca2, 0x0024, 0x0000, + 0x0182, 0xac22, 0x0024, 0xf7c8, 0x0024, 0x48b2, 0x0024, 0xac22, 0x0024, + 0x2800, 0x6ac0, 0xf7cc, 0x1002, 0x0030, 0x0394, 0x3400, 0x4024, 0x3100, + 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, 0x6410, 0x4088, 0x1001, + 0x0030, 0x1111, 0x3100, 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, + 0x6550, 0x0006, 0x6694, 0x408c, 0x1002, 0xf224, 0x0024, 0x0006, 0xa017, + 0x2800, 0x6ed5, 0x0000, 0x0024, 0x2808, 0x3f41, 0x0006, 0x6410, 0x3050, + 0x0024, 0x3000, 0x4024, 0x6014, 0x0024, 0x0000, 0x0024, 0x2800, 0x6e19, + 0x0000, 0x0024, 0xf400, 0x4040, 0x38b0, 0x0024, 0x2808, 0x3f40, 0x3800, + 0x0024, 0x2800, 0x70c1, 0xf224, 0x0024, 0x0000, 0x0024, 0x2808, 0x3f45, + 0x4684, 0x4106, 0xf12c, 0x0024, 0xf148, 0x0024, 0x846c, 0x0024, 0x2808, + 0x3f40, 0xf400, 0x4184, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0xa090, 0x2912, 0x0d00, + 0x3e14, 0xc024, 0x4088, 0x8000, 0x4080, 0x0024, 0x0007, 0x90d1, 0x2800, + 0x7705, 0x0000, 0x0024, 0x0007, 0x9051, 0x3100, 0x4024, 0x4100, 0x0024, + 0x3900, 0x0024, 0x0007, 0x90d1, 0x0004, 0x0000, 0x31f0, 0x4024, 0x6014, + 0x0400, 0x0000, 0x0024, 0x2800, 0x7b51, 0x4080, 0x0024, 0x0000, 0x0000, + 0x2800, 0x7ac5, 0x0000, 0x0024, 0x0007, 0x9053, 0x3300, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0000, 0x2800, 0x7b58, 0x0000, 0x0024, 0x0007, 0x9051, + 0x3900, 0x0024, 0x3200, 0x504c, 0x6410, 0x0024, 0x3cf0, 0x0000, 0x4080, + 0x0024, 0x0006, 0xc691, 0x2800, 0x9405, 0x3009, 0x0400, 0x0007, 0x9051, + 0x0000, 0x1001, 0x3100, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2800, + 0x8849, 0x003f, 0xe000, 0x0006, 0xc693, 0x3900, 0x0c00, 0x3009, 0x0001, + 0x6014, 0x0024, 0x0007, 0x1ad0, 0x2800, 0x8855, 0x3009, 0x0000, 0x4080, + 0x0024, 0x0000, 0x0301, 0x2800, 0x8245, 0x4090, 0x0024, 0x0000, 0x0024, + 0x2800, 0x8355, 0x0000, 0x0024, 0x3009, 0x0000, 0xc012, 0x0024, 0x2800, + 0x8840, 0x3009, 0x2001, 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, 0x0341, + 0x2800, 0x8555, 0x0000, 0x0024, 0x6190, 0x0024, 0x2800, 0x8840, 0x3009, + 0x2000, 0x6012, 0x0024, 0x0000, 0x0381, 0x2800, 0x8715, 0x0000, 0x0024, + 0x6190, 0x0024, 0x2800, 0x8840, 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, + 0x00c0, 0x2800, 0x8855, 0x0000, 0x0024, 0x3009, 0x2000, 0x0006, 0xa090, + 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0081, 0x2800, 0x8d15, 0x0007, + 0x8c13, 0x3300, 0x104c, 0xb010, 0x0024, 0x0002, 0x8001, 0x2800, 0x8f85, + 0x34f0, 0x0024, 0x2800, 0x8d00, 0x0000, 0x0024, 0x0006, 0xc351, 0x3009, + 0x0000, 0x6090, 0x0024, 0x3009, 0x2000, 0x2900, 0x0b80, 0x3009, 0x0405, + 0x0006, 0xc690, 0x0006, 0xc6d1, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, + 0x0024, 0x0006, 0xa093, 0x2800, 0x8b91, 0xb880, 0x0024, 0x2800, 0x9cc0, + 0x3009, 0x2c00, 0x4040, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2800, + 0x9cd8, 0x0000, 0x0024, 0x0006, 0xc693, 0x3009, 0x0c00, 0x3009, 0x0001, + 0x6014, 0x0024, 0x0006, 0xc350, 0x2800, 0x9cc1, 0x0000, 0x0024, 0x6090, + 0x0024, 0x3009, 0x2c00, 0x3009, 0x0005, 0x2900, 0x0b80, 0x0000, 0x9cc8, + 0x3009, 0x0400, 0x4080, 0x0024, 0x0003, 0x8000, 0x2800, 0x9cc5, 0x0000, + 0x0024, 0x6400, 0x0024, 0x0000, 0x0081, 0x2800, 0x9cc9, 0x0000, 0x0024, + 0x0007, 0x8c13, 0x3300, 0x0024, 0xb010, 0x0024, 0x0006, 0xc650, 0x2800, + 0x9cd5, 0x0000, 0x0024, 0x0001, 0x0002, 0x3413, 0x0000, 0x3009, 0x0401, + 0x4010, 0x8406, 0x0000, 0x0281, 0xa010, 0x13c1, 0x4122, 0x0024, 0x0000, + 0x03c2, 0x6122, 0x8002, 0x462c, 0x0024, 0x469c, 0x0024, 0xfee2, 0x0024, + 0x48be, 0x0024, 0x6066, 0x8400, 0x0006, 0xc350, 0x2800, 0x9cc1, 0x0000, + 0x0024, 0x4090, 0x0024, 0x3009, 0x2400, 0x2900, 0x0b80, 0x3009, 0x0005, + 0x0007, 0x1b50, 0x2912, 0x0d00, 0x3613, 0x0024, 0x3a00, 0x0380, 0x4080, + 0x0024, 0x0000, 0x00c1, 0x2800, 0xa585, 0x3009, 0x0000, 0xb010, 0x008c, + 0x4192, 0x0024, 0x6012, 0x0024, 0x0006, 0xf051, 0x2800, 0xa398, 0x3009, + 0x0400, 0x0007, 0x1fd1, 0x30e3, 0x0400, 0x4080, 0x0024, 0x0000, 0x0301, + 0x2800, 0xa585, 0x3009, 0x0000, 0xb010, 0x0024, 0x0000, 0x0101, 0x6012, + 0x0024, 0x0006, 0xf051, 0x2800, 0xa595, 0x0000, 0x0024, 0x3023, 0x0400, + 0xf200, 0x184c, 0xb880, 0xa400, 0x3009, 0x2000, 0x3009, 0x0441, 0x3e10, + 0x4402, 0x2909, 0xa9c0, 0x3e10, 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, + 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, + 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0012, 0x5103, + 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x380d, 0x0030, 0x0250, 0x3e13, + 0xf80e, 0xbe8b, 0x83e0, 0x290c, 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, + 0x4086, 0x984c, 0x0000, 0x00ce, 0x2400, 0xaf8e, 0x3009, 0x1bc0, 0x0000, + 0x01c3, 0xae3a, 0x184c, 0x0000, 0x0043, 0x3009, 0x3842, 0x290c, 0x4840, + 0x3009, 0x3840, 0x4084, 0x9bc0, 0xfe26, 0x9bc2, 0xceba, 0x0024, 0x4e8e, + 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0000, 0x0102, 0x2800, 0xb4c5, + 0x0030, 0x0010, 0x0000, 0x0206, 0x3613, 0x0024, 0x290c, 0x4840, 0x3009, + 0x3840, 0x3000, 0xdbc0, 0xb366, 0x0024, 0x0000, 0x0024, 0x2800, 0xb4d5, + 0x4e8e, 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0030, 0x0010, 0x2800, + 0xb195, 0x0000, 0x0206, 0x36f3, 0xd80e, 0x36f4, 0x180d, 0x36f1, 0x9807, + 0x36f1, 0x1805, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3e10, 0xb812, 0x3e11, 0xb810, + 0x3e12, 0x0024, 0x0006, 0x9f92, 0x0025, 0xffd0, 0x3e04, 0x4bd1, 0x3181, + 0xf847, 0xb68c, 0x4440, 0x3009, 0x0802, 0x6024, 0x3806, 0x0006, 0x8a10, + 0x2903, 0xa905, 0x0000, 0xb948, 0x0000, 0x0800, 0x6101, 0x1602, 0xaf2e, + 0x0024, 0x4214, 0x1be3, 0xaf0e, 0x1811, 0x0fff, 0xfc00, 0xb200, 0x9bc7, + 0x0000, 0x03c0, 0x2800, 0xbd85, 0xb204, 0xa002, 0x2903, 0x6b00, 0x3613, + 0x2002, 0x4680, 0x1bc8, 0x36f1, 0x9810, 0x2000, 0x0000, 0x36f0, 0x9812, + 0x2a08, 0x1b8e, 0x2803, 0x8c80, 0x0000, 0xbe97, 0x0006, 0xd397, 0x2000, + 0x0000, 0x3f00, 0x0024, 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x191e, /*copy 6430*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x6a97, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x5b4e, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x003f, + 0xc000, 0xb600, 0x41c1, 0x0012, 0x5103, 0x000c, 0xc002, 0xdcd6, 0x0024, + 0x0019, 0xd4c2, 0x2800, 0xa845, 0x0001, 0x1188, 0x0013, 0xd9c3, 0x6fd6, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdf95, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xde4e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x1188, 0x0039, + 0x324f, 0x0001, 0x3e8e, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x0014, 0x1b01, 0x0015, 0x59c0, + 0x6fc2, 0x0024, 0x0019, 0x9301, 0x2800, 0xe9d5, 0x0018, 0x50c0, 0x290c, + 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, 0x4086, 0x184c, 0x0000, 0x18c2, + 0x6234, 0x0024, 0x0000, 0x1d02, 0x2800, 0xe5d5, 0x6234, 0x0024, 0x0030, + 0x0317, 0x2800, 0xeb40, 0x3f00, 0x0024, 0x0000, 0x1d82, 0x2800, 0xe855, + 0x6234, 0x0024, 0x2912, 0x0d00, 0x4084, 0x184c, 0xf200, 0x0024, 0x6200, + 0x0024, 0x0006, 0x0017, 0x2800, 0xe540, 0xb080, 0x3c40, 0x0000, 0x0202, + 0x2800, 0xeb55, 0xa024, 0x0024, 0xc020, 0x0024, 0x2800, 0xe540, 0x0030, + 0x02d7, 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, 0xeb55, 0x0000, 0x0024, + 0x2803, 0x2240, 0x000a, 0xcac8, 0x000a, 0x8c8f, 0x0000, 0xec8e, 0x000c, + 0x0981, 0x280a, 0x71c0, 0x002c, 0x9d40, 0x000a, 0x708f, 0x0000, 0xd7ce, + 0x280a, 0xc0d5, 0x0012, 0x5182, 0x6fd6, 0x0024, 0x003f, 0xfd81, 0x280a, + 0x8e45, 0xb710, 0x0024, 0xb710, 0x0024, 0x003f, 0xfc01, 0x6012, 0x0024, + 0x0000, 0x0101, 0x2801, 0x0855, 0xffd2, 0x0024, 0x48b2, 0x0024, 0x4190, + 0x0024, 0x0000, 0x190d, 0x2801, 0x0855, 0x0030, 0x0250, 0xb880, 0x104c, + 0x3cf0, 0x0024, 0x0010, 0x5500, 0xb880, 0x23c0, 0xb882, 0x2000, 0x0007, + 0x8590, 0x2914, 0xbec0, 0x0000, 0x0440, 0x0007, 0x8b50, 0xb880, 0x0024, + 0x2920, 0x0100, 0x3800, 0x0024, 0x2920, 0x0000, 0x0006, 0x8a91, 0x0000, + 0x0800, 0xb880, 0xa440, 0x003f, 0xfd81, 0xb710, 0xa7c0, 0x003f, 0xfc01, + 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x1195, 0x0000, 0x0024, 0xffe2, + 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x1195, + 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0006, + 0x8a90, 0x2801, 0x1195, 0x0000, 0x01c2, 0xb886, 0x8040, 0x3613, 0x03c1, + 0xbcd2, 0x0024, 0x0030, 0x0011, 0x2800, 0xfe15, 0x003f, 0xff42, 0xb886, + 0x8040, 0x3009, 0x03c1, 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0102, + 0x6cd2, 0x0024, 0x3e10, 0x0024, 0x2909, 0x8c80, 0x3e00, 0x4024, 0x36f3, + 0x0024, 0x3e11, 0x8024, 0x3e01, 0xc024, 0x2901, 0x3540, 0x0000, 0x0201, + 0xf400, 0x4512, 0x2900, 0x0c80, 0x3213, 0x1b8c, 0x3100, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2801, 0x1195, 0x0000, 0x0024, 0x291a, 0x8a40, + 0x0000, 0x0100, 0x2920, 0x0200, 0x3633, 0x0024, 0x2920, 0x0280, 0x0000, + 0x0401, 0x408e, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, 0x003f, 0xfd81, + 0xb710, 0x4006, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, + 0x1195, 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, + 0x0000, 0x0024, 0x2801, 0x1195, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, + 0x0780, 0x4080, 0x0024, 0x0000, 0x01c2, 0x2800, 0xfa05, 0x0006, 0x8a90, + 0x2a01, 0x1180, 0x2920, 0x0100, 0x0000, 0x0401, 0x0000, 0x0180, 0x2920, + 0x0200, 0x3613, 0x0024, 0x2920, 0x0280, 0x3613, 0x0024, 0x0000, 0x0401, + 0x2920, 0x0280, 0x4084, 0x984c, 0x0019, 0x9d01, 0x6212, 0x0024, 0x001e, + 0x5c01, 0x2801, 0x0cd5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x0ec5, + 0x0000, 0x0024, 0x001b, 0x5bc1, 0x6212, 0x0024, 0x001b, 0xdd81, 0x2801, + 0x1295, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x1295, 0x0000, 0x0024, + 0x0000, 0x004d, 0x000a, 0xbf4f, 0x280a, 0xb880, 0x0001, 0x0fce, 0x0020, + 0xfb4f, 0x0000, 0x190d, 0x0001, 0x16ce, 0x2920, 0xf440, 0x3009, 0x2bc1, + 0x291a, 0x8a40, 0x36e3, 0x0024, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, + 0xcac0, 0x0000, 0xd7ce, 0x0030, 0x0017, 0x3700, 0x4024, 0x0000, 0x0200, + 0xb102, 0x0024, 0x0000, 0x00c0, 0x2801, 0x15c5, 0x0005, 0x4f92, 0x2909, + 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, 0xa115, 0xb080, 0x0024, + 0x3f00, 0x3400, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xc0c0, 0x0000, + 0xd7ce, 0x0000, 0x004d, 0x0020, 0xfe0f, 0x2820, 0xfb40, 0x0001, 0x17ce, + 0x2801, 0x1995, 0x3009, 0x1000, 0x6012, 0x93cc, 0x0000, 0x0024, 0x2801, + 0x3445, 0x0000, 0x0024, 0x3413, 0x0024, 0x34b0, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0200, 0x2801, 0x1c95, 0xb882, 0x0024, 0x3453, 0x0024, 0x3009, + 0x13c0, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, 0x3445, 0x0000, 0x0024, + 0xb882, 0x130c, 0x0000, 0x004d, 0x0021, 0x058f, 0x2821, 0x0340, 0x0001, + 0x1d8e, 0x2801, 0x2dd5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x2dd5, + 0x0000, 0x0024, 0x34c3, 0x184c, 0x3e13, 0xb80f, 0xf400, 0x4500, 0x0026, + 0x9dcf, 0x0001, 0x218e, 0x0000, 0xfa0d, 0x2926, 0x8e80, 0x3e10, 0x110c, + 0x36f3, 0x0024, 0x2801, 0x2dc0, 0x36f3, 0x980f, 0x001c, 0xdd00, 0x001c, + 0xd901, 0x6ec2, 0x0024, 0x001c, 0xdd00, 0x2801, 0x2495, 0x0018, 0xdbc1, + 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0xc640, 0x3e00, 0x13cc, 0x2801, + 0x2b80, 0x36f3, 0x0024, 0x6ec2, 0x0024, 0x003f, 0xc000, 0x2801, 0x2715, + 0x002a, 0x4001, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0xafc0, 0x3e00, + 0x13cc, 0x2801, 0x2b80, 0x36f3, 0x0024, 0xb400, 0x0024, 0xd100, 0x0024, + 0x0000, 0x0024, 0x2801, 0x2b85, 0x0000, 0x0024, 0x3613, 0x0024, 0x3e11, + 0x4024, 0x2926, 0x8540, 0x3e01, 0x0024, 0x4080, 0x1b8c, 0x0000, 0x0024, + 0x2801, 0x2b85, 0x0000, 0x0024, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, + 0x8e80, 0x3e10, 0x13cc, 0x36f3, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, + 0x0000, 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x3110, 0x8024, 0x2826, + 0xa8c4, 0x31f0, 0xc024, 0x2a26, 0xad00, 0x34c3, 0x184c, 0x3410, 0x8024, + 0x3430, 0xc024, 0x0000, 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x0000, + 0x0024, 0x2801, 0x3454, 0x4d06, 0x0024, 0x0000, 0x0200, 0x2922, 0x1885, + 0x0001, 0x32c8, 0x0000, 0x0200, 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, + 0xc024, 0x291a, 0x8a40, 0x0000, 0x0024, 0x2922, 0x1880, 0x36f3, 0x0024, + 0x0000, 0x004d, 0x0021, 0x0ecf, 0x2821, 0x0bc0, 0x0001, 0x33ce, 0x2801, + 0x16c0, 0x3c30, 0x4024, 0x0000, 0x190d, 0x0000, 0x458e, 0x2821, 0x0f80, + 0x0027, 0x9e0f, 0x0020, 0xcd4f, 0x2820, 0xc780, 0x0001, 0x360e, 0x0006, + 0xf017, 0x0000, 0x0015, 0xb070, 0xbc15, 0x0000, 0x458e, 0x0027, 0x9e0f, + 0x2820, 0xcd80, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e10, 0xb803, 0x3e14, + 0x3811, 0x3e11, 0x3805, 0x3e00, 0x3801, 0x0007, 0xc390, 0x0006, 0xa011, + 0x3010, 0x0444, 0x3050, 0x4405, 0x6458, 0x0302, 0xff94, 0x4081, 0x0003, + 0xffc5, 0x48b6, 0x0024, 0xff82, 0x0024, 0x42b2, 0x0042, 0xb458, 0x0003, + 0x4cd6, 0x9801, 0xf248, 0x1bc0, 0xb58a, 0x0024, 0x6de6, 0x1804, 0x0006, + 0x0010, 0x3810, 0x9bc5, 0x3800, 0xc024, 0x36f4, 0x1811, 0x36f0, 0x9803, + 0x283e, 0x2d80, 0x0fff, 0xffc3, 0x2801, 0x4c40, 0x0000, 0x0024, 0x3413, + 0x0024, 0x2801, 0x4045, 0xf400, 0x4517, 0x2801, 0x4440, 0x6894, 0x13cc, + 0x37b0, 0x184c, 0x6090, 0x1d51, 0x0000, 0x0910, 0x3f00, 0x060c, 0x3100, + 0x4024, 0x6016, 0xb812, 0x000c, 0x8012, 0x2801, 0x42d1, 0xb884, 0x0024, + 0x6894, 0x3002, 0x0000, 0x028d, 0x003a, 0x5e0f, 0x0001, 0x544e, 0x2939, + 0xb0c0, 0x3e10, 0x93cc, 0x4084, 0x9bd2, 0x4282, 0x0024, 0x0000, 0x0040, + 0x2801, 0x4645, 0x4292, 0x130c, 0x3443, 0x0024, 0x2801, 0x4785, 0x000c, + 0x8390, 0x2a01, 0x4b00, 0x3444, 0x0024, 0x3073, 0x0024, 0xc090, 0x014c, + 0x2801, 0x4b00, 0x3800, 0x0024, 0x000c, 0x4113, 0xb880, 0x2380, 0x3304, + 0x4024, 0x3800, 0x05cc, 0xcc92, 0x05cc, 0x3910, 0x0024, 0x3910, 0x4024, + 0x000c, 0x8110, 0x3910, 0x0024, 0x39f0, 0x4024, 0x3810, 0x0024, 0x38d0, + 0x4024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x34c3, 0x0024, 0x3444, 0x0024, + 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x3613, 0x0024, 0x2801, 0x4e45, + 0x6898, 0xb804, 0x0000, 0x0084, 0x293b, 0x1cc0, 0x3613, 0x0024, 0x000c, + 0x8117, 0x3711, 0x0024, 0x37d1, 0x4024, 0x4e8a, 0x0024, 0x0000, 0x0015, + 0x2801, 0x5105, 0xce9a, 0x0024, 0x3f11, 0x0024, 0x3f01, 0x4024, 0x000c, + 0x8197, 0x408a, 0x9bc4, 0x3f15, 0x4024, 0x2801, 0x5345, 0x4284, 0x3c15, + 0x6590, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x0000, + 0x0024, 0x2801, 0x3f18, 0x458a, 0x0024, 0x2a39, 0x53c0, 0x003e, 0x2d4f, + 0x283a, 0x5ed5, 0x0001, 0x37ce, 0x000c, 0x4653, 0x0000, 0x0246, 0xffac, + 0x0c01, 0x48be, 0x0024, 0x4162, 0x4546, 0x6642, 0x4055, 0x3501, 0x8024, + 0x0000, 0x0087, 0x667c, 0x4057, 0x000c, 0x41d5, 0x283a, 0x62d5, 0x3501, + 0x8024, 0x667c, 0x1c47, 0x3701, 0x8024, 0x283a, 0x62d5, 0xc67c, 0x0024, + 0x0000, 0x0024, 0x283a, 0x62c5, 0x0000, 0x0024, 0x2a3a, 0x5ec0, 0x3009, + 0x3851, 0x3e14, 0xf812, 0x3e12, 0xb817, 0x3e11, 0x8024, 0x0006, 0x0293, + 0x3301, 0x8024, 0x468c, 0x3804, 0x0006, 0xa057, 0x2801, 0x6044, 0x0006, + 0x0011, 0x469c, 0x0024, 0x3be1, 0x8024, 0x2801, 0x6055, 0x0006, 0xc392, + 0x3311, 0x0024, 0x33f1, 0x2844, 0x3009, 0x2bc4, 0x0030, 0x04d2, 0x3311, + 0x0024, 0x3a11, 0x0024, 0x3201, 0x8024, 0x003f, 0xfc04, 0xb64c, 0x0fc4, + 0xc648, 0x0024, 0x3a01, 0x0024, 0x3111, 0x1fd3, 0x6498, 0x07c6, 0x868c, + 0x2444, 0x0023, 0xffd2, 0x3901, 0x8e06, 0x0030, 0x0551, 0x3911, 0x8e06, + 0x3961, 0x9c44, 0xf400, 0x44c6, 0xd46c, 0x1bc4, 0x36f1, 0xbc13, 0x2801, + 0x69d5, 0x36f2, 0x9817, 0x002b, 0xffd2, 0x3383, 0x188c, 0x3e01, 0x8c06, + 0x0006, 0xa097, 0x3009, 0x1c12, 0x3213, 0x0024, 0x468c, 0xbc12, 0x002b, + 0xffd2, 0xf400, 0x4197, 0x2801, 0x66c4, 0x3713, 0x0024, 0x2801, 0x6705, + 0x37e3, 0x0024, 0x3009, 0x2c17, 0x3383, 0x0024, 0x3009, 0x0c06, 0x468c, + 0x4197, 0x0006, 0xa052, 0x2801, 0x6904, 0x3713, 0x2813, 0x2801, 0x6945, + 0x37e3, 0x0024, 0x3009, 0x2c17, 0x36f1, 0x8024, 0x36f2, 0x9817, 0x36f4, + 0xd812, 0x2100, 0x0000, 0x3904, 0x5bd1, 0x2a01, 0x5a0e, 0x3e11, 0x7804, + 0x0030, 0x0257, 0x3701, 0x0024, 0x0013, 0x4d05, 0xd45b, 0xe0e1, 0x0007, + 0xc795, 0x2801, 0x7155, 0x0fff, 0xff45, 0x3511, 0x184c, 0x4488, 0xb808, + 0x0006, 0x8a97, 0x2801, 0x7105, 0x3009, 0x1c40, 0x3511, 0x1fc1, 0x0000, + 0x0020, 0xac52, 0x1405, 0x6ce2, 0x0024, 0x0000, 0x0024, 0x2801, 0x7101, + 0x68c2, 0x0024, 0x291a, 0x8a40, 0x3e10, 0x0024, 0x2921, 0xca80, 0x3e00, + 0x4024, 0x36f3, 0x0024, 0x3009, 0x1bc8, 0x36f0, 0x1801, 0x3601, 0x5804, + 0x3e13, 0x780f, 0x3e13, 0xb808, 0x0008, 0x9b0f, 0x0001, 0x740e, 0x2908, + 0x9300, 0x0000, 0x004d, 0x36f3, 0x9808, 0x2000, 0x0000, 0x36f3, 0x580f, + 0x0007, 0x81d7, 0x3711, 0x8024, 0x3711, 0xc024, 0x3700, 0x0024, 0x0000, + 0x2001, 0xb012, 0x0024, 0x0034, 0x0000, 0x2801, 0x7985, 0x0000, 0x01c1, + 0x3700, 0x0024, 0x0002, 0x0001, 0xb012, 0x0024, 0x002e, 0xe001, 0x2801, + 0x7885, 0x6512, 0x0024, 0x0034, 0x0000, 0x2801, 0x7995, 0x0000, 0x01c1, + 0x0030, 0x0117, 0x3f00, 0x0024, 0x0014, 0xc000, 0x0000, 0x01c1, 0x4fce, + 0x0024, 0xffea, 0x0024, 0x48b6, 0x0024, 0x4384, 0x4097, 0xb886, 0x45c6, + 0xfede, 0x0024, 0x4db6, 0x0024, 0x466c, 0x0024, 0x0006, 0xc610, 0x8dd6, + 0x8007, 0x0000, 0x00c6, 0xff6e, 0x0024, 0x48b2, 0x0024, 0x0034, 0x2406, + 0xffee, 0x0024, 0x2914, 0xaa80, 0x40b2, 0x0024, 0xf1c6, 0x0024, 0xf1d6, + 0x0024, 0x0000, 0x0201, 0x8d86, 0x0024, 0x61de, 0x0024, 0x0006, 0xc612, + 0x2801, 0x8001, 0x0006, 0xc713, 0x4c86, 0x0024, 0x2912, 0x1180, 0x0006, + 0xc351, 0x0006, 0x0210, 0x2912, 0x0d00, 0x3810, 0x984c, 0xf200, 0x2043, + 0x2808, 0xa000, 0x3800, 0x0024, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, + 0x3e14, 0x0024, 0x2900, 0xb740, 0x0000, 0x0201, 0x0000, 0x0601, 0x3413, + 0x184c, 0x2903, 0x7680, 0x3cf0, 0x0024, 0x3413, 0x184c, 0x3400, 0x3040, + 0x3009, 0x33c1, 0x0000, 0x1fc1, 0xb010, 0x0024, 0x6014, 0x9040, 0x0006, + 0x8010, 0x2801, 0x88d5, 0x0000, 0x0024, 0x34e3, 0x1bcc, 0x6890, 0x0024, + 0x2801, 0x8a80, 0xb880, 0x2000, 0x3e10, 0x1381, 0x2903, 0xb8c0, 0x3e00, + 0x4024, 0x003f, 0xfe41, 0x36e3, 0x104c, 0x34f0, 0x0024, 0xa010, 0x0024, + 0x36f4, 0x0024, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, + 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, + 0xb804, 0x3e01, 0x534c, 0xbe8a, 0x10c0, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2801, 0x93c5, 0x0000, 0x0024, 0x2903, 0x7680, 0x4082, 0x184c, 0x4c8a, + 0x134c, 0x0000, 0x0001, 0x6890, 0x10c2, 0x4294, 0x0024, 0xac22, 0x0024, + 0xbec2, 0x0024, 0x0000, 0x0024, 0x2801, 0x93c5, 0x0000, 0x0024, 0x6890, + 0x134c, 0xb882, 0x10c2, 0xac22, 0x0024, 0x4c92, 0x0024, 0xdc92, 0x0024, + 0xceca, 0x0024, 0x4e82, 0x1bc5, 0x36f0, 0x9804, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3645, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, + 0x3e14, 0x104c, 0x2900, 0xb740, 0x0000, 0x0081, 0x4080, 0x3040, 0x0000, + 0x0101, 0x2801, 0x9ac5, 0x0000, 0x0024, 0x4090, 0x0024, 0x0006, 0x8050, + 0x2801, 0xaed5, 0x0000, 0x0024, 0x2900, 0xb740, 0x3613, 0x0024, 0xb880, + 0x3000, 0x2801, 0xac80, 0x3009, 0x3380, 0x2900, 0xb740, 0x4122, 0x10cc, + 0x3cf0, 0x0024, 0x3001, 0x0024, 0x3400, 0x0024, 0x6800, 0x0024, 0xa408, + 0x9040, 0x4080, 0x0024, 0x0000, 0x07c1, 0x2801, 0xa055, 0x6894, 0x1380, + 0x6894, 0x130c, 0x3460, 0x0024, 0x6408, 0x4481, 0x4102, 0x1380, 0xf400, + 0x4052, 0x0000, 0x07c1, 0x34f0, 0xc024, 0x6234, 0x0024, 0x6824, 0x0024, + 0xa122, 0x0024, 0x6014, 0x0024, 0x0000, 0x0141, 0x2801, 0xa755, 0x0000, + 0x0024, 0x2900, 0xb740, 0x3613, 0x0024, 0x2801, 0xa5c0, 0xb88a, 0x4002, + 0x2901, 0x8c40, 0x3e00, 0x8024, 0x4c8e, 0xa801, 0x0000, 0x0201, 0x3a10, + 0x1bcc, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, 0xab55, + 0x659a, 0x0024, 0x6540, 0x184c, 0x0030, 0x0010, 0x2801, 0xa348, 0x0000, + 0x0024, 0x2801, 0xab40, 0x36f3, 0x0024, 0x2801, 0xaa00, 0xb88a, 0x0024, + 0x2903, 0x3ec0, 0x34d0, 0x4024, 0x4c8f, 0xa0a1, 0x0000, 0x0201, 0x3000, + 0x084c, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, 0xab55, 0x659a, 0x0024, + 0x6540, 0x10cc, 0x0030, 0x0010, 0x2801, 0xa7c8, 0x0000, 0x0024, 0x34d3, + 0x0024, 0x3423, 0x0024, 0xf400, 0x4510, 0x3009, 0x1380, 0x6090, 0x0024, + 0x3009, 0x2000, 0x6892, 0x108c, 0x34f0, 0x9000, 0xa122, 0x984c, 0x6016, + 0x13c1, 0x0000, 0x0102, 0x2801, 0x9c08, 0x0006, 0x8150, 0x2801, 0xaf40, + 0x3009, 0x1bcc, 0x6890, 0x938c, 0x3800, 0x0024, 0x36f4, 0x0024, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb804, 0x3e11, 0xb807, 0x3e14, + 0x3811, 0x3e04, 0x934c, 0x3430, 0x0024, 0x4080, 0x0024, 0x0000, 0x0206, + 0x2801, 0xb845, 0x0006, 0x8151, 0x3101, 0x130c, 0xff0c, 0x1102, 0x6408, + 0x0024, 0x4204, 0x0024, 0xb882, 0x4092, 0x1005, 0xfe02, 0x48be, 0x0024, + 0x4264, 0x0024, 0x2903, 0xc540, 0xf400, 0x4090, 0x36f4, 0x8024, 0x36f4, + 0x1811, 0x36f1, 0x9807, 0x36f0, 0x9804, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3675, 0x0024, + 0x3643, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, 0x0181, 0x3e10, + 0xb803, 0x3e11, 0x3806, 0x3e11, 0xf810, 0x3e14, 0x7812, 0x3e13, 0xf80e, + 0x2903, 0x47c0, 0x3e03, 0x4024, 0x2900, 0xb740, 0x4088, 0x184c, 0x3413, + 0x184c, 0x2900, 0xb740, 0x6892, 0x3040, 0x4080, 0x3040, 0x0000, 0x0000, + 0x2801, 0xc5c5, 0x0000, 0x0024, 0x6890, 0x0024, 0x2903, 0x47c0, 0x3cd0, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, 0xc615, 0x0000, 0x0024, + 0x3433, 0x0024, 0xf400, 0x4510, 0x34d0, 0x0024, 0x6090, 0x0024, 0x2903, + 0x47c0, 0x3800, 0x0024, 0x4080, 0x10cc, 0xf400, 0x4510, 0x2801, 0xc385, + 0x34d0, 0x0024, 0x2801, 0xc600, 0x0000, 0x0024, 0x3cd0, 0x0024, 0x3433, + 0x0024, 0x34a0, 0x0024, 0xf400, 0x4510, 0x3430, 0x4024, 0x6100, 0x0024, + 0x0000, 0x0341, 0x3840, 0x0024, 0x3000, 0x0024, 0x6012, 0x0024, 0x0006, + 0x0581, 0x2801, 0xe381, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, + 0x2000, 0x0000, 0x0000, 0x0024, 0x34d3, 0x184c, 0x3430, 0x8024, 0x2901, + 0x8c40, 0x3e00, 0x8024, 0x36f3, 0x11cc, 0xb888, 0x104c, 0x3c10, 0x0024, + 0x3c90, 0x4024, 0x2801, 0xcf40, 0x34e3, 0x0024, 0x3411, 0x8024, 0x3491, + 0xc024, 0x4f82, 0x128c, 0x3400, 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, + 0x3800, 0x0024, 0x3440, 0x4024, 0x4142, 0x0024, 0x6498, 0x4050, 0x3009, + 0x2007, 0x0006, 0x8150, 0x3000, 0x11cc, 0x6402, 0x104c, 0x0000, 0x0024, + 0x2801, 0xcc88, 0x0000, 0x0024, 0x3493, 0x0024, 0x2801, 0xff40, 0x34f3, + 0x0024, 0x2801, 0xd6c0, 0xb888, 0x0024, 0x3430, 0x8024, 0x2901, 0x8c40, + 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, 0x5bcc, 0x4142, 0x0024, 0xf400, + 0x4050, 0x3800, 0x0024, 0x3440, 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, + 0x0000, 0x0201, 0x3009, 0x2007, 0x0030, 0x0010, 0x3000, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2801, 0xff55, 0x6498, 0x0024, 0x0006, 0x8150, + 0x3000, 0x134c, 0x6402, 0x984c, 0x0000, 0x0024, 0x2801, 0xd208, 0x0000, + 0x0024, 0x2801, 0xff40, 0x3433, 0x1bcc, 0x0000, 0x0201, 0xb888, 0x104c, + 0x3430, 0x184c, 0x6010, 0x0024, 0x6402, 0x3000, 0x0000, 0x0201, 0x2801, + 0xdf58, 0x0030, 0x0010, 0x4090, 0x124c, 0x2401, 0xde40, 0x0000, 0x0024, + 0x3430, 0x8024, 0x2901, 0x8c40, 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, + 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, 0x3800, 0x0024, 0x3410, 0x4024, + 0x4142, 0x0024, 0x6498, 0x4050, 0x3009, 0x2007, 0x0030, 0x0010, 0x0000, + 0x0201, 0x3473, 0x0024, 0x3490, 0x0024, 0x3e00, 0x13cc, 0x2901, 0x9580, + 0x3444, 0x8024, 0x3000, 0x1bcc, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, + 0xff55, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3470, 0x0024, 0x3e10, 0x104c, + 0x34c0, 0x4024, 0x2901, 0xb1c0, 0x3e00, 0x4024, 0x2801, 0xff40, 0x36e3, + 0x0024, 0x0000, 0x0801, 0x3413, 0x0024, 0x34f0, 0x0024, 0x6012, 0x0024, + 0x0000, 0x07c1, 0x2801, 0xfe88, 0x0000, 0x0024, 0x6010, 0x114c, 0xb888, + 0x32c0, 0x6402, 0x0024, 0x0000, 0x0101, 0x2801, 0xeb18, 0x0000, 0x0024, + 0x4090, 0x134c, 0x2401, 0xea40, 0x3009, 0x184c, 0x3430, 0x8024, 0x2901, + 0x8c40, 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, 0x4024, 0x4142, 0x0024, + 0xf400, 0x4050, 0x3800, 0x0024, 0x3410, 0x4024, 0x4142, 0x0024, 0x6498, + 0x4050, 0x3009, 0x2007, 0x0000, 0x0101, 0x3433, 0x1bcc, 0x2900, 0xb740, + 0x3613, 0x0024, 0x0000, 0x0141, 0x6090, 0x118c, 0x2900, 0xb740, 0x3ca0, + 0x184c, 0x3473, 0x184c, 0xb888, 0x3380, 0x3400, 0x0024, 0x6402, 0x0024, + 0x0000, 0x0201, 0x2801, 0xf1d8, 0x0000, 0x0024, 0x4090, 0x104c, 0x2401, + 0xf100, 0x0000, 0x0024, 0x34a0, 0x8024, 0x2901, 0x8c40, 0x3e00, 0x8024, + 0x0006, 0x8002, 0x4244, 0x118c, 0x4244, 0x0024, 0x6498, 0x4095, 0x3009, + 0x3440, 0x3009, 0x37c1, 0x0000, 0x0201, 0x34f3, 0x0024, 0x0030, 0x0010, + 0x3490, 0x0024, 0x3e00, 0x138c, 0x2901, 0x9580, 0x3444, 0x8024, 0x3000, + 0x1bcc, 0xb010, 0x0024, 0x0000, 0x0024, 0x2801, 0xff55, 0x4112, 0x0024, + 0x3463, 0x0024, 0x34a0, 0x0024, 0x6012, 0x0024, 0x0006, 0x8111, 0x2801, + 0xfb19, 0x0000, 0x0024, 0x3100, 0x11cc, 0x3490, 0x4024, 0x4010, 0x0024, + 0x0000, 0x0a01, 0x6012, 0x0024, 0x0006, 0x8151, 0x2801, 0xfb18, 0x0000, + 0x0024, 0x3613, 0x114c, 0x3101, 0x3804, 0x3490, 0x8024, 0x6428, 0x138c, + 0x3470, 0x8024, 0x3423, 0x0024, 0x3420, 0xc024, 0x4234, 0x1241, 0x4380, + 0x4092, 0x2903, 0xc540, 0x0006, 0x8010, 0x2801, 0xff40, 0x3009, 0x1bcc, + 0x0006, 0x8151, 0x3613, 0x114c, 0x3101, 0x3804, 0x3490, 0x8024, 0x6428, + 0x138c, 0x3470, 0x8024, 0x3423, 0x0024, 0x3420, 0xc024, 0x4234, 0x1241, + 0x4380, 0x4092, 0x2903, 0xcf00, 0x0006, 0x8010, 0x2801, 0xff40, 0x3009, + 0x1bcc, 0x0006, 0x8050, 0x6890, 0x0024, 0x3800, 0x0024, 0x3433, 0x0024, + 0x34d0, 0x0024, 0x4080, 0x0024, 0x0006, 0x8150, 0x2802, 0x04c5, 0x0000, + 0x0024, 0x3000, 0x11cc, 0xb888, 0x10cc, 0x6402, 0x3240, 0x3493, 0x0024, + 0x3444, 0x8024, 0x2802, 0x04d8, 0x4090, 0x0024, 0x2402, 0x0480, 0x0000, + 0x0024, 0x6499, 0x2620, 0xb78e, 0x4001, 0x0000, 0x0000, 0x3433, 0x0024, + 0xcfce, 0x1340, 0xaf0e, 0x0024, 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x36f4, 0x5812, 0x36f1, 0xd810, 0x36f1, 0x1806, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, + 0xf804, 0x0000, 0x3fc3, 0x3e11, 0x7806, 0x3e11, 0xf810, 0xbc82, 0x12cc, + 0x3404, 0x0024, 0x3023, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x3454, + 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x2900, 0xb740, 0x0000, 0x0201, + 0x0006, 0x9301, 0x4088, 0x134c, 0x3400, 0x8024, 0xd204, 0x0024, 0xb234, + 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, 0x3c30, 0x0024, + 0x0000, 0x2000, 0xb400, 0x0024, 0x0000, 0x3001, 0x2802, 0x1255, 0x0000, + 0x3800, 0x0000, 0x0041, 0xfe42, 0x12cc, 0x48b2, 0x1090, 0x3810, 0x0024, + 0x38f0, 0x4024, 0x2802, 0x3340, 0x3430, 0x0024, 0xb400, 0x0024, 0x6012, + 0x0024, 0x0000, 0x3801, 0x2802, 0x1595, 0x0000, 0x3c00, 0x0000, 0x07c0, + 0x0000, 0x0041, 0xb400, 0x12cc, 0xfe02, 0x1150, 0x48b2, 0x0024, 0x689a, + 0x2040, 0x2802, 0x3200, 0x38f0, 0x4024, 0xb400, 0x0024, 0x6012, 0x0024, + 0x0000, 0x3c01, 0x2802, 0x1915, 0x0000, 0x3e00, 0x0000, 0x03c0, 0x0000, + 0x0085, 0x4592, 0x12cc, 0xb400, 0x1150, 0xfe02, 0x0024, 0x48b2, 0x0024, + 0x3810, 0x0024, 0x2802, 0x3200, 0x38f0, 0x4024, 0xb400, 0x0024, 0x6012, + 0x0024, 0x0000, 0x3e01, 0x2802, 0x1c95, 0x0000, 0x3f00, 0x0000, 0x01c0, + 0xf20a, 0x12cc, 0xb400, 0x1150, 0xf252, 0x0024, 0xfe02, 0x0024, 0x48b2, + 0x0024, 0x3810, 0x0024, 0x2802, 0x3200, 0x38f0, 0x4024, 0xb400, 0x130c, + 0x6012, 0x0024, 0x0000, 0x3f01, 0x2802, 0x2015, 0x4390, 0x0024, 0x0000, + 0x0041, 0x0000, 0x0105, 0x4590, 0x13cc, 0xb400, 0x1150, 0xfe02, 0x0024, + 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0x3200, 0x38f0, 0x4024, 0xb400, + 0x0024, 0x6012, 0x1100, 0x0000, 0x01c1, 0x2802, 0x2395, 0x0000, 0x0024, + 0x0000, 0x0041, 0x0000, 0x0145, 0x6890, 0x12cc, 0xb400, 0x1150, 0xfe02, + 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0x3200, 0x38f0, 0x4024, + 0x6012, 0x0024, 0x0000, 0x3f81, 0x2802, 0x2615, 0xb430, 0x0024, 0x6012, + 0x0024, 0x0000, 0x0024, 0x2802, 0x2615, 0x0000, 0x0024, 0x2802, 0x3200, + 0x0000, 0x0185, 0x2802, 0x3340, 0xc890, 0x0024, 0x0000, 0x3fc3, 0x0000, + 0x0201, 0x34d3, 0x0024, 0x2900, 0xb740, 0x3433, 0x184c, 0x0006, 0x9301, + 0x4088, 0x134c, 0x3400, 0x8024, 0xd204, 0x0024, 0xb234, 0x0024, 0x4122, + 0x0024, 0xf400, 0x4055, 0x0000, 0x2001, 0x3500, 0x0024, 0x3c30, 0x0024, + 0x0000, 0x3000, 0xb400, 0x0024, 0x6012, 0x0024, 0x0000, 0x0182, 0x2802, + 0x2c45, 0x0000, 0x0024, 0x2802, 0x3340, 0xc890, 0x0024, 0x459a, 0x12cc, + 0x3404, 0x0024, 0x3023, 0x0024, 0x3010, 0x0024, 0x30d0, 0x4024, 0xac22, + 0x0046, 0x003f, 0xf982, 0x3011, 0xc024, 0x0000, 0x0023, 0xaf2e, 0x0024, + 0x0000, 0x0182, 0xccf2, 0x0024, 0x0000, 0x0fc6, 0x0000, 0x0047, 0xb46c, + 0x2040, 0xfe6e, 0x23c1, 0x3454, 0x0024, 0x3010, 0x0024, 0x30f0, 0x4024, + 0xac22, 0x0024, 0xccb2, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x458a, + 0x134c, 0x0000, 0x0201, 0x2802, 0x2755, 0x0000, 0x3fc3, 0x3430, 0x0024, + 0x36f1, 0xd810, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3675, + 0x0024, 0x3633, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, 0x3e13, + 0xf80e, 0x3e03, 0x4024, 0x2903, 0xac40, 0x0000, 0x0381, 0x000f, 0xff81, + 0x6012, 0x184c, 0x0000, 0x0201, 0x2802, 0x3bc5, 0x0000, 0x0024, 0x2900, + 0xb740, 0x0003, 0x1f08, 0x3613, 0x0024, 0x0000, 0x0401, 0x0006, 0x8a10, + 0x2900, 0xbf40, 0xb880, 0x1bcc, 0xb880, 0x11cc, 0x3413, 0x184c, 0x3c90, + 0x0024, 0x2900, 0xb740, 0x34f3, 0x0024, 0x3473, 0x184c, 0x3c00, 0x0000, + 0x4080, 0x0024, 0x0006, 0x9301, 0x2802, 0x4145, 0x003f, 0xfe04, 0x3490, + 0x8024, 0xa244, 0x0024, 0x2903, 0x8f40, 0xb880, 0x0024, 0x2900, 0xbf40, + 0x003f, 0xfe04, 0x3473, 0x184c, 0x0006, 0x8091, 0x3413, 0x0024, 0x34f0, + 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, 0x3500, + 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0x6892, 0x4055, + 0x3500, 0x0024, 0x3cf0, 0x0024, 0x34a0, 0x0024, 0xf100, 0x0024, 0xb010, + 0x0024, 0x3c60, 0x0024, 0x34b0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0201, + 0x2900, 0xb740, 0x3ce0, 0x0024, 0x0006, 0x9301, 0x3473, 0x184c, 0x3c10, + 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x003f, 0xff01, 0x3500, + 0x0024, 0x3cf0, 0x0024, 0x34c0, 0x0024, 0xa010, 0x0024, 0x0000, 0x03c1, + 0x3c40, 0x0024, 0x34d0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0201, 0x2900, + 0xb740, 0x3cc0, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, + 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, 0x3fc3, 0xb234, + 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x003f, 0xff01, 0x3500, 0x0024, + 0x3cf0, 0x0024, 0x3400, 0x0024, 0xa010, 0x0024, 0x0000, 0x01c1, 0x3900, + 0x0024, 0x34e0, 0x0024, 0xf100, 0x0024, 0xb010, 0x0024, 0x6892, 0x3080, + 0x34f0, 0x0024, 0xb010, 0x0024, 0x3cb0, 0x0024, 0x3450, 0x0024, 0x34a0, + 0x4024, 0xc010, 0x0024, 0x0000, 0x0181, 0x2802, 0x55c5, 0x3100, 0x0024, + 0x6890, 0x07cc, 0x2803, 0x1f00, 0x3900, 0x0024, 0x6012, 0x0024, 0x0000, + 0x0201, 0x2802, 0x5758, 0x0000, 0x0024, 0x2802, 0x5a40, 0x6090, 0x044c, + 0x6012, 0x0024, 0x0000, 0x0281, 0x2802, 0x5988, 0x6012, 0x0024, 0x0000, + 0x0080, 0x2802, 0x5999, 0x0000, 0x0024, 0x2802, 0x5a40, 0x3113, 0x0024, + 0x6890, 0x07cc, 0x2803, 0x1f00, 0x3900, 0x0024, 0x0000, 0x0201, 0x3900, + 0x114c, 0x34b0, 0x0024, 0x6012, 0x0024, 0x0006, 0x08c1, 0x2802, 0x6481, + 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, 0x0000, 0x0000, + 0x0024, 0x2802, 0x6480, 0x0000, 0x0024, 0x0000, 0x0200, 0x0006, 0x8110, + 0x2802, 0x6480, 0x3800, 0x0024, 0x0000, 0x0300, 0x0006, 0x8110, 0x2802, + 0x6480, 0x3800, 0x0024, 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, 0x1f00, + 0x3800, 0x0024, 0x0000, 0x0400, 0x0006, 0x8110, 0x2802, 0x6480, 0x3800, + 0x0024, 0x0000, 0x0500, 0x0006, 0x8110, 0x2802, 0x6480, 0x3800, 0x0024, + 0x0000, 0x0600, 0x0006, 0x8110, 0x2802, 0x6480, 0x3800, 0x0024, 0x0006, + 0x8050, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, 0x0024, 0x3423, 0x184c, + 0x3460, 0x0024, 0x4080, 0x0024, 0x0006, 0x8200, 0x2802, 0x69c5, 0x3e10, + 0x0024, 0x0000, 0x01c0, 0x3e10, 0x0024, 0x3490, 0x0024, 0x2902, 0x07c0, + 0x3e00, 0x13cc, 0x36d3, 0x11cc, 0x3413, 0x0024, 0x4080, 0x3240, 0x34f3, + 0x0024, 0x2802, 0x6d98, 0x0000, 0x0024, 0x0006, 0x8010, 0x6890, 0x0024, + 0x2803, 0x1f00, 0x3800, 0x0024, 0x0000, 0x0180, 0x3e10, 0x0024, 0x3490, + 0x0024, 0x2902, 0x07c0, 0x3e00, 0x13cc, 0x36d3, 0x11cc, 0x3413, 0x0024, + 0x4080, 0x3240, 0x34f3, 0x0024, 0x2802, 0x6d98, 0x0000, 0x0024, 0x0006, + 0x8010, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, 0x0024, 0x0000, 0x0201, + 0x3433, 0x0024, 0x34d0, 0x0024, 0x6012, 0x0024, 0x0006, 0x0ac1, 0x2802, + 0x7f81, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, 0x0000, + 0x0000, 0x0024, 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, + 0x0024, 0x0000, 0x3000, 0x2802, 0x8140, 0x0006, 0x8150, 0x0000, 0x9000, + 0x0006, 0x8150, 0x3433, 0x0024, 0x34d0, 0x4024, 0x4192, 0x0024, 0x4192, + 0x0024, 0x2802, 0x8140, 0xa010, 0x0024, 0x0000, 0x0201, 0x0006, 0x8150, + 0x2900, 0xb740, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, + 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, 0x3cf0, + 0x0024, 0x3490, 0x0024, 0x2802, 0x8140, 0x6090, 0x0024, 0x003f, 0xfe04, + 0x0000, 0x0401, 0x0006, 0x8150, 0x2900, 0xb740, 0x3613, 0x0024, 0x0006, + 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3400, 0xc024, + 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, 0x3fc3, 0xb234, 0x0024, 0x4122, + 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, 0x3500, 0x0024, 0xd024, 0x3000, + 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, 0x3cf0, + 0x0024, 0x3490, 0x0024, 0x2802, 0x8140, 0x6090, 0x0024, 0x0000, 0x4000, + 0x0000, 0x0202, 0x0006, 0x8150, 0x3433, 0x0024, 0x34d0, 0x4024, 0x6122, + 0x0024, 0xa010, 0x0024, 0x0004, 0x8001, 0x3800, 0x110c, 0x0006, 0x8150, + 0x3000, 0x0024, 0x6012, 0x1300, 0x0000, 0x0401, 0x2802, 0x8409, 0x0000, + 0x0024, 0x6890, 0x82cc, 0x2803, 0x1f00, 0x3800, 0x0024, 0x6012, 0x0024, + 0x0006, 0x0cc1, 0x2802, 0xab81, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, + 0x0024, 0x2000, 0x0000, 0x0000, 0x0024, 0x2802, 0xab80, 0x0000, 0x0024, + 0x0016, 0x2200, 0x0006, 0x8190, 0x6892, 0x2040, 0x2802, 0xab80, 0x38f0, + 0x4024, 0x002c, 0x4400, 0x0000, 0x0081, 0x0006, 0x8190, 0x3810, 0x0024, + 0x2802, 0xab80, 0x38f0, 0x4024, 0x003b, 0x8000, 0x0000, 0x0081, 0x0006, + 0x8190, 0x3810, 0x0024, 0x2802, 0xab80, 0x38f0, 0x4024, 0x0007, 0xd000, + 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, 0xab80, 0x38f0, 0x4024, 0x000f, + 0xa000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, 0xab80, 0x38f0, 0x4024, + 0x0015, 0x8880, 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, 0xab80, 0x38f0, + 0x4024, 0x0017, 0x7000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, 0xab80, + 0x38f0, 0x4024, 0x001f, 0x4000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2802, + 0xab80, 0x38f0, 0x4024, 0x002b, 0x1100, 0x0006, 0x8190, 0xb882, 0x2040, + 0x2802, 0xab80, 0x38f0, 0x4024, 0x002e, 0xe000, 0x0006, 0x8190, 0xb882, + 0x2040, 0x2802, 0xab80, 0x38f0, 0x4024, 0x001d, 0xc000, 0x0006, 0x8190, + 0x6892, 0x2040, 0x2802, 0xab80, 0x38f0, 0x4024, 0x0006, 0x8190, 0x0000, + 0x0201, 0x0000, 0xfa04, 0x2900, 0xb740, 0x3613, 0x0024, 0x0006, 0x9301, + 0xb88a, 0x11cc, 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, + 0x0024, 0x0000, 0x3fc3, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, + 0x3500, 0x0024, 0x3cf0, 0x0024, 0x3490, 0x0024, 0xfe50, 0x4005, 0x48b2, + 0x0024, 0xfeca, 0x0024, 0x40b2, 0x0024, 0x3810, 0x0024, 0x2802, 0xab80, + 0x38f0, 0x4024, 0x003f, 0xfe04, 0x0000, 0x0401, 0x0006, 0x8190, 0x2900, + 0xb740, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, + 0x34f0, 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, + 0x3500, 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, + 0x4055, 0x0000, 0x0041, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x3490, 0x0024, + 0xfe02, 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0xab80, 0x38f0, + 0x4024, 0x003f, 0xfe04, 0x0000, 0x0401, 0x0006, 0x8190, 0x2900, 0xb740, + 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, 0x34f0, + 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, 0x3500, + 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, + 0x3500, 0x0024, 0x3cf0, 0x0024, 0x0000, 0x0280, 0x3490, 0x4024, 0xfe02, + 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0xab80, 0x38f0, 0x4024, + 0x0006, 0x8010, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, 0x0024, 0x0000, + 0x0201, 0x2900, 0xb740, 0x3613, 0x11cc, 0x3c10, 0x0024, 0x3490, 0x4024, + 0x6014, 0x13cc, 0x0000, 0x0081, 0x2802, 0xaec5, 0x0006, 0x80d0, 0x0006, + 0x8010, 0x6890, 0x0024, 0x2803, 0x1f00, 0x3800, 0x0024, 0x3010, 0x0024, + 0x6012, 0x0024, 0x0000, 0x0241, 0x2802, 0xce49, 0x0006, 0x8112, 0x0008, + 0x0001, 0x3009, 0x184c, 0x3e10, 0x4024, 0x3000, 0x8024, 0x2901, 0xbac0, + 0x3e00, 0x8024, 0x36f3, 0x004c, 0x3000, 0x3844, 0x0008, 0x0010, 0xb884, + 0x3840, 0x0000, 0x0400, 0x3e00, 0x8024, 0x3201, 0x0024, 0x2903, 0x5680, + 0x6408, 0x4091, 0x0001, 0x0000, 0x000b, 0x8011, 0x0004, 0x0010, 0x36e3, + 0x0024, 0x2915, 0x8300, 0x3009, 0x1bc4, 0x000b, 0x8000, 0x3613, 0x0024, + 0x3e10, 0x0024, 0x3200, 0xc024, 0x2901, 0xbac0, 0x3e00, 0xc024, 0x36f3, + 0x084c, 0x32f0, 0xf844, 0x3e10, 0xc024, 0x3e00, 0x8024, 0x2b01, 0x0091, + 0x0000, 0x0400, 0xf204, 0x0804, 0x2903, 0x5680, 0x6408, 0x0024, 0x000b, + 0x8011, 0x0008, 0x0010, 0x0000, 0x0084, 0x36d3, 0x0024, 0x2915, 0x8300, + 0x0003, 0x8000, 0x0005, 0x0010, 0x0001, 0x0000, 0x2915, 0x8300, 0x000f, + 0x0011, 0x1006, 0x0ac0, 0x32f3, 0x11cc, 0x3200, 0xd08c, 0xff34, 0x0024, + 0x48b6, 0x0024, 0x4020, 0x0024, 0x3c90, 0x0024, 0x2802, 0xca80, 0x34e3, + 0x0024, 0x0006, 0x8112, 0x3613, 0x0024, 0x3e10, 0x0024, 0x3000, 0x4024, + 0x2901, 0xbac0, 0x3e00, 0x4024, 0x36f3, 0x004c, 0x3000, 0x7844, 0xb884, + 0x3841, 0x2b01, 0x0091, 0x0000, 0x0400, 0x3e00, 0x8024, 0x3201, 0x0024, + 0x2903, 0x5680, 0x6408, 0x0024, 0x0003, 0x8000, 0x000b, 0x8011, 0x0008, + 0x0010, 0x36e3, 0x11cc, 0x3423, 0x0024, 0x3494, 0xc024, 0x2903, 0x7ac0, + 0x3301, 0x138c, 0x0001, 0x0000, 0x000f, 0x0011, 0x0004, 0x0010, 0x2903, + 0x8000, 0x3301, 0x0024, 0xf400, 0x4510, 0x000b, 0x8011, 0x3073, 0x0024, + 0x3023, 0x0024, 0x3000, 0x0024, 0x6090, 0x0024, 0x3800, 0x0024, 0x0003, + 0x8000, 0x3004, 0xc024, 0x0008, 0x0010, 0x2903, 0x8000, 0x3301, 0x0024, + 0x0001, 0x0000, 0x000f, 0x0011, 0x0005, 0x0010, 0x2903, 0x8000, 0x3301, + 0x0024, 0xf400, 0x4510, 0x3073, 0x1bc4, 0x6498, 0x008c, 0x3000, 0x0024, + 0x6090, 0x0024, 0x3800, 0x0024, 0x0006, 0x80d0, 0x3000, 0x0024, 0x6402, + 0x0024, 0x0006, 0x8110, 0x2802, 0xbdc8, 0x000b, 0x8000, 0x000b, 0x8010, + 0x0001, 0x0000, 0x2903, 0xe0c0, 0x0004, 0x0011, 0x0005, 0x0011, 0x000b, + 0x8010, 0x0001, 0x0000, 0x291f, 0xc6c0, 0x0002, 0xdf88, 0x30e1, 0x184c, + 0x3000, 0x0024, 0x6012, 0x0024, 0x0008, 0x0001, 0x2802, 0xd015, 0x0000, + 0x0024, 0x6498, 0x0024, 0x3e10, 0x4024, 0x0000, 0x0081, 0x2901, 0xbac0, + 0x3e01, 0x0024, 0x36e3, 0x004c, 0x3000, 0x0024, 0x6012, 0x0024, 0x000b, + 0x8011, 0x2802, 0xdc55, 0x0006, 0x8112, 0x0000, 0x0201, 0x0004, 0x0010, + 0x2915, 0x8300, 0x0001, 0x0000, 0x000b, 0x8011, 0x0005, 0x0010, 0x291f, + 0xc6c0, 0x0001, 0x0000, 0x0006, 0x8110, 0x30e1, 0x0024, 0x3000, 0x0024, + 0x6012, 0x0024, 0x0000, 0x0281, 0x2802, 0xd745, 0x6012, 0x0024, 0x000b, + 0x8001, 0x2802, 0xd7d5, 0x3613, 0x0024, 0x36f3, 0x0024, 0x000b, 0x8001, + 0x6498, 0x184c, 0x0006, 0x8112, 0x0003, 0x8000, 0x3e10, 0x4024, 0x2901, + 0xbac0, 0x3e01, 0x0024, 0x36f3, 0x0024, 0x3009, 0x3844, 0x3e10, 0x0024, + 0x0000, 0x0400, 0x3000, 0x8024, 0x0008, 0x0010, 0x3e00, 0x8024, 0x3201, + 0x0024, 0x2903, 0x5680, 0x6408, 0x4051, 0x36e3, 0x0024, 0x2802, 0xdf80, + 0x3009, 0x1bc4, 0x0000, 0x0400, 0x0000, 0x0011, 0x3613, 0x008c, 0x30d0, + 0x7844, 0x3e10, 0x4024, 0x3000, 0x8024, 0x0008, 0x0010, 0x3e00, 0x8024, + 0x3201, 0x0024, 0x2903, 0x5680, 0x6408, 0x0024, 0x36e3, 0x0024, 0x3009, + 0x1bc4, 0x0006, 0x8a10, 0x0000, 0x01c1, 0x3009, 0x0000, 0xb010, 0x0024, + 0x0000, 0x0024, 0x2802, 0xe385, 0x6192, 0x0024, 0x2900, 0xb740, 0x6102, + 0x184c, 0x4088, 0x0024, 0x0000, 0x0024, 0x2802, 0xe385, 0x0000, 0x0024, + 0x0006, 0x8051, 0x6890, 0x0024, 0x3900, 0x0024, 0x3009, 0x0000, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2903, 0x8e85, 0x0002, 0xe848, 0x0006, 0x9f92, + 0x0000, 0x4003, 0x3009, 0x0811, 0x3100, 0x8024, 0xffa6, 0x0024, 0x48b6, + 0x0024, 0x2903, 0x8e80, 0x4384, 0x0024, 0x2903, 0x8f40, 0x3613, 0x0024, + 0x2900, 0xbf40, 0x0000, 0x0024, 0x2903, 0x8e80, 0x0000, 0x0024, 0x0000, + 0x0401, 0x3473, 0x184c, 0x2900, 0xb740, 0x3c10, 0x0024, 0x3c90, 0x0024, + 0x290b, 0x1400, 0x34f3, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, + 0x1b95, 0x0000, 0x0024, 0x3473, 0x0024, 0x3410, 0x0024, 0x34a0, 0x4024, + 0x6014, 0x1380, 0x0000, 0x0024, 0x2802, 0xf045, 0x4080, 0x0024, 0x0006, + 0x8011, 0x6890, 0x0024, 0xb882, 0x2400, 0x0004, 0x8000, 0x2914, 0xbec0, + 0x0008, 0x0010, 0x0000, 0x0400, 0x3143, 0x108c, 0x6890, 0x27c0, 0x3920, + 0x0024, 0x0004, 0x8000, 0x3900, 0x0024, 0x34e0, 0x0024, 0x4080, 0x0024, + 0x0006, 0x8150, 0x2802, 0xf445, 0x0000, 0x3200, 0x0000, 0x0142, 0x0006, + 0x8210, 0x3613, 0x0024, 0x3e00, 0x7800, 0x3011, 0x8024, 0x30d1, 0xc024, + 0xfef4, 0x4087, 0x48b6, 0x0040, 0xfeee, 0x03c1, 0x2914, 0xa580, 0x42b6, + 0x0024, 0x2802, 0xf840, 0x0007, 0x89d0, 0x0000, 0x0142, 0x3613, 0x0024, + 0x3e00, 0x7800, 0x3031, 0x8024, 0x3010, 0x0024, 0x30d0, 0x4024, 0xfe9c, + 0x4181, 0x48be, 0x0024, 0xfe82, 0x0040, 0x46be, 0x03c1, 0xfef4, 0x4087, + 0x48b6, 0x0024, 0xfeee, 0x0024, 0x2914, 0xa580, 0x42b6, 0x0024, 0x0007, + 0x89d0, 0x0006, 0x8191, 0x4c8a, 0x9800, 0xfed0, 0x4005, 0x48b2, 0x0024, + 0xfeca, 0x0024, 0x40b2, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x3111, + 0x8024, 0x468a, 0x0707, 0x2908, 0xbe80, 0x3101, 0x0024, 0x3123, 0x11cc, + 0x3100, 0x108c, 0x3009, 0x3000, 0x0004, 0x8000, 0x3009, 0x1241, 0x6014, + 0x138c, 0x000b, 0x8011, 0x2802, 0xfe81, 0x0000, 0x0024, 0x3473, 0x0024, + 0x3423, 0x0024, 0x3009, 0x3240, 0x34e3, 0x0024, 0x2803, 0x19c0, 0x0008, + 0x0012, 0x0000, 0x0081, 0x2803, 0x0009, 0x0006, 0x80d0, 0xf400, 0x4004, + 0x3000, 0x0024, 0x6012, 0x0024, 0x0000, 0x0005, 0x2803, 0x0589, 0x0000, + 0x0024, 0x6540, 0x0024, 0x0000, 0x0024, 0x2803, 0x15d8, 0x4490, 0x0024, + 0x2403, 0x04c0, 0x0000, 0x0024, 0x0006, 0x8301, 0x4554, 0x0800, 0x4122, + 0x0024, 0x659a, 0x4055, 0x0006, 0x8341, 0x3d00, 0x0840, 0x4122, 0x0024, + 0xf400, 0x4055, 0x3d00, 0x0024, 0x2803, 0x15c0, 0x0000, 0x0024, 0x4090, + 0x0024, 0xf400, 0x4480, 0x2803, 0x0ad5, 0x000b, 0x8001, 0x6540, 0x0024, + 0x0000, 0x0024, 0x2803, 0x15d8, 0x4490, 0x0024, 0x2403, 0x0a00, 0x0000, + 0x0024, 0x0006, 0x8301, 0x4554, 0x0800, 0x4122, 0x0024, 0x659a, 0x4055, + 0x0006, 0x8341, 0x4122, 0x3400, 0xf400, 0x4055, 0x3210, 0x0024, 0x3d00, + 0x0024, 0x2803, 0x15c0, 0x0000, 0x0024, 0x6014, 0x0024, 0x0001, 0x0000, + 0x2803, 0x1215, 0x0003, 0x8001, 0x0008, 0x0012, 0x0008, 0x0010, 0x0006, + 0x8153, 0x3613, 0x0024, 0x3009, 0x3811, 0x2903, 0xe0c0, 0x0004, 0x0011, + 0x0008, 0x0010, 0x0001, 0x0000, 0x291f, 0xc6c0, 0x0005, 0x0011, 0x000f, + 0x0011, 0x0008, 0x0010, 0x33d0, 0x184c, 0x6010, 0xb844, 0x3e10, 0x0024, + 0x0000, 0x0400, 0x3320, 0x4024, 0x3e00, 0x4024, 0x3301, 0x0024, 0x2903, + 0x5680, 0x6408, 0x0024, 0x36e3, 0x0024, 0x3009, 0x1bc4, 0x3009, 0x1bd1, + 0x6540, 0x0024, 0x0000, 0x0024, 0x2803, 0x15d8, 0x4490, 0x0024, 0x2403, + 0x1580, 0x0000, 0x0024, 0x0006, 0x8301, 0x4554, 0x0840, 0x4122, 0x0024, + 0x659a, 0x4055, 0x0006, 0x8341, 0x4122, 0x3400, 0xf400, 0x4055, 0x3110, + 0x0024, 0x3d00, 0x0024, 0xf400, 0x4510, 0x0030, 0x0013, 0x3073, 0x184c, + 0x3e11, 0x008c, 0x3009, 0x0001, 0x6140, 0x0024, 0x0000, 0x0201, 0x3009, + 0x2000, 0x0006, 0x8300, 0x290c, 0x7300, 0x3e10, 0x0024, 0x3300, 0x1b8c, + 0xb010, 0x0024, 0x0000, 0x0024, 0x2803, 0x1b95, 0x0000, 0x0024, 0x3473, + 0x0024, 0x3423, 0x0024, 0x3009, 0x1240, 0x4080, 0x138c, 0x0000, 0x0804, + 0x2802, 0xff15, 0x6402, 0x0024, 0x0006, 0xd312, 0x0006, 0xd310, 0x0006, + 0x8191, 0x3010, 0x984c, 0x30f0, 0xc024, 0x0000, 0x0021, 0xf2d6, 0x07c6, + 0x290a, 0xf5c0, 0x4682, 0x0400, 0x6894, 0x0840, 0xb886, 0x0bc1, 0xbcd6, + 0x0024, 0x3a10, 0x8024, 0x3af0, 0xc024, 0x36f3, 0x4024, 0x36f3, 0xd80e, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, + 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, + 0x0020, 0x0001, 0x3e14, 0x3811, 0x0030, 0x0050, 0x0030, 0x0251, 0x3e04, + 0xb813, 0x3000, 0x0024, 0xc012, 0x0024, 0x0019, 0x9300, 0x3800, 0x4024, + 0x2903, 0x8c40, 0x3900, 0x0024, 0x2903, 0xa040, 0x0000, 0x0300, 0xb882, + 0x0024, 0x2914, 0xbec0, 0x0006, 0x8010, 0x0000, 0x1540, 0x0007, 0x8190, + 0x2901, 0x8200, 0x3800, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, + 0x2f55, 0x0000, 0x0024, 0x0006, 0x8012, 0x3200, 0x0024, 0x4080, 0x0024, + 0x0030, 0x0010, 0x2803, 0x2f55, 0x0000, 0x0201, 0x3000, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2803, 0x2f55, 0x0000, 0x0024, 0x2901, 0x8200, + 0x0000, 0x0024, 0x4080, 0x0024, 0x0006, 0x8010, 0x2803, 0x2f55, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0201, 0x2803, 0x2b85, 0x0030, 0x0010, + 0x0030, 0x0050, 0xf292, 0x0000, 0xb012, 0x0024, 0x3800, 0x4024, 0x0030, + 0x0010, 0x0000, 0x0201, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2900, 0xbed5, 0x0003, 0x3908, 0x0006, 0x8011, 0x3100, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2803, 0x3745, 0x0000, 0x0024, 0x0007, 0x8a52, + 0x3200, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0x3749, 0x0000, + 0x0024, 0xf292, 0x0800, 0x6012, 0x0024, 0x0000, 0x0000, 0x2803, 0x3705, + 0x0000, 0x0024, 0x3200, 0x0024, 0x4090, 0x0024, 0xb880, 0x2800, 0x3900, + 0x0024, 0x3100, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2902, 0x3585, + 0x0003, 0x3048, 0x2900, 0xbec0, 0x0000, 0x0024, 0x0000, 0x0010, 0x0006, + 0x9f51, 0x0006, 0x9f92, 0x0030, 0x0493, 0x0000, 0x0201, 0x6890, 0xa410, + 0x3b00, 0x2810, 0x0006, 0x8a10, 0x3009, 0x0000, 0x6012, 0x0024, 0x0006, + 0x9fd0, 0x2803, 0x3c88, 0xb880, 0x0024, 0x6890, 0x0024, 0x3009, 0x2000, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e10, 0xb810, 0x3e11, 0x3805, 0x3e02, 0x0024, 0x0030, 0x0010, 0xce9a, + 0x0002, 0x0000, 0x0200, 0x2903, 0x47c0, 0xb024, 0x0024, 0xc020, 0x0024, + 0x0000, 0x0200, 0x2803, 0x4085, 0x6e9a, 0x0002, 0x4182, 0x0024, 0x0000, + 0x0400, 0x2803, 0x4645, 0xae1a, 0x0024, 0x6104, 0x984c, 0x0000, 0x0024, + 0x2900, 0xb749, 0x0003, 0x4608, 0x6103, 0xe4e5, 0x2900, 0xb740, 0x408a, + 0x188c, 0x2900, 0xb740, 0x408a, 0x4141, 0x4583, 0x6465, 0x2803, 0x4640, + 0xceca, 0x1bcc, 0xc408, 0x0024, 0xf2e2, 0x1bc8, 0x36f1, 0x1805, 0x2000, + 0x0011, 0x36f0, 0x9810, 0x2000, 0x0000, 0xdc92, 0x0024, 0x0006, 0x8a17, + 0x3613, 0x1c00, 0x6093, 0xe1e3, 0x0000, 0x03c3, 0x0006, 0x9f95, 0xb132, + 0x9415, 0x3500, 0xfc01, 0x2803, 0x55d5, 0xa306, 0x0024, 0x0006, 0xd397, + 0x003f, 0xc001, 0x3500, 0x184c, 0xb011, 0xe4e5, 0xb182, 0x1c04, 0xd400, + 0x184c, 0x0000, 0x0205, 0xac52, 0x3802, 0x0006, 0xd3c2, 0x4212, 0x0024, + 0xf400, 0x4057, 0xb182, 0x1c04, 0xd400, 0x0024, 0xac52, 0x1404, 0xd142, + 0x0024, 0x0000, 0x3fc4, 0xb142, 0x0024, 0x4122, 0x1bc2, 0xf400, 0x4057, + 0x3700, 0x4024, 0xd101, 0x6465, 0x0006, 0xd397, 0x3f00, 0x3814, 0x0025, + 0xffd4, 0x0006, 0xd317, 0x3710, 0x160c, 0x0006, 0x9f94, 0x37f0, 0x73d5, + 0x6c92, 0x3808, 0x3f10, 0x0024, 0x3ff0, 0x4024, 0x3009, 0x1040, 0x3009, + 0x13c1, 0x6010, 0x0024, 0x0000, 0x0024, 0x2903, 0xa905, 0x0003, 0x51c8, + 0x2803, 0x5414, 0x0006, 0x0001, 0x4010, 0x0024, 0x0005, 0xf601, 0x6010, + 0x0024, 0x0000, 0x0040, 0x2803, 0x5594, 0x0030, 0x0497, 0x3f00, 0x0024, + 0x36f2, 0x1814, 0x4330, 0x9803, 0x2000, 0x0000, 0x8880, 0x1bc1, 0x3613, + 0x0024, 0x3e22, 0xb806, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x7807, 0x6848, 0x930c, 0x3411, + 0x780d, 0x459a, 0x10c0, 0x0000, 0x0201, 0x6012, 0x384e, 0x0000, 0x0241, + 0x2803, 0x5d15, 0x6012, 0x380f, 0x2403, 0x5c45, 0x0000, 0x0024, 0x3000, + 0x0001, 0x3101, 0x8407, 0x6cfe, 0x0024, 0xac42, 0x0024, 0xaf4e, 0x2040, + 0x3911, 0x8024, 0x2803, 0x68c0, 0x0000, 0x0024, 0x0000, 0x0281, 0x2803, + 0x6055, 0x6012, 0x4455, 0x2403, 0x5f85, 0x0000, 0x0024, 0x3000, 0x0001, + 0x3101, 0x8407, 0x4cf2, 0x0024, 0xac42, 0x0024, 0xaf4e, 0x2040, 0x3911, + 0x8024, 0x2803, 0x68c0, 0x0000, 0x0024, 0x0000, 0x0024, 0x2803, 0x6495, + 0x4080, 0x0024, 0x3110, 0x0401, 0xf20f, 0x0203, 0x2403, 0x63c5, 0x8dd6, + 0x0024, 0x4dce, 0x0024, 0xf1fe, 0x0024, 0xaf4e, 0x0024, 0x6dc6, 0x2046, + 0xf1df, 0x0203, 0xaf4f, 0x1011, 0xf20e, 0x07cc, 0x8dd6, 0x2486, 0x2803, + 0x68c0, 0x0000, 0x0024, 0x0000, 0x0024, 0x2803, 0x6715, 0x0000, 0x0024, + 0x0fff, 0xffd1, 0x2403, 0x6645, 0x3010, 0x0001, 0xac4f, 0x0801, 0x3821, + 0x8024, 0x2803, 0x68c0, 0x0000, 0x0024, 0x0fff, 0xffd1, 0x2403, 0x6885, + 0x3010, 0x0001, 0x3501, 0x9407, 0xac47, 0x0801, 0xaf4e, 0x2082, 0x3d11, + 0x8024, 0x36f3, 0xc024, 0x36f3, 0x980d, 0x36f1, 0x5807, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, + 0x9806, 0x0006, 0x9f97, 0x3e00, 0x5c15, 0x0006, 0xd397, 0x003f, 0xc001, + 0x3500, 0x3840, 0xb011, 0xe4e5, 0xb182, 0x1c04, 0xd400, 0x184c, 0x0000, + 0x0205, 0xac52, 0x3802, 0x0006, 0xd3c2, 0x4212, 0x0024, 0xb182, 0x4057, + 0x3701, 0x0024, 0xd400, 0x0024, 0xac52, 0x1404, 0xd142, 0x0024, 0x0000, + 0x3fc4, 0xb142, 0x0024, 0x4122, 0x1bc2, 0xf400, 0x4057, 0x3700, 0x4024, + 0xd101, 0x6465, 0x0006, 0xd397, 0x3f00, 0x3814, 0x0025, 0xffd4, 0x0006, + 0xd317, 0x3710, 0x160c, 0x0006, 0x9f94, 0x37f0, 0x73d5, 0x6c92, 0x0024, + 0x3f10, 0x1040, 0x3ff0, 0x53c1, 0x6010, 0x0024, 0x0000, 0x0024, 0x2803, + 0x7494, 0x0006, 0x0001, 0x4010, 0x0024, 0x0005, 0xf601, 0x6010, 0x9bd4, + 0x0000, 0x0040, 0x2803, 0x7614, 0x0030, 0x0497, 0x3f00, 0x0024, 0x2000, + 0x0000, 0x36f0, 0x5800, 0x0000, 0x0400, 0x6102, 0x0024, 0x3e11, 0x3805, + 0x2803, 0x7989, 0x3e02, 0x0024, 0x2900, 0xb740, 0x408a, 0x188c, 0x2900, + 0xb740, 0x408a, 0x4141, 0x4582, 0x1bc8, 0x2000, 0x0000, 0x36f1, 0x1805, + 0x2900, 0xb740, 0x4102, 0x184c, 0xb182, 0x1bc8, 0x2000, 0x0000, 0x36f1, + 0x1805, 0x3613, 0x0024, 0x3e12, 0xb815, 0x3e11, 0xb807, 0x3e13, 0xf80e, + 0x3e03, 0x4024, 0x680c, 0x0024, 0x0000, 0x0024, 0x2803, 0x7ed8, 0x409c, + 0x0024, 0x2403, 0x7e86, 0x0000, 0x000a, 0x3111, 0xc024, 0xfe4e, 0x0007, + 0x47be, 0x0024, 0xf6fe, 0x0024, 0x3811, 0xc024, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x36f1, 0x9807, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, + 0x3e12, 0xb815, 0x3e11, 0xb807, 0x3e13, 0xf80e, 0x3e03, 0x4024, 0x680c, + 0x0024, 0x0000, 0x0024, 0x2803, 0x8418, 0x409c, 0x0024, 0x2403, 0x83c6, + 0x0000, 0x000a, 0x3111, 0xc024, 0xfe4e, 0x8007, 0x47be, 0x0024, 0xf6fe, + 0x0024, 0x3009, 0x2047, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, 0x9807, + 0x2000, 0x0000, 0x36f2, 0x9815, 0x2a03, 0x858e, 0x3e12, 0xb817, 0x3e10, + 0x3802, 0x0000, 0x800a, 0x0006, 0x9f97, 0x3009, 0x1fc2, 0x3e04, 0x5c00, + 0x6020, 0xb810, 0x0030, 0x0451, 0x2803, 0x8854, 0x0006, 0x0002, 0x4020, + 0x0024, 0x0005, 0xfb02, 0x6024, 0x0024, 0x0025, 0xffd0, 0x2803, 0x8a91, + 0x3100, 0x1c11, 0xb284, 0x0024, 0x0030, 0x0490, 0x3800, 0x8024, 0x0025, + 0xffd0, 0x3980, 0x1810, 0x36f4, 0x7c11, 0x36f0, 0x1802, 0x0030, 0x0717, + 0x3602, 0x8024, 0x2100, 0x0000, 0x3f05, 0xdbd7, 0x0003, 0x8557, 0x3613, + 0x0024, 0x3e00, 0x3801, 0xf400, 0x55c0, 0x0000, 0x0897, 0xf400, 0x57c0, + 0x0000, 0x0024, 0x2000, 0x0000, 0x36f0, 0x1801, 0x0006, 0xd397, 0x2000, + 0x0000, 0x3700, 0x0024, 0xb183, 0xe1e3, 0x0000, 0x0203, 0xac32, 0x40d5, + 0xd122, 0x0024, 0x0000, 0x3fc3, 0xb132, 0x0024, 0x0006, 0xd3c3, 0x4316, + 0x0024, 0xf400, 0x40d5, 0x3500, 0x5803, 0x2000, 0x0000, 0xd010, 0x1bc1, + 0x3613, 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0xb884, 0xb805, 0xb888, 0x3844, + 0x3e11, 0xb80d, 0x3e03, 0xf80e, 0x0000, 0x03ce, 0xf400, 0x4083, 0x2403, + 0x9ace, 0xf400, 0x4105, 0x0000, 0x0206, 0xa562, 0x0024, 0x455a, 0x0024, + 0x0020, 0x0006, 0xd312, 0x0024, 0xb16c, 0x0024, 0x0020, 0x0006, 0x2803, + 0x9945, 0xd342, 0x0024, 0x0000, 0x01c6, 0xd342, 0x0024, 0xd56a, 0x0024, + 0x0020, 0x0006, 0x4448, 0x0024, 0xb16c, 0x0024, 0x0020, 0x0146, 0x2803, + 0x9ac5, 0x0000, 0x0024, 0xd468, 0x0024, 0x4336, 0x0024, 0x0000, 0x4000, + 0x0006, 0xd3c1, 0x0006, 0x9306, 0x4122, 0x0024, 0x462c, 0x4055, 0x4092, + 0x3404, 0xb512, 0x4195, 0x6294, 0x3401, 0x6200, 0x0024, 0x0000, 0x03ce, + 0x2803, 0x9551, 0xb888, 0x0024, 0x36f3, 0xd80e, 0x36f1, 0x980d, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36e3, 0x0024, + 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, + 0xb880, 0xb810, 0x0006, 0x9fd0, 0x3e10, 0x8001, 0x4182, 0x3811, 0x0006, + 0xd311, 0x2803, 0xa405, 0x0006, 0x8a10, 0x0000, 0x0200, 0xbc82, 0xa000, + 0x3910, 0x0024, 0x2903, 0x9240, 0x39f0, 0x4024, 0x0006, 0x9f90, 0x0006, + 0x9f51, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, 0x0000, 0x0024, + 0x2903, 0xa905, 0x0003, 0xa508, 0x36f4, 0x4024, 0x36f0, 0x9810, 0x36f0, + 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x290a, 0xd900, 0x3605, 0x0024, 0x2910, 0x0180, 0x3613, 0x0024, + 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, + 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0006, 0x0002, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0x9f90, 0x3e04, 0xb813, + 0x3009, 0x0012, 0x3213, 0x0024, 0xf400, 0x4480, 0x6026, 0x0024, 0x0000, + 0x0024, 0x2803, 0xb195, 0x0000, 0x0024, 0x0000, 0x0012, 0xf400, 0x4480, + 0x0006, 0x9f50, 0x3009, 0x0002, 0x6026, 0x0024, 0x0000, 0x0024, 0x2903, + 0xa905, 0x0003, 0xb188, 0x0006, 0x9f93, 0x3201, 0x0c11, 0xb58a, 0x0406, + 0x0006, 0x8a11, 0x468e, 0x8400, 0xb68c, 0x9813, 0xcfee, 0x1bd2, 0x0000, + 0x0804, 0xaf0e, 0x9811, 0x4f86, 0x1bd0, 0x0000, 0x0021, 0x6418, 0x9807, + 0x6848, 0x1bc6, 0xad46, 0x9805, 0xf400, 0x4080, 0x36f1, 0x0024, 0x36f0, + 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x2803, 0xbfc0, 0x3e04, 0x3811, 0x0000, 0x0401, 0x2900, + 0xb740, 0x3613, 0x0024, 0x0000, 0x0080, 0xb882, 0x130c, 0xf400, 0x4510, + 0x3010, 0x910c, 0x30f0, 0xc024, 0x6dc2, 0x0024, 0x3810, 0x0024, 0x38f0, + 0x4024, 0x0000, 0x0201, 0x3100, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2803, 0xc315, 0x0000, 0x0024, 0x6894, 0x130c, 0xb886, 0x1040, 0x3430, + 0x4024, 0x6dca, 0x0024, 0x0030, 0x0011, 0x2803, 0xbb91, 0x0000, 0x0024, + 0xbcd2, 0x0024, 0x0000, 0x0201, 0x2803, 0xc305, 0x0000, 0x0024, 0x2900, + 0xb740, 0x3613, 0x0024, 0x36f4, 0x1811, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, 0x800a, + 0x3e14, 0x7813, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e13, + 0xf80e, 0x6812, 0x0024, 0x3e03, 0x7810, 0x0fff, 0xffd3, 0x0000, 0x0091, + 0xbd86, 0x9850, 0x3e10, 0x3804, 0x3e00, 0x7812, 0xbe8a, 0x8bcc, 0x409e, + 0x8086, 0x2403, 0xca47, 0xfe49, 0x2821, 0x526a, 0x8801, 0x5c87, 0x280e, + 0x4eba, 0x9812, 0x4286, 0x40e1, 0xb284, 0x1bc1, 0x4de6, 0x0024, 0xad17, + 0x2627, 0x4fde, 0x9804, 0x4498, 0x1bc0, 0x0000, 0x0024, 0x2803, 0xc855, + 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, 0x9807, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x36f4, 0x5813, 0x2000, 0x0000, 0x36f2, 0x9815, + 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, 0x800a, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e13, 0xf80e, 0x6812, 0x0024, 0x3e03, 0x7810, + 0x3009, 0x1850, 0x3e10, 0x3804, 0x3e10, 0x7812, 0x32f3, 0x0024, 0xbd86, + 0x0024, 0x4091, 0xe2e3, 0x3009, 0x0046, 0x2403, 0xd5c0, 0x3009, 0x0047, + 0x32f0, 0x0801, 0xfe1f, 0x6465, 0x5e8a, 0x0024, 0x44ba, 0x0024, 0xfee2, + 0x0024, 0x5d8a, 0x1800, 0x4482, 0x4160, 0x48ba, 0x8046, 0x4dc6, 0x1822, + 0x4de6, 0x8047, 0x36f3, 0x0024, 0x36f0, 0x5812, 0xad17, 0x2627, 0x4fde, + 0x9804, 0x4498, 0x1bc0, 0x0000, 0x0024, 0x2803, 0xd155, 0x3a11, 0xa807, + 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, + 0x9803, 0x2000, 0x0000, 0x36f2, 0x9815, 0xb386, 0x40d7, 0x4284, 0x184c, + 0x0000, 0x05c0, 0x2803, 0xdb55, 0xf5d8, 0x3804, 0x0000, 0x0984, 0x6400, + 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, 0x0000, 0x800a, 0x0000, 0x00ce, + 0x2403, 0xde8e, 0xffa4, 0x0024, 0x48b6, 0x0024, 0x0000, 0x0024, 0x2803, + 0xde84, 0x4000, 0x40c2, 0x4224, 0x0024, 0x6090, 0x0024, 0xffa4, 0x0024, + 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, 0xd80d, 0x48b6, 0x0024, 0x0fff, + 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, 0x36f1, 0x180a, 0x4080, 0x184c, + 0x3e13, 0x780f, 0x2803, 0xe2c5, 0x4090, 0xb80e, 0x2403, 0xe240, 0x3e04, + 0x0440, 0x3810, 0x0440, 0x3604, 0x0024, 0x3009, 0x1bce, 0x3603, 0x5bcf, + 0x2000, 0x0000, 0x0000, 0x0024, 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6ac0, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1b40, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x144e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x7140, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x01a4, /*copy 420*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x000d, /*copy 13*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x0728, 0x0746, 0x0006, 0x8006, 0x078e, /*Rle(6)*/ + 0x0006, 0x0027, /*copy 39*/ + 0x0763, 0x0763, 0x0763, 0x0763, 0x0763, 0x0992, 0x0976, 0x097a, 0x097e, + 0x0982, 0x0986, 0x098a, 0x098e, 0x09c1, 0x09c5, 0x09c8, 0x09c8, 0x09c8, + 0x09c8, 0x09d0, 0x09e3, 0x0aae, 0x0a1a, 0x0a1f, 0x0a25, 0x0a2b, 0x0a30, + 0x0a35, 0x0a3a, 0x0a3f, 0x0a44, 0x0a49, 0x0a4e, 0x0a53, 0x0a6c, 0x0a8b, + 0x0aaa, 0x5a82, 0x5a82, 0x0006, 0x8006, 0x0000, /*Rle(6)*/ + 0x0006, 0x0018, /*copy 24*/ + 0x6fb8, 0xc180, 0xc180, 0x6fb8, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a82, + 0x5a82, 0x6fb8, 0xc180, 0xc180, 0x6fb8, 0x0000, 0x0000, 0x5a82, 0x5a82, + 0x5a82, 0x5a82, 0x6fb8, 0xc180, 0xc180, 0x6fb8, 0x0007, 0x0001, /*copy 1*/ + 0x8025, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x5c4e, 0x0007, 0x0001, /*copy 1*/ + 0x5800, 0x0006, 0x0001, /*copy 1*/ + 0x0001, 0x0006, 0x8007, 0x0000, /*Rle(7)*/ + 0x0006, 0x0018, /*copy 24*/ + 0x0002, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, + 0x0000, 0xfffd, 0xffff, 0x0001, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, + 0xfffa, 0xffff, 0x0004, 0x0000, 0xffff, 0xffff, 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 8414 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/patches_flac_latm.h b/targets/esp32/components/VS1053/include/patches_flac_latm.h new file mode 100644 index 00000000..e44ba0ba --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_flac_latm.h @@ -0,0 +1,980 @@ + +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x0558, /*copy 1368*/ + 0x2a00, 0xc000, 0x3e12, 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, + 0x8257, 0x3700, 0x984c, 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, + 0x2910, 0x0181, 0x0000, 0x14c8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, + 0x0195, 0x0000, 0x14c8, 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2245, + 0x3e13, 0x780e, 0x3e11, 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, + 0xb808, 0x003f, 0xe004, 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, + 0x48be, 0x4497, 0x4090, 0x1c46, 0xf06c, 0x0024, 0x2400, 0x1e80, 0x6090, + 0x41c3, 0x6628, 0x1c47, 0x0000, 0x0024, 0x2800, 0x1d49, 0xf07e, 0x0024, + 0xf400, 0x4182, 0x673a, 0x1c46, 0x0000, 0x0024, 0x2800, 0x1e89, 0xf06c, + 0x0024, 0xf400, 0x41c3, 0x0000, 0x0024, 0x4224, 0x3442, 0x2903, 0xf500, + 0x4336, 0x37c3, 0x0000, 0x1805, 0x2903, 0xf500, 0x4508, 0x40c2, 0x450a, + 0x9808, 0x0000, 0x0207, 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, + 0x3d01, 0x5bc1, 0x36f3, 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, + 0x580e, 0x0007, 0x8257, 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, + 0xd428, 0x3c02, 0x0006, 0xc717, 0x2800, 0x2605, 0x4284, 0x0024, 0x3613, + 0x3c02, 0x0006, 0xc357, 0x2901, 0x6280, 0x3e11, 0x5c05, 0x4284, 0x1bc5, + 0x0000, 0x0024, 0x2800, 0x2945, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, + 0x0024, 0x3613, 0x0024, 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, + 0x2900, 0x48c0, 0x0006, 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, + 0x8257, 0x3700, 0x8024, 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x2b51, + 0x3600, 0x9844, 0x2900, 0x3100, 0x0000, 0x2bc8, 0x2911, 0xf140, 0x0000, + 0x0024, 0x0030, 0x0057, 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, + 0xa024, 0x164c, 0x8000, 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, + 0x6d82, 0xd024, 0x44c0, 0x0006, 0xa402, 0x2800, 0x3015, 0xd024, 0x0024, + 0x0000, 0x0000, 0x2800, 0x3015, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, + 0x8024, 0x36f2, 0x1800, 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, + 0x3e13, 0xb80d, 0x3e13, 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, + 0xb807, 0x3e14, 0xf801, 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, + 0xbf8e, 0x9c42, 0x3e01, 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, + 0x8250, 0x0fff, 0xfd85, 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, + 0x2800, 0x3751, 0xf25a, 0x104c, 0x34f3, 0x0024, 0x2800, 0x3751, 0x0000, + 0x0024, 0x3413, 0x084c, 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, + 0x2400, 0x3980, 0x4efa, 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, + 0x4d64, 0x48b2, 0xa201, 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, + 0x36f4, 0xd801, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, + 0xd80a, 0x36f3, 0x980d, 0x2000, 0x0000, 0x36f4, 0x5810, 0x3e12, 0xb817, + 0x3e14, 0xf812, 0x3e01, 0xb811, 0x0007, 0x9717, 0x0020, 0xffd2, 0x0030, + 0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, 0x3b81, 0x8024, 0x3101, 0x8024, + 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, 0x4800, 0x36f1, 0x9811, 0x36f3, + 0x0024, 0x3009, 0x3848, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, + 0x0001, 0x0010, 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, + 0x9e40, 0x3604, 0x1811, 0x3613, 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, + 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, + 0x0024, 0x36f4, 0x1811, 0x3009, 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, + 0x3600, 0x3840, 0x3e13, 0x780e, 0x3e13, 0xf808, 0x3e00, 0x0024, 0x0000, + 0x3fce, 0x0027, 0x9e0f, 0x2922, 0xb680, 0x0000, 0x190d, 0x36f3, 0x0024, + 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, 0x0000, 0x3009, 0x1800, 0x3613, + 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, + 0x3e13, 0x7801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, + 0x3811, 0x3e14, 0xb813, 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, + 0x34e5, 0xc024, 0x3524, 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, + 0x4a0c, 0x3d44, 0x8024, 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, + 0x6010, 0x3400, 0x3710, 0x8024, 0x2800, 0x5484, 0x3af0, 0x8024, 0x3df0, + 0x0024, 0x3591, 0x4024, 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, + 0x4020, 0x1753, 0xbf8e, 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, + 0x528e, 0xfe6d, 0x2819, 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, + 0xad56, 0x904c, 0xaf5e, 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, + 0x2046, 0x3cf4, 0x0024, 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, + 0x2800, 0x4d15, 0x3c00, 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, + 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f3, 0x5801, 0x3405, 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, + 0x9815, 0x2814, 0x9c91, 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, + 0x3e14, 0x3811, 0x0006, 0xa090, 0x2912, 0x0d00, 0x3e14, 0xc024, 0x4088, + 0x8000, 0x4080, 0x0024, 0x0007, 0x90d1, 0x2800, 0x5f85, 0x0000, 0x0024, + 0x0007, 0x9051, 0x3100, 0x4024, 0x4100, 0x0024, 0x3900, 0x0024, 0x0007, + 0x90d1, 0x0004, 0x0000, 0x31f0, 0x4024, 0x6014, 0x0400, 0x0000, 0x0024, + 0x2800, 0x63d1, 0x4080, 0x0024, 0x0000, 0x0000, 0x2800, 0x6345, 0x0000, + 0x0024, 0x0007, 0x9053, 0x3300, 0x0024, 0x4080, 0x0024, 0x0000, 0x0000, + 0x2800, 0x63d8, 0x0000, 0x0024, 0x0007, 0x9051, 0x3900, 0x0024, 0x3200, + 0x504c, 0x6410, 0x0024, 0x3cf0, 0x0000, 0x4080, 0x0024, 0x0006, 0xc691, + 0x2800, 0x7c85, 0x3009, 0x0400, 0x0000, 0x1001, 0x0007, 0x9051, 0x3100, + 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2800, 0x70c9, 0x003f, 0xe000, + 0x0006, 0xc693, 0x3900, 0x0c00, 0x3009, 0x0001, 0x6014, 0x0024, 0x0007, + 0x1ad0, 0x2800, 0x70d5, 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0301, + 0x2800, 0x6ac5, 0x4090, 0x0024, 0x0000, 0x0024, 0x2800, 0x6bd5, 0x0000, + 0x0024, 0x3009, 0x0000, 0xc012, 0x0024, 0x2800, 0x70c0, 0x3009, 0x2001, + 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, 0x0341, 0x2800, 0x6dd5, 0x0000, + 0x0024, 0x6190, 0x0024, 0x2800, 0x70c0, 0x3009, 0x2000, 0x6012, 0x0024, + 0x0000, 0x0381, 0x2800, 0x6f95, 0x0000, 0x0024, 0x6190, 0x0024, 0x2800, + 0x70c0, 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, 0x00c0, 0x2800, 0x70d5, + 0x0000, 0x0024, 0x3009, 0x2000, 0x0006, 0xa090, 0x3009, 0x0000, 0x4080, + 0x0024, 0x0000, 0x0081, 0x2800, 0x7595, 0x0007, 0x8c13, 0x3300, 0x104c, + 0xb010, 0x0024, 0x0002, 0x8001, 0x2800, 0x7805, 0x34f0, 0x0024, 0x2800, + 0x7580, 0x0000, 0x0024, 0x0006, 0xc351, 0x3009, 0x0000, 0x6090, 0x0024, + 0x3009, 0x2000, 0x2900, 0x0b80, 0x3009, 0x0405, 0x0006, 0xc6d1, 0x0006, + 0xc690, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, 0x0006, 0xa093, + 0x2800, 0x7411, 0xb880, 0x0024, 0x2800, 0x8540, 0x3009, 0x2c00, 0x4040, + 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2800, 0x8558, 0x0000, 0x0024, + 0x0006, 0xc693, 0x3009, 0x0c00, 0x3009, 0x0001, 0x6014, 0x0024, 0x0006, + 0xc350, 0x2800, 0x8541, 0x0000, 0x0024, 0x6090, 0x0024, 0x3009, 0x2c00, + 0x3009, 0x0005, 0x2900, 0x0b80, 0x0000, 0x8548, 0x3009, 0x0400, 0x4080, + 0x0024, 0x0003, 0x8000, 0x2800, 0x8545, 0x0000, 0x0024, 0x6400, 0x0024, + 0x0000, 0x0081, 0x2800, 0x8549, 0x0000, 0x0024, 0x0007, 0x8c13, 0x3300, + 0x0024, 0xb010, 0x0024, 0x0006, 0xc650, 0x2800, 0x8555, 0x0000, 0x0024, + 0x0001, 0x0002, 0x3413, 0x0000, 0x3009, 0x0401, 0x4010, 0x8406, 0x0000, + 0x0281, 0xa010, 0x13c1, 0x4122, 0x0024, 0x0000, 0x03c2, 0x6122, 0x8002, + 0x462c, 0x0024, 0x469c, 0x0024, 0xfee2, 0x0024, 0x48be, 0x0024, 0x6066, + 0x8400, 0x0006, 0xc350, 0x2800, 0x8541, 0x0000, 0x0024, 0x4090, 0x0024, + 0x3009, 0x2400, 0x2900, 0x0b80, 0x3009, 0x0005, 0x0007, 0x1b50, 0x2912, + 0x0d00, 0x3613, 0x0024, 0x3a00, 0x0380, 0x4080, 0x0024, 0x0000, 0x00c1, + 0x2800, 0x8e05, 0x3009, 0x0000, 0xb010, 0x008c, 0x4192, 0x0024, 0x6012, + 0x0024, 0x0006, 0xf051, 0x2800, 0x8c18, 0x3009, 0x0400, 0x0007, 0x1fd1, + 0x30e3, 0x0400, 0x4080, 0x0024, 0x0000, 0x0301, 0x2800, 0x8e05, 0x3009, + 0x0000, 0xb010, 0x0024, 0x0000, 0x0101, 0x6012, 0x0024, 0x0006, 0xf051, + 0x2800, 0x8e15, 0x0000, 0x0024, 0x3023, 0x0400, 0xf200, 0x184c, 0xb880, + 0xa400, 0x3009, 0x2000, 0x3009, 0x0441, 0x3e10, 0x4402, 0x2909, 0xa9c0, + 0x3e10, 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x1811, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, 0x0081, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0xf250, 0x3e04, 0xb813, + 0x3009, 0x0000, 0x6012, 0x0024, 0x003f, 0xff01, 0x2800, 0x9905, 0x0006, + 0x0611, 0x6194, 0x0400, 0x0000, 0x0041, 0xa020, 0x984c, 0x0000, 0x01c2, + 0xfe02, 0x0024, 0x48b2, 0x0024, 0x3e10, 0x0024, 0x2921, 0xca80, 0x3e00, + 0x4024, 0x3100, 0x5bcc, 0x2921, 0xdd40, 0xb122, 0x0024, 0x291a, 0x8a40, + 0x0000, 0xab08, 0x0007, 0x2052, 0x0006, 0x8a93, 0x3100, 0x184c, 0xa010, + 0x0024, 0x0000, 0x0041, 0x6090, 0x0024, 0x2922, 0x1880, 0x6090, 0x0024, + 0xb880, 0x010c, 0x3100, 0x2800, 0xfe02, 0x8c44, 0x3613, 0x0fc5, 0x4eb2, + 0x0024, 0x3009, 0x2040, 0x0000, 0x00c0, 0x2921, 0xbb80, 0x3e00, 0x23c1, + 0x0000, 0x01c1, 0x6012, 0x0024, 0x0003, 0xf680, 0x2800, 0x9f55, 0x0000, + 0x0024, 0x36f3, 0x0024, 0x291a, 0x8a40, 0x0000, 0xab08, 0x2900, 0x4580, + 0x3e00, 0x0024, 0x3413, 0x0040, 0x36f3, 0x03c1, 0x3009, 0x0c44, 0x3009, + 0x0fc5, 0x6ce2, 0x0024, 0x3c10, 0x0024, 0xbc82, 0x33c1, 0x3410, 0x2040, + 0x34e0, 0x63c1, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2800, 0xa809, 0x4c82, + 0x0024, 0x0000, 0x01c4, 0x4c86, 0x184c, 0x003f, 0xff40, 0xad06, 0x0024, + 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, 0xc024, 0x36f3, 0x0024, 0x2921, + 0x9440, 0x0000, 0x0080, 0xb88a, 0x104c, 0x3410, 0x0c46, 0x34e0, 0x4fc7, + 0xbce2, 0x984c, 0x4cf2, 0x0024, 0x3e10, 0x0024, 0x2921, 0x9780, 0x3e00, + 0x4024, 0x2800, 0xaa00, 0x36e3, 0x0024, 0x0000, 0x0024, 0x2800, 0xaa18, + 0x0000, 0x0024, 0x4ce6, 0x184c, 0x3e10, 0x8024, 0x2921, 0x9780, 0x3e00, + 0xc024, 0x36e3, 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2922, 0x1880, + 0x3613, 0x0024, 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, + 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x7802, 0x3e14, 0x0024, 0x2903, 0x9bc0, 0x0000, 0x0201, 0x0000, + 0x0601, 0x3413, 0x184c, 0x2903, 0xa300, 0x3cf0, 0x0024, 0x3413, 0x184c, + 0x3400, 0x3040, 0x3009, 0x33c1, 0x0000, 0x1fc1, 0xb010, 0x0024, 0x6014, + 0x9040, 0x0006, 0x8010, 0x2800, 0xb495, 0x0000, 0x0024, 0x34e3, 0x1bcc, + 0x6890, 0x0024, 0x2800, 0xb640, 0xb880, 0x2000, 0x3e10, 0x1381, 0x2903, + 0xd400, 0x3e00, 0x4024, 0x003f, 0xfe41, 0x36e3, 0x104c, 0x34f0, 0x0024, + 0xa010, 0x0024, 0x36f4, 0x0024, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x0006, 0x9f97, + 0x3e00, 0x5c15, 0x3009, 0x3840, 0x3009, 0x3814, 0x0025, 0xffd4, 0x0006, + 0xd317, 0x3710, 0x160c, 0x0006, 0x9f94, 0x37f0, 0x73d5, 0x6c92, 0x0024, + 0x3f10, 0x1040, 0x3ff0, 0x53c1, 0x6010, 0x0024, 0x0000, 0x0024, 0x2800, + 0xbc54, 0x0006, 0x0001, 0x4010, 0x0024, 0x0005, 0xf601, 0x6010, 0x9bd4, + 0x0000, 0x0040, 0x2800, 0xbdd4, 0x0030, 0x0497, 0x3f00, 0x0024, 0x2000, + 0x0000, 0x36f0, 0x5800, 0x2a08, 0x1b8e, 0x2803, 0xae80, 0x0000, 0xbe57, + 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x19f8, /*copy 6648*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x6257, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x58ce, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x4d86, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdd55, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xdc0e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x0948, 0x0039, + 0x324f, 0x0001, 0x364e, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x0019, 0x9301, 0x2800, 0xdfc0, + 0x0018, 0x50c0, 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, 0xe155, 0x0000, + 0x0024, 0x2803, 0x5840, 0x000a, 0xcac8, 0x000a, 0x8c8f, 0x0000, 0xe28e, + 0x000c, 0x0981, 0x280a, 0x71c0, 0x002c, 0x9d40, 0x000a, 0x708f, 0x0000, + 0xd7ce, 0x280a, 0xc0d5, 0x0012, 0x5182, 0x6fd6, 0x0024, 0x003f, 0xfd81, + 0x280a, 0x8e45, 0xb710, 0x0024, 0x003f, 0xf800, 0xb600, 0x0024, 0x0015, + 0xb801, 0x6012, 0x0024, 0x003f, 0xfd81, 0x2801, 0xbac5, 0x0001, 0x0a48, + 0xb710, 0x0024, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, + 0x0015, 0xffd2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x190d, + 0x2801, 0x0015, 0x0030, 0x0250, 0xb880, 0x104c, 0x3cf0, 0x0024, 0x0010, + 0x5500, 0xb880, 0x23c0, 0xb882, 0x2000, 0x0007, 0x8590, 0x2914, 0xbec0, + 0x0000, 0x0440, 0x0007, 0x8b50, 0xb880, 0x0024, 0x2920, 0x0100, 0x3800, + 0x0024, 0x2920, 0x0000, 0x0006, 0x8a91, 0x0000, 0x0800, 0xb880, 0xa440, + 0x003f, 0xfd81, 0xb710, 0xa7c0, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, + 0x0101, 0x2801, 0x0955, 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, + 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x0955, 0x0000, 0x0024, 0x2912, + 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0006, 0x8a90, 0x2801, 0x0955, + 0x0000, 0x01c2, 0xb886, 0x8040, 0x3613, 0x03c1, 0xbcd2, 0x0024, 0x0030, + 0x0011, 0x2800, 0xf5d5, 0x003f, 0xff42, 0xb886, 0x8040, 0x3009, 0x03c1, + 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0102, 0x6cd2, 0x0024, 0x3e10, + 0x0024, 0x2909, 0x8c80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3e11, 0x8024, + 0x3e01, 0xc024, 0x2901, 0x2d00, 0x0000, 0x0201, 0xf400, 0x4512, 0x2900, + 0x0c80, 0x3213, 0x1b8c, 0x3100, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2801, 0x0955, 0x0000, 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2920, + 0x0200, 0x3633, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, 0x408e, 0x0024, + 0x2920, 0x0280, 0x0000, 0x0401, 0x003f, 0xfd81, 0xb710, 0x4006, 0x003f, + 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x0955, 0x0000, 0x0024, + 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, + 0x0955, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, + 0x0000, 0x01c2, 0x2800, 0xf1c5, 0x0006, 0x8a90, 0x2a01, 0x0940, 0x2920, + 0x0100, 0x0000, 0x0401, 0x0000, 0x0180, 0x2920, 0x0200, 0x3613, 0x0024, + 0x2920, 0x0280, 0x3613, 0x0024, 0x0000, 0x0401, 0x2920, 0x0280, 0x4084, + 0x984c, 0x0019, 0x9d01, 0x6212, 0x0024, 0x001e, 0x5c01, 0x2801, 0x0495, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x0685, 0x0000, 0x0024, 0x001b, + 0x5bc1, 0x6212, 0x0024, 0x001b, 0xdd81, 0x2801, 0x0a55, 0x6012, 0x0024, + 0x0000, 0x0024, 0x2801, 0x0a55, 0x0000, 0x0024, 0x0000, 0x004d, 0x000a, + 0xbf4f, 0x280a, 0xb880, 0x0001, 0x078e, 0x0020, 0xfb4f, 0x0000, 0x190d, + 0x0001, 0x0e8e, 0x2920, 0xf440, 0x3009, 0x2bc1, 0x291a, 0x8a40, 0x36e3, + 0x0024, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xcac0, 0x0000, 0xd7ce, + 0x0030, 0x0017, 0x3700, 0x4024, 0x0000, 0x0200, 0xb102, 0x0024, 0x0000, + 0x00c0, 0x2801, 0x0d85, 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, + 0x0006, 0x0197, 0x0006, 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0000, + 0x190d, 0x000a, 0x708f, 0x280a, 0xc0c0, 0x0000, 0xd7ce, 0x0000, 0x004d, + 0x0020, 0xfe0f, 0x2820, 0xfb40, 0x0001, 0x0f8e, 0x2801, 0x1155, 0x3009, + 0x1000, 0x6012, 0x93cc, 0x0000, 0x0024, 0x2801, 0x2c05, 0x0000, 0x0024, + 0x3413, 0x0024, 0x34b0, 0x0024, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, + 0x1455, 0xb882, 0x0024, 0x3453, 0x0024, 0x3009, 0x13c0, 0x4080, 0x0024, + 0x0000, 0x0200, 0x2801, 0x2c05, 0x0000, 0x0024, 0xb882, 0x130c, 0x0000, + 0x004d, 0x0021, 0x058f, 0x2821, 0x0340, 0x0001, 0x154e, 0x2801, 0x2595, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x2595, 0x0000, 0x0024, 0x34c3, + 0x184c, 0x3e13, 0xb80f, 0xf400, 0x4500, 0x0026, 0x9dcf, 0x0001, 0x194e, + 0x0000, 0xfa0d, 0x2926, 0x8e80, 0x3e10, 0x110c, 0x36f3, 0x0024, 0x2801, + 0x2580, 0x36f3, 0x980f, 0x001c, 0xdd00, 0x001c, 0xd901, 0x6ec2, 0x0024, + 0x001c, 0xdd00, 0x2801, 0x1c55, 0x0018, 0xdbc1, 0x3413, 0x184c, 0xf400, + 0x4500, 0x2926, 0xc640, 0x3e00, 0x13cc, 0x2801, 0x2340, 0x36f3, 0x0024, + 0x6ec2, 0x0024, 0x003f, 0xc000, 0x2801, 0x1ed5, 0x002a, 0x4001, 0x3413, + 0x184c, 0xf400, 0x4500, 0x2926, 0xafc0, 0x3e00, 0x13cc, 0x2801, 0x2340, + 0x36f3, 0x0024, 0xb400, 0x0024, 0xd100, 0x0024, 0x0000, 0x0024, 0x2801, + 0x2345, 0x0000, 0x0024, 0x3613, 0x0024, 0x3e11, 0x4024, 0x2926, 0x8540, + 0x3e01, 0x0024, 0x4080, 0x1b8c, 0x0000, 0x0024, 0x2801, 0x2345, 0x0000, + 0x0024, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0x8e80, 0x3e10, 0x13cc, + 0x36f3, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x0000, 0x4000, 0x0000, + 0x0021, 0x6d06, 0x0024, 0x3110, 0x8024, 0x2826, 0xa8c4, 0x31f0, 0xc024, + 0x2a26, 0xad00, 0x34c3, 0x184c, 0x3410, 0x8024, 0x3430, 0xc024, 0x0000, + 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x0000, 0x0024, 0x2801, 0x2c14, + 0x4d06, 0x0024, 0x0000, 0x0200, 0x2922, 0x1885, 0x0001, 0x2a88, 0x0000, + 0x0200, 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, 0xc024, 0x291a, 0x8a40, + 0x0000, 0x0024, 0x2922, 0x1880, 0x36f3, 0x0024, 0x0000, 0x004d, 0x0021, + 0x0ecf, 0x2821, 0x0bc0, 0x0001, 0x2b8e, 0x2801, 0x0e80, 0x3c30, 0x4024, + 0x0000, 0x190d, 0x0000, 0x3fce, 0x2821, 0x0f80, 0x0027, 0x9e0f, 0x0020, + 0xcd4f, 0x2820, 0xc780, 0x0001, 0x2dce, 0x0006, 0xf017, 0x0000, 0x0015, + 0xb070, 0xbc15, 0x0000, 0x3fce, 0x0027, 0x9e0f, 0x2820, 0xcd80, 0x0000, + 0x190d, 0x3613, 0x0024, 0x3e10, 0xb803, 0x3e14, 0x3811, 0x3e11, 0x3805, + 0x3e00, 0x3801, 0x0007, 0xc390, 0x0006, 0xa011, 0x3010, 0x0444, 0x3050, + 0x4405, 0x6458, 0x0302, 0xff94, 0x4081, 0x0003, 0xffc5, 0x48b6, 0x0024, + 0xff82, 0x0024, 0x42b2, 0x0042, 0xb458, 0x0003, 0x4cd6, 0x9801, 0xf248, + 0x1bc0, 0xb58a, 0x0024, 0x6de6, 0x1804, 0x0006, 0x0010, 0x3810, 0x9bc5, + 0x3800, 0xc024, 0x36f4, 0x1811, 0x36f0, 0x9803, 0x283e, 0x2d80, 0x0fff, + 0xffc3, 0x2801, 0x4400, 0x0000, 0x0024, 0x3413, 0x0024, 0x2801, 0x3805, + 0xf400, 0x4517, 0x2801, 0x3c00, 0x6894, 0x13cc, 0x37b0, 0x184c, 0x6090, + 0x1d51, 0x0000, 0x0910, 0x3f00, 0x060c, 0x3100, 0x4024, 0x6016, 0xb812, + 0x000c, 0x8012, 0x2801, 0x3a91, 0xb884, 0x0024, 0x6894, 0x3002, 0x0000, + 0x028d, 0x003a, 0x5e0f, 0x0001, 0x4c0e, 0x2939, 0xb0c0, 0x3e10, 0x93cc, + 0x4084, 0x9bd2, 0x4282, 0x0024, 0x0000, 0x0040, 0x2801, 0x3e05, 0x4292, + 0x130c, 0x3443, 0x0024, 0x2801, 0x3f45, 0x000c, 0x8390, 0x2a01, 0x42c0, + 0x3444, 0x0024, 0x3073, 0x0024, 0xc090, 0x014c, 0x2801, 0x42c0, 0x3800, + 0x0024, 0x000c, 0x4113, 0xb880, 0x2380, 0x3304, 0x4024, 0x3800, 0x05cc, + 0xcc92, 0x05cc, 0x3910, 0x0024, 0x3910, 0x4024, 0x000c, 0x8110, 0x3910, + 0x0024, 0x39f0, 0x4024, 0x3810, 0x0024, 0x38d0, 0x4024, 0x3810, 0x0024, + 0x38f0, 0x4024, 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, + 0x0024, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, + 0x4284, 0x0024, 0x3613, 0x0024, 0x2801, 0x4605, 0x6898, 0xb804, 0x0000, + 0x0084, 0x293b, 0x1cc0, 0x3613, 0x0024, 0x000c, 0x8117, 0x3711, 0x0024, + 0x37d1, 0x4024, 0x4e8a, 0x0024, 0x0000, 0x0015, 0x2801, 0x48c5, 0xce9a, + 0x0024, 0x3f11, 0x0024, 0x3f01, 0x4024, 0x000c, 0x8197, 0x408a, 0x9bc4, + 0x3f15, 0x4024, 0x2801, 0x4b05, 0x4284, 0x3c15, 0x6590, 0x0024, 0x0000, + 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x0000, 0x0024, 0x2801, 0x36d8, + 0x458a, 0x0024, 0x2a39, 0x53c0, 0x003e, 0x2d4f, 0x283a, 0x5ed5, 0x0001, + 0x2f8e, 0x000c, 0x4653, 0x0000, 0x0246, 0xffac, 0x0c01, 0x48be, 0x0024, + 0x4162, 0x4546, 0x6642, 0x4055, 0x3501, 0x8024, 0x0000, 0x0087, 0x667c, + 0x4057, 0x000c, 0x41d5, 0x283a, 0x62d5, 0x3501, 0x8024, 0x667c, 0x1c47, + 0x3701, 0x8024, 0x283a, 0x62d5, 0xc67c, 0x0024, 0x0000, 0x0024, 0x283a, + 0x62c5, 0x0000, 0x0024, 0x2a3a, 0x5ec0, 0x3009, 0x3851, 0x3e14, 0xf812, + 0x3e12, 0xb817, 0x3e11, 0x8024, 0x0006, 0x0293, 0x3301, 0x8024, 0x468c, + 0x3804, 0x0006, 0xa057, 0x2801, 0x5804, 0x0006, 0x0011, 0x469c, 0x0024, + 0x3be1, 0x8024, 0x2801, 0x5815, 0x0006, 0xc392, 0x3311, 0x0024, 0x33f1, + 0x2844, 0x3009, 0x2bc4, 0x0030, 0x04d2, 0x3311, 0x0024, 0x3a11, 0x0024, + 0x3201, 0x8024, 0x003f, 0xfc04, 0xb64c, 0x0fc4, 0xc648, 0x0024, 0x3a01, + 0x0024, 0x3111, 0x1fd3, 0x6498, 0x07c6, 0x868c, 0x2444, 0x0023, 0xffd2, + 0x3901, 0x8e06, 0x0030, 0x0551, 0x3911, 0x8e06, 0x3961, 0x9c44, 0xf400, + 0x44c6, 0xd46c, 0x1bc4, 0x36f1, 0xbc13, 0x2801, 0x6195, 0x36f2, 0x9817, + 0x002b, 0xffd2, 0x3383, 0x188c, 0x3e01, 0x8c06, 0x0006, 0xa097, 0x3009, + 0x1c12, 0x3213, 0x0024, 0x468c, 0xbc12, 0x002b, 0xffd2, 0xf400, 0x4197, + 0x2801, 0x5e84, 0x3713, 0x0024, 0x2801, 0x5ec5, 0x37e3, 0x0024, 0x3009, + 0x2c17, 0x3383, 0x0024, 0x3009, 0x0c06, 0x468c, 0x4197, 0x0006, 0xa052, + 0x2801, 0x60c4, 0x3713, 0x2813, 0x2801, 0x6105, 0x37e3, 0x0024, 0x3009, + 0x2c17, 0x36f1, 0x8024, 0x36f2, 0x9817, 0x36f4, 0xd812, 0x2100, 0x0000, + 0x3904, 0x5bd1, 0x2a01, 0x51ce, 0x3e11, 0x7804, 0x0030, 0x0257, 0x3701, + 0x0024, 0x0013, 0x4d05, 0xd45b, 0xe0e1, 0x0007, 0xc795, 0x2801, 0x6915, + 0x0fff, 0xff45, 0x3511, 0x184c, 0x4488, 0xb808, 0x0006, 0x8a97, 0x2801, + 0x68c5, 0x3009, 0x1c40, 0x3511, 0x1fc1, 0x0000, 0x0020, 0xac52, 0x1405, + 0x6ce2, 0x0024, 0x0000, 0x0024, 0x2801, 0x68c1, 0x68c2, 0x0024, 0x291a, + 0x8a40, 0x3e10, 0x0024, 0x2921, 0xca80, 0x3e00, 0x4024, 0x36f3, 0x0024, + 0x3009, 0x1bc8, 0x36f0, 0x1801, 0x3601, 0x5804, 0x3e13, 0x780f, 0x3e13, + 0xb808, 0x0008, 0x9b0f, 0x0001, 0x6bce, 0x2908, 0x9300, 0x0000, 0x004d, + 0x36f3, 0x9808, 0x2000, 0x0000, 0x36f3, 0x580f, 0x0007, 0x81d7, 0x3711, + 0x8024, 0x3711, 0xc024, 0x3700, 0x0024, 0x0000, 0x2001, 0xb012, 0x0024, + 0x0034, 0x0000, 0x2801, 0x6f05, 0x0000, 0x01c1, 0x0030, 0x0117, 0x3f00, + 0x0024, 0x0014, 0xc000, 0x0000, 0x01c1, 0x4fce, 0x0024, 0xffea, 0x0024, + 0x48b6, 0x0024, 0x4384, 0x4097, 0xb886, 0x45c6, 0xfede, 0x0024, 0x4db6, + 0x0024, 0x466c, 0x0024, 0x0006, 0xc610, 0x8dd6, 0x8007, 0x0000, 0x00c6, + 0xff6e, 0x0024, 0x48b2, 0x0024, 0x0034, 0x2406, 0xffee, 0x0024, 0x2914, + 0xaa80, 0x40b2, 0x0024, 0xf1c6, 0x0024, 0xf1d6, 0x0024, 0x0000, 0x0201, + 0x8d86, 0x0024, 0x61de, 0x0024, 0x0006, 0xc612, 0x2801, 0x7581, 0x0006, + 0xc713, 0x4c86, 0x0024, 0x2912, 0x1180, 0x0006, 0xc351, 0x0006, 0x0210, + 0x2912, 0x0d00, 0x3810, 0x984c, 0xf200, 0x2043, 0x2808, 0xa000, 0x3800, + 0x0024, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, + 0x7810, 0x3e14, 0x7812, 0x3e14, 0xc024, 0x2922, 0x1880, 0x0000, 0x0180, + 0x2921, 0xdd40, 0x6892, 0x184c, 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, + 0x7cc5, 0x0000, 0x0024, 0x2801, 0xb840, 0xb880, 0x0024, 0x2921, 0xdd40, + 0x6892, 0x184c, 0x4080, 0x0024, 0x0000, 0x0181, 0x2801, 0x7ed5, 0x0000, + 0x0024, 0x2801, 0xb840, 0xb880, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0101, 0x2801, 0x80c5, 0x0000, 0x0024, 0x2801, + 0xb840, 0xb880, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, + 0x0000, 0x00c1, 0x2801, 0x82c5, 0x0000, 0x0024, 0x2801, 0xb840, 0xb880, + 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, 0x0000, 0x0141, + 0x2801, 0x84c5, 0x0006, 0xf250, 0x2801, 0xb840, 0xb880, 0x0024, 0x2921, + 0xdd40, 0x3613, 0x0024, 0x0000, 0x0101, 0x2921, 0xdd40, 0x3613, 0x2000, + 0x0000, 0x03c1, 0x6012, 0x03cc, 0x3613, 0x2000, 0x2801, 0x8a15, 0x0006, + 0xf051, 0x3009, 0x3841, 0x2921, 0xdd40, 0x0000, 0x0201, 0xb080, 0x024c, + 0x3009, 0x2000, 0x2921, 0xdd40, 0x0000, 0x0401, 0x3009, 0x0401, 0xc100, + 0x0024, 0x2801, 0x8b40, 0x3009, 0x2400, 0x3009, 0x0002, 0x2920, 0x5d00, + 0x3e00, 0x8024, 0x36f3, 0x024c, 0x3009, 0x2000, 0x0000, 0x0101, 0x2921, + 0xdd40, 0x3613, 0x0024, 0x0000, 0x0141, 0x3013, 0x0024, 0x3009, 0x21c0, + 0x3009, 0x0000, 0x6012, 0x0024, 0x0007, 0x1b51, 0x2801, 0x9c95, 0x0000, + 0x0101, 0x0007, 0xc251, 0x2921, 0xdd40, 0x3613, 0x0024, 0x0000, 0x03c1, + 0x6012, 0x2400, 0x3100, 0x984c, 0x2801, 0x93d5, 0x0007, 0xc292, 0x3009, + 0x3841, 0x2921, 0xdd40, 0x0000, 0x0201, 0x4082, 0x044c, 0xb080, 0x0024, + 0x3910, 0x0024, 0x39f0, 0x7841, 0x2921, 0xdd40, 0x0000, 0x0401, 0x3211, + 0x1bcc, 0xb182, 0x0bc5, 0xcec2, 0x0024, 0x3a10, 0x0024, 0x2801, 0x9500, + 0x3af0, 0x4024, 0x2920, 0x5d00, 0x3e00, 0x8024, 0x36f3, 0x044c, 0x3910, + 0x0024, 0x39f0, 0x4024, 0x0007, 0x1b52, 0x0000, 0x0141, 0x2921, 0xdd40, + 0x3613, 0x0024, 0x3111, 0x2240, 0xb880, 0x03cc, 0x31f1, 0x6800, 0xb182, + 0x8000, 0x6ce6, 0x0024, 0x002e, 0xe002, 0x2801, 0xa385, 0xb886, 0x0024, + 0x6de2, 0x0b8c, 0x0000, 0x00c1, 0x2801, 0x9b51, 0x3009, 0x0800, 0xb010, + 0x0024, 0x4192, 0x0024, 0x6012, 0x0024, 0x0007, 0x1b52, 0x2801, 0x9b58, + 0x0000, 0x0024, 0x6890, 0xa004, 0x2801, 0xa380, 0x3009, 0x2800, 0x4e82, + 0x0024, 0x0000, 0x0020, 0xf2c2, 0x0024, 0x2801, 0xa380, 0x3009, 0x2000, + 0x3009, 0x07c0, 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, 0xa385, 0x0000, + 0x0024, 0x3093, 0x0400, 0x4080, 0x03cc, 0x0017, 0x7001, 0x2801, 0xa295, + 0x3009, 0x0000, 0x6012, 0x0024, 0x0007, 0x1b50, 0x2801, 0xa201, 0xb880, + 0x0024, 0x0000, 0x00c1, 0x31f3, 0x0024, 0x3009, 0x0400, 0xb010, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0000, 0x2801, 0xa289, 0x0000, 0x0024, 0x2801, + 0xa380, 0x3009, 0x2000, 0x0006, 0xf050, 0x3009, 0x0000, 0x4000, 0x0024, + 0x3009, 0x2000, 0x0000, 0x0081, 0x0006, 0xf250, 0x3009, 0x0000, 0x6012, + 0x0024, 0x0007, 0xc151, 0x2801, 0xa5c5, 0x0000, 0x0024, 0x2801, 0xb840, + 0xb880, 0x0024, 0x2921, 0xdd40, 0x6892, 0x184c, 0x6892, 0x2400, 0x2921, + 0xdd40, 0x3009, 0x184c, 0x4080, 0x0024, 0x0000, 0x0381, 0x2801, 0xa885, + 0x0000, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x2921, 0xdd40, 0x6892, + 0x184c, 0x4080, 0x0024, 0x0000, 0x0240, 0x2801, 0xab05, 0x0000, 0x00c1, + 0x2921, 0xdd40, 0x6892, 0x184c, 0x0000, 0x00c1, 0x0000, 0x0240, 0x0006, + 0x0592, 0x2922, 0x1880, 0x3613, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x4080, 0x2800, 0x0000, 0x0201, 0x2801, 0xae15, 0x3613, 0x0024, 0x2921, + 0xdd40, 0x0001, 0xb088, 0x3613, 0x0024, 0x4090, 0x1bcc, 0x0000, 0x0241, + 0x2801, 0xb015, 0x0006, 0x0613, 0x2921, 0xdd40, 0x3613, 0x0024, 0x2801, + 0xb080, 0x3b00, 0x0024, 0x2801, 0xb840, 0xb880, 0x0024, 0x0006, 0x0653, + 0xb880, 0x184c, 0x2921, 0xdd40, 0x6892, 0x2c00, 0x4080, 0x0024, 0x0006, + 0x0650, 0x2801, 0xb605, 0x0000, 0x4003, 0x3000, 0x184c, 0xff86, 0x0024, + 0x48b6, 0x0024, 0x2921, 0xdd40, 0x6892, 0x2002, 0x0000, 0x0201, 0x2921, + 0xdd40, 0x4088, 0x184c, 0x3000, 0x4024, 0x4100, 0x0024, 0x4488, 0x2000, + 0x0000, 0x4003, 0x2801, 0xb295, 0x0006, 0x0650, 0x2921, 0xdd40, 0x6892, + 0x184c, 0x4080, 0x0024, 0x0000, 0x0201, 0x2801, 0xb805, 0x0000, 0x0024, + 0x2921, 0xdd40, 0x3613, 0x0024, 0x6890, 0x0024, 0x36f4, 0xc024, 0x36f4, + 0x5812, 0x36f1, 0x5810, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e14, 0x3811, 0x0006, + 0x8a91, 0x0006, 0x05d0, 0x3e14, 0xb813, 0x0007, 0x8b52, 0x3e13, 0xf80e, + 0x3e03, 0x504c, 0xb880, 0x0024, 0x3c00, 0x33c0, 0x2921, 0xb380, 0x3800, + 0x0024, 0x2920, 0x6a00, 0x0030, 0x0253, 0x0000, 0x0400, 0xb882, 0xa440, + 0xb880, 0xa7c1, 0x3a00, 0x0024, 0x0013, 0x1040, 0x3b00, 0x0024, 0x0000, + 0x0180, 0x2922, 0x1880, 0x3613, 0x0024, 0x4f82, 0x0024, 0x003f, 0xf801, + 0xb010, 0x0024, 0x0015, 0xb801, 0x6012, 0x0024, 0x0007, 0x8a50, 0x2801, + 0xdfd5, 0x0000, 0x0201, 0x0006, 0x8a90, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x003f, 0xfe00, 0x3613, 0x0042, 0xb882, 0x83c3, 0xbdc2, 0x0024, 0x3009, + 0x2040, 0x2921, 0xdd40, 0x6892, 0xa3c1, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2801, 0xca95, 0x0000, 0x0024, 0x2901, 0x7780, 0x0006, 0x05d1, 0x4080, + 0x2400, 0x0006, 0xf052, 0x2801, 0xca85, 0x0000, 0x0024, 0x3613, 0x0841, + 0x3e10, 0x4802, 0x2909, 0xa9c0, 0x3e10, 0x8024, 0x36e3, 0x0024, 0x0006, + 0x05d1, 0x3100, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2921, 0xc305, + 0x0001, 0xdb48, 0x0006, 0x0592, 0xb880, 0x104c, 0x3613, 0x33c0, 0x2922, + 0x1880, 0x0000, 0x0100, 0x3200, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2900, 0x90d5, 0x0001, 0xd3c8, 0x0006, 0x0613, 0xb880, 0x0024, 0x0006, + 0x0610, 0x3b00, 0x0024, 0x0000, 0x0201, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x0000, 0x00c1, 0x3423, 0x0024, 0x3c00, 0x0024, 0xa010, 0x0001, 0x4100, + 0x0024, 0x0000, 0x3fc1, 0x3800, 0x0024, 0x34e0, 0x0024, 0x6012, 0x0024, + 0x0006, 0x0610, 0x2801, 0xcf85, 0x0000, 0x0024, 0x2900, 0x90c0, 0x0000, + 0x0024, 0x0006, 0x0650, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2801, 0xdac5, 0x0000, 0x0024, 0xf200, 0x184c, 0xf200, 0x0024, 0xf200, + 0x0024, 0xb182, 0x3840, 0x2921, 0xca80, 0x3e00, 0x4024, 0x0000, 0x01c1, + 0x291a, 0x8a40, 0x36e3, 0x0024, 0xb888, 0x4411, 0x3000, 0x0024, 0xb012, + 0x0024, 0x6410, 0x2001, 0x0000, 0x0024, 0x2801, 0xdac1, 0x0000, 0x0024, + 0x4192, 0x0024, 0x2401, 0xda81, 0x0000, 0x0024, 0x2921, 0xdd40, 0x6892, + 0x184c, 0x6498, 0x0024, 0x2921, 0xc300, 0x0000, 0x0024, 0x291a, 0x8a40, + 0x3413, 0x0024, 0xf400, 0x4512, 0x0030, 0x0010, 0x0000, 0x0201, 0x2900, + 0x0c80, 0x34f3, 0x0024, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0100, + 0x2801, 0xec95, 0x0000, 0x0401, 0x2922, 0x1880, 0x3613, 0x0024, 0x2921, + 0xdd40, 0x3613, 0x0024, 0x2801, 0xeac0, 0xb78e, 0x4006, 0x3000, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, 0xec89, 0xf292, 0x0024, 0x6012, + 0x904c, 0x0006, 0x05d1, 0x2801, 0xe318, 0x3100, 0x0024, 0x3000, 0x0024, + 0x4090, 0x0024, 0x3800, 0x0024, 0x3100, 0x0024, 0x4080, 0x4512, 0x34f3, + 0x184c, 0x2801, 0xe5d5, 0x0007, 0x0553, 0x36f3, 0x0800, 0x6090, 0x0024, + 0x4080, 0xa800, 0x0000, 0x0024, 0x2801, 0xec88, 0x0000, 0x0024, 0x3009, + 0x184c, 0x0006, 0xf312, 0x4ffe, 0xb841, 0x2921, 0xdd40, 0x6892, 0x41c7, + 0xb182, 0x9bcc, 0x291a, 0x8a40, 0xcfce, 0x0024, 0x0004, 0x0001, 0xb880, + 0x010c, 0x6890, 0x2000, 0x0007, 0x80d0, 0xb880, 0xa800, 0x3000, 0x2c00, + 0x0007, 0x1ad0, 0xff82, 0x0024, 0x48b2, 0x0024, 0xf400, 0x4040, 0x0000, + 0x03c1, 0xb010, 0x0024, 0x3009, 0x2000, 0x0000, 0x0201, 0x0030, 0x0010, + 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0180, 0x2801, 0xc1c5, 0x0000, + 0x0024, 0x6890, 0x1bcd, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, + 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, + 0xb804, 0x3e01, 0x534c, 0xbe8a, 0x10c0, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2801, 0xf6c5, 0x0000, 0x0024, 0x2903, 0xa300, 0x4082, 0x184c, 0x4c8a, + 0x134c, 0x0000, 0x0001, 0x6890, 0x10c2, 0x4294, 0x0024, 0xac22, 0x0024, + 0xbec2, 0x0024, 0x0000, 0x0024, 0x2801, 0xf6c5, 0x0000, 0x0024, 0x6890, + 0x134c, 0xb882, 0x10c2, 0xac22, 0x0024, 0x4c92, 0x0024, 0xdc92, 0x0024, + 0xceca, 0x0024, 0x4e82, 0x1bc5, 0x36f0, 0x9804, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3645, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, + 0x3e14, 0x104c, 0x2903, 0x9bc0, 0x0000, 0x0081, 0x4080, 0x3040, 0x0000, + 0x0101, 0x2801, 0xfdc5, 0x0000, 0x0024, 0x4090, 0x0024, 0x0006, 0x8050, + 0x2802, 0x11d5, 0x0000, 0x0024, 0x2903, 0x9bc0, 0x3613, 0x0024, 0xb880, + 0x3000, 0x2802, 0x0f80, 0x3009, 0x3380, 0x2903, 0x9bc0, 0x4122, 0x10cc, + 0x3cf0, 0x0024, 0x3001, 0x0024, 0x3400, 0x0024, 0x6800, 0x0024, 0xa408, + 0x9040, 0x4080, 0x0024, 0x0000, 0x07c1, 0x2802, 0x0355, 0x6894, 0x1380, + 0x6894, 0x130c, 0x3460, 0x0024, 0x6408, 0x4481, 0x4102, 0x1380, 0xf400, + 0x4052, 0x0000, 0x07c1, 0x34f0, 0xc024, 0x6234, 0x0024, 0x6824, 0x0024, + 0xa122, 0x0024, 0x6014, 0x0024, 0x0000, 0x0141, 0x2802, 0x0a55, 0x0000, + 0x0024, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x2802, 0x08c0, 0xb88a, 0x4002, + 0x2901, 0xef40, 0x3e00, 0x8024, 0x4c8e, 0xa801, 0x0000, 0x0201, 0x3a10, + 0x1bcc, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, 0x2802, 0x0e55, + 0x659a, 0x0024, 0x6540, 0x184c, 0x0030, 0x0010, 0x2802, 0x0648, 0x0000, + 0x0024, 0x2802, 0x0e40, 0x36f3, 0x0024, 0x2802, 0x0d00, 0xb88a, 0x0024, + 0x2903, 0x74c0, 0x34d0, 0x4024, 0x4c8f, 0xa0a1, 0x0000, 0x0201, 0x3000, + 0x084c, 0xb010, 0x0024, 0x0000, 0x0024, 0x2802, 0x0e55, 0x659a, 0x0024, + 0x6540, 0x10cc, 0x0030, 0x0010, 0x2802, 0x0ac8, 0x0000, 0x0024, 0x34d3, + 0x0024, 0x3423, 0x0024, 0xf400, 0x4510, 0x3009, 0x1380, 0x6090, 0x0024, + 0x3009, 0x2000, 0x6892, 0x108c, 0x34f0, 0x9000, 0xa122, 0x984c, 0x6016, + 0x13c1, 0x0000, 0x0102, 0x2801, 0xff08, 0x0006, 0x8150, 0x2802, 0x1240, + 0x3009, 0x1bcc, 0x6890, 0x938c, 0x3800, 0x0024, 0x36f4, 0x0024, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb804, 0x3e11, 0xb807, 0x3e14, + 0x3811, 0x3e04, 0x934c, 0x3430, 0x0024, 0x4080, 0x0024, 0x0000, 0x0206, + 0x2802, 0x1b45, 0x0006, 0x8151, 0x3101, 0x130c, 0xff0c, 0x1102, 0x6408, + 0x0024, 0x4204, 0x0024, 0xb882, 0x4092, 0x1005, 0xfe02, 0x48be, 0x0024, + 0x4264, 0x0024, 0x2903, 0xe080, 0xf400, 0x4090, 0x36f4, 0x8024, 0x36f4, + 0x1811, 0x36f1, 0x9807, 0x36f0, 0x9804, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3675, 0x0024, + 0x3643, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, 0x0181, 0x3e10, + 0xb803, 0x3e11, 0x3806, 0x3e11, 0xf810, 0x3e14, 0x7812, 0x3e13, 0xf80e, + 0x2903, 0x7dc0, 0x3e03, 0x4024, 0x2903, 0x9bc0, 0x4088, 0x184c, 0x3413, + 0x184c, 0x2903, 0x9bc0, 0x6892, 0x3040, 0x4080, 0x3040, 0x0000, 0x0000, + 0x2802, 0x28c5, 0x0000, 0x0024, 0x6890, 0x0024, 0x2903, 0x7dc0, 0x3cd0, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2802, 0x2915, 0x0000, 0x0024, + 0x3433, 0x0024, 0xf400, 0x4510, 0x34d0, 0x0024, 0x6090, 0x0024, 0x2903, + 0x7dc0, 0x3800, 0x0024, 0x4080, 0x10cc, 0xf400, 0x4510, 0x2802, 0x2685, + 0x34d0, 0x0024, 0x2802, 0x2900, 0x0000, 0x0024, 0x3cd0, 0x0024, 0x3433, + 0x0024, 0x34a0, 0x0024, 0xf400, 0x4510, 0x3430, 0x4024, 0x6100, 0x0024, + 0x0000, 0x0341, 0x3840, 0x0024, 0x3000, 0x0024, 0x6012, 0x0024, 0x0006, + 0x0681, 0x2802, 0x4681, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, + 0x2000, 0x0000, 0x0000, 0x0024, 0x34d3, 0x184c, 0x3430, 0x8024, 0x2901, + 0xef40, 0x3e00, 0x8024, 0x36f3, 0x11cc, 0xb888, 0x104c, 0x3c10, 0x0024, + 0x3c90, 0x4024, 0x2802, 0x3240, 0x34e3, 0x0024, 0x3411, 0x8024, 0x3491, + 0xc024, 0x4f82, 0x128c, 0x3400, 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, + 0x3800, 0x0024, 0x3440, 0x4024, 0x4142, 0x0024, 0x6498, 0x4050, 0x3009, + 0x2007, 0x0006, 0x8150, 0x3000, 0x11cc, 0x6402, 0x104c, 0x0000, 0x0024, + 0x2802, 0x2f88, 0x0000, 0x0024, 0x3493, 0x0024, 0x2802, 0x6240, 0x34f3, + 0x0024, 0x2802, 0x39c0, 0xb888, 0x0024, 0x3430, 0x8024, 0x2901, 0xef40, + 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, 0x5bcc, 0x4142, 0x0024, 0xf400, + 0x4050, 0x3800, 0x0024, 0x3440, 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, + 0x0000, 0x0201, 0x3009, 0x2007, 0x0030, 0x0010, 0x3000, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2802, 0x6255, 0x6498, 0x0024, 0x0006, 0x8150, + 0x3000, 0x134c, 0x6402, 0x984c, 0x0000, 0x0024, 0x2802, 0x3508, 0x0000, + 0x0024, 0x2802, 0x6240, 0x3433, 0x1bcc, 0x0000, 0x0201, 0xb888, 0x104c, + 0x3430, 0x184c, 0x6010, 0x0024, 0x6402, 0x3000, 0x0000, 0x0201, 0x2802, + 0x4258, 0x0030, 0x0010, 0x4090, 0x124c, 0x2402, 0x4140, 0x0000, 0x0024, + 0x3430, 0x8024, 0x2901, 0xef40, 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, + 0x4024, 0x4142, 0x0024, 0xf400, 0x4050, 0x3800, 0x0024, 0x3410, 0x4024, + 0x4142, 0x0024, 0x6498, 0x4050, 0x3009, 0x2007, 0x0030, 0x0010, 0x0000, + 0x0201, 0x3473, 0x0024, 0x3490, 0x0024, 0x3e00, 0x13cc, 0x2901, 0xf880, + 0x3444, 0x8024, 0x3000, 0x1bcc, 0xb010, 0x0024, 0x0000, 0x0024, 0x2802, + 0x6255, 0x0000, 0x0024, 0x34c3, 0x184c, 0x3470, 0x0024, 0x3e10, 0x104c, + 0x34c0, 0x4024, 0x2902, 0x14c0, 0x3e00, 0x4024, 0x2802, 0x6240, 0x36e3, + 0x0024, 0x0000, 0x0801, 0x3413, 0x0024, 0x34f0, 0x0024, 0x6012, 0x0024, + 0x0000, 0x07c1, 0x2802, 0x6188, 0x0000, 0x0024, 0x6010, 0x114c, 0xb888, + 0x32c0, 0x6402, 0x0024, 0x0000, 0x0101, 0x2802, 0x4e18, 0x0000, 0x0024, + 0x4090, 0x134c, 0x2402, 0x4d40, 0x3009, 0x184c, 0x3430, 0x8024, 0x2901, + 0xef40, 0x3e00, 0x8024, 0x4c8e, 0x130c, 0x3400, 0x4024, 0x4142, 0x0024, + 0xf400, 0x4050, 0x3800, 0x0024, 0x3410, 0x4024, 0x4142, 0x0024, 0x6498, + 0x4050, 0x3009, 0x2007, 0x0000, 0x0101, 0x3433, 0x1bcc, 0x2903, 0x9bc0, + 0x3613, 0x0024, 0x0000, 0x0141, 0x6090, 0x118c, 0x2903, 0x9bc0, 0x3ca0, + 0x184c, 0x3473, 0x184c, 0xb888, 0x3380, 0x3400, 0x0024, 0x6402, 0x0024, + 0x0000, 0x0201, 0x2802, 0x54d8, 0x0000, 0x0024, 0x4090, 0x104c, 0x2402, + 0x5400, 0x0000, 0x0024, 0x34a0, 0x8024, 0x2901, 0xef40, 0x3e00, 0x8024, + 0x0006, 0x8002, 0x4244, 0x118c, 0x4244, 0x0024, 0x6498, 0x4095, 0x3009, + 0x3440, 0x3009, 0x37c1, 0x0000, 0x0201, 0x34f3, 0x0024, 0x0030, 0x0010, + 0x3490, 0x0024, 0x3e00, 0x138c, 0x2901, 0xf880, 0x3444, 0x8024, 0x3000, + 0x1bcc, 0xb010, 0x0024, 0x0000, 0x0024, 0x2802, 0x6255, 0x4112, 0x0024, + 0x3463, 0x0024, 0x34a0, 0x0024, 0x6012, 0x0024, 0x0006, 0x8111, 0x2802, + 0x5e19, 0x0000, 0x0024, 0x3100, 0x11cc, 0x3490, 0x4024, 0x4010, 0x0024, + 0x0000, 0x0a01, 0x6012, 0x0024, 0x0006, 0x8151, 0x2802, 0x5e18, 0x0000, + 0x0024, 0x3613, 0x114c, 0x3101, 0x3804, 0x3490, 0x8024, 0x6428, 0x138c, + 0x3470, 0x8024, 0x3423, 0x0024, 0x3420, 0xc024, 0x4234, 0x1241, 0x4380, + 0x4092, 0x2903, 0xe080, 0x0006, 0x8010, 0x2802, 0x6240, 0x3009, 0x1bcc, + 0x0006, 0x8151, 0x3613, 0x114c, 0x3101, 0x3804, 0x3490, 0x8024, 0x6428, + 0x138c, 0x3470, 0x8024, 0x3423, 0x0024, 0x3420, 0xc024, 0x4234, 0x1241, + 0x4380, 0x4092, 0x2903, 0xea40, 0x0006, 0x8010, 0x2802, 0x6240, 0x3009, + 0x1bcc, 0x0006, 0x8050, 0x6890, 0x0024, 0x3800, 0x0024, 0x3433, 0x0024, + 0x34d0, 0x0024, 0x4080, 0x0024, 0x0006, 0x8150, 0x2802, 0x67c5, 0x0000, + 0x0024, 0x3000, 0x11cc, 0xb888, 0x10cc, 0x6402, 0x3240, 0x3493, 0x0024, + 0x3444, 0x8024, 0x2802, 0x67d8, 0x4090, 0x0024, 0x2402, 0x6780, 0x0000, + 0x0024, 0x6499, 0x2620, 0xb78e, 0x4001, 0x0000, 0x0000, 0x3433, 0x0024, + 0xcfce, 0x1340, 0xaf0e, 0x0024, 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, + 0xd80e, 0x36f4, 0x5812, 0x36f1, 0xd810, 0x36f1, 0x1806, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, + 0xf804, 0x0000, 0x3fc3, 0x3e11, 0x7806, 0x3e11, 0xf810, 0xbc82, 0x12cc, + 0x3404, 0x0024, 0x3023, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x3454, + 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x2903, 0x9bc0, 0x0000, 0x0201, + 0x0006, 0x9301, 0x4088, 0x134c, 0x3400, 0x8024, 0xd204, 0x0024, 0xb234, + 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, 0x3c30, 0x0024, + 0x0000, 0x2000, 0xb400, 0x0024, 0x0000, 0x3001, 0x2802, 0x7555, 0x0000, + 0x3800, 0x0000, 0x0041, 0xfe42, 0x12cc, 0x48b2, 0x1090, 0x3810, 0x0024, + 0x38f0, 0x4024, 0x2802, 0x9640, 0x3430, 0x0024, 0xb400, 0x0024, 0x6012, + 0x0024, 0x0000, 0x3801, 0x2802, 0x7895, 0x0000, 0x3c00, 0x0000, 0x07c0, + 0x0000, 0x0041, 0xb400, 0x12cc, 0xfe02, 0x1150, 0x48b2, 0x0024, 0x689a, + 0x2040, 0x2802, 0x9500, 0x38f0, 0x4024, 0xb400, 0x0024, 0x6012, 0x0024, + 0x0000, 0x3c01, 0x2802, 0x7c15, 0x0000, 0x3e00, 0x0000, 0x03c0, 0x0000, + 0x0085, 0x4592, 0x12cc, 0xb400, 0x1150, 0xfe02, 0x0024, 0x48b2, 0x0024, + 0x3810, 0x0024, 0x2802, 0x9500, 0x38f0, 0x4024, 0xb400, 0x0024, 0x6012, + 0x0024, 0x0000, 0x3e01, 0x2802, 0x7f95, 0x0000, 0x3f00, 0x0000, 0x01c0, + 0xf20a, 0x12cc, 0xb400, 0x1150, 0xf252, 0x0024, 0xfe02, 0x0024, 0x48b2, + 0x0024, 0x3810, 0x0024, 0x2802, 0x9500, 0x38f0, 0x4024, 0xb400, 0x130c, + 0x6012, 0x0024, 0x0000, 0x3f01, 0x2802, 0x8315, 0x4390, 0x0024, 0x0000, + 0x0041, 0x0000, 0x0105, 0x4590, 0x13cc, 0xb400, 0x1150, 0xfe02, 0x0024, + 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0x9500, 0x38f0, 0x4024, 0xb400, + 0x0024, 0x6012, 0x1100, 0x0000, 0x01c1, 0x2802, 0x8695, 0x0000, 0x0024, + 0x0000, 0x0041, 0x0000, 0x0145, 0x6890, 0x12cc, 0xb400, 0x1150, 0xfe02, + 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2802, 0x9500, 0x38f0, 0x4024, + 0x6012, 0x0024, 0x0000, 0x3f81, 0x2802, 0x8915, 0xb430, 0x0024, 0x6012, + 0x0024, 0x0000, 0x0024, 0x2802, 0x8915, 0x0000, 0x0024, 0x2802, 0x9500, + 0x0000, 0x0185, 0x2802, 0x9640, 0xc890, 0x0024, 0x0000, 0x3fc3, 0x0000, + 0x0201, 0x34d3, 0x0024, 0x2903, 0x9bc0, 0x3433, 0x184c, 0x0006, 0x9301, + 0x4088, 0x134c, 0x3400, 0x8024, 0xd204, 0x0024, 0xb234, 0x0024, 0x4122, + 0x0024, 0xf400, 0x4055, 0x0000, 0x2001, 0x3500, 0x0024, 0x3c30, 0x0024, + 0x0000, 0x3000, 0xb400, 0x0024, 0x6012, 0x0024, 0x0000, 0x0182, 0x2802, + 0x8f45, 0x0000, 0x0024, 0x2802, 0x9640, 0xc890, 0x0024, 0x459a, 0x12cc, + 0x3404, 0x0024, 0x3023, 0x0024, 0x3010, 0x0024, 0x30d0, 0x4024, 0xac22, + 0x0046, 0x003f, 0xf982, 0x3011, 0xc024, 0x0000, 0x0023, 0xaf2e, 0x0024, + 0x0000, 0x0182, 0xccf2, 0x0024, 0x0000, 0x0fc6, 0x0000, 0x0047, 0xb46c, + 0x2040, 0xfe6e, 0x23c1, 0x3454, 0x0024, 0x3010, 0x0024, 0x30f0, 0x4024, + 0xac22, 0x0024, 0xccb2, 0x0024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x458a, + 0x134c, 0x0000, 0x0201, 0x2802, 0x8a55, 0x0000, 0x3fc3, 0x3430, 0x0024, + 0x36f1, 0xd810, 0x36f1, 0x5806, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3675, + 0x0024, 0x3633, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, 0x3e13, + 0xf80e, 0x3e03, 0x4024, 0x2903, 0xc780, 0x0000, 0x0381, 0x000f, 0xff81, + 0x6012, 0x0024, 0x0000, 0x0401, 0x2802, 0x9f05, 0x0000, 0x0024, 0x0000, + 0x0201, 0x3613, 0x0024, 0x2903, 0x9bc0, 0x0003, 0x5508, 0x003f, 0xfe04, + 0x0006, 0x8090, 0xb880, 0x11cc, 0x3413, 0x184c, 0x3c90, 0x0024, 0x2903, + 0x9bc0, 0x34f3, 0x0024, 0x0006, 0x9301, 0x3473, 0x184c, 0x3c10, 0x0024, + 0x34f0, 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, + 0x3500, 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0x6892, + 0x4055, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x34a0, 0x0024, 0xf100, 0x0024, + 0xb010, 0x0024, 0x3c60, 0x0024, 0x34b0, 0x0024, 0xb010, 0x0024, 0x0000, + 0x0201, 0x2903, 0x9bc0, 0x3ce0, 0x0024, 0x0006, 0x9301, 0x3473, 0x184c, + 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x003f, 0xff01, + 0x3500, 0x0024, 0x3cf0, 0x0024, 0x34c0, 0x0024, 0xa010, 0x0024, 0x0000, + 0x03c1, 0x3c40, 0x0024, 0x34d0, 0x0024, 0xb010, 0x0024, 0x0000, 0x0201, + 0x2903, 0x9bc0, 0x3cc0, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, + 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, 0x3fc3, + 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x003f, 0xff01, 0x3500, + 0x0024, 0x3cf0, 0x0024, 0x3400, 0x0024, 0xa010, 0x0024, 0x0000, 0x01c1, + 0x3800, 0x0024, 0x34e0, 0x0024, 0xf100, 0x0024, 0xb010, 0x0024, 0x6892, + 0x3080, 0x34f0, 0x0024, 0xb010, 0x0024, 0x3cb0, 0x0024, 0x3450, 0x0024, + 0x34a0, 0x4024, 0xc010, 0x0024, 0x0000, 0x0181, 0x2802, 0xb585, 0x3000, + 0x0024, 0x6890, 0x03cc, 0x2803, 0x5500, 0x3800, 0x0024, 0x6012, 0x0024, + 0x0000, 0x0201, 0x2802, 0xb718, 0x0000, 0x0024, 0x2802, 0xba00, 0x6090, + 0x004c, 0x6012, 0x0024, 0x0000, 0x0281, 0x2802, 0xb948, 0x6012, 0x0024, + 0x0000, 0x0080, 0x2802, 0xb959, 0x0000, 0x0024, 0x2802, 0xba00, 0x3013, + 0x0024, 0x6890, 0x03cc, 0x2803, 0x5500, 0x3800, 0x0024, 0x0000, 0x0201, + 0x3800, 0x114c, 0x34b0, 0x0024, 0x6012, 0x0024, 0x0006, 0x09c1, 0x2802, + 0xc441, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, 0x0000, + 0x0000, 0x0024, 0x2802, 0xc440, 0x0000, 0x0024, 0x0000, 0x0200, 0x0006, + 0x8110, 0x2802, 0xc440, 0x3800, 0x0024, 0x0000, 0x0300, 0x0006, 0x8110, + 0x2802, 0xc440, 0x3800, 0x0024, 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, + 0x5500, 0x3800, 0x0024, 0x0000, 0x0400, 0x0006, 0x8110, 0x2802, 0xc440, + 0x3800, 0x0024, 0x0000, 0x0500, 0x0006, 0x8110, 0x2802, 0xc440, 0x3800, + 0x0024, 0x0000, 0x0600, 0x0006, 0x8110, 0x2802, 0xc440, 0x3800, 0x0024, + 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, 0x3423, + 0x184c, 0x3460, 0x0024, 0x4080, 0x0024, 0x0006, 0x8200, 0x2802, 0xc985, + 0x3e10, 0x0024, 0x0000, 0x01c0, 0x3e10, 0x0024, 0x3490, 0x0024, 0x2902, + 0x6ac0, 0x3e00, 0x13cc, 0x36d3, 0x11cc, 0x3413, 0x0024, 0x4080, 0x3240, + 0x34f3, 0x0024, 0x2802, 0xcd58, 0x0000, 0x0024, 0x0006, 0x8010, 0x6890, + 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, 0x0000, 0x0180, 0x3e10, 0x0024, + 0x3490, 0x0024, 0x2902, 0x6ac0, 0x3e00, 0x13cc, 0x36d3, 0x11cc, 0x3413, + 0x0024, 0x4080, 0x3240, 0x34f3, 0x0024, 0x2802, 0xcd58, 0x0000, 0x0024, + 0x0006, 0x8010, 0x6890, 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, 0x0000, + 0x0201, 0x3433, 0x0024, 0x34d0, 0x0024, 0x6012, 0x0024, 0x0006, 0x0bc1, + 0x2802, 0xdf41, 0x4012, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, + 0x0000, 0x0000, 0x0024, 0x0006, 0x8050, 0x6890, 0x0024, 0x2803, 0x5500, + 0x3800, 0x0024, 0x0000, 0x3000, 0x2802, 0xe100, 0x0006, 0x8150, 0x0000, + 0x9000, 0x0006, 0x8150, 0x3433, 0x0024, 0x34d0, 0x4024, 0x4192, 0x0024, + 0x4192, 0x0024, 0x2802, 0xe100, 0xa010, 0x0024, 0x0000, 0x0201, 0x0006, + 0x8150, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, + 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, + 0x3cf0, 0x0024, 0x3490, 0x0024, 0x2802, 0xe100, 0x6090, 0x0024, 0x003f, + 0xfe04, 0x0000, 0x0401, 0x0006, 0x8150, 0x2903, 0x9bc0, 0x3613, 0x0024, + 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3400, + 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, 0x3fc3, 0xb234, 0x0024, + 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, 0x3500, 0x0024, 0xd024, + 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, 0x4055, 0x3500, 0x0024, + 0x3cf0, 0x0024, 0x3490, 0x0024, 0x2802, 0xe100, 0x6090, 0x0024, 0x0000, + 0x4000, 0x0000, 0x0202, 0x0006, 0x8150, 0x3433, 0x0024, 0x34d0, 0x4024, + 0x6122, 0x0024, 0xa010, 0x0024, 0x0004, 0x8001, 0x3800, 0x110c, 0x0006, + 0x8150, 0x3000, 0x0024, 0x6012, 0x1300, 0x0000, 0x0401, 0x2802, 0xe3c9, + 0x0000, 0x0024, 0x6890, 0x82cc, 0x2803, 0x5500, 0x3800, 0x0024, 0x6012, + 0x0024, 0x0006, 0x0dc1, 0x2803, 0x0b41, 0x4012, 0x0024, 0xf400, 0x4057, + 0x3702, 0x0024, 0x2000, 0x0000, 0x0000, 0x0024, 0x2803, 0x0b40, 0x0000, + 0x0024, 0x0016, 0x2200, 0x0006, 0x8190, 0x6892, 0x2040, 0x2803, 0x0b40, + 0x38f0, 0x4024, 0x002c, 0x4400, 0x0000, 0x0081, 0x0006, 0x8190, 0x3810, + 0x0024, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x003b, 0x8000, 0x0000, 0x0081, + 0x0006, 0x8190, 0x3810, 0x0024, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x0007, + 0xd000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2803, 0x0b40, 0x38f0, 0x4024, + 0x000f, 0xa000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2803, 0x0b40, 0x38f0, + 0x4024, 0x0015, 0x8880, 0x0006, 0x8190, 0xb882, 0x2040, 0x2803, 0x0b40, + 0x38f0, 0x4024, 0x0017, 0x7000, 0x0006, 0x8190, 0xb882, 0x2040, 0x2803, + 0x0b40, 0x38f0, 0x4024, 0x001f, 0x4000, 0x0006, 0x8190, 0xb882, 0x2040, + 0x2803, 0x0b40, 0x38f0, 0x4024, 0x002b, 0x1100, 0x0006, 0x8190, 0xb882, + 0x2040, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x002e, 0xe000, 0x0006, 0x8190, + 0xb882, 0x2040, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x001d, 0xc000, 0x0006, + 0x8190, 0x6892, 0x2040, 0x2803, 0x0b40, 0x38f0, 0x4024, 0x0006, 0x8190, + 0x0000, 0x0201, 0x0000, 0xfa04, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x0006, + 0x9301, 0xb88a, 0x11cc, 0x3c10, 0x0024, 0x34f0, 0x8024, 0x3410, 0xc024, + 0xd234, 0x0024, 0x0000, 0x3fc3, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, + 0x4055, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x3490, 0x0024, 0xfe50, 0x4005, + 0x48b2, 0x0024, 0xfeca, 0x0024, 0x40b2, 0x0024, 0x3810, 0x0024, 0x2803, + 0x0b40, 0x38f0, 0x4024, 0x003f, 0xfe04, 0x0000, 0x0401, 0x0006, 0x8190, + 0x2903, 0x9bc0, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, + 0x0024, 0x34f0, 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, + 0x0000, 0x3fc3, 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, + 0x9301, 0x3500, 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, + 0xf400, 0x4055, 0x0000, 0x0041, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x3490, + 0x0024, 0xfe02, 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2803, 0x0b40, + 0x38f0, 0x4024, 0x003f, 0xfe04, 0x0000, 0x0401, 0x0006, 0x8190, 0x2903, + 0x9bc0, 0x3613, 0x0024, 0x0006, 0x9301, 0x3473, 0x0024, 0x3c10, 0x0024, + 0x34f0, 0x8024, 0x3400, 0xc024, 0xa346, 0x0024, 0xd234, 0x0024, 0x0000, + 0x3fc3, 0xb234, 0x0024, 0x4122, 0x1042, 0xf400, 0x4055, 0x0006, 0x9301, + 0x3500, 0x0024, 0xd024, 0x3000, 0xb234, 0x0024, 0x4122, 0x0024, 0xf400, + 0x4055, 0x3500, 0x0024, 0x3cf0, 0x0024, 0x0000, 0x0280, 0x3490, 0x4024, + 0xfe02, 0x0024, 0x48b2, 0x0024, 0x3810, 0x0024, 0x2803, 0x0b40, 0x38f0, + 0x4024, 0x0006, 0x8010, 0x6890, 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, + 0x0000, 0x0201, 0x2903, 0x9bc0, 0x3613, 0x11cc, 0x3c10, 0x0024, 0x3490, + 0x4024, 0x6014, 0x13cc, 0x0000, 0x0081, 0x2803, 0x0e85, 0x0006, 0x80d0, + 0x0006, 0x8010, 0x6890, 0x0024, 0x2803, 0x5500, 0x3800, 0x0024, 0x3000, + 0x0024, 0x6012, 0x0024, 0x0000, 0x0241, 0x2803, 0x1309, 0x0000, 0x0024, + 0x6890, 0x034c, 0xb882, 0x2000, 0x0006, 0x8310, 0x2914, 0xbec0, 0x0000, + 0x1000, 0x0000, 0x0800, 0x3613, 0x0024, 0x3e10, 0x0024, 0x0006, 0x8300, + 0x290c, 0x7300, 0x3e10, 0x0024, 0x2803, 0x5500, 0x36e3, 0x0024, 0x0006, + 0x8110, 0x30e1, 0x184c, 0x3000, 0x0024, 0x6012, 0x0024, 0x0008, 0x0001, + 0x2803, 0x1515, 0x0000, 0x0024, 0x6498, 0x0024, 0x3e10, 0x4024, 0x0000, + 0x0081, 0x2902, 0x1dc0, 0x3e01, 0x0024, 0x36e3, 0x004c, 0x3000, 0x0024, + 0x6012, 0x0024, 0x000b, 0x8011, 0x2803, 0x20d5, 0x0006, 0x8112, 0x0000, + 0x0201, 0x0004, 0x0010, 0x2915, 0x8300, 0x0001, 0x0000, 0x000b, 0x8011, + 0x0005, 0x0010, 0x291f, 0xc6c0, 0x0001, 0x0000, 0x0006, 0x8110, 0x30e1, + 0x0024, 0x3000, 0x0024, 0x6012, 0x0024, 0x0000, 0x0281, 0x2803, 0x1c45, + 0x6012, 0x0024, 0x000b, 0x8001, 0x2803, 0x1cd5, 0x3613, 0x0024, 0x36f3, + 0x0024, 0x000b, 0x8001, 0x6498, 0x184c, 0x0006, 0x8112, 0x0003, 0x8000, + 0x3e10, 0x4024, 0x2902, 0x1dc0, 0x3e01, 0x0024, 0x36f3, 0x0024, 0x3009, + 0x3844, 0x3e10, 0x0024, 0x0000, 0x0400, 0x3000, 0x8024, 0x0008, 0x0010, + 0x3e00, 0x8024, 0x3201, 0x0024, 0x6408, 0x4051, 0x2903, 0x8740, 0x0003, + 0x2388, 0x0000, 0x0400, 0x0000, 0x0011, 0x3613, 0x008c, 0x30d0, 0x7844, + 0x3e10, 0x4024, 0x3000, 0x8024, 0x0008, 0x0010, 0x3e00, 0x8024, 0x3201, + 0x0024, 0x2903, 0x8740, 0x6408, 0x0024, 0x0006, 0x8a10, 0x0000, 0x01c1, + 0x36e3, 0x0000, 0xb010, 0x9bc4, 0x0000, 0x0024, 0x2803, 0x2785, 0x0000, + 0x0024, 0x6192, 0x184c, 0x2903, 0x9bc0, 0x6102, 0x0024, 0x4088, 0x0024, + 0x0000, 0x0024, 0x2803, 0x2785, 0x0000, 0x0024, 0x6890, 0x0b4c, 0x3a00, + 0x0024, 0x0000, 0x0401, 0x2903, 0x9bc0, 0x3613, 0x11cc, 0x3413, 0x0024, + 0x3c90, 0x0024, 0x290b, 0x1400, 0x34f3, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0024, 0x2803, 0x5195, 0x0000, 0x0024, 0x3423, 0x0024, 0x34e0, 0x0024, + 0x4080, 0x0024, 0x0006, 0x8151, 0x2803, 0x2f05, 0x0000, 0x3200, 0x0000, + 0x0142, 0x0006, 0x8211, 0x3613, 0x0024, 0x3e00, 0x7800, 0x3111, 0x8024, + 0x31d1, 0xc024, 0xfef4, 0x4087, 0x48b6, 0x0440, 0xfeee, 0x07c1, 0x2914, + 0xa580, 0x42b6, 0x0024, 0x2803, 0x3300, 0x0007, 0x89d0, 0x0000, 0x0142, + 0x3613, 0x0024, 0x3e00, 0x7800, 0x3131, 0x8024, 0x3110, 0x0024, 0x31d0, + 0x4024, 0xfe9c, 0x4181, 0x48be, 0x0024, 0xfe82, 0x0440, 0x46be, 0x07c1, + 0xfef4, 0x4087, 0x48b6, 0x0024, 0xfeee, 0x0024, 0x2914, 0xa580, 0x42b6, + 0x0024, 0x0007, 0x89d0, 0x0006, 0x8191, 0x4c8a, 0x9800, 0xfed0, 0x4005, + 0x48b2, 0x0024, 0xfeca, 0x0024, 0x40b2, 0x0024, 0x3810, 0x0024, 0x38f0, + 0x4024, 0x3111, 0x8024, 0x468a, 0x0707, 0x2908, 0xbe80, 0x3101, 0x0024, + 0x3123, 0x11cc, 0x3100, 0x108c, 0x3009, 0x3000, 0x0004, 0x8000, 0x3009, + 0x1241, 0x6014, 0x138c, 0x000b, 0x8011, 0x2803, 0x3941, 0x0000, 0x0024, + 0x3473, 0x0024, 0x3423, 0x0024, 0x3009, 0x3240, 0x34e3, 0x0024, 0x2803, + 0x4fc0, 0x0008, 0x0012, 0x0006, 0x80d0, 0x2803, 0x3ac9, 0x0000, 0x0024, + 0xf400, 0x4004, 0x3000, 0x0024, 0x4090, 0x0024, 0xf400, 0x4480, 0x2803, + 0x4095, 0x000b, 0x8001, 0x0000, 0x0005, 0x6540, 0x0024, 0x0000, 0x0024, + 0x2803, 0x4bd8, 0x4490, 0x0024, 0x2403, 0x3fc0, 0x0000, 0x0024, 0x0006, + 0x8301, 0x4554, 0x0800, 0x4122, 0x0024, 0x659a, 0x4055, 0x0006, 0x8341, + 0x4122, 0x3400, 0xf400, 0x4055, 0x3210, 0x0024, 0x3d00, 0x0024, 0x2803, + 0x4bc0, 0x0000, 0x0024, 0x6014, 0x0024, 0x0001, 0x0000, 0x2803, 0x4815, + 0x0000, 0x0005, 0x0008, 0x0012, 0x0008, 0x0010, 0x0003, 0x8001, 0x0006, + 0x8153, 0x3613, 0x0024, 0x3009, 0x3811, 0x2903, 0xfc00, 0x0004, 0x0011, + 0x0008, 0x0010, 0x0001, 0x0000, 0x291f, 0xc6c0, 0x0005, 0x0011, 0x000f, + 0x0011, 0x0008, 0x0010, 0x33d0, 0x184c, 0x6010, 0xb844, 0x3e10, 0x0024, + 0x0000, 0x0400, 0x3320, 0x4024, 0x3e00, 0x4024, 0x3301, 0x0024, 0x2903, + 0x8740, 0x6408, 0x0024, 0x36e3, 0x0024, 0x3009, 0x1bc4, 0x3009, 0x1bd1, + 0x6540, 0x0024, 0x0000, 0x0024, 0x2803, 0x4bd8, 0x4490, 0x0024, 0x2403, + 0x4b80, 0x0000, 0x0024, 0x0006, 0x8301, 0x4554, 0x0840, 0x4122, 0x0024, + 0x659a, 0x4055, 0x0006, 0x8341, 0x4122, 0x3400, 0xf400, 0x4055, 0x3110, + 0x0024, 0x3d00, 0x0024, 0xf400, 0x4510, 0x0030, 0x0013, 0x3073, 0x184c, + 0x3e11, 0x008c, 0x3009, 0x0001, 0x6140, 0x0024, 0x0000, 0x0201, 0x3009, + 0x2000, 0x0006, 0x8300, 0x290c, 0x7300, 0x3e10, 0x0024, 0x3300, 0x1b8c, + 0xb010, 0x0024, 0x0000, 0x0024, 0x2803, 0x5195, 0x0000, 0x0024, 0x3473, + 0x0024, 0x3423, 0x0024, 0x3009, 0x1240, 0x4080, 0x138c, 0x0000, 0x0804, + 0x2803, 0x39d5, 0x6402, 0x0024, 0x0006, 0xd312, 0x0006, 0xd310, 0x0006, + 0x8191, 0x3010, 0x984c, 0x30f0, 0xc024, 0x0000, 0x0021, 0xf2d6, 0x07c6, + 0x290a, 0xf5c0, 0x4682, 0x0400, 0x6894, 0x0840, 0xb886, 0x0bc1, 0xbcd6, + 0x0024, 0x3a10, 0x8024, 0x3af0, 0xc024, 0x36f3, 0x4024, 0x36f3, 0xd80e, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, + 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, + 0x0020, 0x0001, 0x3e14, 0x3811, 0x0030, 0x0050, 0x0030, 0x0251, 0x3e04, + 0xb813, 0x3000, 0x0024, 0xc012, 0x0024, 0x0019, 0x9300, 0x3800, 0x4024, + 0x2903, 0xae40, 0x3900, 0x0024, 0x2903, 0xbb80, 0x0000, 0x0300, 0xb882, + 0x0024, 0x2914, 0xbec0, 0x0006, 0x8010, 0x0000, 0x1540, 0x0007, 0x8190, + 0x2900, 0xadc0, 0x3800, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, + 0x6555, 0x0000, 0x0024, 0x0006, 0x8012, 0x3200, 0x0024, 0x4080, 0x0024, + 0x0030, 0x0010, 0x2803, 0x6555, 0x0000, 0x0201, 0x3000, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0024, 0x2803, 0x6555, 0x0000, 0x0024, 0x2900, 0xadc0, + 0x0000, 0x0024, 0x4080, 0x0024, 0x0006, 0x8010, 0x2803, 0x6555, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0201, 0x2803, 0x6185, 0x0030, 0x0010, + 0x0030, 0x0050, 0xf292, 0x0000, 0xb012, 0x0024, 0x3800, 0x4024, 0x0030, + 0x0010, 0x0000, 0x0201, 0x3000, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2900, 0xbe95, 0x0003, 0x6f08, 0x0006, 0x8011, 0x3100, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2803, 0x6d45, 0x0000, 0x0024, 0x0007, 0x8a52, + 0x3200, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2803, 0x6d49, 0x0000, + 0x0024, 0xf292, 0x0800, 0x6012, 0x0024, 0x0000, 0x0000, 0x2803, 0x6d05, + 0x0000, 0x0024, 0x3200, 0x0024, 0x4090, 0x0024, 0xb880, 0x2800, 0x3900, + 0x0024, 0x3100, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2902, 0x9885, + 0x0003, 0x6648, 0x2900, 0xbe80, 0x0000, 0x0024, 0x0000, 0x0010, 0x0006, + 0x9f51, 0x0006, 0x9f92, 0x0030, 0x0493, 0x0000, 0x0201, 0x6890, 0xa410, + 0x3b00, 0x2810, 0x0006, 0x8a10, 0x3009, 0x0000, 0x6012, 0x0024, 0x0006, + 0x9fd0, 0x2803, 0x7288, 0xb880, 0x0024, 0x6890, 0x0024, 0x3009, 0x2000, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e10, 0xb810, 0x3e11, 0x3805, 0x3e02, 0x0024, 0x0030, 0x0010, 0xce9a, + 0x0002, 0x0000, 0x0200, 0x2903, 0x7dc0, 0xb024, 0x0024, 0xc020, 0x0024, + 0x0000, 0x0200, 0x2803, 0x7685, 0x6e9a, 0x0002, 0x4182, 0x0024, 0x0000, + 0x0400, 0x2803, 0x7c45, 0xae1a, 0x0024, 0x6104, 0x984c, 0x0000, 0x0024, + 0x2903, 0x9bc9, 0x0003, 0x7c08, 0x6103, 0xe4e5, 0x2903, 0x9bc0, 0x408a, + 0x188c, 0x2903, 0x9bc0, 0x408a, 0x4141, 0x4583, 0x6465, 0x2803, 0x7c40, + 0xceca, 0x1bcc, 0xc408, 0x0024, 0xf2e2, 0x1bc8, 0x36f1, 0x1805, 0x2000, + 0x0011, 0x36f0, 0x9810, 0x2000, 0x0000, 0xdc92, 0x0024, 0x0006, 0x8a17, + 0x3613, 0x1c00, 0x6093, 0xe1e3, 0x0000, 0x03c3, 0x0006, 0x9f95, 0xb132, + 0x9415, 0x3500, 0xfc01, 0x2803, 0x8695, 0xa306, 0x0024, 0x3009, 0x184c, + 0x3009, 0x3814, 0x0025, 0xffd4, 0x0006, 0xd317, 0x3710, 0x160c, 0x0006, + 0x9f94, 0x37f0, 0x73d5, 0x6c92, 0x3808, 0x3f10, 0x0024, 0x3ff0, 0x4024, + 0x3009, 0x1040, 0x3009, 0x13c1, 0x6010, 0x0024, 0x0000, 0x0024, 0x2903, + 0xc445, 0x0003, 0x8288, 0x2803, 0x84d4, 0x0006, 0x0001, 0x4010, 0x0024, + 0x0005, 0xf601, 0x6010, 0x0024, 0x0000, 0x0040, 0x2803, 0x8654, 0x0030, + 0x0497, 0x3f00, 0x0024, 0x36f2, 0x1814, 0x4330, 0x9803, 0x2000, 0x0000, + 0x8880, 0x1bc1, 0x3613, 0x0024, 0x3e22, 0xb806, 0x3e05, 0xb814, 0x3615, + 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x7807, + 0x6848, 0x930c, 0x3411, 0x780d, 0x459a, 0x10c0, 0x0000, 0x0201, 0x6012, + 0x384e, 0x0000, 0x0241, 0x2803, 0x8dd5, 0x6012, 0x380f, 0x2403, 0x8d05, + 0x0000, 0x0024, 0x3000, 0x0001, 0x3101, 0x8407, 0x6cfe, 0x0024, 0xac42, + 0x0024, 0xaf4e, 0x2040, 0x3911, 0x8024, 0x2803, 0x9980, 0x0000, 0x0024, + 0x0000, 0x0281, 0x2803, 0x9115, 0x6012, 0x4455, 0x2403, 0x9045, 0x0000, + 0x0024, 0x3000, 0x0001, 0x3101, 0x8407, 0x4cf2, 0x0024, 0xac42, 0x0024, + 0xaf4e, 0x2040, 0x3911, 0x8024, 0x2803, 0x9980, 0x0000, 0x0024, 0x0000, + 0x0024, 0x2803, 0x9555, 0x4080, 0x0024, 0x3110, 0x0401, 0xf20f, 0x0203, + 0x2403, 0x9485, 0x8dd6, 0x0024, 0x4dce, 0x0024, 0xf1fe, 0x0024, 0xaf4e, + 0x0024, 0x6dc6, 0x2046, 0xf1df, 0x0203, 0xaf4f, 0x1011, 0xf20e, 0x07cc, + 0x8dd6, 0x2486, 0x2803, 0x9980, 0x0000, 0x0024, 0x0000, 0x0024, 0x2803, + 0x97d5, 0x0000, 0x0024, 0x0fff, 0xffd1, 0x2403, 0x9705, 0x3010, 0x0001, + 0xac4f, 0x0801, 0x3821, 0x8024, 0x2803, 0x9980, 0x0000, 0x0024, 0x0fff, + 0xffd1, 0x2403, 0x9945, 0x3010, 0x0001, 0x3501, 0x9407, 0xac47, 0x0801, + 0xaf4e, 0x2082, 0x3d11, 0x8024, 0x36f3, 0xc024, 0x36f3, 0x980d, 0x36f1, + 0x5807, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36e3, 0x0024, + 0x2000, 0x0000, 0x36f2, 0x9806, 0x3e10, 0xb812, 0x3e11, 0xb810, 0x3e12, + 0x0024, 0x0006, 0x9f92, 0x0025, 0xffd0, 0x3e04, 0x4bd1, 0x3181, 0xf847, + 0xb68c, 0x4440, 0x3009, 0x0802, 0x6024, 0x3806, 0x0006, 0x8a10, 0x2903, + 0xc445, 0x0003, 0x9dc8, 0x0000, 0x0800, 0x6101, 0x1602, 0xaf2e, 0x0024, + 0x4214, 0x1be3, 0xaf0e, 0x1811, 0x0fff, 0xfc00, 0xb200, 0x9bc7, 0x0000, + 0x03c0, 0x2803, 0xa205, 0xb204, 0xa002, 0x2900, 0xb800, 0x3613, 0x2002, + 0x4680, 0x1bc8, 0x36f1, 0x9810, 0x2000, 0x0000, 0x36f0, 0x9812, 0x0000, + 0x0400, 0x6102, 0x0024, 0x3e11, 0x3805, 0x2803, 0xa609, 0x3e02, 0x0024, + 0x2903, 0x9bc0, 0x408a, 0x188c, 0x2903, 0x9bc0, 0x408a, 0x4141, 0x4582, + 0x1bc8, 0x2000, 0x0000, 0x36f1, 0x1805, 0x2903, 0x9bc0, 0x4102, 0x184c, + 0xb182, 0x1bc8, 0x2000, 0x0000, 0x36f1, 0x1805, 0x2a03, 0xa78e, 0x3e12, + 0xb817, 0x3e10, 0x3802, 0x0000, 0x800a, 0x0006, 0x9f97, 0x3009, 0x1fc2, + 0x3e04, 0x5c00, 0x6020, 0xb810, 0x0030, 0x0451, 0x2803, 0xaa54, 0x0006, + 0x0002, 0x4020, 0x0024, 0x0005, 0xfb02, 0x6024, 0x0024, 0x0025, 0xffd0, + 0x2803, 0xac91, 0x3100, 0x1c11, 0xb284, 0x0024, 0x0030, 0x0490, 0x3800, + 0x8024, 0x0025, 0xffd0, 0x3980, 0x1810, 0x36f4, 0x7c11, 0x36f0, 0x1802, + 0x0030, 0x0717, 0x3602, 0x8024, 0x2100, 0x0000, 0x3f05, 0xdbd7, 0x0003, + 0xa757, 0x3613, 0x0024, 0x3e00, 0x3801, 0xf400, 0x55c0, 0x0000, 0x0897, + 0xf400, 0x57c0, 0x0000, 0x0024, 0x2000, 0x0000, 0x36f0, 0x1801, 0x3613, + 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0xb884, 0xb805, 0xb88a, 0x3844, 0x3e11, + 0xb80d, 0x3e03, 0xf80e, 0x0000, 0x03ce, 0x2403, 0xb68e, 0xf400, 0x4083, + 0x0000, 0x0206, 0xa562, 0x0024, 0x455a, 0x0024, 0x0020, 0x0006, 0xd312, + 0x0024, 0xb16c, 0x0024, 0x0000, 0x01c6, 0x2803, 0xb685, 0x0000, 0x0024, + 0xd56a, 0x0024, 0x4336, 0x0024, 0x0000, 0x4000, 0x0006, 0x9306, 0x4092, + 0x0024, 0xb512, 0x0024, 0x462c, 0x0024, 0x6294, 0x4195, 0x6200, 0x3401, + 0x0000, 0x03ce, 0x2803, 0xb391, 0xb88a, 0x0024, 0x36f3, 0xd80e, 0x36f1, + 0x980d, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0xb880, 0xb810, 0x0006, 0x9fd0, 0x3e10, 0x8001, 0x4182, + 0x3811, 0x0006, 0xd311, 0x2803, 0xbf45, 0x0006, 0x8a10, 0x0000, 0x0200, + 0xbc82, 0xa000, 0x3910, 0x0024, 0x2903, 0xb080, 0x39f0, 0x4024, 0x0006, + 0x9f90, 0x0006, 0x9f51, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, + 0x0000, 0x0024, 0x2903, 0xc445, 0x0003, 0xc048, 0x36f4, 0x4024, 0x36f0, + 0x9810, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x290a, 0xd900, 0x3605, 0x0024, 0x2910, 0x0180, + 0x3613, 0x0024, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0006, + 0x0002, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0x9f90, + 0x3e04, 0xb813, 0x3009, 0x0012, 0x3213, 0x0024, 0xf400, 0x4480, 0x6026, + 0x0024, 0x0000, 0x0024, 0x2803, 0xccd5, 0x0000, 0x0024, 0x0000, 0x0012, + 0xf400, 0x4480, 0x0006, 0x9f50, 0x3009, 0x0002, 0x6026, 0x0024, 0x0000, + 0x0024, 0x2903, 0xc445, 0x0003, 0xccc8, 0x0006, 0x9f93, 0x3201, 0x0c11, + 0xb58a, 0x0406, 0x0006, 0x8a11, 0x468e, 0x8400, 0xb68c, 0x9813, 0xcfee, + 0x1bd2, 0x0000, 0x0804, 0xaf0e, 0x9811, 0x4f86, 0x1bd0, 0x0000, 0x0021, + 0x6418, 0x9807, 0x6848, 0x1bc6, 0xad46, 0x9805, 0xf400, 0x4080, 0x36f1, + 0x0024, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, + 0x3e10, 0xb803, 0x3e11, 0x3805, 0x2803, 0xdb00, 0x3e04, 0x3811, 0x0000, + 0x0401, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x0000, 0x0080, 0xb882, 0x130c, + 0xf400, 0x4510, 0x3010, 0x910c, 0x30f0, 0xc024, 0x6dc2, 0x0024, 0x3810, + 0x0024, 0x38f0, 0x4024, 0x0000, 0x0201, 0x3100, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0024, 0x2803, 0xde55, 0x0000, 0x0024, 0x6894, 0x130c, 0xb886, + 0x1040, 0x3430, 0x4024, 0x6dca, 0x0024, 0x0030, 0x0011, 0x2803, 0xd6d1, + 0x0000, 0x0024, 0xbcd2, 0x0024, 0x0000, 0x0201, 0x2803, 0xde45, 0x0000, + 0x0024, 0x2903, 0x9bc0, 0x3613, 0x0024, 0x36f4, 0x1811, 0x36f1, 0x1805, + 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, + 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb815, + 0x0000, 0x800a, 0x3e14, 0x7813, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, + 0xb807, 0x3e13, 0xf80e, 0x6812, 0x0024, 0x3e03, 0x7810, 0x0fff, 0xffd3, + 0x0000, 0x0091, 0xbd86, 0x9850, 0x3e10, 0x3804, 0x3e00, 0x7812, 0xbe8a, + 0x8bcc, 0x409e, 0x8086, 0x2403, 0xe587, 0xfe49, 0x2821, 0x526a, 0x8801, + 0x5c87, 0x280e, 0x4eba, 0x9812, 0x4286, 0x40e1, 0xb284, 0x1bc1, 0x4de6, + 0x0024, 0xad17, 0x2627, 0x4fde, 0x9804, 0x4498, 0x1bc0, 0x0000, 0x0024, + 0x2803, 0xe395, 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f4, 0x5813, 0x2000, 0x0000, + 0x36f2, 0x9815, 0x3613, 0x0024, 0x3e12, 0xb815, 0x0000, 0x800a, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e13, 0xf80e, 0x6812, 0x0024, + 0x3e03, 0x7810, 0x3009, 0x1850, 0x3e10, 0x3804, 0x3e10, 0x7812, 0x32f3, + 0x0024, 0xbd86, 0x0024, 0x4091, 0xe2e3, 0x3009, 0x0046, 0x2403, 0xf100, + 0x3009, 0x0047, 0x32f0, 0x0801, 0xfe1f, 0x6465, 0x5e8a, 0x0024, 0x44ba, + 0x0024, 0xfee2, 0x0024, 0x5d8a, 0x1800, 0x4482, 0x4160, 0x48ba, 0x8046, + 0x4dc6, 0x1822, 0x4de6, 0x8047, 0x36f3, 0x0024, 0x36f0, 0x5812, 0xad17, + 0x2627, 0x4fde, 0x9804, 0x4498, 0x1bc0, 0x0000, 0x0024, 0x2803, 0xec95, + 0x3a11, 0xa807, 0x36f3, 0x4024, 0x36f3, 0xd80e, 0x36f1, 0x9807, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x2000, 0x0000, 0x36f2, 0x9815, 0xb386, 0x40d7, + 0x4284, 0x184c, 0x0000, 0x05c0, 0x2803, 0xf695, 0xf5d8, 0x3804, 0x0000, + 0x0984, 0x6400, 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, 0x0000, 0x800a, + 0x0000, 0x00ce, 0x2403, 0xf9ce, 0xffa4, 0x0024, 0x48b6, 0x0024, 0x0000, + 0x0024, 0x2803, 0xf9c4, 0x4000, 0x40c2, 0x4224, 0x0024, 0x6090, 0x0024, + 0xffa4, 0x0024, 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, 0xd80d, 0x48b6, + 0x0024, 0x0fff, 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, 0x36f1, 0x180a, + 0x4080, 0x184c, 0x3e13, 0x780f, 0x2803, 0xfe05, 0x4090, 0xb80e, 0x2403, + 0xfd80, 0x3e04, 0x0440, 0x3810, 0x0440, 0x3604, 0x0024, 0x3009, 0x1bce, + 0x3603, 0x5bcf, 0x2000, 0x0000, 0x0000, 0x0024, 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6280, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1440, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x3c4e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x59c0, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x01a4, /*copy 420*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x000b, /*copy 11*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x0007, 0x0001, /*copy 1*/ + 0x181a, 0x0006, 0x0002, /*copy 2*/ + 0x08b4, 0x08d2, 0x0006, 0x8006, 0x091a, /*Rle(6)*/ + 0x0006, 0x0025, /*copy 37*/ + 0x08ef, 0x08ef, 0x08ef, 0x08ef, 0x08ef, 0x0b11, 0x0af5, 0x0af9, 0x0afd, + 0x0b01, 0x0b05, 0x0b09, 0x0b0d, 0x0b40, 0x0b44, 0x0b47, 0x0b47, 0x0b47, + 0x0b47, 0x0b4f, 0x0b62, 0x0c2d, 0x0b99, 0x0b9e, 0x0ba4, 0x0baa, 0x0baf, + 0x0bb4, 0x0bb9, 0x0bbe, 0x0bc3, 0x0bc8, 0x0bcd, 0x0bd2, 0x0beb, 0x0c0a, + 0x0c29, 0x0007, 0x0001, /*copy 1*/ + 0x5800, 0x0006, 0x0001, /*copy 1*/ + 0x0001, 0x0006, 0x8007, 0x0000, /*Rle(7)*/ + 0x0006, 0x0018, /*copy 24*/ + 0x0002, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, + 0x0000, 0xfffd, 0xffff, 0x0001, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, + 0xfffa, 0xffff, 0x0004, 0x0000, 0xffff, 0xffff, 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 8588 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/patches_latm.h b/targets/esp32/components/VS1053/include/patches_latm.h new file mode 100644 index 00000000..115525f1 --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_latm.h @@ -0,0 +1,644 @@ + +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x001e, /*copy 30*/ + 0x2a00, 0xc000, 0x3e12, 0xb817, 0x3e14, 0xf812, 0x3e01, 0xb811, 0x0007, + 0x9717, 0x0020, 0xffd2, 0x0030, 0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, + 0x3b81, 0x8024, 0x3101, 0x8024, 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, + 0x4800, 0x36f1, 0x9811, 0x0007, 0x0001, /*copy 1*/ + 0x8060, 0x0006, 0x0536, /*copy 1334*/ + 0xf400, 0x4095, 0x0000, 0x02c2, 0x6124, 0x0024, 0x0000, 0x0024, 0x2800, + 0x1ac5, 0x4192, 0x4542, 0x0000, 0x0041, 0x2000, 0x0015, 0x0030, 0x0317, + 0x2000, 0x0000, 0x3f00, 0x4024, 0x2000, 0x0000, 0x0000, 0x0000, 0x3e12, + 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, 0x8257, 0x3700, 0x984c, + 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, 0x2910, 0x0181, 0x0000, + 0x1bc8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, 0x0195, 0x0000, 0x1bc8, + 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2945, 0x3e13, 0x780e, 0x3e11, + 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, 0xb808, 0x003f, 0xe004, + 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, 0x48be, 0x4497, 0x4090, + 0x1c46, 0xf06c, 0x0024, 0x2400, 0x2580, 0x6090, 0x41c3, 0x6628, 0x1c47, + 0x0000, 0x0024, 0x2800, 0x2449, 0xf07e, 0x0024, 0xf400, 0x4182, 0x673a, + 0x1c46, 0x0000, 0x0024, 0x2800, 0x2589, 0xf06c, 0x0024, 0xf400, 0x41c3, + 0x0000, 0x0024, 0x4224, 0x3442, 0x2900, 0xb7c0, 0x4336, 0x37c3, 0x0000, + 0x1805, 0x2900, 0xb7c0, 0x4508, 0x40c2, 0x450a, 0x9808, 0x0000, 0x0207, + 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, 0x3d01, 0x5bc1, 0x36f3, + 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, 0x580e, 0x0007, 0x8257, + 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, 0xd428, 0x3c02, 0x0006, + 0xc717, 0x2800, 0x2d05, 0x4284, 0x0024, 0x3613, 0x3c02, 0x0006, 0xc357, + 0x2901, 0x6480, 0x3e11, 0x5c05, 0x4284, 0x1bc5, 0x0000, 0x0024, 0x2800, + 0x3045, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, 0x0024, 0x3613, 0x0024, + 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, 0x2900, 0x4900, 0x0006, + 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, 0x8257, 0x3700, 0x8024, + 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x3251, 0x3600, 0x9844, 0x2900, + 0x3800, 0x0000, 0x32c8, 0x2911, 0xf140, 0x0000, 0x0024, 0x0030, 0x0057, + 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, 0xa024, 0x164c, 0x8000, + 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, 0x6d82, 0xd024, 0x44c0, + 0x0006, 0xa402, 0x2800, 0x3715, 0xd024, 0x0024, 0x0000, 0x0000, 0x2800, + 0x3715, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, 0x8024, 0x36f2, 0x1800, + 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, 0x3e13, 0xb80d, 0x3e13, + 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0xf801, + 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, 0xbf8e, 0x9c42, 0x3e01, + 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, 0x8250, 0x0fff, 0xfd85, + 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, 0x2800, 0x3e51, 0xf25a, + 0x104c, 0x34f3, 0x0024, 0x2800, 0x3e51, 0x0000, 0x0024, 0x3413, 0x084c, + 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, 0x2400, 0x4080, 0x4efa, + 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, 0x4d64, 0x48b2, 0xa201, + 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, 0x36f4, 0xd801, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0xd80a, 0x36f3, 0x980d, + 0x2000, 0x0000, 0x36f4, 0x5810, 0x36f3, 0x0024, 0x3009, 0x3848, 0x3e14, + 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, + 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, 0x9e40, 0x3604, 0x1811, 0x3613, + 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, + 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x36f4, 0x1811, 0x3009, + 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e13, 0x7801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, + 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, 0x34e5, 0xc024, 0x3524, + 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, 0x4a0c, 0x3d44, 0x8024, + 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, 0x6010, 0x3400, 0x3710, + 0x8024, 0x2800, 0x54c4, 0x3af0, 0x8024, 0x3df0, 0x0024, 0x3591, 0x4024, + 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, 0x4020, 0x1753, 0xbf8e, + 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, 0x52ce, 0xfe6d, 0x2819, + 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, 0xad56, 0x904c, 0xaf5e, + 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, 0x2046, 0x3cf4, 0x0024, + 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, 0x2800, 0x4d55, 0x3c00, + 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0x5801, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x2814, 0x9c91, + 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3655, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb810, 0x3e13, + 0xf80e, 0x3e03, 0x534c, 0x3450, 0x4024, 0x6814, 0x0024, 0x0000, 0x0024, + 0x2800, 0x73d8, 0x4192, 0x0024, 0x2400, 0x7381, 0x0000, 0x0024, 0xf400, + 0x4450, 0x2938, 0x1880, 0x3613, 0x0024, 0x3c10, 0x050c, 0x3c10, 0x4024, + 0x3c90, 0x8024, 0x34f3, 0x0024, 0x3464, 0x0024, 0x3011, 0x0c40, 0x3011, + 0x4c41, 0x2915, 0x9900, 0x3011, 0x8f82, 0x3411, 0x2c40, 0x3411, 0x6c41, + 0x2915, 0xa580, 0x34e1, 0xaf82, 0x3009, 0x3040, 0x4c8a, 0x0040, 0x3010, + 0x7041, 0x2800, 0x6614, 0x3010, 0xb382, 0x3411, 0x0024, 0x3411, 0x6c44, + 0x34e1, 0xac45, 0xbe8a, 0xaf86, 0x0fe0, 0x0006, 0x3009, 0x3044, 0x3009, + 0x3045, 0x3009, 0x3386, 0x3411, 0x0024, 0x3411, 0x4ccc, 0x2915, 0x9900, + 0x34e1, 0x984c, 0x3e10, 0x7800, 0x3009, 0x3802, 0x3011, 0x0c40, 0x3011, + 0x4c41, 0x2915, 0x9900, 0x30e1, 0x8f82, 0x3009, 0x1bc6, 0x2915, 0xa940, + 0x36f1, 0x5804, 0x3011, 0x2c40, 0x3011, 0x6c41, 0x30b1, 0xac42, 0x3009, + 0x0c40, 0x3009, 0x0c41, 0x2915, 0x9900, 0x3613, 0x0f82, 0x3e10, 0x7800, + 0x3009, 0x3802, 0x3010, 0x1044, 0x3010, 0x5045, 0x2915, 0x9900, 0x3010, + 0x9386, 0x3009, 0x1bc6, 0x2915, 0xa940, 0x36f1, 0x5804, 0xf1ca, 0xac40, + 0x4ce2, 0xac41, 0x3009, 0x2ec2, 0x2800, 0x6ed2, 0x629c, 0x0024, 0xf1c2, + 0x4182, 0x3c10, 0x0c44, 0x3c10, 0x4c45, 0x2915, 0x4780, 0x3ce0, 0x8f86, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2800, 0x7395, 0x0020, 0x0000, 0x3411, + 0x0c40, 0x3411, 0x4c41, 0x2915, 0xb780, 0x34e1, 0x8f82, 0x0000, 0x03c3, + 0x4234, 0x0024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2915, 0x4355, 0x0000, + 0x7388, 0x0000, 0x0000, 0x3a10, 0x0d8c, 0x36f3, 0x538c, 0x36f3, 0xd80e, + 0x36f1, 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3645, + 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, + 0x3e11, 0xb810, 0x3e13, 0xf80e, 0x3e03, 0x534c, 0x3440, 0x4024, 0x4192, + 0x0024, 0x2400, 0x8f81, 0x0000, 0x0024, 0xb68c, 0x4450, 0x2938, 0x1880, + 0x3613, 0x050c, 0x3c10, 0x0c40, 0x3c10, 0x4c41, 0x3ce0, 0x8f82, 0x003c, + 0x2584, 0x2915, 0x9900, 0x0018, 0x8245, 0x3411, 0x2c40, 0x3411, 0x6c41, + 0x2915, 0xa580, 0x34e1, 0xac42, 0x4c8a, 0xb040, 0x3009, 0x3041, 0x2800, + 0x8094, 0x3009, 0x3382, 0x3411, 0x0f4c, 0x3411, 0x6c44, 0x34e1, 0xac45, + 0xbe8a, 0xac46, 0x499c, 0xb044, 0xf38c, 0xb045, 0x3009, 0x3386, 0x3009, + 0x0c40, 0x3009, 0x0c41, 0xf1ca, 0x8f82, 0x4ce2, 0x1044, 0x3411, 0x4024, + 0x2800, 0x82d2, 0x4294, 0x1386, 0x6294, 0x0024, 0xf1c2, 0x0024, 0x4e8a, + 0x4195, 0x35e3, 0x0024, 0x2915, 0xa955, 0xf400, 0x4546, 0x3009, 0x2c40, + 0x3009, 0x2c41, 0x3009, 0x2c42, 0x3009, 0x0c40, 0x3009, 0x0c41, 0xf1ca, + 0x8f82, 0x4ce2, 0x9044, 0x3009, 0x1045, 0x2800, 0x8745, 0x3009, 0x1386, + 0x2800, 0x8752, 0x4294, 0x0024, 0x6294, 0x0024, 0xf1c2, 0x0024, 0x4e8a, + 0x4195, 0x35e3, 0x0024, 0x2915, 0xa955, 0xf400, 0x4546, 0xf1ca, 0xac40, + 0x4ce2, 0xac41, 0x3009, 0x2ec2, 0x2800, 0x89d2, 0x629c, 0x0024, 0xf1c2, + 0x4182, 0x3c20, 0x0c84, 0x3cf0, 0x8fc6, 0x6264, 0x4017, 0x3cf0, 0x4fc5, + 0x2800, 0x8f88, 0x0020, 0x0000, 0x2800, 0x8cd9, 0xf400, 0x45c0, 0x6cea, + 0x0024, 0x0000, 0x0024, 0x2800, 0x8f89, 0x0020, 0x0000, 0x3411, 0x0c40, + 0x3411, 0x4c41, 0x2915, 0xb780, 0x34e1, 0x8f82, 0x0000, 0x03c3, 0x4234, + 0x0024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2915, 0x4355, 0x0000, 0x8f88, + 0x0000, 0x0000, 0x3a10, 0x0d8c, 0x36f3, 0x53cc, 0x36f3, 0xd80e, 0x36f1, + 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0xf400, + 0x4595, 0x35e3, 0x3840, 0x3e13, 0xf80e, 0x3e13, 0x7808, 0x3510, 0x0024, + 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, + 0x0024, 0x0001, 0xb0ce, 0x002b, 0xb30f, 0x292d, 0xa940, 0x0000, 0x004d, + 0x36d3, 0x0024, 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, + 0x1800, 0xf400, 0x4595, 0x35f3, 0x3840, 0x3e13, 0xf80e, 0x3e13, 0x7808, + 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, 0x0024, 0x0000, + 0x9b8e, 0x0028, 0x088f, 0x2927, 0xff80, 0x0000, 0x008d, 0x36e3, 0x0024, + 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, 0x1800, 0x0028, + 0x2b0f, 0x0000, 0xa10e, 0x2828, 0x0b15, 0x0007, 0x2605, 0x3613, 0x0001, + 0x3e14, 0x3811, 0x0001, 0x0011, 0x0001, 0xcc10, 0x2915, 0x94c0, 0x0000, + 0x4000, 0x3e10, 0x534c, 0x3430, 0xc024, 0x3e10, 0xc024, 0x2927, 0xc4c0, + 0x3e01, 0x0024, 0x36d3, 0x0024, 0x0001, 0x0011, 0x0001, 0xcc10, 0x2915, + 0x94c0, 0x0000, 0x4000, 0x2828, 0x0b00, 0x36f4, 0x1811, 0x3e00, 0x0024, + 0x2800, 0xa500, 0x0028, 0x2bc8, 0x3605, 0x7840, 0x3e13, 0x780e, 0x3e13, + 0xf808, 0x3e05, 0x4024, 0x0000, 0x434e, 0x0027, 0x9e0f, 0x2922, 0xa6c0, + 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, + 0x0000, 0x3009, 0x1800, 0xf400, 0x4595, 0x35d3, 0x3840, 0x3e13, 0xf80e, + 0x3e13, 0x7808, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e10, + 0x0024, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, 0x0024, + 0x0000, 0xaa4e, 0x0025, 0xf54f, 0x2925, 0xe580, 0x0000, 0x004d, 0x36c3, + 0x0024, 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, 0x1800, + 0x3433, 0x0000, 0x6890, 0x3040, 0x3cc0, 0xa000, 0x0008, 0x6201, 0x000d, + 0x3500, 0x3613, 0x110c, 0x3e10, 0x0024, 0x3e10, 0x4024, 0x34c0, 0x8024, + 0x2900, 0x9280, 0x3e00, 0x8024, 0x0026, 0x0a4f, 0x0000, 0xae0e, 0x2825, + 0xf880, 0x0000, 0x07cd, 0x0000, 0x0801, 0x6012, 0x0024, 0x0000, 0x0024, + 0x2826, 0x0a85, 0x0000, 0x0024, 0x2800, 0xab00, 0x0000, 0x0024, 0x3605, + 0x7840, 0x3e13, 0x780e, 0x3e13, 0xf808, 0x3e05, 0x4024, 0x0000, 0xb30e, + 0x0022, 0xf54f, 0x2922, 0xda80, 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, + 0xd808, 0x36f3, 0x580e, 0x2000, 0x0000, 0x3009, 0x1800, 0x3e00, 0x0024, + 0x2800, 0x9740, 0x0022, 0xf608, 0x3605, 0x7840, 0x3e13, 0x780e, 0x3e13, + 0xf808, 0x3e05, 0x4024, 0x0000, 0xb70e, 0x0022, 0xa1cf, 0x2922, 0x9980, + 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, + 0x0000, 0x3009, 0x1800, 0x3009, 0x3400, 0x2800, 0xafc0, 0x0022, 0xa288, + 0xb386, 0x40d7, 0x4284, 0x184c, 0x0000, 0x05c0, 0x2800, 0xb955, 0xf5d8, + 0x3804, 0x0000, 0x0984, 0x6400, 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, + 0x0000, 0x800a, 0x0000, 0x00ce, 0x2400, 0xbc8e, 0xffa4, 0x0024, 0x48b6, + 0x0024, 0x0000, 0x0024, 0x2800, 0xbc84, 0x4000, 0x40c2, 0x4224, 0x0024, + 0x6090, 0x0024, 0xffa4, 0x0024, 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, + 0xd80d, 0x48b6, 0x0024, 0x0fff, 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, + 0x36f1, 0x180a, 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x0e92, /*copy 3730*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x6457, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x590e, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x003f, + 0xc000, 0xb600, 0x41c1, 0x0012, 0x5103, 0x000c, 0xc002, 0xdcd6, 0x0024, + 0x0019, 0xd4c2, 0x2802, 0x8345, 0x0001, 0x0988, 0x0013, 0xd9c3, 0x6fd6, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdf95, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xde4e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x0988, 0x0039, + 0x324f, 0x0001, 0x384e, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x2a00, 0xe180, 0x000a, 0x8c8f, + 0x0000, 0xe2ce, 0x000c, 0x0981, 0x280a, 0x71c0, 0x002c, 0x9d40, 0x000a, + 0x708f, 0x0000, 0xd7ce, 0x280a, 0xc0d5, 0x0012, 0x5182, 0x6fd6, 0x0024, + 0x003f, 0xfd81, 0x280a, 0x8e45, 0xb710, 0x0024, 0x003f, 0xf800, 0xb600, + 0x0024, 0x0015, 0xb801, 0x6012, 0x0024, 0x003f, 0xfd81, 0x2802, 0x4ec5, + 0x0001, 0x0a88, 0xb710, 0x0024, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, + 0x0101, 0x2801, 0x0055, 0xffd2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, + 0x0000, 0x190d, 0x2801, 0x0055, 0x0030, 0x0250, 0xb880, 0x104c, 0x3cf0, + 0x0024, 0x0010, 0x5500, 0xb880, 0x23c0, 0xb882, 0x2000, 0x0007, 0x8590, + 0x2914, 0xbec0, 0x0000, 0x0440, 0x0007, 0x8b50, 0xb880, 0x0024, 0x2920, + 0x0100, 0x3800, 0x0024, 0x2920, 0x0000, 0x0006, 0x8a91, 0x0000, 0x0800, + 0xb880, 0xa440, 0x003f, 0xfd81, 0xb710, 0xa7c0, 0x003f, 0xfc01, 0x6012, + 0x0024, 0x0000, 0x0101, 0x2801, 0x0995, 0x0000, 0x0024, 0xffe2, 0x0024, + 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x0995, 0x0000, + 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0006, 0x8a90, + 0x2801, 0x0995, 0x0000, 0x01c2, 0xb886, 0x8040, 0x3613, 0x03c1, 0xbcd2, + 0x0024, 0x0030, 0x0011, 0x2800, 0xf615, 0x003f, 0xff42, 0xb886, 0x8040, + 0x3009, 0x03c1, 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0102, 0x6cd2, + 0x0024, 0x3e10, 0x0024, 0x2909, 0x8c80, 0x3e00, 0x4024, 0x36f3, 0x0024, + 0x3e11, 0x8024, 0x3e01, 0xc024, 0x2901, 0x2e40, 0x0000, 0x0201, 0xf400, + 0x4512, 0x2900, 0x0c80, 0x3213, 0x1b8c, 0x3100, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0024, 0x2801, 0x0995, 0x0000, 0x0024, 0x291a, 0x8a40, 0x0000, + 0x0100, 0x2920, 0x0200, 0x3633, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, + 0x408e, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, 0x003f, 0xfd81, 0xb710, + 0x4006, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x0995, + 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, + 0x0024, 0x2801, 0x0995, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, + 0x4080, 0x0024, 0x0000, 0x01c2, 0x2800, 0xf205, 0x0006, 0x8a90, 0x2a01, + 0x0980, 0x2920, 0x0100, 0x0000, 0x0401, 0x0000, 0x0180, 0x2920, 0x0200, + 0x3613, 0x0024, 0x2920, 0x0280, 0x3613, 0x0024, 0x0000, 0x0401, 0x2920, + 0x0280, 0x4084, 0x984c, 0x0019, 0x9d01, 0x6212, 0x0024, 0x001e, 0x5c01, + 0x2801, 0x04d5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x06c5, 0x0000, + 0x0024, 0x001b, 0x5bc1, 0x6212, 0x0024, 0x001b, 0xdd81, 0x2801, 0x0a95, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x0a95, 0x0000, 0x0024, 0x0000, + 0x004d, 0x000a, 0xbf4f, 0x280a, 0xb880, 0x0001, 0x07ce, 0x0020, 0xfb4f, + 0x0000, 0x190d, 0x0001, 0x0ece, 0x2920, 0xf440, 0x3009, 0x2bc1, 0x291a, + 0x8a40, 0x36e3, 0x0024, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xcac0, + 0x0000, 0xd7ce, 0x0030, 0x0017, 0x3700, 0x4024, 0x0000, 0x0200, 0xb102, + 0x0024, 0x0000, 0x00c0, 0x2801, 0x0dc5, 0x0005, 0x4f92, 0x2909, 0xf840, + 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, 0xa115, 0xb080, 0x0024, 0x3f00, + 0x3400, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xc0c0, 0x0000, 0xd7ce, + 0x0000, 0x004d, 0x0020, 0xfe0f, 0x2820, 0xfb40, 0x0001, 0x0fce, 0x2801, + 0x1195, 0x3009, 0x1000, 0x6012, 0x93cc, 0x0000, 0x0024, 0x2801, 0x2c45, + 0x0000, 0x0024, 0x3413, 0x0024, 0x34b0, 0x0024, 0x4080, 0x0024, 0x0000, + 0x0200, 0x2801, 0x1495, 0xb882, 0x0024, 0x3453, 0x0024, 0x3009, 0x13c0, + 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, 0x2c45, 0x0000, 0x0024, 0xb882, + 0x130c, 0x0000, 0x004d, 0x0021, 0x058f, 0x2821, 0x0340, 0x0001, 0x158e, + 0x2801, 0x25d5, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x25d5, 0x0000, + 0x0024, 0x34c3, 0x184c, 0x3e13, 0xb80f, 0xf400, 0x4500, 0x0026, 0x9dcf, + 0x0001, 0x198e, 0x0000, 0xfa0d, 0x2926, 0x8e80, 0x3e10, 0x110c, 0x36f3, + 0x0024, 0x2801, 0x25c0, 0x36f3, 0x980f, 0x001c, 0xdd00, 0x001c, 0xd901, + 0x6ec2, 0x0024, 0x001c, 0xdd00, 0x2801, 0x1c95, 0x0018, 0xdbc1, 0x3413, + 0x184c, 0xf400, 0x4500, 0x2926, 0xc640, 0x3e00, 0x13cc, 0x2801, 0x2380, + 0x36f3, 0x0024, 0x6ec2, 0x0024, 0x003f, 0xc000, 0x2801, 0x1f15, 0x002a, + 0x4001, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0xafc0, 0x3e00, 0x13cc, + 0x2801, 0x2380, 0x36f3, 0x0024, 0xb400, 0x0024, 0xd100, 0x0024, 0x0000, + 0x0024, 0x2801, 0x2385, 0x0000, 0x0024, 0x3613, 0x0024, 0x3e11, 0x4024, + 0x2926, 0x8540, 0x3e01, 0x0024, 0x4080, 0x1b8c, 0x0000, 0x0024, 0x2801, + 0x2385, 0x0000, 0x0024, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0x8e80, + 0x3e10, 0x13cc, 0x36f3, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x0000, + 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x3110, 0x8024, 0x2826, 0xa8c4, + 0x31f0, 0xc024, 0x2a26, 0xad00, 0x34c3, 0x184c, 0x3410, 0x8024, 0x3430, + 0xc024, 0x0000, 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x0000, 0x0024, + 0x2801, 0x2c54, 0x4d06, 0x0024, 0x0000, 0x0200, 0x2922, 0x1885, 0x0001, + 0x2ac8, 0x0000, 0x0200, 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, 0xc024, + 0x291a, 0x8a40, 0x0000, 0x0024, 0x2922, 0x1880, 0x36f3, 0x0024, 0x0000, + 0x004d, 0x0021, 0x0ecf, 0x2821, 0x0bc0, 0x0001, 0x2bce, 0x2801, 0x0ec0, + 0x3c30, 0x4024, 0x0000, 0x190d, 0x0001, 0x2d4e, 0x2821, 0x0f80, 0x0021, + 0x420f, 0x0000, 0x190d, 0x3e00, 0x0024, 0x2801, 0xca80, 0x0021, 0x42c8, + 0x0020, 0xcd4f, 0x2820, 0xc780, 0x0001, 0x2f0e, 0x0006, 0xf017, 0x0000, + 0x0015, 0xb070, 0xbc15, 0x0001, 0x30ce, 0x0020, 0xdf0f, 0x2820, 0xcd80, + 0x0000, 0x190d, 0x3e00, 0x23c1, 0x2801, 0xca80, 0x0020, 0xdfc8, 0x3613, + 0x0024, 0x3e10, 0xb803, 0x3e14, 0x3811, 0x3e11, 0x3805, 0x3e00, 0x3801, + 0x0007, 0xc390, 0x0006, 0xa011, 0x3010, 0x0444, 0x3050, 0x4405, 0x6458, + 0x0302, 0xff94, 0x4081, 0x0003, 0xffc5, 0x48b6, 0x0024, 0xff82, 0x0024, + 0x42b2, 0x0042, 0xb458, 0x0003, 0x4cd6, 0x9801, 0xf248, 0x1bc0, 0xb58a, + 0x0024, 0x6de6, 0x1804, 0x0006, 0x0010, 0x3810, 0x9bc5, 0x3800, 0xc024, + 0x36f4, 0x1811, 0x36f0, 0x9803, 0x283e, 0x2d80, 0x0fff, 0xffc3, 0x2801, + 0x4600, 0x0000, 0x0024, 0x3413, 0x0024, 0x2801, 0x3a05, 0xf400, 0x4517, + 0x2801, 0x3e00, 0x6894, 0x13cc, 0x37b0, 0x184c, 0x6090, 0x1d51, 0x0000, + 0x0910, 0x3f00, 0x060c, 0x3100, 0x4024, 0x6016, 0xb812, 0x000c, 0x8012, + 0x2801, 0x3c91, 0xb884, 0x0024, 0x6894, 0x3002, 0x0000, 0x028d, 0x003a, + 0x5e0f, 0x0001, 0x4e0e, 0x2939, 0xb0c0, 0x3e10, 0x93cc, 0x4084, 0x9bd2, + 0x4282, 0x0024, 0x0000, 0x0040, 0x2801, 0x4005, 0x4292, 0x130c, 0x3443, + 0x0024, 0x2801, 0x4145, 0x000c, 0x8390, 0x2a01, 0x44c0, 0x3444, 0x0024, + 0x3073, 0x0024, 0xc090, 0x014c, 0x2801, 0x44c0, 0x3800, 0x0024, 0x000c, + 0x4113, 0xb880, 0x2380, 0x3304, 0x4024, 0x3800, 0x05cc, 0xcc92, 0x05cc, + 0x3910, 0x0024, 0x3910, 0x4024, 0x000c, 0x8110, 0x3910, 0x0024, 0x39f0, + 0x4024, 0x3810, 0x0024, 0x38d0, 0x4024, 0x3810, 0x0024, 0x38f0, 0x4024, + 0x34c3, 0x0024, 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, + 0x3613, 0x0024, 0x2801, 0x4805, 0x6898, 0xb804, 0x0000, 0x0084, 0x293b, + 0x1cc0, 0x3613, 0x0024, 0x000c, 0x8117, 0x3711, 0x0024, 0x37d1, 0x4024, + 0x4e8a, 0x0024, 0x0000, 0x0015, 0x2801, 0x4ac5, 0xce9a, 0x0024, 0x3f11, + 0x0024, 0x3f01, 0x4024, 0x000c, 0x8197, 0x408a, 0x9bc4, 0x3f15, 0x4024, + 0x2801, 0x4d05, 0x4284, 0x3c15, 0x6590, 0x0024, 0x0000, 0x0024, 0x2839, + 0x53d5, 0x4284, 0x0024, 0x0000, 0x0024, 0x2801, 0x38d8, 0x458a, 0x0024, + 0x2a39, 0x53c0, 0x003e, 0x2d4f, 0x283a, 0x5ed5, 0x0001, 0x318e, 0x000c, + 0x4653, 0x0000, 0x0246, 0xffac, 0x0c01, 0x48be, 0x0024, 0x4162, 0x4546, + 0x6642, 0x4055, 0x3501, 0x8024, 0x0000, 0x0087, 0x667c, 0x4057, 0x000c, + 0x41d5, 0x283a, 0x62d5, 0x3501, 0x8024, 0x667c, 0x1c47, 0x3701, 0x8024, + 0x283a, 0x62d5, 0xc67c, 0x0024, 0x0000, 0x0024, 0x283a, 0x62c5, 0x0000, + 0x0024, 0x2a3a, 0x5ec0, 0x3009, 0x3851, 0x3e14, 0xf812, 0x3e12, 0xb817, + 0x3e11, 0x8024, 0x0006, 0x0293, 0x3301, 0x8024, 0x468c, 0x3804, 0x0006, + 0xa057, 0x2801, 0x5a04, 0x0006, 0x0011, 0x469c, 0x0024, 0x3be1, 0x8024, + 0x2801, 0x5a15, 0x0006, 0xc392, 0x3311, 0x0024, 0x33f1, 0x2844, 0x3009, + 0x2bc4, 0x0030, 0x04d2, 0x3311, 0x0024, 0x3a11, 0x0024, 0x3201, 0x8024, + 0x003f, 0xfc04, 0xb64c, 0x0fc4, 0xc648, 0x0024, 0x3a01, 0x0024, 0x3111, + 0x1fd3, 0x6498, 0x07c6, 0x868c, 0x2444, 0x0023, 0xffd2, 0x3901, 0x8e06, + 0x0030, 0x0551, 0x3911, 0x8e06, 0x3961, 0x9c44, 0xf400, 0x44c6, 0xd46c, + 0x1bc4, 0x36f1, 0xbc13, 0x2801, 0x6395, 0x36f2, 0x9817, 0x002b, 0xffd2, + 0x3383, 0x188c, 0x3e01, 0x8c06, 0x0006, 0xa097, 0x3009, 0x1c12, 0x3213, + 0x0024, 0x468c, 0xbc12, 0x002b, 0xffd2, 0xf400, 0x4197, 0x2801, 0x6084, + 0x3713, 0x0024, 0x2801, 0x60c5, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x3383, + 0x0024, 0x3009, 0x0c06, 0x468c, 0x4197, 0x0006, 0xa052, 0x2801, 0x62c4, + 0x3713, 0x2813, 0x2801, 0x6305, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x36f1, + 0x8024, 0x36f2, 0x9817, 0x36f4, 0xd812, 0x2100, 0x0000, 0x3904, 0x5bd1, + 0x2a01, 0x53ce, 0x3e11, 0x7804, 0x0030, 0x0257, 0x3701, 0x0024, 0x0013, + 0x4d05, 0xd45b, 0xe0e1, 0x0007, 0xc795, 0x2801, 0x6b15, 0x0fff, 0xff45, + 0x3511, 0x184c, 0x4488, 0xb808, 0x0006, 0x8a97, 0x2801, 0x6ac5, 0x3009, + 0x1c40, 0x3511, 0x1fc1, 0x0000, 0x0020, 0xac52, 0x1405, 0x6ce2, 0x0024, + 0x0000, 0x0024, 0x2801, 0x6ac1, 0x68c2, 0x0024, 0x291a, 0x8a40, 0x3e10, + 0x0024, 0x2921, 0xca80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3009, 0x1bc8, + 0x36f0, 0x1801, 0x3601, 0x5804, 0x3e13, 0x780f, 0x3e13, 0xb808, 0x0008, + 0x9b0f, 0x0001, 0x6dce, 0x2908, 0x9300, 0x0000, 0x004d, 0x36f3, 0x9808, + 0x2000, 0x0000, 0x36f3, 0x580f, 0x0007, 0x81d7, 0x3711, 0x8024, 0x3711, + 0xc024, 0x3700, 0x0024, 0x0000, 0x2001, 0xb012, 0x0024, 0x0034, 0x0000, + 0x2801, 0x7105, 0x0000, 0x01c1, 0x0030, 0x0117, 0x3f00, 0x0024, 0x0014, + 0xc000, 0x0000, 0x01c1, 0x4fce, 0x0024, 0xffea, 0x0024, 0x48b6, 0x0024, + 0x4384, 0x4097, 0xb886, 0x45c6, 0xfede, 0x0024, 0x4db6, 0x0024, 0x466c, + 0x0024, 0x0006, 0xc610, 0x8dd6, 0x8007, 0x0000, 0x00c6, 0xff6e, 0x0024, + 0x48b2, 0x0024, 0x0034, 0x2406, 0xffee, 0x0024, 0x2914, 0xaa80, 0x40b2, + 0x0024, 0xf1c6, 0x0024, 0xf1d6, 0x0024, 0x0000, 0x0201, 0x8d86, 0x0024, + 0x61de, 0x0024, 0x0006, 0xc612, 0x2801, 0x7781, 0x0006, 0xc713, 0x4c86, + 0x0024, 0x2912, 0x1180, 0x0006, 0xc351, 0x0006, 0x0210, 0x2912, 0x0d00, + 0x3810, 0x984c, 0xf200, 0x2043, 0x2808, 0xa000, 0x3800, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, + 0x3811, 0x0006, 0xa090, 0x2912, 0x0d00, 0x3e14, 0xc024, 0x4088, 0x8000, + 0x4080, 0x0024, 0x0007, 0x90d1, 0x2801, 0x7f45, 0x0000, 0x0024, 0x0007, + 0x9051, 0x3100, 0x4024, 0x4100, 0x0024, 0x3900, 0x0024, 0x0007, 0x90d1, + 0x0004, 0x0000, 0x31f0, 0x4024, 0x6014, 0x0400, 0x0000, 0x0024, 0x2801, + 0x8391, 0x4080, 0x0024, 0x0000, 0x0000, 0x2801, 0x8305, 0x0000, 0x0024, + 0x0007, 0x9053, 0x3300, 0x0024, 0x4080, 0x0024, 0x0000, 0x0000, 0x2801, + 0x8398, 0x0000, 0x0024, 0x0007, 0x9051, 0x3900, 0x0024, 0x3200, 0x504c, + 0x6410, 0x0024, 0x3cf0, 0x0000, 0x4080, 0x0024, 0x0006, 0xc691, 0x2801, + 0x9c45, 0x3009, 0x0400, 0x0000, 0x1001, 0x0007, 0x9051, 0x3100, 0x0024, + 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2801, 0x9089, 0x003f, 0xe000, 0x0006, + 0xc693, 0x3900, 0x0c00, 0x3009, 0x0001, 0x6014, 0x0024, 0x0007, 0x1ad0, + 0x2801, 0x9095, 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0301, 0x2801, + 0x8a85, 0x4090, 0x0024, 0x0000, 0x0024, 0x2801, 0x8b95, 0x0000, 0x0024, + 0x3009, 0x0000, 0xc012, 0x0024, 0x2801, 0x9080, 0x3009, 0x2001, 0x3009, + 0x0000, 0x6012, 0x0024, 0x0000, 0x0341, 0x2801, 0x8d95, 0x0000, 0x0024, + 0x6190, 0x0024, 0x2801, 0x9080, 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, + 0x0381, 0x2801, 0x8f55, 0x0000, 0x0024, 0x6190, 0x0024, 0x2801, 0x9080, + 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, 0x00c0, 0x2801, 0x9095, 0x0000, + 0x0024, 0x3009, 0x2000, 0x0006, 0xa090, 0x3009, 0x0000, 0x4080, 0x0024, + 0x0000, 0x0081, 0x2801, 0x9555, 0x0007, 0x8c13, 0x3300, 0x104c, 0xb010, + 0x0024, 0x0002, 0x8001, 0x2801, 0x97c5, 0x34f0, 0x0024, 0x2801, 0x9540, + 0x0000, 0x0024, 0x0006, 0xc351, 0x3009, 0x0000, 0x6090, 0x0024, 0x3009, + 0x2000, 0x2900, 0x0b80, 0x3009, 0x0405, 0x0006, 0xc6d1, 0x0006, 0xc690, + 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, 0x0006, 0xa093, 0x2801, + 0x93d1, 0xb880, 0x0024, 0x2801, 0xa500, 0x3009, 0x2c00, 0x4040, 0x0024, + 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2801, 0xa518, 0x0000, 0x0024, 0x0006, + 0xc693, 0x3009, 0x0c00, 0x3009, 0x0001, 0x6014, 0x0024, 0x0006, 0xc350, + 0x2801, 0xa501, 0x0000, 0x0024, 0x6090, 0x0024, 0x3009, 0x2c00, 0x3009, + 0x0005, 0x2900, 0x0b80, 0x0001, 0xa508, 0x3009, 0x0400, 0x4080, 0x0024, + 0x0003, 0x8000, 0x2801, 0xa505, 0x0000, 0x0024, 0x6400, 0x0024, 0x0000, + 0x0081, 0x2801, 0xa509, 0x0000, 0x0024, 0x0007, 0x8c13, 0x3300, 0x0024, + 0xb010, 0x0024, 0x0006, 0xc650, 0x2801, 0xa515, 0x0000, 0x0024, 0x0001, + 0x0002, 0x3413, 0x0000, 0x3009, 0x0401, 0x4010, 0x8406, 0x0000, 0x0281, + 0xa010, 0x13c1, 0x4122, 0x0024, 0x0000, 0x03c2, 0x6122, 0x8002, 0x462c, + 0x0024, 0x469c, 0x0024, 0xfee2, 0x0024, 0x48be, 0x0024, 0x6066, 0x8400, + 0x0006, 0xc350, 0x2801, 0xa501, 0x0000, 0x0024, 0x4090, 0x0024, 0x3009, + 0x2400, 0x2900, 0x0b80, 0x3009, 0x0005, 0x0007, 0x1b50, 0x2912, 0x0d00, + 0x3613, 0x0024, 0x3a00, 0x0380, 0x4080, 0x0024, 0x0000, 0x00c1, 0x2801, + 0xadc5, 0x3009, 0x0000, 0xb010, 0x008c, 0x4192, 0x0024, 0x6012, 0x0024, + 0x0006, 0xf051, 0x2801, 0xabd8, 0x3009, 0x0400, 0x0007, 0x1fd1, 0x30e3, + 0x0400, 0x4080, 0x0024, 0x0000, 0x0301, 0x2801, 0xadc5, 0x3009, 0x0000, + 0xb010, 0x0024, 0x0000, 0x0101, 0x6012, 0x0024, 0x0006, 0xf051, 0x2801, + 0xadd5, 0x0000, 0x0024, 0x3023, 0x0400, 0xf200, 0x184c, 0xb880, 0xa400, + 0x3009, 0x2000, 0x3009, 0x0441, 0x3e10, 0x4402, 0x2909, 0xa9c0, 0x3e10, + 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x1811, 0x36f1, 0x9807, + 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, + 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, + 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, + 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xf810, + 0x0001, 0x0010, 0x3e14, 0x7812, 0xb882, 0x3813, 0x2914, 0xbec0, 0x0000, + 0x2200, 0xb886, 0x12cc, 0x2801, 0xba40, 0x3454, 0x8024, 0x0001, 0x0000, + 0x3000, 0x984c, 0x4234, 0xb843, 0xf400, 0x4095, 0x003b, 0xffc2, 0x3500, + 0x4024, 0xb122, 0x0842, 0x4010, 0x0bc3, 0x4010, 0x0024, 0x4010, 0x0024, + 0x4010, 0x0024, 0x4d82, 0x4011, 0x2938, 0x0600, 0xf400, 0x4450, 0x3223, + 0x184c, 0x3210, 0x8024, 0x32d0, 0xc024, 0x2938, 0x0600, 0x4d82, 0x4450, + 0x3243, 0x1bc3, 0x6396, 0x0024, 0x0005, 0xdf90, 0x3000, 0x0024, 0x6302, + 0x0024, 0x0005, 0xe110, 0x2801, 0xb511, 0x0000, 0x0024, 0x2801, 0xc0c0, + 0x4086, 0x0024, 0x3200, 0x930c, 0x6398, 0x1111, 0x4244, 0x0844, 0xf400, + 0x4095, 0x3500, 0x584c, 0x4438, 0x0805, 0x453a, 0x4115, 0x3500, 0x8024, + 0x6122, 0x4155, 0x4280, 0x1404, 0x0001, 0x0002, 0x4244, 0x0024, 0x4244, + 0x0024, 0x4244, 0x0024, 0x4244, 0x0024, 0x2938, 0x2f80, 0xf400, 0x4090, + 0x6396, 0x0024, 0x0005, 0xdf50, 0x3000, 0x0024, 0x6302, 0x0024, 0x0005, + 0xe0d2, 0x2801, 0xbc51, 0x0000, 0x0381, 0x3073, 0x0024, 0x3023, 0x0024, + 0x3000, 0x0024, 0x6012, 0x0024, 0x0001, 0x2212, 0x2801, 0xc5d5, 0x0005, + 0x1453, 0x0001, 0x0011, 0x3093, 0x184c, 0x3000, 0x4024, 0x2900, 0x7680, + 0x3e00, 0x4024, 0x2801, 0xc7c0, 0x36f3, 0x0024, 0x0001, 0x0011, 0x0005, + 0xe3c1, 0x3613, 0x024c, 0x3e10, 0x4024, 0x3000, 0x8024, 0x2900, 0x5a00, + 0x3e00, 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x5812, 0x36f1, + 0xd810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, 0x00c1, 0xb880, 0xb803, 0x3e10, + 0x904c, 0x3e11, 0x3806, 0x3e11, 0xf810, 0x0006, 0xf450, 0x3e14, 0x7812, + 0x3e14, 0xc024, 0x3cf0, 0x2080, 0x3009, 0x23c0, 0x3009, 0x2380, 0x0000, + 0x0640, 0x3009, 0x2000, 0x2921, 0x9440, 0x0000, 0x00c0, 0x2921, 0xdd40, + 0x3613, 0x0024, 0xf400, 0x4004, 0x0000, 0x01c0, 0x6400, 0x0024, 0x0000, + 0x00c0, 0x2801, 0xeac5, 0x0000, 0x01c1, 0x6412, 0x4100, 0x0006, 0x0581, + 0x2801, 0xe041, 0x4412, 0x0024, 0xf400, 0x4057, 0x3702, 0x0024, 0x2000, + 0x0000, 0x0000, 0x0024, 0x0000, 0x0641, 0x0006, 0xf410, 0x3613, 0x0000, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0xd615, 0x0000, 0x0024, 0x3009, + 0x2004, 0x2900, 0xb3c0, 0x3e01, 0x0024, 0x2801, 0xe040, 0x36f3, 0x0024, + 0x0000, 0x0641, 0x0006, 0xf410, 0x3613, 0x0000, 0x6012, 0x0024, 0x0000, + 0x0024, 0x2801, 0xd915, 0x0000, 0x0024, 0x3009, 0x2004, 0x2900, 0xa1c0, + 0x3e01, 0x0024, 0x2801, 0xe040, 0x36f3, 0x0024, 0x0006, 0xf450, 0x3613, + 0x0000, 0x6090, 0x3804, 0x2900, 0xb3c0, 0x3009, 0x2000, 0x2801, 0xe040, + 0x36f3, 0x0024, 0x2923, 0x4f00, 0x0007, 0x2050, 0x2801, 0xe040, 0x3009, + 0x2000, 0x2923, 0x7580, 0x0001, 0xe048, 0x34d3, 0x184c, 0x3430, 0x0024, + 0x2922, 0x4fc0, 0x3e00, 0x0024, 0x2801, 0xe040, 0x36f3, 0x0024, 0x0007, + 0x2050, 0x0000, 0x3fc0, 0x3613, 0x0024, 0x2923, 0x8480, 0x3e00, 0x0024, + 0x36f3, 0x2000, 0x0000, 0x1800, 0x3413, 0x0024, 0xf400, 0x4510, 0x34f0, + 0x4024, 0x6192, 0x0024, 0x6014, 0x2001, 0x0007, 0x2051, 0x2801, 0xe2c1, + 0x0000, 0x0280, 0x3009, 0x2400, 0x3009, 0x0400, 0x4080, 0x0024, 0x0006, + 0xf352, 0x2801, 0xebd5, 0x3009, 0x0842, 0x3009, 0x0bc3, 0x4d86, 0x0024, + 0x0000, 0x0201, 0x2801, 0xe705, 0x0030, 0x0013, 0x0006, 0x8a93, 0x3009, + 0x0c40, 0x3009, 0x0fc1, 0x6cde, 0x0024, 0x0000, 0x0201, 0x2801, 0xebc1, + 0x0030, 0x0013, 0x3300, 0x0024, 0xb010, 0x0024, 0x0000, 0x0100, 0x2801, + 0xebd5, 0x0000, 0x00c1, 0x2921, 0x9440, 0x3613, 0x0024, 0x2921, 0xdd40, + 0x3613, 0x0024, 0xf400, 0x4004, 0x0000, 0x01c0, 0x6400, 0x0024, 0x0000, + 0x01c1, 0x2801, 0xd215, 0x0000, 0x00c0, 0x2921, 0x9440, 0x3613, 0x0024, + 0x2921, 0xc300, 0x0000, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x5812, 0x36f1, + 0xd810, 0x36f1, 0x1806, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, + 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, + 0x0000, 0x800a, 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7810, 0x3e14, + 0x7812, 0x3e14, 0xc024, 0x2922, 0x1880, 0x0000, 0x0180, 0x2921, 0xdd40, + 0x6892, 0x184c, 0x4080, 0x0024, 0x0000, 0x0024, 0x2801, 0xf3c5, 0x0000, + 0x0024, 0x2802, 0x2f40, 0xb880, 0x0024, 0x2921, 0xdd40, 0x6892, 0x184c, + 0x4080, 0x0024, 0x0000, 0x0181, 0x2801, 0xf5d5, 0x0000, 0x0024, 0x2802, + 0x2f40, 0xb880, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0101, 0x2801, 0xf7c5, 0x0000, 0x0024, 0x2802, 0x2f40, 0xb880, + 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, 0x0000, 0x00c1, + 0x2801, 0xf9c5, 0x0000, 0x0024, 0x2802, 0x2f40, 0xb880, 0x0024, 0x2921, + 0xdd40, 0x3613, 0x0024, 0x4080, 0x0024, 0x0000, 0x0141, 0x2801, 0xfbc5, + 0x0006, 0xf250, 0x2802, 0x2f40, 0xb880, 0x0024, 0x2921, 0xdd40, 0x3613, + 0x0024, 0x0000, 0x0101, 0x2921, 0xdd40, 0x3613, 0x2000, 0x0000, 0x03c1, + 0x6012, 0x03cc, 0x3613, 0x2000, 0x2802, 0x0115, 0x0006, 0xf051, 0x3009, + 0x3841, 0x2921, 0xdd40, 0x0000, 0x0201, 0xb080, 0x024c, 0x3009, 0x2000, + 0x2921, 0xdd40, 0x0000, 0x0401, 0x3009, 0x0401, 0xc100, 0x0024, 0x2802, + 0x0240, 0x3009, 0x2400, 0x3009, 0x0002, 0x2920, 0x5d00, 0x3e00, 0x8024, + 0x36f3, 0x024c, 0x3009, 0x2000, 0x0000, 0x0101, 0x2921, 0xdd40, 0x3613, + 0x0024, 0x0000, 0x0141, 0x3013, 0x0024, 0x3009, 0x21c0, 0x3009, 0x0000, + 0x6012, 0x0024, 0x0007, 0x1b51, 0x2802, 0x1395, 0x0000, 0x0101, 0x0007, + 0xc251, 0x2921, 0xdd40, 0x3613, 0x0024, 0x0000, 0x03c1, 0x6012, 0x2400, + 0x3100, 0x984c, 0x2802, 0x0ad5, 0x0007, 0xc292, 0x3009, 0x3841, 0x2921, + 0xdd40, 0x0000, 0x0201, 0x4082, 0x044c, 0xb080, 0x0024, 0x3910, 0x0024, + 0x39f0, 0x7841, 0x2921, 0xdd40, 0x0000, 0x0401, 0x3211, 0x1bcc, 0xb182, + 0x0bc5, 0xcec2, 0x0024, 0x3a10, 0x0024, 0x2802, 0x0c00, 0x3af0, 0x4024, + 0x2920, 0x5d00, 0x3e00, 0x8024, 0x36f3, 0x044c, 0x3910, 0x0024, 0x39f0, + 0x4024, 0x0007, 0x1b52, 0x0000, 0x0141, 0x2921, 0xdd40, 0x3613, 0x0024, + 0x3111, 0x2240, 0xb880, 0x03cc, 0x31f1, 0x6800, 0xb182, 0x8000, 0x6ce6, + 0x0024, 0x002e, 0xe002, 0x2802, 0x1a85, 0xb886, 0x0024, 0x6de2, 0x0b8c, + 0x0000, 0x00c1, 0x2802, 0x1251, 0x3009, 0x0800, 0xb010, 0x0024, 0x4192, + 0x0024, 0x6012, 0x0024, 0x0007, 0x1b52, 0x2802, 0x1258, 0x0000, 0x0024, + 0x6890, 0xa004, 0x2802, 0x1a80, 0x3009, 0x2800, 0x4e82, 0x0024, 0x0000, + 0x0020, 0xf2c2, 0x0024, 0x2802, 0x1a80, 0x3009, 0x2000, 0x3009, 0x07c0, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2802, 0x1a85, 0x0000, 0x0024, 0x3093, + 0x0400, 0x4080, 0x03cc, 0x0017, 0x7001, 0x2802, 0x1995, 0x3009, 0x0000, + 0x6012, 0x0024, 0x0007, 0x1b50, 0x2802, 0x1901, 0xb880, 0x0024, 0x0000, + 0x00c1, 0x31f3, 0x0024, 0x3009, 0x0400, 0xb010, 0x0024, 0x4080, 0x0024, + 0x0000, 0x0000, 0x2802, 0x1989, 0x0000, 0x0024, 0x2802, 0x1a80, 0x3009, + 0x2000, 0x0006, 0xf050, 0x3009, 0x0000, 0x4000, 0x0024, 0x3009, 0x2000, + 0x0000, 0x0081, 0x0006, 0xf250, 0x3009, 0x0000, 0x6012, 0x0024, 0x0007, + 0xc151, 0x2802, 0x1cc5, 0x0000, 0x0024, 0x2802, 0x2f40, 0xb880, 0x0024, + 0x2921, 0xdd40, 0x6892, 0x184c, 0x6892, 0x2400, 0x2921, 0xdd40, 0x3009, + 0x184c, 0x4080, 0x0024, 0x0000, 0x0381, 0x2802, 0x1f85, 0x0000, 0x0024, + 0x2921, 0xdd40, 0x3613, 0x0024, 0x2921, 0xdd40, 0x6892, 0x184c, 0x4080, + 0x0024, 0x0000, 0x0240, 0x2802, 0x2205, 0x0000, 0x00c1, 0x2921, 0xdd40, + 0x6892, 0x184c, 0x0000, 0x00c1, 0x0000, 0x0240, 0x0006, 0x0752, 0x2922, + 0x1880, 0x3613, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x4080, 0x2800, + 0x0000, 0x0201, 0x2802, 0x2515, 0x3613, 0x0024, 0x2921, 0xdd40, 0x0002, + 0x2788, 0x3613, 0x0024, 0x4090, 0x1bcc, 0x0000, 0x0241, 0x2802, 0x2715, + 0x0006, 0x07d3, 0x2921, 0xdd40, 0x3613, 0x0024, 0x2802, 0x2780, 0x3b00, + 0x0024, 0x2802, 0x2f40, 0xb880, 0x0024, 0x0006, 0x0813, 0xb880, 0x184c, + 0x2921, 0xdd40, 0x6892, 0x2c00, 0x4080, 0x0024, 0x0006, 0x0810, 0x2802, + 0x2d05, 0x0000, 0x4003, 0x3000, 0x184c, 0xff86, 0x0024, 0x48b6, 0x0024, + 0x2921, 0xdd40, 0x6892, 0x2002, 0x0000, 0x0201, 0x2921, 0xdd40, 0x4088, + 0x184c, 0x3000, 0x4024, 0x4100, 0x0024, 0x4488, 0x2000, 0x0000, 0x4003, + 0x2802, 0x2995, 0x0006, 0x0810, 0x2921, 0xdd40, 0x6892, 0x184c, 0x4080, + 0x0024, 0x0000, 0x0201, 0x2802, 0x2f05, 0x0000, 0x0024, 0x2921, 0xdd40, + 0x3613, 0x0024, 0x6890, 0x0024, 0x36f4, 0xc024, 0x36f4, 0x5812, 0x36f1, + 0x5810, 0x36f0, 0xd804, 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, + 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x0000, 0x0081, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, + 0xb807, 0x3e14, 0x3811, 0x0006, 0xf250, 0x3e04, 0xb813, 0x3009, 0x0000, + 0x6012, 0x0024, 0x003f, 0xff01, 0x2802, 0x3a05, 0x0006, 0x07d1, 0x6194, + 0x0400, 0x0000, 0x0041, 0xa020, 0x984c, 0x0000, 0x01c2, 0xfe02, 0x0024, + 0x48b2, 0x0024, 0x3e10, 0x0024, 0x2921, 0xca80, 0x3e00, 0x4024, 0x3100, + 0x5bcc, 0x2921, 0xdd40, 0xb122, 0x0024, 0x291a, 0x8a40, 0x0002, 0x4c08, + 0x0007, 0x2052, 0x0006, 0x8a93, 0x3100, 0x184c, 0xa010, 0x0024, 0x0000, + 0x0041, 0x6090, 0x0024, 0x2922, 0x1880, 0x6090, 0x0024, 0xb880, 0x010c, + 0x3100, 0x2800, 0xfe02, 0x8c44, 0x3613, 0x0fc5, 0x4eb2, 0x0024, 0x3009, + 0x2040, 0x0000, 0x00c0, 0x2921, 0xbb80, 0x3e00, 0x23c1, 0x0000, 0x01c1, + 0x6012, 0x0024, 0x0003, 0xf680, 0x2802, 0x4055, 0x0000, 0x0024, 0x36f3, + 0x0024, 0x291a, 0x8a40, 0x0002, 0x4c08, 0x2901, 0xca80, 0x3e00, 0x0024, + 0x3413, 0x0040, 0x36f3, 0x03c1, 0x3009, 0x0c44, 0x3009, 0x0fc5, 0x6ce2, + 0x0024, 0x3c10, 0x0024, 0xbc82, 0x33c1, 0x3410, 0x2040, 0x34e0, 0x63c1, + 0x4c82, 0x0024, 0x0000, 0x0024, 0x2802, 0x4909, 0x4c82, 0x0024, 0x0000, + 0x01c4, 0x4c86, 0x184c, 0x003f, 0xff40, 0xad06, 0x0024, 0x3e10, 0x8024, + 0x2921, 0xca80, 0x3e00, 0xc024, 0x36f3, 0x0024, 0x2921, 0x9440, 0x0000, + 0x0080, 0xb88a, 0x104c, 0x3410, 0x0c46, 0x34e0, 0x4fc7, 0xbce2, 0x984c, + 0x4cf2, 0x0024, 0x3e10, 0x0024, 0x2921, 0x9780, 0x3e00, 0x4024, 0x2802, + 0x4b00, 0x36e3, 0x0024, 0x0000, 0x0024, 0x2802, 0x4b18, 0x0000, 0x0024, + 0x4ce6, 0x184c, 0x3e10, 0x8024, 0x2921, 0x9780, 0x3e00, 0xc024, 0x36e3, + 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2922, 0x1880, 0x3613, 0x0024, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, + 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, 0x3e10, 0x7802, + 0x3e10, 0xf804, 0x3e14, 0x3811, 0x0006, 0x8a91, 0x0006, 0x0790, 0x3e14, + 0xb813, 0x0007, 0x8b52, 0x3e13, 0xf80e, 0x3e03, 0x504c, 0xb880, 0x0024, + 0x3c00, 0x33c0, 0x2921, 0xb380, 0x3800, 0x0024, 0x2920, 0x6a00, 0x0030, + 0x0253, 0x0000, 0x0400, 0xb882, 0xa440, 0xb880, 0xa7c1, 0x3a00, 0x0024, + 0x0013, 0x1040, 0x3b00, 0x0024, 0x0000, 0x0180, 0x2922, 0x1880, 0x3613, + 0x0024, 0x4f82, 0x0024, 0x003f, 0xf801, 0xb010, 0x0024, 0x0015, 0xb801, + 0x6012, 0x0024, 0x0007, 0x8a50, 0x2802, 0x73d5, 0x0000, 0x0201, 0x0006, + 0x8a90, 0x2921, 0xdd40, 0x3613, 0x0024, 0x003f, 0xfe00, 0x3613, 0x0042, + 0xb882, 0x83c3, 0xbdc2, 0x0024, 0x3009, 0x2040, 0x2921, 0xdd40, 0x6892, + 0xa3c1, 0x4080, 0x0024, 0x0000, 0x0024, 0x2802, 0x5e95, 0x0000, 0x0024, + 0x2901, 0xee80, 0x0006, 0x0791, 0x4080, 0x2400, 0x0006, 0xf052, 0x2802, + 0x5e85, 0x0000, 0x0024, 0x3613, 0x0841, 0x3e10, 0x4802, 0x2909, 0xa9c0, + 0x3e10, 0x8024, 0x36e3, 0x0024, 0x0006, 0x0791, 0x3100, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2921, 0xc305, 0x0002, 0x6f48, 0x0006, 0x0752, + 0xb880, 0x104c, 0x3613, 0x33c0, 0x2922, 0x1880, 0x0000, 0x0100, 0x3200, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2902, 0x31d5, 0x0002, 0x67c8, + 0x0006, 0x07d3, 0xb880, 0x0024, 0x0006, 0x07d0, 0x3b00, 0x0024, 0x0000, + 0x0201, 0x2921, 0xdd40, 0x3613, 0x0024, 0x0000, 0x00c1, 0x3423, 0x0024, + 0x3c00, 0x0024, 0xa010, 0x0001, 0x4100, 0x0024, 0x0000, 0x3fc1, 0x3800, + 0x0024, 0x34e0, 0x0024, 0x6012, 0x0024, 0x0006, 0x07d0, 0x2802, 0x6385, + 0x0000, 0x0024, 0x2902, 0x31c0, 0x0000, 0x0024, 0x0006, 0x0810, 0x3000, + 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, 0x2802, 0x6ec5, 0x0000, 0x0024, + 0xf200, 0x184c, 0xf200, 0x0024, 0xf200, 0x0024, 0xb182, 0x3840, 0x2921, + 0xca80, 0x3e00, 0x4024, 0x0000, 0x01c1, 0x291a, 0x8a40, 0x36e3, 0x0024, + 0xb888, 0x4411, 0x3000, 0x0024, 0xb012, 0x0024, 0x6410, 0x2001, 0x0000, + 0x0024, 0x2802, 0x6ec1, 0x0000, 0x0024, 0x4192, 0x0024, 0x2402, 0x6e81, + 0x0000, 0x0024, 0x2921, 0xdd40, 0x6892, 0x184c, 0x6498, 0x0024, 0x2921, + 0xc300, 0x0000, 0x0024, 0x291a, 0x8a40, 0x3413, 0x0024, 0xf400, 0x4512, + 0x0030, 0x0010, 0x0000, 0x0201, 0x2900, 0x0c80, 0x34f3, 0x0024, 0x3000, + 0x0024, 0xb010, 0x0024, 0x0000, 0x0100, 0x2802, 0x8095, 0x0000, 0x0401, + 0x2922, 0x1880, 0x3613, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0x2802, + 0x7ec0, 0xb78e, 0x4006, 0x3000, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2802, 0x8089, 0xf292, 0x0024, 0x6012, 0x904c, 0x0006, 0x0791, 0x2802, + 0x7718, 0x3100, 0x0024, 0x3000, 0x0024, 0x4090, 0x0024, 0x3800, 0x0024, + 0x3100, 0x0024, 0x4080, 0x4512, 0x34f3, 0x184c, 0x2802, 0x79d5, 0x0007, + 0x0553, 0x36f3, 0x0800, 0x6090, 0x0024, 0x4080, 0xa800, 0x0000, 0x0024, + 0x2802, 0x8088, 0x0000, 0x0024, 0x3009, 0x184c, 0x0006, 0xf312, 0x4ffe, + 0xb841, 0x2921, 0xdd40, 0x6892, 0x41c7, 0xb182, 0x9bcc, 0x291a, 0x8a40, + 0xcfce, 0x0024, 0x0004, 0x0001, 0xb880, 0x010c, 0x6890, 0x2000, 0x0007, + 0x80d0, 0xb880, 0xa800, 0x3000, 0x2c00, 0x0007, 0x1ad0, 0xff82, 0x0024, + 0x48b2, 0x0024, 0xf400, 0x4040, 0x0000, 0x03c1, 0xb010, 0x0024, 0x3009, + 0x2000, 0x0000, 0x0201, 0x0030, 0x0010, 0x3000, 0x0024, 0xb010, 0x0024, + 0x0000, 0x0180, 0x2802, 0x55c5, 0x0000, 0x0024, 0x6890, 0x1bcd, 0x36f3, + 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f0, 0xd804, 0x36f0, 0x5802, + 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, + 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0012, 0x5103, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x380d, 0x0030, 0x0250, 0x3e13, 0xf80e, + 0xbe8b, 0x83e0, 0x290c, 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, 0x4086, + 0x984c, 0x0000, 0x00ce, 0x2402, 0x8a8e, 0x3009, 0x1bc0, 0x0000, 0x01c3, + 0xae3a, 0x184c, 0x0000, 0x0043, 0x3009, 0x3842, 0x290c, 0x4840, 0x3009, + 0x3840, 0x4084, 0x9bc0, 0xfe26, 0x9bc2, 0xceba, 0x0024, 0x4e8e, 0x0024, + 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0000, 0x0102, 0x2802, 0x8fc5, 0x0030, + 0x0010, 0x0000, 0x0206, 0x3613, 0x0024, 0x290c, 0x4840, 0x3009, 0x3840, + 0x3000, 0xdbc0, 0xb366, 0x0024, 0x0000, 0x0024, 0x2802, 0x8fd5, 0x4e8e, + 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0030, 0x0010, 0x2802, 0x8c95, + 0x0000, 0x0206, 0x36f3, 0xd80e, 0x36f4, 0x180d, 0x36f1, 0x9807, 0x36f1, + 0x1805, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, + 0x2000, 0x0000, 0x36f2, 0x9817, 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6480, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1b40, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x144e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x7980, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x01a4, /*copy 420*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x0012, /*copy 18*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x0750, 0x075c, 0x076f, 0x0768, 0x0773, 0x0775, 0x077b, + 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 5594 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/patches_pitch.h b/targets/esp32/components/VS1053/include/patches_pitch.h new file mode 100644 index 00000000..5c2effe7 --- /dev/null +++ b/targets/esp32/components/VS1053/include/patches_pitch.h @@ -0,0 +1,688 @@ + +#ifndef SKIP_PLUGIN_VARNAME +const unsigned short PLUGIN[] = { + /* Compressed plugin */ +#endif + 0x0007, 0x0001, /*copy 1*/ + 0x8050, 0x0006, 0x0020, /*copy 32*/ + 0x2a00, 0xc000, 0x2a02, 0x75c0, 0x3e12, 0xb817, 0x3e14, 0xf812, 0x3e01, + 0xb811, 0x0007, 0x9717, 0x0020, 0xffd2, 0x0030, 0x11d1, 0x3111, 0x8024, + 0x3704, 0xc024, 0x3b81, 0x8024, 0x3101, 0x8024, 0x3b81, 0x8024, 0x3f04, + 0xc024, 0x2808, 0x4800, 0x36f1, 0x9811, 0x0007, 0x0001, /*copy 1*/ + 0x8060, 0x0006, 0x0516, /*copy 1302*/ + 0xf400, 0x4095, 0x0000, 0x02c2, 0x6124, 0x0024, 0x0000, 0x0024, 0x2800, + 0x1ac5, 0x4192, 0x4542, 0x0000, 0x0041, 0x2000, 0x0015, 0x0030, 0x0317, + 0x2000, 0x0000, 0x3f00, 0x4024, 0x2000, 0x0000, 0x0000, 0x0000, 0x3e12, + 0x3800, 0x3e00, 0xb804, 0x0030, 0x0015, 0x0007, 0x8257, 0x3700, 0x984c, + 0xf224, 0x1444, 0xf224, 0x0024, 0x0008, 0x0002, 0x2910, 0x0181, 0x0000, + 0x1bc8, 0xb428, 0x1402, 0x0000, 0x8004, 0x2910, 0x0195, 0x0000, 0x1bc8, + 0xb428, 0x0024, 0x0006, 0x0095, 0x2800, 0x2945, 0x3e13, 0x780e, 0x3e11, + 0x7803, 0x3e13, 0xf806, 0x3e11, 0xf801, 0x3510, 0xb808, 0x003f, 0xe004, + 0xfec4, 0x3800, 0x48be, 0x17c3, 0xfec6, 0x41c2, 0x48be, 0x4497, 0x4090, + 0x1c46, 0xf06c, 0x0024, 0x2400, 0x2580, 0x6090, 0x41c3, 0x6628, 0x1c47, + 0x0000, 0x0024, 0x2800, 0x2449, 0xf07e, 0x0024, 0xf400, 0x4182, 0x673a, + 0x1c46, 0x0000, 0x0024, 0x2800, 0x2589, 0xf06c, 0x0024, 0xf400, 0x41c3, + 0x0000, 0x0024, 0x4224, 0x3442, 0x2902, 0xb7c0, 0x4336, 0x37c3, 0x0000, + 0x1805, 0x2902, 0xb7c0, 0x4508, 0x40c2, 0x450a, 0x9808, 0x0000, 0x0207, + 0xa478, 0x1bc0, 0xc45a, 0x1807, 0x0030, 0x03d5, 0x3d01, 0x5bc1, 0x36f3, + 0xd806, 0x3601, 0x5803, 0x36f3, 0x0024, 0x36f3, 0x580e, 0x0007, 0x8257, + 0x0000, 0x6004, 0x3730, 0x8024, 0xb244, 0x1c04, 0xd428, 0x3c02, 0x0006, + 0xc717, 0x2800, 0x2d05, 0x4284, 0x0024, 0x3613, 0x3c02, 0x0006, 0xc357, + 0x2901, 0x6b00, 0x3e11, 0x5c05, 0x4284, 0x1bc5, 0x0007, 0x8257, 0x2800, + 0x3285, 0x0002, 0x0001, 0x3701, 0x0024, 0x0006, 0xc357, 0xb412, 0x9c02, + 0x002e, 0xe001, 0x2800, 0x3005, 0x6212, 0x0024, 0x0000, 0x0024, 0x2800, + 0x3295, 0x0000, 0x0024, 0x0030, 0x0117, 0x3f00, 0x0024, 0x3613, 0x0024, + 0x3e10, 0x3813, 0x3e14, 0x8024, 0x3e04, 0x8024, 0x2900, 0x4b40, 0x0006, + 0x02d3, 0x36e3, 0x0024, 0x3009, 0x1bd3, 0x0007, 0x8257, 0x3700, 0x8024, + 0xf224, 0x0024, 0x0000, 0x0024, 0x2800, 0x3491, 0x3600, 0x9844, 0x2900, + 0x3a40, 0x0000, 0x3508, 0x2911, 0xf140, 0x0000, 0x0024, 0x0030, 0x0057, + 0x3700, 0x0024, 0xf200, 0x4595, 0x0fff, 0xfe02, 0xa024, 0x164c, 0x8000, + 0x17cc, 0x3f00, 0x0024, 0x3500, 0x0024, 0x0021, 0x6d82, 0xd024, 0x44c0, + 0x0006, 0xa402, 0x2800, 0x3955, 0xd024, 0x0024, 0x0000, 0x0000, 0x2800, + 0x3955, 0x000b, 0x6d57, 0x3009, 0x3c00, 0x36f0, 0x8024, 0x36f2, 0x1800, + 0x2000, 0x0000, 0x0000, 0x0024, 0x3e14, 0x7810, 0x3e13, 0xb80d, 0x3e13, + 0xf80a, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0xf801, + 0x3e15, 0x3815, 0x0001, 0x000a, 0x0006, 0xc4d7, 0xbf8e, 0x9c42, 0x3e01, + 0x9c03, 0x0006, 0xa017, 0x0023, 0xffd1, 0x0007, 0x8250, 0x0fff, 0xfd85, + 0x3001, 0x0024, 0xa45a, 0x4494, 0x0000, 0x0093, 0x2800, 0x4091, 0xf25a, + 0x104c, 0x34f3, 0x0024, 0x2800, 0x4091, 0x0000, 0x0024, 0x3413, 0x084c, + 0x0000, 0x0095, 0x3281, 0xf806, 0x4091, 0x4d64, 0x2400, 0x42c0, 0x4efa, + 0x9c10, 0xf1eb, 0x6061, 0xfe55, 0x2f66, 0x5653, 0x4d64, 0x48b2, 0xa201, + 0x4efa, 0xa201, 0x36f3, 0x3c10, 0x36f5, 0x1815, 0x36f4, 0xd801, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0xd80a, 0x36f3, 0x980d, + 0x2000, 0x0000, 0x36f4, 0x5810, 0x36f3, 0x0024, 0x3009, 0x3848, 0x3e14, + 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, 0x2915, 0x94c0, + 0x0001, 0xcc11, 0x36f0, 0x0024, 0x2927, 0x9e40, 0x3604, 0x1811, 0x3613, + 0x0024, 0x3e14, 0x3811, 0x3e00, 0x0024, 0x0000, 0x4000, 0x0001, 0x0010, + 0x2915, 0x94c0, 0x0001, 0xcc11, 0x36f0, 0x0024, 0x36f4, 0x1811, 0x3009, + 0x1808, 0x2000, 0x0000, 0x0000, 0x190d, 0x3613, 0x0024, 0x3e22, 0xb815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e13, 0x7801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x3e14, 0xb813, + 0x3e03, 0xf80e, 0xb488, 0x44d5, 0x3543, 0x134c, 0x34e5, 0xc024, 0x3524, + 0x8024, 0x35a4, 0xc024, 0x3710, 0x8a0c, 0x3540, 0x4a0c, 0x3d44, 0x8024, + 0x3a10, 0x8024, 0x3590, 0x0024, 0x4010, 0x15c1, 0x6010, 0x3400, 0x3710, + 0x8024, 0x2800, 0x5704, 0x3af0, 0x8024, 0x3df0, 0x0024, 0x3591, 0x4024, + 0x3530, 0x4024, 0x4192, 0x4050, 0x6100, 0x1482, 0x4020, 0x1753, 0xbf8e, + 0x1582, 0x4294, 0x4011, 0xbd86, 0x408e, 0x2400, 0x550e, 0xfe6d, 0x2819, + 0x520e, 0x0a00, 0x5207, 0x2819, 0x4fbe, 0x0024, 0xad56, 0x904c, 0xaf5e, + 0x1010, 0xf7d4, 0x0024, 0xf7fc, 0x2042, 0x6498, 0x2046, 0x3cf4, 0x0024, + 0x3400, 0x170c, 0x4090, 0x1492, 0x35a4, 0xc024, 0x2800, 0x4f95, 0x3c00, + 0x0024, 0x4480, 0x914c, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f3, 0x5801, 0x3405, + 0x9014, 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x2814, 0x9c91, + 0x0000, 0x004d, 0x2814, 0x9940, 0x003f, 0x0013, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3655, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb810, 0x3e13, + 0xf80e, 0x3e03, 0x534c, 0x3450, 0x4024, 0x6814, 0x0024, 0x0000, 0x0024, + 0x2800, 0x7618, 0x4192, 0x0024, 0x2400, 0x75c1, 0x0000, 0x0024, 0xf400, + 0x4450, 0x2938, 0x1880, 0x3613, 0x0024, 0x3c10, 0x050c, 0x3c10, 0x4024, + 0x3c90, 0x8024, 0x34f3, 0x0024, 0x3464, 0x0024, 0x3011, 0x0c40, 0x3011, + 0x4c41, 0x2915, 0x9900, 0x3011, 0x8f82, 0x3411, 0x2c40, 0x3411, 0x6c41, + 0x2915, 0xa580, 0x34e1, 0xaf82, 0x3009, 0x3040, 0x4c8a, 0x0040, 0x3010, + 0x7041, 0x2800, 0x6854, 0x3010, 0xb382, 0x3411, 0x0024, 0x3411, 0x6c44, + 0x34e1, 0xac45, 0xbe8a, 0xaf86, 0x0fe0, 0x0006, 0x3009, 0x3044, 0x3009, + 0x3045, 0x3009, 0x3386, 0x3411, 0x0024, 0x3411, 0x4ccc, 0x2915, 0x9900, + 0x34e1, 0x984c, 0x3e10, 0x7800, 0x3009, 0x3802, 0x3011, 0x0c40, 0x3011, + 0x4c41, 0x2915, 0x9900, 0x30e1, 0x8f82, 0x3009, 0x1bc6, 0x2915, 0xa940, + 0x36f1, 0x5804, 0x3011, 0x2c40, 0x3011, 0x6c41, 0x30b1, 0xac42, 0x3009, + 0x0c40, 0x3009, 0x0c41, 0x2915, 0x9900, 0x3613, 0x0f82, 0x3e10, 0x7800, + 0x3009, 0x3802, 0x3010, 0x1044, 0x3010, 0x5045, 0x2915, 0x9900, 0x3010, + 0x9386, 0x3009, 0x1bc6, 0x2915, 0xa940, 0x36f1, 0x5804, 0xf1ca, 0xac40, + 0x4ce2, 0xac41, 0x3009, 0x2ec2, 0x2800, 0x7112, 0x629c, 0x0024, 0xf1c2, + 0x4182, 0x3c10, 0x0c44, 0x3c10, 0x4c45, 0x2915, 0x4780, 0x3ce0, 0x8f86, + 0x4080, 0x0024, 0x0000, 0x0024, 0x2800, 0x75d5, 0x0020, 0x0000, 0x3411, + 0x0c40, 0x3411, 0x4c41, 0x2915, 0xb780, 0x34e1, 0x8f82, 0x0000, 0x03c3, + 0x4234, 0x0024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2915, 0x4355, 0x0000, + 0x75c8, 0x0000, 0x0000, 0x3a10, 0x0d8c, 0x36f3, 0x538c, 0x36f3, 0xd80e, + 0x36f1, 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, + 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, + 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3645, + 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, + 0x3e11, 0xb810, 0x3e13, 0xf80e, 0x3e03, 0x534c, 0x3440, 0x4024, 0x4192, + 0x0024, 0x2400, 0x91c1, 0x0000, 0x0024, 0xb68c, 0x4450, 0x2938, 0x1880, + 0x3613, 0x050c, 0x3c10, 0x0c40, 0x3c10, 0x4c41, 0x3ce0, 0x8f82, 0x003c, + 0x2584, 0x2915, 0x9900, 0x0018, 0x8245, 0x3411, 0x2c40, 0x3411, 0x6c41, + 0x2915, 0xa580, 0x34e1, 0xac42, 0x4c8a, 0xb040, 0x3009, 0x3041, 0x2800, + 0x82d4, 0x3009, 0x3382, 0x3411, 0x0f4c, 0x3411, 0x6c44, 0x34e1, 0xac45, + 0xbe8a, 0xac46, 0x499c, 0xb044, 0xf38c, 0xb045, 0x3009, 0x3386, 0x3009, + 0x0c40, 0x3009, 0x0c41, 0xf1ca, 0x8f82, 0x4ce2, 0x1044, 0x3411, 0x4024, + 0x2800, 0x8512, 0x4294, 0x1386, 0x6294, 0x0024, 0xf1c2, 0x0024, 0x4e8a, + 0x4195, 0x35e3, 0x0024, 0x2915, 0xa955, 0xf400, 0x4546, 0x3009, 0x2c40, + 0x3009, 0x2c41, 0x3009, 0x2c42, 0x3009, 0x0c40, 0x3009, 0x0c41, 0xf1ca, + 0x8f82, 0x4ce2, 0x9044, 0x3009, 0x1045, 0x2800, 0x8985, 0x3009, 0x1386, + 0x2800, 0x8992, 0x4294, 0x0024, 0x6294, 0x0024, 0xf1c2, 0x0024, 0x4e8a, + 0x4195, 0x35e3, 0x0024, 0x2915, 0xa955, 0xf400, 0x4546, 0xf1ca, 0xac40, + 0x4ce2, 0xac41, 0x3009, 0x2ec2, 0x2800, 0x8c12, 0x629c, 0x0024, 0xf1c2, + 0x4182, 0x3c20, 0x0c84, 0x3cf0, 0x8fc6, 0x6264, 0x4017, 0x3cf0, 0x4fc5, + 0x2800, 0x91c8, 0x0020, 0x0000, 0x2800, 0x8f19, 0xf400, 0x45c0, 0x6cea, + 0x0024, 0x0000, 0x0024, 0x2800, 0x91c9, 0x0020, 0x0000, 0x3411, 0x0c40, + 0x3411, 0x4c41, 0x2915, 0xb780, 0x34e1, 0x8f82, 0x0000, 0x03c3, 0x4234, + 0x0024, 0x4c82, 0x0024, 0x0000, 0x0024, 0x2915, 0x4355, 0x0000, 0x91c8, + 0x0000, 0x0000, 0x3a10, 0x0d8c, 0x36f3, 0x53cc, 0x36f3, 0xd80e, 0x36f1, + 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0xf400, + 0x4595, 0x35e3, 0x3840, 0x3e13, 0xf80e, 0x3e13, 0x7808, 0x3510, 0x0024, + 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, + 0x0024, 0x0001, 0xce8e, 0x002b, 0xb30f, 0x292d, 0xa940, 0x0000, 0x004d, + 0x36d3, 0x0024, 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, + 0x1800, 0xf400, 0x4595, 0x35f3, 0x3840, 0x3e13, 0xf80e, 0x3e13, 0x7808, + 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, 0x0024, 0x0000, + 0x9dce, 0x0028, 0x088f, 0x2927, 0xff80, 0x0000, 0x008d, 0x36e3, 0x0024, + 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, 0x1800, 0x0028, + 0x2b0f, 0x0000, 0xa34e, 0x2828, 0x0b15, 0x0007, 0x2605, 0x3613, 0x0001, + 0x3e14, 0x3811, 0x0001, 0x0011, 0x0001, 0xcc10, 0x2915, 0x94c0, 0x0000, + 0x4000, 0x3e10, 0x534c, 0x3430, 0xc024, 0x3e10, 0xc024, 0x2927, 0xc4c0, + 0x3e01, 0x0024, 0x36d3, 0x0024, 0x0001, 0x0011, 0x0001, 0xcc10, 0x2915, + 0x94c0, 0x0000, 0x4000, 0x2828, 0x0b00, 0x36f4, 0x1811, 0x3e00, 0x0024, + 0x2800, 0xa740, 0x0028, 0x2bc8, 0x3605, 0x7840, 0x3e13, 0x780e, 0x3e13, + 0xf808, 0x3e05, 0x4024, 0x0000, 0x458e, 0x0027, 0x9e0f, 0x2922, 0xa6c0, + 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, + 0x0000, 0x3009, 0x1800, 0xf400, 0x4595, 0x35d3, 0x3840, 0x3e13, 0xf80e, + 0x3e13, 0x7808, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e10, + 0x0024, 0x3510, 0x0024, 0x3e10, 0x0024, 0x3510, 0x0024, 0x3e00, 0x0024, + 0x0000, 0xac8e, 0x0025, 0xf54f, 0x2925, 0xe580, 0x0000, 0x004d, 0x36c3, + 0x0024, 0x36f3, 0x5808, 0x36f3, 0xd80e, 0x2000, 0x0000, 0x3009, 0x1800, + 0x3433, 0x0000, 0x6890, 0x3040, 0x3cc0, 0xa000, 0x0008, 0x6201, 0x000d, + 0x3500, 0x3613, 0x110c, 0x3e10, 0x0024, 0x3e10, 0x4024, 0x34c0, 0x8024, + 0x2900, 0x94c0, 0x3e00, 0x8024, 0x0026, 0x0a4f, 0x0000, 0xb04e, 0x2825, + 0xf880, 0x0000, 0x07cd, 0x0000, 0x0801, 0x6012, 0x0024, 0x0000, 0x0024, + 0x2826, 0x0a85, 0x0000, 0x0024, 0x2800, 0xad40, 0x0000, 0x0024, 0x3605, + 0x7840, 0x3e13, 0x780e, 0x3e13, 0xf808, 0x3e05, 0x4024, 0x0000, 0xb54e, + 0x0022, 0xf54f, 0x2922, 0xda80, 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, + 0xd808, 0x36f3, 0x580e, 0x2000, 0x0000, 0x3009, 0x1800, 0x3e00, 0x0024, + 0x2800, 0x9980, 0x0022, 0xf608, 0x3605, 0x7840, 0x3e13, 0x780e, 0x3e13, + 0xf808, 0x3e05, 0x4024, 0x0000, 0xb94e, 0x0022, 0xa1cf, 0x2922, 0x9980, + 0x0000, 0x190d, 0x36f3, 0x0024, 0x36f3, 0xd808, 0x36f3, 0x580e, 0x2000, + 0x0000, 0x3009, 0x1800, 0x3009, 0x3400, 0x2800, 0xb200, 0x0022, 0xa288, + 0x2a01, 0x5a4e, 0x2a02, 0x7c0e, 0x2a02, 0x964e, 0x0007, 0x0001, /*copy 1*/ + 0x8300, 0x0006, 0x0ff6, /*copy 4086*/ + 0x0030, 0x0055, 0xb080, 0x1402, 0x0fdf, 0xffc1, 0x0007, 0x9257, 0xb212, + 0x3c00, 0x3d00, 0x4024, 0x0006, 0x0097, 0x3f10, 0x0024, 0x3f00, 0x0024, + 0x0030, 0x0297, 0x3f00, 0x0024, 0x0007, 0x9017, 0x3f00, 0x0024, 0x0007, + 0x81d7, 0x3f10, 0x0024, 0xc090, 0x3c00, 0x0006, 0x0297, 0xb080, 0x3c00, + 0x0000, 0x0401, 0x000a, 0x1055, 0x0006, 0x0017, 0x3f10, 0x3401, 0x000a, + 0x2795, 0x3f00, 0x3401, 0x0001, 0x6ad7, 0xf400, 0x55c0, 0x0000, 0x0817, + 0xb080, 0x57c0, 0x0014, 0x958f, 0x0000, 0x5b4e, 0x0030, 0x0017, 0x3700, + 0x0024, 0x0004, 0x0001, 0xb012, 0x0024, 0x0000, 0x004d, 0x280f, 0xe115, + 0x0006, 0x2016, 0x0006, 0x01d7, 0x3f00, 0x0024, 0x0000, 0x190d, 0x000f, + 0xf94f, 0x0000, 0xcd0e, 0x280f, 0xe100, 0x0006, 0x2016, 0x0000, 0x0080, + 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, 0x0006, 0x0197, 0x0006, + 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0007, 0x8a57, 0x3700, 0x0024, + 0x4080, 0x0024, 0x0000, 0x0040, 0x2800, 0xced5, 0x0006, 0xa2d7, 0x3009, + 0x3c00, 0x0006, 0xa157, 0x3009, 0x1c00, 0x0006, 0x01d7, 0x0000, 0x190d, + 0x000a, 0x708f, 0x0000, 0xd7ce, 0x290b, 0x1a80, 0x3f00, 0x184c, 0x0030, + 0x0017, 0x4080, 0x1c01, 0x0000, 0x0200, 0x2800, 0xcb15, 0xb102, 0x0024, + 0x0000, 0xcd08, 0x2800, 0xcb15, 0x0000, 0xd3ce, 0x0011, 0x210f, 0x0000, + 0x190d, 0x280f, 0xcb00, 0x3613, 0x0024, 0x0006, 0xa115, 0x0006, 0x01d7, + 0x37f0, 0x1401, 0x6100, 0x1c01, 0x4012, 0x0024, 0x0000, 0x8000, 0x6010, + 0x0024, 0x34f3, 0x0400, 0x2800, 0xd698, 0x0000, 0x0024, 0x0000, 0x8001, + 0x6010, 0x3c01, 0x0000, 0x000d, 0x2811, 0x8259, 0x0000, 0x0024, 0x2a11, + 0x2100, 0x0030, 0x0257, 0x3700, 0x0024, 0x4080, 0x0024, 0x0000, 0x0024, + 0x2800, 0xd9d5, 0x0006, 0x0197, 0x0006, 0xa115, 0x3f00, 0x3400, 0x003f, + 0xc000, 0xb600, 0x41c1, 0x0012, 0x5103, 0x000c, 0xc002, 0xdcd6, 0x0024, + 0x0019, 0xd4c2, 0x2802, 0x0c45, 0x0001, 0x1008, 0x0013, 0xd9c3, 0x6fd6, + 0x0024, 0x0000, 0x190d, 0x2800, 0xdf95, 0x0014, 0x1b01, 0x0020, 0x480f, + 0x0000, 0xde4e, 0x0000, 0x190d, 0x2820, 0x41c0, 0x0001, 0x1008, 0x0039, + 0x324f, 0x0001, 0x3ece, 0x2820, 0x4a18, 0xb882, 0x0024, 0x2a20, 0x48c0, + 0x003f, 0xfd00, 0xb700, 0x0024, 0x003f, 0xf901, 0x6010, 0x0024, 0x0000, + 0x0024, 0x280a, 0xc505, 0x0000, 0x190d, 0x0014, 0x1b01, 0x0015, 0x59c0, + 0x6fc2, 0x0024, 0x0000, 0x0024, 0x2800, 0xe9d5, 0x0000, 0x0024, 0x290c, + 0x4840, 0x3613, 0x0024, 0x290c, 0x4840, 0x4086, 0x184c, 0x0000, 0x18c2, + 0x6234, 0x0024, 0x0000, 0x1d02, 0x2800, 0xe5d5, 0x6234, 0x0024, 0x0030, + 0x0317, 0x2800, 0xe9c0, 0x3f00, 0x0024, 0x0000, 0x1d82, 0x2800, 0xe855, + 0x6234, 0x0024, 0x2912, 0x0d00, 0x4084, 0x184c, 0xf200, 0x0024, 0x6200, + 0x0024, 0x0006, 0x0017, 0x2800, 0xe540, 0xb080, 0x3c40, 0x0000, 0x0202, + 0x2800, 0xe9d5, 0xa024, 0x0024, 0xc020, 0x0024, 0x2800, 0xe540, 0x0030, + 0x02d7, 0x000a, 0x8c8f, 0x0000, 0xeb0e, 0x000c, 0x0981, 0x280a, 0x71c0, + 0x002c, 0x9d40, 0x000a, 0x708f, 0x0000, 0xd7ce, 0x280a, 0xc0d5, 0x0012, + 0x5182, 0x6fd6, 0x0024, 0x003f, 0xfd81, 0x280a, 0x8e45, 0xb710, 0x0024, + 0xb710, 0x0024, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, + 0x06d5, 0xffd2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x190d, + 0x2801, 0x06d5, 0x0030, 0x0250, 0xb880, 0x104c, 0x3cf0, 0x0024, 0x0010, + 0x5500, 0xb880, 0x23c0, 0xb882, 0x2000, 0x0007, 0x8590, 0x2914, 0xbec0, + 0x0000, 0x0440, 0x0007, 0x8b50, 0xb880, 0x0024, 0x2920, 0x0100, 0x3800, + 0x0024, 0x2920, 0x0000, 0x0006, 0x8a91, 0x0000, 0x0800, 0xb880, 0xa440, + 0x003f, 0xfd81, 0xb710, 0xa7c0, 0x003f, 0xfc01, 0x6012, 0x0024, 0x0000, + 0x0101, 0x2801, 0x1015, 0x0000, 0x0024, 0xffe2, 0x0024, 0x48b2, 0x0024, + 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, 0x1015, 0x0000, 0x0024, 0x2912, + 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, 0x0006, 0x8a90, 0x2801, 0x1015, + 0x0000, 0x01c2, 0xb886, 0x8040, 0x3613, 0x03c1, 0xbcd2, 0x0024, 0x0030, + 0x0011, 0x2800, 0xfc95, 0x003f, 0xff42, 0xb886, 0x8040, 0x3009, 0x03c1, + 0x0000, 0x0020, 0xac22, 0x0024, 0x0000, 0x0102, 0x6cd2, 0x0024, 0x3e10, + 0x0024, 0x2909, 0x8c80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3e11, 0x8024, + 0x3e01, 0xc024, 0x2901, 0x34c0, 0x0000, 0x0201, 0xf400, 0x4512, 0x2900, + 0x0c80, 0x3213, 0x1b8c, 0x3100, 0x0024, 0xb010, 0x0024, 0x0000, 0x0024, + 0x2801, 0x1015, 0x0000, 0x0024, 0x291a, 0x8a40, 0x0000, 0x0100, 0x2920, + 0x0200, 0x3633, 0x0024, 0x2920, 0x0280, 0x0000, 0x0401, 0x408e, 0x0024, + 0x2920, 0x0280, 0x0000, 0x0401, 0x003f, 0xfd81, 0xb710, 0x4006, 0x003f, + 0xfc01, 0x6012, 0x0024, 0x0000, 0x0101, 0x2801, 0x1015, 0x0000, 0x0024, + 0xffe2, 0x0024, 0x48b2, 0x0024, 0x4190, 0x0024, 0x0000, 0x0024, 0x2801, + 0x1015, 0x0000, 0x0024, 0x2912, 0x2d80, 0x0000, 0x0780, 0x4080, 0x0024, + 0x0000, 0x01c2, 0x2800, 0xf885, 0x0006, 0x8a90, 0x2a01, 0x1000, 0x2920, + 0x0100, 0x0000, 0x0401, 0x0000, 0x0180, 0x2920, 0x0200, 0x3613, 0x0024, + 0x2920, 0x0280, 0x3613, 0x0024, 0x0000, 0x0401, 0x2920, 0x0280, 0x4084, + 0x984c, 0x0019, 0x9d01, 0x6212, 0x0024, 0x001e, 0x5c01, 0x2801, 0x0b55, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x0d45, 0x0000, 0x0024, 0x001b, + 0x5bc1, 0x6212, 0x0024, 0x001b, 0xdd81, 0x2801, 0x1115, 0x6012, 0x0024, + 0x0000, 0x0024, 0x2801, 0x1115, 0x0000, 0x0024, 0x0000, 0x004d, 0x000a, + 0xbf4f, 0x280a, 0xb880, 0x0001, 0x0e4e, 0x0020, 0xfb4f, 0x0000, 0x190d, + 0x0001, 0x154e, 0x2920, 0xf440, 0x3009, 0x2bc1, 0x291a, 0x8a40, 0x36e3, + 0x0024, 0x0000, 0x190d, 0x000a, 0x708f, 0x280a, 0xcac0, 0x0000, 0xd7ce, + 0x0030, 0x0017, 0x3700, 0x4024, 0x0000, 0x0200, 0xb102, 0x0024, 0x0000, + 0x00c0, 0x2801, 0x1445, 0x0005, 0x4f92, 0x2909, 0xf840, 0x3613, 0x2800, + 0x0006, 0x0197, 0x0006, 0xa115, 0xb080, 0x0024, 0x3f00, 0x3400, 0x0000, + 0x190d, 0x000a, 0x708f, 0x280a, 0xc0c0, 0x0000, 0xd7ce, 0x0000, 0x004d, + 0x0020, 0xfe0f, 0x2820, 0xfb40, 0x0001, 0x164e, 0x2801, 0x1815, 0x3009, + 0x1000, 0x6012, 0x93cc, 0x0000, 0x0024, 0x2801, 0x32c5, 0x0000, 0x0024, + 0x3413, 0x0024, 0x34b0, 0x0024, 0x4080, 0x0024, 0x0000, 0x0200, 0x2801, + 0x1b15, 0xb882, 0x0024, 0x3453, 0x0024, 0x3009, 0x13c0, 0x4080, 0x0024, + 0x0000, 0x0200, 0x2801, 0x32c5, 0x0000, 0x0024, 0xb882, 0x130c, 0x0000, + 0x004d, 0x0021, 0x058f, 0x2821, 0x0340, 0x0001, 0x1c0e, 0x2801, 0x2c55, + 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0x2c55, 0x0000, 0x0024, 0x34c3, + 0x184c, 0x3e13, 0xb80f, 0xf400, 0x4500, 0x0026, 0x9dcf, 0x0001, 0x200e, + 0x0000, 0xfa0d, 0x2926, 0x8e80, 0x3e10, 0x110c, 0x36f3, 0x0024, 0x2801, + 0x2c40, 0x36f3, 0x980f, 0x001c, 0xdd00, 0x001c, 0xd901, 0x6ec2, 0x0024, + 0x001c, 0xdd00, 0x2801, 0x2315, 0x0018, 0xdbc1, 0x3413, 0x184c, 0xf400, + 0x4500, 0x2926, 0xc640, 0x3e00, 0x13cc, 0x2801, 0x2a00, 0x36f3, 0x0024, + 0x6ec2, 0x0024, 0x003f, 0xc000, 0x2801, 0x2595, 0x002a, 0x4001, 0x3413, + 0x184c, 0xf400, 0x4500, 0x2926, 0xafc0, 0x3e00, 0x13cc, 0x2801, 0x2a00, + 0x36f3, 0x0024, 0xb400, 0x0024, 0xd100, 0x0024, 0x0000, 0x0024, 0x2801, + 0x2a05, 0x0000, 0x0024, 0x3613, 0x0024, 0x3e11, 0x4024, 0x2926, 0x8540, + 0x3e01, 0x0024, 0x4080, 0x1b8c, 0x0000, 0x0024, 0x2801, 0x2a05, 0x0000, + 0x0024, 0x3413, 0x184c, 0xf400, 0x4500, 0x2926, 0x8e80, 0x3e10, 0x13cc, + 0x36f3, 0x0024, 0x3110, 0x8024, 0x31f0, 0xc024, 0x0000, 0x4000, 0x0000, + 0x0021, 0x6d06, 0x0024, 0x3110, 0x8024, 0x2826, 0xa8c4, 0x31f0, 0xc024, + 0x2a26, 0xad00, 0x34c3, 0x184c, 0x3410, 0x8024, 0x3430, 0xc024, 0x0000, + 0x4000, 0x0000, 0x0021, 0x6d06, 0x0024, 0x0000, 0x0024, 0x2801, 0x32d4, + 0x4d06, 0x0024, 0x0000, 0x0200, 0x2922, 0x1885, 0x0001, 0x3148, 0x0000, + 0x0200, 0x3e10, 0x8024, 0x2921, 0xca80, 0x3e00, 0xc024, 0x291a, 0x8a40, + 0x0000, 0x0024, 0x2922, 0x1880, 0x36f3, 0x0024, 0x0000, 0x004d, 0x0021, + 0x0ecf, 0x2821, 0x0bc0, 0x0001, 0x324e, 0x2801, 0x1540, 0x3c30, 0x4024, + 0x0000, 0x190d, 0x0001, 0x33ce, 0x2821, 0x0f80, 0x0021, 0x420f, 0x0000, + 0x190d, 0x3e00, 0x0024, 0x2801, 0xe840, 0x0021, 0x42c8, 0x0020, 0xcd4f, + 0x2820, 0xc780, 0x0001, 0x358e, 0x0006, 0xf017, 0x0000, 0x0015, 0xb070, + 0xbc15, 0x0001, 0x374e, 0x0020, 0xdf0f, 0x2820, 0xcd80, 0x0000, 0x190d, + 0x3e00, 0x23c1, 0x2801, 0xe840, 0x0020, 0xdfc8, 0x3613, 0x0024, 0x3e10, + 0xb803, 0x3e14, 0x3811, 0x3e11, 0x3805, 0x3e00, 0x3801, 0x0007, 0xc390, + 0x0006, 0xa011, 0x3010, 0x0444, 0x3050, 0x4405, 0x6458, 0x0302, 0xff94, + 0x4081, 0x0003, 0xffc5, 0x48b6, 0x0024, 0xff82, 0x0024, 0x42b2, 0x0042, + 0xb458, 0x0003, 0x4cd6, 0x9801, 0xf248, 0x1bc0, 0xb58a, 0x0024, 0x6de6, + 0x1804, 0x0006, 0x0010, 0x3810, 0x9bc5, 0x3800, 0xc024, 0x36f4, 0x1811, + 0x36f0, 0x9803, 0x283e, 0x2d80, 0x0fff, 0xffc3, 0x2801, 0x4c80, 0x0000, + 0x0024, 0x3413, 0x0024, 0x2801, 0x4085, 0xf400, 0x4517, 0x2801, 0x4480, + 0x6894, 0x13cc, 0x37b0, 0x184c, 0x6090, 0x1d51, 0x0000, 0x0910, 0x3f00, + 0x060c, 0x3100, 0x4024, 0x6016, 0xb812, 0x000c, 0x8012, 0x2801, 0x4311, + 0xb884, 0x0024, 0x6894, 0x3002, 0x0000, 0x028d, 0x003a, 0x5e0f, 0x0001, + 0x548e, 0x2939, 0xb0c0, 0x3e10, 0x93cc, 0x4084, 0x9bd2, 0x4282, 0x0024, + 0x0000, 0x0040, 0x2801, 0x4685, 0x4292, 0x130c, 0x3443, 0x0024, 0x2801, + 0x47c5, 0x000c, 0x8390, 0x2a01, 0x4b40, 0x3444, 0x0024, 0x3073, 0x0024, + 0xc090, 0x014c, 0x2801, 0x4b40, 0x3800, 0x0024, 0x000c, 0x4113, 0xb880, + 0x2380, 0x3304, 0x4024, 0x3800, 0x05cc, 0xcc92, 0x05cc, 0x3910, 0x0024, + 0x3910, 0x4024, 0x000c, 0x8110, 0x3910, 0x0024, 0x39f0, 0x4024, 0x3810, + 0x0024, 0x38d0, 0x4024, 0x3810, 0x0024, 0x38f0, 0x4024, 0x34c3, 0x0024, + 0x3444, 0x0024, 0x3073, 0x0024, 0x3063, 0x0024, 0x3000, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, 0x0024, 0x3613, 0x0024, + 0x2801, 0x4e85, 0x6898, 0xb804, 0x0000, 0x0084, 0x293b, 0x1cc0, 0x3613, + 0x0024, 0x000c, 0x8117, 0x3711, 0x0024, 0x37d1, 0x4024, 0x4e8a, 0x0024, + 0x0000, 0x0015, 0x2801, 0x5145, 0xce9a, 0x0024, 0x3f11, 0x0024, 0x3f01, + 0x4024, 0x000c, 0x8197, 0x408a, 0x9bc4, 0x3f15, 0x4024, 0x2801, 0x5385, + 0x4284, 0x3c15, 0x6590, 0x0024, 0x0000, 0x0024, 0x2839, 0x53d5, 0x4284, + 0x0024, 0x0000, 0x0024, 0x2801, 0x3f58, 0x458a, 0x0024, 0x2a39, 0x53c0, + 0x003e, 0x2d4f, 0x283a, 0x5ed5, 0x0001, 0x380e, 0x000c, 0x4653, 0x0000, + 0x0246, 0xffac, 0x0c01, 0x48be, 0x0024, 0x4162, 0x4546, 0x6642, 0x4055, + 0x3501, 0x8024, 0x0000, 0x0087, 0x667c, 0x4057, 0x000c, 0x41d5, 0x283a, + 0x62d5, 0x3501, 0x8024, 0x667c, 0x1c47, 0x3701, 0x8024, 0x283a, 0x62d5, + 0xc67c, 0x0024, 0x0000, 0x0024, 0x283a, 0x62c5, 0x0000, 0x0024, 0x2a3a, + 0x5ec0, 0x3009, 0x3851, 0x3e14, 0xf812, 0x3e12, 0xb817, 0x3e11, 0x8024, + 0x0006, 0x0293, 0x3301, 0x8024, 0x468c, 0x3804, 0x0006, 0xa057, 0x2801, + 0x6084, 0x0006, 0x0011, 0x469c, 0x0024, 0x3be1, 0x8024, 0x2801, 0x6095, + 0x0006, 0xc392, 0x3311, 0x0024, 0x33f1, 0x2844, 0x3009, 0x2bc4, 0x0030, + 0x04d2, 0x3311, 0x0024, 0x3a11, 0x0024, 0x3201, 0x8024, 0x003f, 0xfc04, + 0xb64c, 0x0fc4, 0xc648, 0x0024, 0x3a01, 0x0024, 0x3111, 0x1fd3, 0x6498, + 0x07c6, 0x868c, 0x2444, 0x0023, 0xffd2, 0x3901, 0x8e06, 0x0030, 0x0551, + 0x3911, 0x8e06, 0x3961, 0x9c44, 0xf400, 0x44c6, 0xd46c, 0x1bc4, 0x36f1, + 0xbc13, 0x2801, 0x6a15, 0x36f2, 0x9817, 0x002b, 0xffd2, 0x3383, 0x188c, + 0x3e01, 0x8c06, 0x0006, 0xa097, 0x3009, 0x1c12, 0x3213, 0x0024, 0x468c, + 0xbc12, 0x002b, 0xffd2, 0xf400, 0x4197, 0x2801, 0x6704, 0x3713, 0x0024, + 0x2801, 0x6745, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x3383, 0x0024, 0x3009, + 0x0c06, 0x468c, 0x4197, 0x0006, 0xa052, 0x2801, 0x6944, 0x3713, 0x2813, + 0x2801, 0x6985, 0x37e3, 0x0024, 0x3009, 0x2c17, 0x36f1, 0x8024, 0x36f2, + 0x9817, 0x36f4, 0xd812, 0x2100, 0x0000, 0x3904, 0x5bd1, 0x2a01, 0x5a4e, + 0x3e11, 0x7804, 0x0030, 0x0257, 0x3701, 0x0024, 0x0013, 0x4d05, 0xd45b, + 0xe0e1, 0x0007, 0xc795, 0x2801, 0x7195, 0x0fff, 0xff45, 0x3511, 0x184c, + 0x4488, 0xb808, 0x0006, 0x8a97, 0x2801, 0x7145, 0x3009, 0x1c40, 0x3511, + 0x1fc1, 0x0000, 0x0020, 0xac52, 0x1405, 0x6ce2, 0x0024, 0x0000, 0x0024, + 0x2801, 0x7141, 0x68c2, 0x0024, 0x291a, 0x8a40, 0x3e10, 0x0024, 0x2921, + 0xca80, 0x3e00, 0x4024, 0x36f3, 0x0024, 0x3009, 0x1bc8, 0x36f0, 0x1801, + 0x3601, 0x5804, 0x3e13, 0x780f, 0x3e13, 0xb808, 0x0008, 0x9b0f, 0x0001, + 0x744e, 0x2908, 0x9300, 0x0000, 0x004d, 0x36f3, 0x9808, 0x2000, 0x0000, + 0x36f3, 0x580f, 0x0007, 0x81d7, 0x3711, 0x8024, 0x3711, 0xc024, 0x3700, + 0x0024, 0x0000, 0x2001, 0xb012, 0x0024, 0x0034, 0x0000, 0x2801, 0x79c5, + 0x0000, 0x01c1, 0x3700, 0x0024, 0x0002, 0x0001, 0xb012, 0x0024, 0x002e, + 0xe001, 0x2801, 0x78c5, 0x6512, 0x0024, 0x0034, 0x0000, 0x2801, 0x79d5, + 0x0000, 0x01c1, 0x0030, 0x0117, 0x3f00, 0x0024, 0x0014, 0xc000, 0x0000, + 0x01c1, 0x4fce, 0x0024, 0xffea, 0x0024, 0x48b6, 0x0024, 0x4384, 0x4097, + 0xb886, 0x45c6, 0xfede, 0x0024, 0x4db6, 0x0024, 0x466c, 0x0024, 0x0006, + 0xc610, 0x8dd6, 0x8007, 0x0000, 0x00c6, 0xff6e, 0x0024, 0x48b2, 0x0024, + 0x0034, 0x2406, 0xffee, 0x0024, 0x2914, 0xaa80, 0x40b2, 0x0024, 0xf1c6, + 0x0024, 0xf1d6, 0x0024, 0x0000, 0x0201, 0x8d86, 0x0024, 0x61de, 0x0024, + 0x0006, 0xc612, 0x2801, 0x8041, 0x0006, 0xc713, 0x4c86, 0x0024, 0x2912, + 0x1180, 0x0006, 0xc351, 0x0006, 0x0210, 0x2912, 0x0d00, 0x3810, 0x984c, + 0xf200, 0x2043, 0x2808, 0xa000, 0x3800, 0x0024, 0x3e12, 0xb817, 0x3e12, + 0x7808, 0x3e11, 0xb811, 0x3e15, 0x7810, 0x3e18, 0xb823, 0x3e18, 0x3821, + 0x3e10, 0x3801, 0x48b2, 0x0024, 0x3e10, 0x3801, 0x3e11, 0x3802, 0x3009, + 0x3814, 0x0030, 0x0717, 0x3f05, 0xc024, 0x0030, 0x0351, 0x3100, 0x0024, + 0x4080, 0x0024, 0x0030, 0x10d1, 0x2801, 0x8d45, 0x0001, 0x800a, 0x0006, + 0x6514, 0x3111, 0x8024, 0x6894, 0x13c1, 0x6618, 0x0024, 0xfe44, 0x1000, + 0x4cb2, 0x0406, 0x3c10, 0x0024, 0x3c50, 0x4024, 0x34f0, 0x4024, 0x661c, + 0x1040, 0xfe64, 0x0024, 0x4cb2, 0x0024, 0x3cf0, 0x4024, 0xbc82, 0x3080, + 0x0030, 0x0351, 0x3100, 0x8024, 0xfea8, 0x0024, 0x5ca2, 0x0024, 0x0000, + 0x0182, 0xac22, 0x0024, 0xf7c8, 0x0024, 0x48b2, 0x0024, 0xac22, 0x0024, + 0x2801, 0x90c0, 0xf7cc, 0x1002, 0x0030, 0x0394, 0x3400, 0x4024, 0x3100, + 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, 0x6410, 0x4088, 0x1001, + 0x0030, 0x1111, 0x3100, 0x184c, 0x0006, 0xc051, 0x291e, 0x8080, 0x0006, + 0x6550, 0x0006, 0x6694, 0x408c, 0x1002, 0xf224, 0x0024, 0x0006, 0xa017, + 0x2801, 0x94d5, 0x0000, 0x0024, 0x2808, 0x3f41, 0x0006, 0x6410, 0x3050, + 0x0024, 0x3000, 0x4024, 0x6014, 0x0024, 0x0000, 0x0024, 0x2801, 0x9419, + 0x0000, 0x0024, 0xf400, 0x4040, 0x38b0, 0x0024, 0x2808, 0x3f40, 0x3800, + 0x0024, 0x2801, 0x96c1, 0xf224, 0x0024, 0x0000, 0x0024, 0x2808, 0x3f45, + 0x4684, 0x4106, 0xf12c, 0x0024, 0xf148, 0x0024, 0x846c, 0x0024, 0x2808, + 0x3f40, 0xf400, 0x4184, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, + 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, + 0x3805, 0x3e11, 0xb807, 0x3e14, 0x3811, 0x0006, 0xa090, 0x2912, 0x0d00, + 0x3e14, 0xc024, 0x4088, 0x8000, 0x4080, 0x0024, 0x0007, 0x90d1, 0x2801, + 0x9d05, 0x0000, 0x0024, 0x0007, 0x9051, 0x3100, 0x4024, 0x4100, 0x0024, + 0x3900, 0x0024, 0x0007, 0x90d1, 0x0004, 0x0000, 0x31f0, 0x4024, 0x6014, + 0x0400, 0x0000, 0x0024, 0x2801, 0xa151, 0x4080, 0x0024, 0x0000, 0x0000, + 0x2801, 0xa0c5, 0x0000, 0x0024, 0x0007, 0x9053, 0x3300, 0x0024, 0x4080, + 0x0024, 0x0000, 0x0000, 0x2801, 0xa158, 0x0000, 0x0024, 0x0007, 0x9051, + 0x3900, 0x0024, 0x3200, 0x504c, 0x6410, 0x0024, 0x3cf0, 0x0000, 0x4080, + 0x0024, 0x0006, 0xc691, 0x2801, 0xba05, 0x3009, 0x0400, 0x0007, 0x9051, + 0x0000, 0x1001, 0x3100, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2801, + 0xae49, 0x003f, 0xe000, 0x0006, 0xc693, 0x3900, 0x0c00, 0x3009, 0x0001, + 0x6014, 0x0024, 0x0007, 0x1ad0, 0x2801, 0xae55, 0x3009, 0x0000, 0x4080, + 0x0024, 0x0000, 0x0301, 0x2801, 0xa845, 0x4090, 0x0024, 0x0000, 0x0024, + 0x2801, 0xa955, 0x0000, 0x0024, 0x3009, 0x0000, 0xc012, 0x0024, 0x2801, + 0xae40, 0x3009, 0x2001, 0x3009, 0x0000, 0x6012, 0x0024, 0x0000, 0x0341, + 0x2801, 0xab55, 0x0000, 0x0024, 0x6190, 0x0024, 0x2801, 0xae40, 0x3009, + 0x2000, 0x6012, 0x0024, 0x0000, 0x0381, 0x2801, 0xad15, 0x0000, 0x0024, + 0x6190, 0x0024, 0x2801, 0xae40, 0x3009, 0x2000, 0x6012, 0x0024, 0x0000, + 0x00c0, 0x2801, 0xae55, 0x0000, 0x0024, 0x3009, 0x2000, 0x0006, 0xa090, + 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0x0081, 0x2801, 0xb315, 0x0007, + 0x8c13, 0x3300, 0x104c, 0xb010, 0x0024, 0x0002, 0x8001, 0x2801, 0xb585, + 0x34f0, 0x0024, 0x2801, 0xb300, 0x0000, 0x0024, 0x0006, 0xc351, 0x3009, + 0x0000, 0x6090, 0x0024, 0x3009, 0x2000, 0x2900, 0x0b80, 0x3009, 0x0405, + 0x0006, 0xc690, 0x0006, 0xc6d1, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, + 0x0024, 0x0006, 0xa093, 0x2801, 0xb191, 0xb880, 0x0024, 0x2801, 0xc2c0, + 0x3009, 0x2c00, 0x4040, 0x0024, 0x6012, 0x0024, 0x0006, 0xc6d0, 0x2801, + 0xc2d8, 0x0000, 0x0024, 0x0006, 0xc693, 0x3009, 0x0c00, 0x3009, 0x0001, + 0x6014, 0x0024, 0x0006, 0xc350, 0x2801, 0xc2c1, 0x0000, 0x0024, 0x6090, + 0x0024, 0x3009, 0x2c00, 0x3009, 0x0005, 0x2900, 0x0b80, 0x0001, 0xc2c8, + 0x3009, 0x0400, 0x4080, 0x0024, 0x0003, 0x8000, 0x2801, 0xc2c5, 0x0000, + 0x0024, 0x6400, 0x0024, 0x0000, 0x0081, 0x2801, 0xc2c9, 0x0000, 0x0024, + 0x0007, 0x8c13, 0x3300, 0x0024, 0xb010, 0x0024, 0x0006, 0xc650, 0x2801, + 0xc2d5, 0x0000, 0x0024, 0x0001, 0x0002, 0x3413, 0x0000, 0x3009, 0x0401, + 0x4010, 0x8406, 0x0000, 0x0281, 0xa010, 0x13c1, 0x4122, 0x0024, 0x0000, + 0x03c2, 0x6122, 0x8002, 0x462c, 0x0024, 0x469c, 0x0024, 0xfee2, 0x0024, + 0x48be, 0x0024, 0x6066, 0x8400, 0x0006, 0xc350, 0x2801, 0xc2c1, 0x0000, + 0x0024, 0x4090, 0x0024, 0x3009, 0x2400, 0x2900, 0x0b80, 0x3009, 0x0005, + 0x0007, 0x1b50, 0x2912, 0x0d00, 0x3613, 0x0024, 0x3a00, 0x0380, 0x4080, + 0x0024, 0x0000, 0x00c1, 0x2801, 0xcb85, 0x3009, 0x0000, 0xb010, 0x008c, + 0x4192, 0x0024, 0x6012, 0x0024, 0x0006, 0xf051, 0x2801, 0xc998, 0x3009, + 0x0400, 0x0007, 0x1fd1, 0x30e3, 0x0400, 0x4080, 0x0024, 0x0000, 0x0301, + 0x2801, 0xcb85, 0x3009, 0x0000, 0xb010, 0x0024, 0x0000, 0x0101, 0x6012, + 0x0024, 0x0006, 0xf051, 0x2801, 0xcb95, 0x0000, 0x0024, 0x3023, 0x0400, + 0xf200, 0x184c, 0xb880, 0xa400, 0x3009, 0x2000, 0x3009, 0x0441, 0x3e10, + 0x4402, 0x2909, 0xa9c0, 0x3e10, 0x8024, 0x36e3, 0x0024, 0x36f4, 0xc024, + 0x36f4, 0x1811, 0x36f1, 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, + 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, + 0x3e11, 0x3805, 0x3e11, 0xf810, 0x0001, 0x0010, 0x3e14, 0x7812, 0xb882, + 0x3813, 0x2914, 0xbec0, 0x0000, 0x2200, 0xb886, 0x12cc, 0x2801, 0xd800, + 0x3454, 0x8024, 0x0001, 0x0000, 0x3000, 0x984c, 0x4234, 0xb843, 0xf400, + 0x4095, 0x003b, 0xffc2, 0x3500, 0x4024, 0xb122, 0x0842, 0x4010, 0x0bc3, + 0x4010, 0x0024, 0x4010, 0x0024, 0x4010, 0x0024, 0x4d82, 0x4011, 0x2938, + 0x0600, 0xf400, 0x4450, 0x3223, 0x184c, 0x3210, 0x8024, 0x32d0, 0xc024, + 0x2938, 0x0600, 0x4d82, 0x4450, 0x3243, 0x1bc3, 0x6396, 0x0024, 0x0005, + 0xdf90, 0x3000, 0x0024, 0x6302, 0x0024, 0x0005, 0xe110, 0x2801, 0xd2d1, + 0x0000, 0x0024, 0x2801, 0xde80, 0x4086, 0x0024, 0x3200, 0x930c, 0x6398, + 0x1111, 0x4244, 0x0844, 0xf400, 0x4095, 0x3500, 0x584c, 0x4438, 0x0805, + 0x453a, 0x4115, 0x3500, 0x8024, 0x6122, 0x4155, 0x4280, 0x1404, 0x0001, + 0x0002, 0x4244, 0x0024, 0x4244, 0x0024, 0x4244, 0x0024, 0x4244, 0x0024, + 0x2938, 0x2f80, 0xf400, 0x4090, 0x6396, 0x0024, 0x0005, 0xdf50, 0x3000, + 0x0024, 0x6302, 0x0024, 0x0005, 0xe0d2, 0x2801, 0xda11, 0x0000, 0x0381, + 0x3073, 0x0024, 0x3023, 0x0024, 0x3000, 0x0024, 0x6012, 0x0024, 0x0001, + 0x2212, 0x2801, 0xe395, 0x0005, 0x1453, 0x0001, 0x0011, 0x3093, 0x184c, + 0x3000, 0x4024, 0x2900, 0x78c0, 0x3e00, 0x4024, 0x2801, 0xe580, 0x36f3, + 0x0024, 0x0005, 0xe3c1, 0x0001, 0x0011, 0x3613, 0x024c, 0x3e10, 0x4024, + 0x3000, 0x8024, 0x2900, 0x5c40, 0x3e00, 0x8024, 0x36e3, 0x0024, 0x36f4, + 0xc024, 0x36f4, 0x5812, 0x36f1, 0xd810, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x0000, + 0x00c1, 0xb880, 0xb803, 0x3e10, 0x904c, 0x3e11, 0x3806, 0x3e11, 0xf810, + 0x0006, 0xf450, 0x3e14, 0x7812, 0x3e14, 0xc024, 0x3cf0, 0x2080, 0x3009, + 0x23c0, 0x3009, 0x2380, 0x0000, 0x0640, 0x3009, 0x2000, 0x2921, 0x9440, + 0x0000, 0x00c0, 0x2921, 0xdd40, 0x3613, 0x0024, 0xf400, 0x4004, 0x0000, + 0x01c0, 0x6400, 0x0024, 0x0000, 0x00c0, 0x2802, 0x0885, 0x0000, 0x01c1, + 0x6412, 0x4100, 0x0006, 0x0581, 0x2801, 0xfe01, 0x4412, 0x0024, 0xf400, + 0x4057, 0x3702, 0x0024, 0x2000, 0x0000, 0x0000, 0x0024, 0x0006, 0xf410, + 0x0000, 0x0641, 0x3613, 0x0000, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, + 0xf3d5, 0x0000, 0x0024, 0x3009, 0x2004, 0x2900, 0xb600, 0x3e01, 0x0024, + 0x2801, 0xfe00, 0x36f3, 0x0024, 0x0006, 0xf410, 0x0000, 0x0641, 0x3613, + 0x0000, 0x6012, 0x0024, 0x0000, 0x0024, 0x2801, 0xf6d5, 0x0000, 0x0024, + 0x3009, 0x2004, 0x2900, 0xa400, 0x3e01, 0x0024, 0x2801, 0xfe00, 0x36f3, + 0x0024, 0x0006, 0xf450, 0x3613, 0x0000, 0x6090, 0x3804, 0x2900, 0xb600, + 0x3009, 0x2000, 0x2801, 0xfe00, 0x36f3, 0x0024, 0x2923, 0x4f00, 0x0007, + 0x2050, 0x2801, 0xfe00, 0x3009, 0x2000, 0x2923, 0x7580, 0x0001, 0xfe08, + 0x34d3, 0x184c, 0x3430, 0x0024, 0x2922, 0x4fc0, 0x3e00, 0x0024, 0x2801, + 0xfe00, 0x36f3, 0x0024, 0x0000, 0x3fc0, 0x0007, 0x2050, 0x3613, 0x0024, + 0x2923, 0x8480, 0x3e00, 0x0024, 0x36f3, 0x2000, 0x0000, 0x1800, 0x3413, + 0x0024, 0xf400, 0x4510, 0x34f0, 0x4024, 0x6192, 0x0024, 0x6014, 0x2001, + 0x0007, 0x2051, 0x2802, 0x0081, 0x0000, 0x0280, 0x3009, 0x2400, 0x3009, + 0x0400, 0x4080, 0x0024, 0x0006, 0xf352, 0x2802, 0x0995, 0x3009, 0x0842, + 0x3009, 0x0bc3, 0x4d86, 0x0024, 0x0000, 0x0201, 0x2802, 0x04c5, 0x0030, + 0x0013, 0x0006, 0x8a93, 0x3009, 0x0c40, 0x3009, 0x0fc1, 0x6cde, 0x0024, + 0x0000, 0x0201, 0x2802, 0x0981, 0x0030, 0x0013, 0x3300, 0x0024, 0xb010, + 0x0024, 0x0000, 0x0100, 0x2802, 0x0995, 0x0000, 0x00c1, 0x2921, 0x9440, + 0x3613, 0x0024, 0x2921, 0xdd40, 0x3613, 0x0024, 0xf400, 0x4004, 0x0000, + 0x01c0, 0x6400, 0x0024, 0x0000, 0x01c1, 0x2801, 0xefd5, 0x0000, 0x00c0, + 0x2921, 0x9440, 0x3613, 0x0024, 0x2921, 0xc300, 0x0000, 0x0024, 0x36f4, + 0xc024, 0x36f4, 0x5812, 0x36f1, 0xd810, 0x36f1, 0x1806, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x0012, + 0x5103, 0x3e11, 0x3805, 0x3e11, 0xb807, 0x3e14, 0x380d, 0x0030, 0x0250, + 0x3e13, 0xf80e, 0xbe8b, 0x83e0, 0x290c, 0x4840, 0x3613, 0x0024, 0x290c, + 0x4840, 0x4086, 0x984c, 0x0000, 0x00ce, 0x2402, 0x138e, 0x3009, 0x1bc0, + 0x0000, 0x01c3, 0xae3a, 0x184c, 0x0000, 0x0043, 0x3009, 0x3842, 0x290c, + 0x4840, 0x3009, 0x3840, 0x4084, 0x9bc0, 0xfe26, 0x9bc2, 0xceba, 0x0024, + 0x4e8e, 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0000, 0x0102, 0x2802, + 0x18c5, 0x0030, 0x0010, 0x0000, 0x0206, 0x3613, 0x0024, 0x290c, 0x4840, + 0x3009, 0x3840, 0x3000, 0xdbc0, 0xb366, 0x0024, 0x0000, 0x0024, 0x2802, + 0x18d5, 0x4e8e, 0x0024, 0x4e9a, 0x0024, 0x4f8e, 0x0024, 0x0030, 0x0010, + 0x2802, 0x1595, 0x0000, 0x0206, 0x36f3, 0xd80e, 0x36f4, 0x180d, 0x36f1, + 0x9807, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, + 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, + 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3635, 0x0024, 0x0000, 0x800a, + 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, 0x3805, 0x3e11, 0xb810, 0x3e04, + 0x7812, 0x34d3, 0x0024, 0x3400, 0x0024, 0xf200, 0x1102, 0xf200, 0x0024, + 0xf200, 0x0024, 0x3cf0, 0x0024, 0x2914, 0xba00, 0x0000, 0x1600, 0x0000, + 0x4001, 0x6012, 0x108c, 0x3ce0, 0x0024, 0x2802, 0x2209, 0x0000, 0x0386, + 0x0000, 0x4000, 0x3423, 0x0024, 0x3ce0, 0x0024, 0x0000, 0x0041, 0x3413, + 0x0024, 0x34b0, 0x8024, 0xfe22, 0x1100, 0x48b6, 0x0024, 0xad66, 0x0024, + 0xfe02, 0x0024, 0x2915, 0x8600, 0x48b2, 0x0024, 0x4c8a, 0x104c, 0x0000, + 0x0041, 0x34f0, 0x0024, 0xfe02, 0x0024, 0x0000, 0xf001, 0x6eba, 0x0024, + 0xf040, 0x0024, 0x6012, 0x0024, 0x0000, 0x0041, 0x2802, 0x2a08, 0x0000, + 0xf002, 0xf040, 0x104c, 0x3400, 0xc024, 0xfe26, 0x0024, 0x48b6, 0x0024, + 0xfe02, 0x0024, 0x2915, 0x8600, 0x48b2, 0x0024, 0x4480, 0x33c0, 0x0000, + 0xf004, 0x2802, 0x2a18, 0x0000, 0x0024, 0x003f, 0x1004, 0x0006, 0x0090, + 0x0000, 0x0041, 0xb884, 0x108c, 0x6896, 0xa004, 0x34e0, 0x0024, 0xfe02, + 0x0024, 0x2914, 0xa580, 0x48b2, 0x0024, 0x0006, 0x0110, 0x3423, 0x23c0, + 0x34f0, 0x0024, 0x3410, 0x2380, 0xb880, 0xa140, 0x3009, 0x23c0, 0x3009, + 0x2340, 0x3009, 0x0000, 0x4080, 0x0024, 0x0000, 0xba11, 0x2802, 0x2f95, + 0x0000, 0x0024, 0x2802, 0x3780, 0x3ce4, 0x4024, 0x4080, 0x138c, 0x0000, + 0x0001, 0x2802, 0x3418, 0x0006, 0x0011, 0x0000, 0xba00, 0x6090, 0x108c, + 0x3ce0, 0x0400, 0x6014, 0x0024, 0x0006, 0xa052, 0x2802, 0x3351, 0x0004, + 0x0001, 0x6014, 0x0024, 0x0000, 0x0024, 0x2802, 0x3791, 0x0000, 0x0024, + 0x3009, 0x0800, 0x2802, 0x3780, 0x3009, 0x2400, 0x0000, 0xba00, 0x6090, + 0x108c, 0x6090, 0x0024, 0x3ce0, 0x0400, 0x6014, 0x0024, 0x0006, 0xa052, + 0x2802, 0x3711, 0x0004, 0x0001, 0x6014, 0x0024, 0x0000, 0x0024, 0x2802, + 0x3791, 0x0000, 0x0024, 0x3009, 0x0800, 0x3009, 0x2400, 0x3613, 0x108c, + 0x290f, 0xfdc0, 0x34e4, 0x3810, 0x0000, 0x0810, 0x290f, 0xfcc0, 0x3009, + 0x1bcc, 0x36f4, 0x5812, 0x36f1, 0x9810, 0x36f1, 0x1805, 0x36f0, 0x9803, + 0x36f0, 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, + 0x0000, 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, + 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, + 0xb803, 0x3e11, 0x3805, 0x3e14, 0x3811, 0x0006, 0x01d1, 0x0006, 0xc610, + 0x3e04, 0xb813, 0x3009, 0x0000, 0x3009, 0x0401, 0x6014, 0x0024, 0x0030, + 0x0312, 0x2802, 0x4355, 0x0000, 0x0024, 0x3200, 0x044c, 0x3009, 0x0401, + 0x6014, 0x0024, 0x0006, 0x0292, 0x2802, 0x4355, 0x0006, 0xc351, 0x3009, + 0x0400, 0x3009, 0x0801, 0x6014, 0x0024, 0x0000, 0x0024, 0x2802, 0x5985, + 0x0000, 0x0024, 0x0030, 0x0311, 0x3100, 0x0024, 0x4080, 0x0024, 0x0010, + 0x0000, 0x2802, 0x4515, 0x0000, 0x0024, 0x3900, 0x0024, 0x3100, 0x0024, + 0x4080, 0x0024, 0x0001, 0xffc0, 0x2802, 0x4b98, 0x0030, 0x00d2, 0x3201, + 0x0024, 0xb408, 0x0024, 0x0006, 0x01d3, 0x2802, 0x47d5, 0x0001, 0xf400, + 0x0001, 0x0c04, 0x4408, 0x0401, 0x3613, 0x2004, 0x0006, 0xc350, 0x6810, + 0xac44, 0x3009, 0x2c81, 0x3e10, 0x0000, 0x2902, 0x1b40, 0x3e00, 0x2c00, + 0x36f3, 0x0000, 0x6090, 0x0024, 0x3009, 0x2000, 0x3009, 0x0005, 0x459a, + 0x0024, 0x2908, 0x9300, 0x0002, 0x5988, 0x3201, 0x0024, 0xb408, 0x0024, + 0x0000, 0x0081, 0x2802, 0x4d15, 0x0006, 0x02d3, 0x0001, 0x0c04, 0x0001, + 0xf400, 0x4408, 0x8c00, 0x6012, 0x044c, 0x3009, 0x184c, 0x2802, 0x4ed5, + 0x0004, 0x0003, 0x4448, 0x0024, 0x39f0, 0x3800, 0xb884, 0x3801, 0x0000, + 0x0041, 0x3100, 0x0024, 0xfe02, 0x0024, 0x2915, 0x8600, 0x48b2, 0x0024, + 0x0006, 0x01d0, 0x0006, 0x02d1, 0xffc0, 0x1bcc, 0x48b2, 0x0024, 0x4cc2, + 0x0024, 0x4cc2, 0x0024, 0x3009, 0x2001, 0x0000, 0x0081, 0x3009, 0x0400, + 0x6012, 0x0024, 0x0006, 0xc353, 0x2802, 0x5595, 0x0030, 0x0312, 0x3200, + 0x404c, 0x3613, 0x2001, 0x3e10, 0x4c01, 0xf212, 0x0024, 0x3e00, 0x4024, + 0x2902, 0x1b40, 0x0002, 0x56c8, 0x3200, 0x404c, 0x3613, 0x2001, 0x3e10, + 0x4c01, 0x2902, 0x1b40, 0x3e00, 0x4024, 0x3023, 0x0c00, 0x36f3, 0x2340, + 0x3009, 0x0000, 0x0006, 0xc610, 0x3009, 0x2000, 0x3009, 0x0c00, 0x6090, + 0x0024, 0x3009, 0x2c00, 0x3009, 0x0c05, 0x2908, 0x9300, 0x459a, 0x0024, + 0x36f4, 0x9813, 0x36f4, 0x1811, 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, + 0x1801, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, + 0x36f2, 0x9817, 0x3613, 0x0024, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, + 0xb814, 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0xb803, 0x3e11, 0x3811, + 0x3e14, 0xb813, 0x3e13, 0xf80e, 0x2902, 0x3b80, 0x3e03, 0x4024, 0x4194, + 0x0024, 0x002b, 0x1103, 0x2802, 0x7355, 0x0006, 0xc351, 0x3009, 0x0402, + 0x6236, 0x0024, 0x0010, 0x0003, 0x2802, 0x7351, 0x0030, 0x0311, 0x3100, + 0x8024, 0x6236, 0x0024, 0x0000, 0x0024, 0x2802, 0x7105, 0x0000, 0x0024, + 0x3100, 0x8024, 0x4284, 0x0024, 0x0006, 0x0793, 0x2802, 0x7109, 0x0000, + 0x0024, 0xf100, 0x0012, 0xb888, 0x4491, 0x3300, 0x8024, 0x0006, 0x0753, + 0x6404, 0x2c02, 0x0000, 0x0024, 0x2802, 0x6818, 0x4094, 0x0024, 0x2402, + 0x6782, 0x3613, 0x0024, 0x3220, 0x3840, 0x2902, 0xafc0, 0x32e0, 0x7801, + 0x3243, 0x1bc1, 0x6498, 0x0024, 0x3920, 0x1800, 0x36f3, 0x0024, 0x0006, + 0x0753, 0xb888, 0x0c02, 0x0006, 0x0793, 0x3b10, 0x8024, 0x3004, 0x8024, + 0x3300, 0x884c, 0x0006, 0x0753, 0x6404, 0x2c02, 0x0000, 0x0024, 0x2802, + 0x6d18, 0x4094, 0x4491, 0x2402, 0x6c82, 0x3613, 0x0024, 0x3220, 0x3840, + 0x2902, 0xafc0, 0x32e0, 0x7801, 0x3243, 0x1bc1, 0x6498, 0x0024, 0x3920, + 0x1800, 0x36f3, 0x0024, 0x0006, 0x0753, 0x0000, 0x0083, 0x3300, 0x984c, + 0x0006, 0x07d3, 0x3b00, 0x8024, 0x0006, 0x02d3, 0x3009, 0x0c02, 0x6236, + 0x0024, 0x0000, 0x0082, 0x2802, 0x7085, 0x0000, 0x0024, 0xb884, 0xac02, + 0x0006, 0x0293, 0x3009, 0x2c02, 0x2802, 0x7340, 0x3009, 0x1bcc, 0x0006, + 0x02d2, 0x3613, 0x0802, 0x4294, 0x0024, 0x0006, 0x0293, 0x2802, 0x7305, + 0x6894, 0x0024, 0xb884, 0xa802, 0x3009, 0x2c02, 0x3009, 0x1bcc, 0x36f3, + 0x4024, 0x36f3, 0xd80e, 0x36f4, 0x9813, 0x36f1, 0x1811, 0x36f0, 0x9803, + 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, + 0x9817, 0x3613, 0x0024, 0x3e22, 0xb815, 0x3e05, 0xb814, 0xb880, 0x1854, + 0x3e10, 0xb811, 0x0007, 0x9251, 0xb884, 0x3812, 0x0006, 0x0792, 0x3900, + 0xb813, 0x0006, 0x0753, 0x0006, 0x1002, 0x0002, 0x5c11, 0x3a10, 0x8024, + 0x0006, 0x8002, 0x3a00, 0x8024, 0x0006, 0x1002, 0x0007, 0x9252, 0x3b00, + 0x9813, 0x3a04, 0x4024, 0x36f4, 0x8024, 0x36f0, 0x9811, 0x3405, 0x9014, + 0x36e3, 0x0024, 0x2000, 0x0000, 0x36f2, 0x9815, 0x3009, 0x3857, 0x3e18, + 0x3822, 0x3e18, 0x780a, 0x3e10, 0x3801, 0x48b2, 0x3855, 0x3e10, 0x3801, + 0x0000, 0x800a, 0x3e14, 0x3811, 0x3e14, 0xb813, 0x0006, 0x0013, 0x0023, + 0xffd1, 0x0006, 0x0192, 0x3009, 0x0800, 0x4080, 0x8c10, 0x0030, 0x0552, + 0x2802, 0x8bc5, 0xf400, 0x4401, 0x0006, 0x0093, 0x3e10, 0xb803, 0x3e01, + 0x0c40, 0x4000, 0x8cc4, 0x4010, 0x8c02, 0x0000, 0x0001, 0x6010, 0x4012, + 0x0006, 0x0113, 0x2802, 0x8398, 0x6428, 0x8c80, 0x0004, 0x0013, 0x3283, + 0x0024, 0x0006, 0x0193, 0x3009, 0x0203, 0x3009, 0x0c02, 0xfe26, 0x0024, + 0x48b6, 0x8841, 0xfe42, 0x0024, 0x4db6, 0x0024, 0xffb0, 0x4003, 0x48b2, + 0x0024, 0xffa6, 0x8203, 0x40b2, 0x8f82, 0x0030, 0x0555, 0x3d10, 0x4c80, + 0xfe26, 0x0024, 0x48b6, 0x8bc1, 0xfe42, 0x0024, 0x4db6, 0x0024, 0xffb0, + 0x4003, 0x48b2, 0x0024, 0xffa6, 0x1bc4, 0x40b2, 0x8c02, 0x4290, 0x3401, + 0x3009, 0x2f00, 0x2802, 0x8c95, 0x3009, 0x0c00, 0x4000, 0x4401, 0x4100, + 0x0024, 0x0000, 0x0001, 0x6014, 0x4010, 0x0004, 0x0001, 0x2802, 0x8c98, + 0x4010, 0x0024, 0x2802, 0x8c80, 0xf400, 0x4010, 0x3e00, 0x8200, 0x3a10, + 0x0200, 0x3a00, 0x3803, 0x0006, 0x0152, 0x6104, 0x8b00, 0x6090, 0x8901, + 0x6014, 0xa800, 0x0006, 0xa053, 0x2802, 0x8f48, 0xb880, 0x4402, 0x3009, + 0x2b80, 0x3009, 0x08c0, 0x4090, 0x4402, 0x3009, 0x2800, 0x0006, 0x0012, + 0x3009, 0x2810, 0x3009, 0x0c01, 0x6214, 0x0024, 0x0006, 0x0092, 0x2802, + 0x9198, 0x0000, 0x0100, 0x0004, 0x0001, 0x4214, 0x0024, 0x3009, 0x0801, + 0x4112, 0x8c10, 0x6010, 0x020c, 0x6204, 0x020c, 0x3083, 0x1803, 0x2802, + 0x9389, 0x36f0, 0x820c, 0x3009, 0x2c10, 0x36f4, 0x9813, 0x36f4, 0x1811, + 0x36f0, 0x1801, 0x2210, 0x0000, 0x36f5, 0x4024, 0x36f0, 0x1801, 0x36f8, + 0x580a, 0x36f8, 0x1822, 0x0030, 0x0717, 0x2100, 0x0000, 0x3f05, 0xdbd7, + 0x3009, 0x3853, 0x3e18, 0x3823, 0x3e18, 0x780a, 0x3e10, 0x3801, 0x48b2, + 0x0024, 0x3e10, 0x3801, 0x0000, 0x800a, 0x3e10, 0xb803, 0x3e11, 0x3810, + 0x3e04, 0x7812, 0x0006, 0x0010, 0x0006, 0x0191, 0x3009, 0x0400, 0x4080, + 0x8012, 0x0030, 0x0553, 0x2802, 0xa385, 0x3009, 0x0840, 0x0006, 0x0093, + 0x32f3, 0x0c40, 0x4000, 0x4481, 0x4010, 0x8843, 0xf400, 0x4011, 0x0004, + 0x0001, 0x6014, 0x8cc4, 0x0030, 0x0550, 0x2802, 0x9dd1, 0x3009, 0x0f82, + 0x0ffc, 0x0010, 0x3183, 0x0024, 0x0030, 0x0550, 0x6428, 0x184c, 0xfe27, + 0xe6e7, 0x48b6, 0x8447, 0xfe4e, 0x8c87, 0x4db6, 0x0024, 0xffbe, 0x8bc3, + 0x48b2, 0x0024, 0xffae, 0x8f82, 0x40b2, 0x0024, 0xfe26, 0x2041, 0x48b6, + 0x87c7, 0xfe4e, 0x0024, 0x4db6, 0x8c87, 0xffbe, 0x0024, 0x48b2, 0x0024, + 0xffae, 0x0024, 0x40b2, 0x8c02, 0x4290, 0x2001, 0x3009, 0x2c00, 0x2802, + 0xa415, 0x36f1, 0x9807, 0x2802, 0xa400, 0xf400, 0x4452, 0x3b10, 0x0bc0, + 0x3b00, 0x0024, 0x0006, 0x0150, 0x3223, 0x0300, 0x6090, 0x8101, 0x6014, + 0x4484, 0x0004, 0x0001, 0x2802, 0xa708, 0x6414, 0xa300, 0xb880, 0x810c, + 0x3009, 0x2380, 0x3009, 0x00c0, 0x4090, 0x4484, 0x6414, 0xa000, 0x0006, + 0xa051, 0x2802, 0xa891, 0x0006, 0x0010, 0x0ffc, 0x0013, 0x3283, 0x0024, + 0xf400, 0x4484, 0x3009, 0x0400, 0x6408, 0xa012, 0x0000, 0x0400, 0x2802, + 0xaa98, 0x6404, 0x8412, 0x0004, 0x0002, 0x4428, 0x0024, 0x6404, 0x0024, + 0x0000, 0x0413, 0x2802, 0xad08, 0x3283, 0x0024, 0xf400, 0x4480, 0x6014, + 0x0024, 0x0ffc, 0x0013, 0x2802, 0xacd1, 0x0000, 0x0024, 0x3283, 0x0024, + 0x3009, 0x2412, 0x36f4, 0x5812, 0x36f1, 0x1810, 0x36f0, 0x9803, 0x36f0, + 0x1801, 0x2210, 0x0000, 0x36f0, 0x1801, 0x36f8, 0x580a, 0x36f8, 0x1823, + 0x0030, 0x0713, 0x2100, 0x0000, 0x3b04, 0xdbd3, 0x3613, 0x0024, 0x3e12, + 0x8024, 0x3e10, 0xb803, 0x3e14, 0x3811, 0x3e14, 0xb813, 0x3e13, 0x780e, + 0x3e03, 0xc024, 0x0001, 0x000a, 0x0006, 0x0755, 0x3504, 0x0024, 0x0020, + 0x0b91, 0x3880, 0x0024, 0x3880, 0x4024, 0xbd86, 0x3410, 0x0008, 0x2b91, + 0x003f, 0x15d2, 0x0000, 0x0053, 0x0000, 0x058e, 0x2402, 0xb4ce, 0xfe25, + 0x0829, 0x5017, 0x0829, 0x000e, 0x7b91, 0x5016, 0x020c, 0x4db6, 0x0001, + 0x4d16, 0x1bcf, 0xf1d6, 0x980e, 0xf7d0, 0x1bcd, 0x36f4, 0x9813, 0x36f4, + 0x1811, 0x36f0, 0x9803, 0x2000, 0x0000, 0x36f2, 0x8024, 0xb386, 0x40d7, + 0x4284, 0x184c, 0x0000, 0x05c0, 0x2802, 0xb955, 0xf5d8, 0x3804, 0x0000, + 0x0984, 0x6400, 0xb84a, 0x3e13, 0xf80d, 0xa204, 0x380e, 0x0000, 0x800a, + 0x0000, 0x00ce, 0x2402, 0xbc8e, 0xffa4, 0x0024, 0x48b6, 0x0024, 0x0000, + 0x0024, 0x2802, 0xbc84, 0x4000, 0x40c2, 0x4224, 0x0024, 0x6090, 0x0024, + 0xffa4, 0x0024, 0x0fff, 0xfe83, 0xfe86, 0x1bce, 0x36f3, 0xd80d, 0x48b6, + 0x0024, 0x0fff, 0xff03, 0xa230, 0x45c3, 0x2000, 0x0000, 0x36f1, 0x180a, + 0x0007, 0x0001, /*copy 1*/ + 0x802e, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x6b00, 0x0007, 0x0001, /*copy 1*/ + 0x8030, 0x0006, 0x0002, /*copy 2*/ + 0x2800, 0x1b40, 0x0007, 0x0001, /*copy 1*/ + 0x8028, 0x0006, 0x0002, /*copy 2*/ + 0x2a00, 0x148e, 0x0007, 0x0001, /*copy 1*/ + 0x8032, 0x0006, 0x0002, /*copy 2*/ + 0x2801, 0x9740, 0x0007, 0x0001, /*copy 1*/ + 0x3580, 0x0006, 0x8038, 0x0000, /*Rle(56)*/ + 0x0007, 0x0001, /*copy 1*/ + 0xfab3, 0x0006, 0x01bc, /*copy 444*/ + 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffff, 0xfffe, 0xfffb, 0xfff9, + 0xfff5, 0xfff2, 0xffed, 0xffe8, 0xffe3, 0xffde, 0xffd8, 0xffd3, 0xffce, + 0xffca, 0xffc7, 0xffc4, 0xffc4, 0xffc5, 0xffc7, 0xffcc, 0xffd3, 0xffdc, + 0xffe6, 0xfff3, 0x0001, 0x0010, 0x001f, 0x002f, 0x003f, 0x004e, 0x005b, + 0x0066, 0x006f, 0x0074, 0x0075, 0x0072, 0x006b, 0x005f, 0x004f, 0x003c, + 0x0024, 0x0009, 0xffed, 0xffcf, 0xffb0, 0xff93, 0xff77, 0xff5f, 0xff4c, + 0xff3d, 0xff35, 0xff34, 0xff3b, 0xff4a, 0xff60, 0xff7e, 0xffa2, 0xffcd, + 0xfffc, 0x002e, 0x0061, 0x0094, 0x00c4, 0x00f0, 0x0114, 0x0131, 0x0144, + 0x014b, 0x0146, 0x0134, 0x0116, 0x00eb, 0x00b5, 0x0075, 0x002c, 0xffde, + 0xff8e, 0xff3d, 0xfeef, 0xfea8, 0xfe6a, 0xfe39, 0xfe16, 0xfe05, 0xfe06, + 0xfe1b, 0xfe43, 0xfe7f, 0xfecd, 0xff2a, 0xff95, 0x0009, 0x0082, 0x00fd, + 0x0173, 0x01e1, 0x0242, 0x0292, 0x02cc, 0x02ec, 0x02f2, 0x02da, 0x02a5, + 0x0253, 0x01e7, 0x0162, 0x00c9, 0x0021, 0xff70, 0xfebc, 0xfe0c, 0xfd68, + 0xfcd5, 0xfc5b, 0xfc00, 0xfbc9, 0xfbb8, 0xfbd2, 0xfc16, 0xfc85, 0xfd1b, + 0xfdd6, 0xfeae, 0xff9e, 0x009c, 0x01a0, 0x02a1, 0x0392, 0x046c, 0x0523, + 0x05b0, 0x060a, 0x062c, 0x0613, 0x05bb, 0x0526, 0x0456, 0x0351, 0x021f, + 0x00c9, 0xff5a, 0xfde1, 0xfc6a, 0xfb05, 0xf9c0, 0xf8aa, 0xf7d0, 0xf73d, + 0xf6fa, 0xf70f, 0xf77e, 0xf848, 0xf96b, 0xfadf, 0xfc9a, 0xfe8f, 0x00ad, + 0x02e3, 0x051a, 0x073f, 0x0939, 0x0af4, 0x0c5a, 0x0d59, 0x0de1, 0x0de5, + 0x0d5c, 0x0c44, 0x0a9e, 0x0870, 0x05c7, 0x02b4, 0xff4e, 0xfbaf, 0xf7f8, + 0xf449, 0xf0c7, 0xed98, 0xeae0, 0xe8c4, 0xe765, 0xe6e3, 0xe756, 0xe8d2, + 0xeb67, 0xef19, 0xf3e9, 0xf9cd, 0x00b5, 0x088a, 0x112b, 0x1a72, 0x2435, + 0x2e42, 0x3866, 0x426b, 0x4c1b, 0x553e, 0x5da2, 0x6516, 0x6b6f, 0x7087, + 0x7441, 0x7686, 0x774a, 0x7686, 0x7441, 0x7087, 0x6b6f, 0x6516, 0x5da2, + 0x553e, 0x4c1b, 0x426b, 0x3866, 0x2e42, 0x2435, 0x1a72, 0x112b, 0x088a, + 0x00b5, 0xf9cd, 0xf3e9, 0xef19, 0xeb67, 0xe8d2, 0xe756, 0xe6e3, 0xe765, + 0xe8c4, 0xeae0, 0xed98, 0xf0c7, 0xf449, 0xf7f8, 0xfbaf, 0xff4e, 0x02b4, + 0x05c7, 0x0870, 0x0a9e, 0x0c44, 0x0d5c, 0x0de5, 0x0de1, 0x0d59, 0x0c5a, + 0x0af4, 0x0939, 0x073f, 0x051a, 0x02e3, 0x00ad, 0xfe8f, 0xfc9a, 0xfadf, + 0xf96b, 0xf848, 0xf77e, 0xf70f, 0xf6fa, 0xf73d, 0xf7d0, 0xf8aa, 0xf9c0, + 0xfb05, 0xfc6a, 0xfde1, 0xff5a, 0x00c9, 0x021f, 0x0351, 0x0456, 0x0526, + 0x05bb, 0x0613, 0x062c, 0x060a, 0x05b0, 0x0523, 0x046c, 0x0392, 0x02a1, + 0x01a0, 0x009c, 0xff9e, 0xfeae, 0xfdd6, 0xfd1b, 0xfc85, 0xfc16, 0xfbd2, + 0xfbb8, 0xfbc9, 0xfc00, 0xfc5b, 0xfcd5, 0xfd68, 0xfe0c, 0xfebc, 0xff70, + 0x0021, 0x00c9, 0x0162, 0x01e7, 0x0253, 0x02a5, 0x02da, 0x02f2, 0x02ec, + 0x02cc, 0x0292, 0x0242, 0x01e1, 0x0173, 0x00fd, 0x0082, 0x0009, 0xff95, + 0xff2a, 0xfecd, 0xfe7f, 0xfe43, 0xfe1b, 0xfe06, 0xfe05, 0xfe16, 0xfe39, + 0xfe6a, 0xfea8, 0xfeef, 0xff3d, 0xff8e, 0xffde, 0x002c, 0x0075, 0x00b5, + 0x00eb, 0x0116, 0x0134, 0x0146, 0x014b, 0x0144, 0x0131, 0x0114, 0x00f0, + 0x00c4, 0x0094, 0x0061, 0x002e, 0xfffc, 0xffcd, 0xffa2, 0xff7e, 0xff60, + 0xff4a, 0xff3b, 0xff34, 0xff35, 0xff3d, 0xff4c, 0xff5f, 0xff77, 0xff93, + 0xffb0, 0xffcf, 0xffed, 0x0009, 0x0024, 0x003c, 0x004f, 0x005f, 0x006b, + 0x0072, 0x0075, 0x0074, 0x006f, 0x0066, 0x005b, 0x004e, 0x003f, 0x002f, + 0x001f, 0x0010, 0x0001, 0xfff3, 0xffe6, 0xffdc, 0xffd3, 0xffcc, 0xffc7, + 0xffc5, 0xffc4, 0xffc4, 0xffc7, 0xffca, 0xffce, 0xffd3, 0xffd8, 0xffde, + 0xffe3, 0xffe8, 0xffed, 0xfff2, 0xfff5, 0xfff9, 0xfffb, 0xfffe, 0xffff, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xffd8, 0x0052, 0xff62, + 0x0116, 0xfe3a, 0x02c3, 0xfbd5, 0x0633, 0xf6b8, 0x0e89, 0xe5ee, 0x511e, + 0x511e, 0xe5ee, 0x0e89, 0xf6b8, 0x0633, 0xfbd5, 0x02c3, 0xfe3a, 0x0116, + 0xff62, 0x0052, 0xffd8, 0x0007, 0x0001, /*copy 1*/ + 0x180b, 0x0006, 0x0012, /*copy 18*/ + 0x000f, 0x0010, 0x001c, 0xfab3, 0x3580, 0x8037, 0xa037, 0x0001, 0x0000, + 0x3580, 0x01a4, 0x07c7, 0x07d3, 0x07e6, 0x07df, 0x07ea, 0x07ec, 0x07f2, + 0x0007, 0x0001, /*copy 1*/ + 0x8025, 0x0006, 0x0002, /*copy 2*/ + 0x2a01, 0x824e, 0x0007, 0x0001, /*copy 1*/ + 0x5800, 0x0006, 0x0005, /*copy 5*/ + 0x0000, 0x0c00, 0x0000, 0x0100, 0x0100, 0x0006, 0x8006, 0x0000, /*Rle(6)*/ + 0x000a, 0x0001, /*copy 1*/ + 0x0050, +#define PLUGIN_SIZE 5964 +#ifndef SKIP_PLUGIN_VARNAME +}; +#endif diff --git a/targets/esp32/components/VS1053/include/spectrum_analyzer.h b/targets/esp32/components/VS1053/include/spectrum_analyzer.h new file mode 100644 index 00000000..f163468f --- /dev/null +++ b/targets/esp32/components/VS1053/include/spectrum_analyzer.h @@ -0,0 +1,124 @@ + +const unsigned short PLUGIN[950] = { + /* Compressed plugin */ + 0x0007, 0x0001, 0x8050, 0x0006, 0x0018, 0x3613, 0x0024, 0x3e00, /* 0 */ + 0x3801, 0x0000, 0x16d7, 0xf400, 0x55c0, 0x0000, 0x0c17, 0xf400, /* 8 */ + 0x57c0, 0x0007, 0x9257, 0xb080, 0x0024, 0x3f00, 0x0024, 0x2000, /* 10 */ + 0x0000, 0x36f0, 0x1801, 0x2800, 0x31c0, 0x0007, 0x0001, 0x805c, /* 18 */ + 0x0006, 0x00d6, 0x3e12, 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, /* 20 */ + 0x3615, 0x0024, 0x0000, 0x800a, 0x3e10, 0x3801, 0x0006, 0x0000, /* 28 */ + 0x3e10, 0xb803, 0x0000, 0x0303, 0x3e11, 0x3805, 0x3e11, 0xb807, /* 30 */ + 0x3e14, 0x3812, 0xb884, 0x130c, 0x3410, 0x4024, 0x4112, 0x10d0, /* 38 */ + 0x4010, 0x008c, 0x4010, 0x0024, 0xf400, 0x4012, 0x3000, 0x3840, /* 40 */ + 0x3009, 0x3801, 0x0000, 0x0041, 0xfe02, 0x0024, 0x2900, 0x8200, /* 48 */ + 0x48b2, 0x0024, 0x36f3, 0x0844, 0x6306, 0x8845, 0xae3a, 0x8840, /* 50 */ + 0xbf8e, 0x8b41, 0xac32, 0xa846, 0xffc8, 0xabc7, 0x3e01, 0x7800, /* 58 */ + 0xf400, 0x4480, 0x6090, 0x0024, 0x6090, 0x0024, 0xf400, 0x4015, /* 60 */ + 0x3009, 0x3446, 0x3009, 0x37c7, 0x3009, 0x1800, 0x3009, 0x3844, /* 68 */ + 0x48b3, 0xe1e0, 0x4882, 0x4040, 0xfeca, 0x0024, 0x5ac2, 0x0024, /* 70 */ + 0x5a52, 0x0024, 0x4cc2, 0x0024, 0x48ba, 0x4040, 0x4eea, 0x4801, /* 78 */ + 0x4eca, 0x9800, 0xff80, 0x1bc1, 0xf1eb, 0xe3e2, 0xf1ea, 0x184c, /* 80 */ + 0x4c8b, 0xe5e4, 0x48be, 0x9804, 0x488e, 0x41c6, 0xfe82, 0x0024, /* 88 */ + 0x5a8e, 0x0024, 0x525e, 0x1b85, 0x4ffe, 0x0024, 0x48b6, 0x41c6, /* 90 */ + 0x4dd6, 0x48c7, 0x4df6, 0x0024, 0xf1d6, 0x0024, 0xf1d6, 0x0024, /* 98 */ + 0x4eda, 0x0024, 0x0000, 0x0fc3, 0x2900, 0x8200, 0x4e82, 0x0024, /* a0 */ + 0x4084, 0x130c, 0x0006, 0x0100, 0x3440, 0x4024, 0x4010, 0x0024, /* a8 */ + 0xf400, 0x4012, 0x3200, 0x4024, 0xb132, 0x0024, 0x4214, 0x0024, /* b0 */ + 0xf224, 0x0024, 0x6230, 0x0024, 0x0001, 0x0001, 0x2800, 0x2b49, /* b8 */ + 0x0000, 0x0024, 0xf400, 0x40c2, 0x3200, 0x0024, 0xff82, 0x0024, /* c0 */ + 0x48b2, 0x0024, 0xb130, 0x0024, 0x6202, 0x0024, 0x003f, 0xf001, /* c8 */ + 0x2800, 0x2e51, 0x0000, 0x1046, 0xfe64, 0x0024, 0x48be, 0x0024, /* d0 */ + 0x2800, 0x2f40, 0x3a01, 0x8024, 0x3200, 0x0024, 0xb010, 0x0024, /* d8 */ + 0xc020, 0x0024, 0x3a00, 0x0024, 0x36f4, 0x1812, 0x36f1, 0x9807, /* e0 */ + 0x36f1, 0x1805, 0x36f0, 0x9803, 0x36f0, 0x1801, 0x3405, 0x9014, /* e8 */ + 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, /* f0 */ + 0x0007, 0x0001, 0x80c7, 0x0006, 0x01ae, 0x3e12, 0xb817, 0x3e12, /* f8 */ + 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000, 0x800a, 0x3e10, /* 100 */ + 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7810, 0x3e14, 0x7813, 0x0006, /* 108 */ + 0x0051, 0x3e13, 0xf80e, 0x3e13, 0x4024, 0x3009, 0x3840, 0x3009, /* 110 */ + 0x3852, 0x2911, 0xf140, 0x0006, 0x06d0, 0x3100, 0x5bd2, 0x0006, /* 118 */ + 0xc351, 0x3009, 0x1bc0, 0x3009, 0x0402, 0x6126, 0x0024, 0x0006, /* 120 */ + 0x00d1, 0x2800, 0x4d45, 0x0000, 0x0024, 0x0006, 0x0011, 0xb882, /* 128 */ + 0x184c, 0x3009, 0x3850, 0x0006, 0x0010, 0x3009, 0x3800, 0x2914, /* 130 */ + 0xbec0, 0x0000, 0x1800, 0x0006, 0x0010, 0xb882, 0x0024, 0x2915, /* 138 */ + 0x7ac0, 0x0000, 0x1700, 0x0000, 0x0301, 0x3900, 0x5bc0, 0x0006, /* 140 */ + 0xc351, 0x3009, 0x1bd0, 0x3009, 0x0404, 0x0006, 0x0051, 0x2800, /* 148 */ + 0x3d40, 0x3901, 0x0024, 0x4448, 0x0401, 0x4192, 0x0024, 0x6498, /* 150 */ + 0x2401, 0x001f, 0x4001, 0x6412, 0x0024, 0x0006, 0x0011, 0x2800, /* 158 */ + 0x3c91, 0x0000, 0x058e, 0x2400, 0x4c4e, 0x0000, 0x0013, 0x0006, /* 160 */ + 0x0051, 0x0006, 0x1a03, 0x3100, 0x4024, 0xf212, 0x44c4, 0x4346, /* 168 */ + 0x0024, 0xf400, 0x40d5, 0x3500, 0x8024, 0x612a, 0x0024, 0x0000, /* 170 */ + 0x0024, 0x2800, 0x4c91, 0x0000, 0x0024, 0x3613, 0x0024, 0x3100, /* 178 */ + 0x3800, 0x2915, 0x7dc0, 0xf200, 0x0024, 0x003f, 0xfec2, 0x4082, /* 180 */ + 0x4411, 0x3113, 0x1bc0, 0xa122, 0x0024, 0x0000, 0x2002, 0x6124, /* 188 */ + 0x2401, 0x0000, 0x1002, 0x2800, 0x4648, 0x0000, 0x0024, 0x003f, /* 190 */ + 0xf802, 0x3100, 0x4024, 0xb124, 0x0024, 0x2800, 0x4c00, 0x3900, /* 198 */ + 0x8024, 0x6124, 0x0024, 0x0000, 0x0802, 0x2800, 0x4888, 0x0000, /* 1a0 */ + 0x0024, 0x003f, 0xfe02, 0x3100, 0x4024, 0xb124, 0x0024, 0x2800, /* 1a8 */ + 0x4c00, 0x3900, 0x8024, 0x6124, 0x0024, 0x0000, 0x0402, 0x2800, /* 1b0 */ + 0x4ac8, 0x0000, 0x0024, 0x003f, 0xff02, 0x3100, 0x4024, 0xb124, /* 1b8 */ + 0x0024, 0x2800, 0x4c00, 0x3900, 0x8024, 0x6124, 0x0401, 0x003f, /* 1c0 */ + 0xff82, 0x2800, 0x4c08, 0xb124, 0x0024, 0x3900, 0x8024, 0xb882, /* 1c8 */ + 0x8c4c, 0x3830, 0x4024, 0x0006, 0x0091, 0x3904, 0xc024, 0x0006, /* 1d0 */ + 0x00d1, 0x0000, 0x0013, 0x3100, 0x904c, 0x4202, 0x0024, 0x39f0, /* 1d8 */ + 0x4024, 0x3100, 0x4024, 0x3c00, 0x4024, 0xf400, 0x44c1, 0x34f0, /* 1e0 */ + 0x8024, 0x6126, 0x0024, 0x0006, 0x06d0, 0x2800, 0x5b98, 0x4294, /* 1e8 */ + 0x0024, 0x2400, 0x5b42, 0x0000, 0x0024, 0xf400, 0x4411, 0x3123, /* 1f0 */ + 0x0024, 0x3100, 0x8024, 0x4202, 0x0024, 0x4182, 0x2401, 0x0000, /* 1f8 */ + 0x2002, 0x2800, 0x5b49, 0x0000, 0x0024, 0x3013, 0x184c, 0x30f0, /* 200 */ + 0x7852, 0x6124, 0xb850, 0x0006, 0x0001, 0x2800, 0x55c8, 0x4088, /* 208 */ + 0x44c2, 0x4224, 0x0024, 0x4122, 0x0024, 0x4122, 0x0024, 0xf400, /* 210 */ + 0x4051, 0x2900, 0x7200, 0x0000, 0x5708, 0x4224, 0x0024, 0x4122, /* 218 */ + 0x0024, 0x4122, 0x0024, 0x2900, 0x6780, 0xf400, 0x4051, 0x0002, /* 220 */ + 0x0002, 0x3009, 0x1bd0, 0x3023, 0x1bd2, 0x30e0, 0x4024, 0x6124, /* 228 */ + 0x0024, 0x0000, 0x0024, 0x2800, 0x5b48, 0x0000, 0x0024, 0x3613, /* 230 */ + 0x0024, 0x3e14, 0xc024, 0x2900, 0x1700, 0x3e14, 0x0024, 0x36e3, /* 238 */ + 0x008c, 0x30e0, 0x8024, 0x6822, 0x4411, 0x3123, 0x0024, 0x3900, /* 240 */ + 0x4024, 0x3033, 0x0c4c, 0x0006, 0x0011, 0x6892, 0x04c2, 0xa122, /* 248 */ + 0x0402, 0x6126, 0x0024, 0x0006, 0x0093, 0x2800, 0x64c1, 0x0000, /* 250 */ + 0x0024, 0xb882, 0x184c, 0x3413, 0x3812, 0x0006, 0x00d2, 0x3a00, /* 258 */ + 0x5bd2, 0x3300, 0x4024, 0x0000, 0x0013, 0x3c00, 0x4024, 0xf400, /* 260 */ + 0x44c1, 0x34f0, 0x8024, 0x6126, 0x0024, 0x0006, 0x0111, 0x2800, /* 268 */ + 0x64d8, 0x4294, 0x0024, 0x2400, 0x6482, 0x0000, 0x0024, 0x0003, /* 270 */ + 0xf001, 0x3101, 0x0024, 0xb412, 0x0024, 0x0028, 0x0001, 0x2800, /* 278 */ + 0x6485, 0x6144, 0x0024, 0x0004, 0x0002, 0x2800, 0x6441, 0x4422, /* 280 */ + 0x0024, 0x0000, 0x1002, 0x6422, 0x0024, 0x2800, 0x6480, 0x3900, /* 288 */ + 0x4024, 0x3900, 0x4024, 0x3113, 0x0c4c, 0x36f3, 0x4024, 0x36f3, /* 290 */ + 0xd80e, 0x36f4, 0x5813, 0x36f1, 0x5810, 0x36f0, 0xd804, 0x36f0, /* 298 */ + 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815, 0x2000, /* 2a0 */ + 0x0000, 0x36f2, 0x9817, 0x0007, 0x0001, 0x1868, 0x0006, 0x000f, /* 2a8 */ + 0x0032, 0x004f, 0x007e, 0x00c8, 0x013d, 0x01f8, 0x0320, 0x04f6, /* 2b0 */ + 0x07e0, 0x0c80, 0x13d8, 0x1f7f, 0x3200, 0x4f5f, 0x61a8, 0x0006, /* 2b8 */ + 0x8008, 0x0000, 0x0007, 0x0001, 0x819e, 0x0006, 0x0054, 0x3e12, /* 2c0 */ + 0xb814, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, 0x3e11, /* 2c8 */ + 0x7806, 0x3e11, 0xf813, 0x3e13, 0xf80e, 0x3e13, 0x4024, 0x3e04, /* 2d0 */ + 0x7810, 0x449a, 0x0040, 0x0001, 0x0003, 0x2800, 0x70c4, 0x4036, /* 2d8 */ + 0x03c1, 0x0003, 0xffc2, 0xb326, 0x0024, 0x0018, 0x0042, 0x4326, /* 2e0 */ + 0x4495, 0x4024, 0x40d2, 0x0000, 0x0180, 0xa100, 0x4090, 0x0010, /* 2e8 */ + 0x0fc2, 0x4204, 0x0024, 0xbc82, 0x4091, 0x459a, 0x0024, 0x0000, /* 2f0 */ + 0x0054, 0x2800, 0x6fc4, 0xbd86, 0x4093, 0x2400, 0x6f85, 0xfe01, /* 2f8 */ + 0x5e0c, 0x5c43, 0x5f2d, 0x5e46, 0x020c, 0x5c56, 0x8a0c, 0x5e53, /* 300 */ + 0x5e0c, 0x5c43, 0x5f2d, 0x5e46, 0x020c, 0x5c56, 0x8a0c, 0x5e52, /* 308 */ + 0x0024, 0x4cb2, 0x4405, 0x0018, 0x0044, 0x654a, 0x0024, 0x2800, /* 310 */ + 0x7dc0, 0x36f4, 0x5810, 0x0007, 0x0001, 0x81c8, 0x0006, 0x0080, /* 318 */ + 0x3e12, 0xb814, 0x0000, 0x800a, 0x3e10, 0x3801, 0x3e10, 0xb803, /* 320 */ + 0x3e11, 0x7806, 0x3e11, 0xf813, 0x3e13, 0xf80e, 0x3e13, 0x4024, /* 328 */ + 0x3e04, 0x7810, 0x449a, 0x0040, 0x0000, 0x0803, 0x2800, 0x7c84, /* 330 */ + 0x30f0, 0x4024, 0x0fff, 0xfec2, 0xa020, 0x0024, 0x0fff, 0xff02, /* 338 */ + 0xa122, 0x0024, 0x4036, 0x0024, 0x0000, 0x1fc2, 0xb326, 0x0024, /* 340 */ + 0x0010, 0x4002, 0x4326, 0x4495, 0x4024, 0x40d2, 0x0000, 0x0180, /* 348 */ + 0xa100, 0x4090, 0x0010, 0x0042, 0x4204, 0x0024, 0xbc82, 0x4091, /* 350 */ + 0x459a, 0x0024, 0x0000, 0x0054, 0x2800, 0x7b84, 0xbd86, 0x4093, /* 358 */ + 0x2400, 0x7b45, 0xfe01, 0x5e0c, 0x5c43, 0x5f2d, 0x5e46, 0x0024, /* 360 */ + 0x5c56, 0x0024, 0x5e53, 0x5e0c, 0x5c43, 0x5f2d, 0x5e46, 0x0024, /* 368 */ + 0x5c56, 0x0024, 0x5e52, 0x0024, 0x4cb2, 0x4405, 0x0010, 0x4004, /* 370 */ + 0x654a, 0x9810, 0x0000, 0x0144, 0xa54a, 0x1bd1, 0x0006, 0x0013, /* 378 */ + 0x3301, 0xc444, 0x687e, 0x2005, 0xad76, 0x8445, 0x4ed6, 0x8784, /* 380 */ + 0x36f3, 0x64c2, 0xac72, 0x8785, 0x4ec2, 0xa443, 0x3009, 0x2440, /* 388 */ + 0x3009, 0x2741, 0x36f3, 0xd80e, 0x36f1, 0xd813, 0x36f1, 0x5806, /* 390 */ + 0x36f0, 0x9803, 0x36f0, 0x1801, 0x2000, 0x0000, 0x36f2, 0x9814, /* 398 */ + 0x0007, 0x0001, 0x8208, 0x0006, 0x000e, 0x4c82, 0x0024, 0x0000, /* 3a0 */ + 0x0024, 0x2000, 0x0005, 0xf5c2, 0x0024, 0x0000, 0x0980, 0x2000, /* 3a8 */ + 0x0000, 0x6010, 0x0024, 0x000a, 0x0001, 0x0050, +#define PLUGIN_SIZE 950 +}; diff --git a/targets/esp32/components/VS1053/include/vs10xx_uc.h b/targets/esp32/components/VS1053/include/vs10xx_uc.h new file mode 100644 index 00000000..b310fca9 --- /dev/null +++ b/targets/esp32/components/VS1053/include/vs10xx_uc.h @@ -0,0 +1,561 @@ +#ifndef VS10XX_MICROCONTROLLER_DEFINITIONS_H +#define VS10XX_MICROCONTROLLER_DEFINITIONS_H + +/* + + VLSI Solution microcontroller definitions for: + VS1063, VS1053 (and VS8053), VS1033, VS1003, VS1103, VS1011. + + v1.01 2012-11-26 HH Added VS1053 recording registers, bug fixes + v1.00 2012-11-23 HH Initial version + +*/ + + + + + +/* SCI registers */ +#define SCI_num_registers 0x0f +#define VS_WRITE_COMMAND 0x02 +#define VS_READ_COMMAND 0x03 + +#define SCI_MODE 0x00 +#define SCI_STATUS 0x01 +#define SCI_BASS 0x02 +#define SCI_CLOCKF 0x03 +#define SCI_DECODE_TIME 0x04 +#define SCI_AUDATA 0x05 +#define SCI_WRAM 0x06 +#define SCI_WRAMADDR 0x07 +#define SCI_HDAT0 0x08 /* VS1063, VS1053, VS1033, VS1003, VS1011 */ +#define SCI_IN0 0x08 /* VS1103 */ +#define SCI_HDAT1 0x09 /* VS1063, VS1053, VS1033, VS1003, VS1011 */ +#define SCI_IN1 0x09 /* VS1103 */ +#define SCI_AIADDR 0x0A +#define SCI_VOL 0x0B +#define SCI_AICTRL0 0x0C /* VS1063, VS1053, VS1033, VS1003, VS1011 */ +#define SCI_MIXERVOL 0x0C /* VS1103 */ +#define SCI_AICTRL1 0x0D /* VS1063, VS1053, VS1033, VS1003, VS1011 */ +#define SCI_ADPCMRECCTL 0x0D /* VS1103 */ +#define SCI_AICTRL2 0x0E +#define SCI_AICTRL3 0x0F + + +/* SCI register recording aliases */ + +#define SCI_RECQUALITY 0x07 /* (WRAMADDR) VS1063 */ +#define SCI_RECDATA 0x08 /* (HDAT0) VS1063 */ +#define SCI_RECWORDS 0x09 /* (HDAT1) VS1063 */ +#define SCI_RECRATE 0x0C /* (AICTRL0) VS1063, VS1053 */ +#define SCI_RECDIV 0x0C /* (AICTRL0) VS1033, VS1003 */ +#define SCI_RECGAIN 0x0D /* (AICTRL1) VS1063, VS1053, VS1033, VS1003 */ +#define SCI_RECMAXAUTO 0x0E /* (AICTRL2) VS1063, VS1053, VS1033 */ +#define SCI_RECMODE 0x0F /* (AICTRL3) VS1063, VS1053 */ + + +/* SCI_MODE bits */ + +#define SM_DIFF_B 0 +#define SM_LAYER12_B 1 /* VS1063, VS1053, VS1033, VS1011 */ +#define SM_RECORD_PATH_B 1 /* VS1103 */ +#define SM_RESET_B 2 +#define SM_CANCEL_B 3 /* VS1063, VS1053 */ +#define SM_OUTOFWAV_B 3 /* VS1033, VS1003, VS1011 */ +#define SM_OUTOFMIDI_B 3 /* VS1103 */ +#define SM_EARSPEAKER_LO_B 4 /* VS1053, VS1033 */ +#define SM_PDOWN_B 4 /* VS1003, VS1103 */ +#define SM_TESTS_B 5 +#define SM_STREAM_B 6 /* VS1053, VS1033, VS1003, VS1011 */ +#define SM_ICONF_B 6 /* VS1103 */ +#define SM_EARSPEAKER_HI_B 7 /* VS1053, VS1033 */ +#define SM_DACT_B 8 +#define SM_SDIORD_B 9 +#define SM_SDISHARE_B 10 +#define SM_SDINEW_B 11 +#define SM_ENCODE_B 12 /* VS1063 */ +#define SM_ADPCM_B 12 /* VS1053, VS1033, VS1003 */ +#define SM_EARSPEAKER_1103_B 12 /* VS1103 */ +#define SM_ADPCM_HP_B 13 /* VS1033, VS1003 */ +#define SM_LINE1_B 14 /* VS1063, VS1053 */ +#define SM_LINE_IN_B 14 /* VS1033, VS1003, VS1103 */ +#define SM_CLK_RANGE_B 15 /* VS1063, VS1053, VS1033 */ +#define SM_ADPCM_1103_B 15 /* VS1103 */ + +#define SM_DIFF (1<< 0) +#define SM_LAYER12 (1<< 1) /* VS1063, VS1053, VS1033, VS1011 */ +#define SM_RECORD_PATH (1<< 1) /* VS1103 */ +#define SM_RESET (1<< 2) +#define SM_CANCEL (1<< 3) /* VS1063, VS1053 */ +#define SM_OUTOFWAV (1<< 3) /* VS1033, VS1003, VS1011 */ +#define SM_OUTOFMIDI (1<< 3) /* VS1103 */ +#define SM_EARSPEAKER_LO (1<< 4) /* VS1053, VS1033 */ +#define SM_PDOWN (1<< 4) /* VS1003, VS1103 */ +#define SM_TESTS (1<< 5) +#define SM_STREAM (1<< 6) /* VS1053, VS1033, VS1003, VS1011 */ +#define SM_ICONF (1<< 6) /* VS1103 */ +#define SM_EARSPEAKER_HI (1<< 7) /* VS1053, VS1033 */ +#define SM_DACT (1<< 8) +#define SM_SDIORD (1<< 9) +#define SM_SDISHARE (1<<10) +#define SM_SDINEW (1<<11) +#define SM_ENCODE (1<<12) /* VS1063 */ +#define SM_ADPCM (1<<12) /* VS1053, VS1033, VS1003 */ +#define SM_EARSPEAKER1103 (1<<12) /* VS1103 */ +#define SM_ADPCM_HP (1<<13) /* VS1033, VS1003 */ +#define SM_LINE1 (1<<14) /* VS1063, VS1053 */ +#define SM_LINE_IN (1<<14) /* VS1033, VS1003, VS1103 */ +#define SM_CLK_RANGE (1<<15) /* VS1063, VS1053, VS1033 */ +#define SM_ADPCM_1103 (1<<15) /* VS1103 */ + +#define SM_ICONF_BITS 2 +#define SM_ICONF_MASK 0x00c0 + +#define SM_EARSPEAKER_1103_BITS 2 +#define SM_EARSPEAKER_1103_MASK 0x3000 + + +/* SCI_STATUS bits */ + +#define SS_REFERENCE_SEL_B 0 /* VS1063, VS1053 */ +#define SS_AVOL_B 0 /* VS1033, VS1003, VS1103, VS1011 */ +#define SS_AD_CLOCK_B 1 /* VS1063, VS1053 */ +#define SS_APDOWN1_B 2 +#define SS_APDOWN2_B 3 +#define SS_VER_B 4 +#define SS_VCM_DISABLE_B 10 /* VS1063, VS1053 */ +#define SS_VCM_OVERLOAD_B 11 /* VS1063, VS1053 */ +#define SS_SWING_B 12 /* VS1063, VS1053 */ +#define SS_DO_NOT_JUMP_B 15 /* VS1063, VS1053 */ + +#define SS_REFERENCE_SEL (1<< 0) /* VS1063, VS1053 */ +#define SS_AVOL (1<< 0) /* VS1033, VS1003, VS1103, VS1011 */ +#define SS_AD_CLOCK (1<< 1) /* VS1063, VS1053 */ +#define SS_APDOWN1 (1<< 2) +#define SS_APDOWN2 (1<< 3) +#define SS_VER (1<< 4) +#define SS_VCM_DISABLE (1<<10) /* VS1063, VS1053 */ +#define SS_VCM_OVERLOAD (1<<11) /* VS1063, VS1053 */ +#define SS_SWING (1<<12) /* VS1063, VS1053 */ +#define SS_DO_NOT_JUMP (1<<15) /* VS1063, VS1053 */ + +#define SS_SWING_BITS 3 +#define SS_SWING_MASK 0x7000 +#define SS_VER_BITS 4 +#define SS_VER_MASK 0x00f0 +#define SS_AVOL_BITS 2 +#define SS_AVOL_MASK 0x0003 + +#define SS_VER_VS1001 0x00 +#define SS_VER_VS1011 0x10 +#define SS_VER_VS1002 0x20 +#define SS_VER_VS1003 0x30 +#define SS_VER_VS1053 0x40 +#define SS_VER_VS8053 0x40 +#define SS_VER_VS1033 0x50 +#define SS_VER_VS1063 0x60 +#define SS_VER_VS1103 0x70 + + +/* SCI_BASS bits */ + +#define ST_AMPLITUDE_B 12 +#define ST_FREQLIMIT_B 8 +#define SB_AMPLITUDE_B 4 +#define SB_FREQLIMIT_B 0 + +#define ST_AMPLITUDE (1<<12) +#define ST_FREQLIMIT (1<< 8) +#define SB_AMPLITUDE (1<< 4) +#define SB_FREQLIMIT (1<< 0) + +#define ST_AMPLITUDE_BITS 4 +#define ST_AMPLITUDE_MASK 0xf000 +#define ST_FREQLIMIT_BITS 4 +#define ST_FREQLIMIT_MASK 0x0f00 +#define SB_AMPLITUDE_BITS 4 +#define SB_AMPLITUDE_MASK 0x00f0 +#define SB_FREQLIMIT_BITS 4 +#define SB_FREQLIMIT_MASK 0x000f + + +/* SCI_CLOCKF bits */ + +#define SC_MULT_B 13 /* VS1063, VS1053, VS1033, VS1103, VS1003 */ +#define SC_ADD_B 11 /* VS1063, VS1053, VS1033, VS1003 */ +#define SC_FREQ_B 0 /* VS1063, VS1053, VS1033, VS1103, VS1003 */ + +#define SC_MULT (1<<13) /* VS1063, VS1053, VS1033, VS1103, VS1003 */ +#define SC_ADD (1<<11) /* VS1063, VS1053, VS1033, VS1003 */ +#define SC_FREQ (1<< 0) /* VS1063, VS1053, VS1033, VS1103, VS1003 */ + +#define SC_MULT_BITS 3 +#define SC_MULT_MASK 0xe000 +#define SC_ADD_BITS 2 +#define SC_ADD_MASK 0x1800 +#define SC_FREQ_BITS 11 +#define SC_FREQ_MASK 0x07ff + +/* The following macro is for VS1063, VS1053, VS1033, VS1003, VS1103. + Divide hz by two when calling if SM_CLK_RANGE = 1 */ +#define HZ_TO_SC_FREQ(hz) (((hz)-8000000+2000)/4000) + +/* The following macro is for VS1011. + The macro will automatically set the clock doubler if XTALI < 16 MHz */ +#define HZ_TO_SCI_CLOCKF(hz) ((((hz)<16000000)?0x8000:0)+((hz)+1000)/2000) + +/* Following are for VS1003 and VS1033 */ +#define SC_MULT_03_10X 0x0000 +#define SC_MULT_03_15X 0x2000 +#define SC_MULT_03_20X 0x4000 +#define SC_MULT_03_25X 0x6000 +#define SC_MULT_03_30X 0x8000 +#define SC_MULT_03_35X 0xa000 +#define SC_MULT_03_40X 0xc000 +#define SC_MULT_03_45X 0xe000 + +/* Following are for VS1053 and VS1063 */ +#define SC_MULT_53_10X 0x0000 +#define SC_MULT_53_20X 0x2000 +#define SC_MULT_53_25X 0x4000 +#define SC_MULT_53_30X 0x6000 +#define SC_MULT_53_35X 0x8000 +#define SC_MULT_53_40X 0xa000 +#define SC_MULT_53_45X 0xc000 +#define SC_MULT_53_50X 0xe000 + +/* Following are for VS1003 and VS1033 */ +#define SC_ADD_03_00X 0x0000 +#define SC_ADD_03_05X 0x0800 +#define SC_ADD_03_10X 0x1000 +#define SC_ADD_03_15X 0x1800 + +/* Following are for VS1053 and VS1063 */ +#define SC_ADD_53_00X 0x0000 +#define SC_ADD_53_10X 0x0800 +#define SC_ADD_53_15X 0x1000 +#define SC_ADD_53_20X 0x1800 + + +/* SCI_WRAMADDR bits */ + +#define SCI_WRAM_X_START 0x0000 +#define SCI_WRAM_Y_START 0x4000 +#define SCI_WRAM_I_START 0x8000 +#define SCI_WRAM_IO_START 0xC000 +#define SCI_WRAM_PARAMETRIC_START 0xC0C0 /* VS1063 */ +#define SCI_WRAM_Y2_START 0xE000 /* VS1063 */ + +#define SCI_WRAM_X_OFFSET 0x0000 +#define SCI_WRAM_Y_OFFSET 0x4000 +#define SCI_WRAM_I_OFFSET 0x8000 +#define SCI_WRAM_IO_OFFSET 0x0000 /* I/O addresses are @0xC000 -> no offset */ +#define SCI_WRAM_PARAMETRIC_OFFSET (0xC0C0-0x1E00) /* VS1063 */ +#define SCI_WRAM_Y2_OFFSET 0x0000 /* VS1063 */ + + +/* SCI_VOL bits */ + +#define SV_LEFT_B 8 +#define SV_RIGHT_B 0 + +#define SV_LEFT (1<<8) +#define SV_RIGHT (1<<0) + +#define SV_LEFT_BITS 8 +#define SV_LEFT_MASK 0xFF00 +#define SV_RIGHT_BITS 8 +#define SV_RIGHT_MASK 0x00FF + + +/* SCI_MIXERVOL bits for VS1103 */ + +#define SMV_ACTIVE_B 15 +#define SMV_GAIN3_B 10 +#define SMV_GAIN2_B 5 +#define SMV_GAIN1_B 0 + +#define SMV_ACTIVE (1<<15) +#define SMV_GAIN3 (1<<10) +#define SMV_GAIN2 (1<< 5) +#define SMV_GAIN1 (1<< 0) + +#define SMV_GAIN3_BITS 5 +#define SMV_GAIN3_MASK 0x7c00 +#define SMV_GAIN2_BITS 5 +#define SMV_GAIN2_MASK 0x04e0 +#define SMV_GAIN1_BITS 5 +#define SMV_GAIN1_MASK 0x001f + + +/* SCI_ADPCMRECCTL bits for VS1103 */ + +#define SARC_DREQ512_B 8 +#define SARC_OUTODADPCM_B 7 +#define SARC_MANUALGAIN_B 6 +#define SARC_GAIN4_B 0 + +#define SARC_DREQ512 (1<<8) +#define SARC_OUTODADPCM (1<<7) +#define SARC_MANUALGAIN (1<<6) +#define SARC_GAIN4 (1<<0) + +#define SARC_GAIN4_BITS 6 +#define SARC_GAIN4_MASK 0x003f + + +/* SCI_RECQUALITY bits for VS1063 */ + +#define RQ_MODE_B 14 +#define RQ_MULT_B 12 +#define RQ_OGG_PAR_SERIAL_NUMBER_B 11 +#define RQ_OGG_LIMIT_FRAME_LENGTH_B 10 +#define RQ_MP3_NO_BIT_RESERVOIR_B 10 +#define RQ_BITRATE_BASE_B 0 + +#define RQ_MODE (1<<14) +#define RQ_MULT (1<<12) +#define RQ_OGG_PAR_SERIAL_NUMBER (1<<11) +#define RQ_OGG_LIMIT_FRAME_LENGTH (1<<10) +#define RQ_MP3_NO_BIT_RESERVOIR (1<<10) +#define RQ_BITRATE_BASE (1<< 0) + +#define RQ_MODE_BITS 2 +#define RQ_MODE_MASK 0xc000 +#define RQ_MULT_BITS 2 +#define RQ_MULT_MASK 0x3000 +#define RQ_BITRATE_BASE_BITS 9 +#define RQ_BITRATE_BASE_MASK 0x01ff + +#define RQ_MODE_QUALITY 0x0000 +#define RQ_MODE_VBR 0x4000 +#define RQ_MODE_ABR 0x8000 +#define RQ_MODE_CBR 0xc000 + +#define RQ_MULT_10 0x0000 +#define RQ_MULT_100 0x1000 +#define RQ_MULT_1000 0x2000 +#define RQ_MULT_10000 0x3000 + + +/* SCI_RECMODE bits for VS1063 */ + +#define RM_63_CODEC_B 15 +#define RM_63_AEC_B 14 +#define RM_63_UART_TX_B 13 +#define RM_63_PAUSE_B 11 +#define RM_63_NO_RIFF_B 10 +#define RM_63_FORMAT_B 4 +#define RM_63_ADC_MODE_B 0 + +#define RM_63_CODEC (1<<15) +#define RM_63_AEC (1<<14) +#define RM_63_UART_TX (1<<13) +#define RM_63_PAUSE (1<<11) +#define RM_63_NO_RIFF (1<<10) +#define RM_63_FORMAT (1<< 4) +#define RM_63_ADC_MODE (1<< 0) + +#define RM_63_FORMAT_BITS 4 +#define RM_63_FORMAT_MASK 0x00f0 +#define RM_63_ADCMODE_BITS 3 +#define RM_63_ADCMODE_MASK 0x0007 + +#define RM_63_FORMAT_IMA_ADPCM 0x0000 +#define RM_63_FORMAT_PCM 0x0010 +#define RM_63_FORMAT_G711_ULAW 0x0020 +#define RM_63_FORMAT_G711_ALAW 0x0030 +#define RM_63_FORMAT_G722_ADPCM 0x0040 +#define RM_63_FORMAT_OGG_VORBIS 0x0050 +#define RM_63_FORMAT_MP3 0x0060 + +#define RM_63_ADC_MODE_JOINT_AGC_STEREO 0x0000 +#define RM_63_ADC_MODE_DUAL_AGC_STEREO 0x0001 +#define RM_63_ADC_MODE_LEFT 0x0002 +#define RM_63_ADC_MODE_RIGHT 0x0003 +#define RM_63_ADC_MODE_MONO 0x0004 + + +/* SCI_RECMODE bits for VS1053 */ + +#define RM_53_FORMAT_B 2 +#define RM_53_ADC_MODE_B 0 + +#define RM_53_FORMAT (1<< 2) +#define RM_53_ADC_MODE (1<< 0) + +#define RM_53_ADCMODE_BITS 2 +#define RM_53_ADCMODE_MASK 0x0003 + +#define RM_53_FORMAT_IMA_ADPCM 0x0000 +#define RM_53_FORMAT_PCM 0x0004 + +#define RM_53_ADC_MODE_JOINT_AGC_STEREO 0x0000 +#define RM_53_ADC_MODE_DUAL_AGC_STEREO 0x0001 +#define RM_53_ADC_MODE_LEFT 0x0002 +#define RM_53_ADC_MODE_RIGHT 0x0003 + + +/* VS1063 definitions */ + +/* VS1063 / VS1053 Parametric */ +#define PAR_CHIP_ID 0x1e00 /* VS1063, VS1053, 32 bits */ +#define PAR_VERSION 0x1e02 /* VS1063, VS1053 */ +#define PAR_CONFIG1 0x1e03 /* VS1063, VS1053 */ +#define PAR_PLAY_SPEED 0x1e04 /* VS1063, VS1053 */ +#define PAR_BITRATE_PER_100 0x1e05 /* VS1063 */ +#define PAR_BYTERATE 0x1e05 /* VS1053 */ +#define PAR_END_FILL_BYTE 0x1e06 /* VS1063, VS1053 */ +#define PAR_RATE_TUNE 0x1e07 /* VS1063, 32 bits */ +#define PAR_PLAY_MODE 0x1e09 /* VS1063 */ +#define PAR_SAMPLE_COUNTER 0x1e0a /* VS1063, 32 bits */ +#define PAR_VU_METER 0x1e0c /* VS1063 */ +#define PAR_AD_MIXER_GAIN 0x1e0d /* VS1063 */ +#define PAR_AD_MIXER_CONFIG 0x1e0e /* VS1063 */ +#define PAR_PCM_MIXER_RATE 0x1e0f /* VS1063 */ +#define PAR_PCM_MIXER_FREE 0x1e10 /* VS1063 */ +#define PAR_PCM_MIXER_VOL 0x1e11 /* VS1063 */ +#define PAR_EQ5_DUMMY 0x1e12 /* VS1063 */ +#define PAR_EQ5_LEVEL1 0x1e13 /* VS1063 */ +#define PAR_EQ5_FREQ1 0x1e14 /* VS1063 */ +#define PAR_EQ5_LEVEL2 0x1e15 /* VS1063 */ +#define PAR_EQ5_FREQ2 0x1e16 /* VS1063 */ +#define PAR_JUMP_POINTS 0x1e16 /* VS1053 */ +#define PAR_EQ5_LEVEL3 0x1e17 /* VS1063 */ +#define PAR_EQ5_FREQ3 0x1e18 /* VS1063 */ +#define PAR_EQ5_LEVEL4 0x1e19 /* VS1063 */ +#define PAR_EQ5_FREQ4 0x1e1a /* VS1063 */ +#define PAR_EQ5_LEVEL5 0x1e1b /* VS1063 */ +#define PAR_EQ5_UPDATED 0x1e1c /* VS1063 */ +#define PAR_SPEED_SHIFTER 0x1e1d /* VS1063 */ +#define PAR_EARSPEAKER_LEVEL 0x1e1e /* VS1063 */ +#define PAR_SDI_FREE 0x1e1f /* VS1063 */ +#define PAR_AUDIO_FILL 0x1e20 /* VS1063 */ +#define PAR_RESERVED0 0x1e21 /* VS1063 */ +#define PAR_RESERVED1 0x1e22 /* VS1063 */ +#define PAR_RESERVED2 0x1e23 /* VS1063 */ +#define PAR_RESERVED3 0x1e24 /* VS1063 */ +#define PAR_LATEST_SOF 0x1e25 /* VS1063, 32 bits */ +#define PAR_LATEST_JUMP 0x1e26 /* VS1053 */ +#define PAR_POSITION_MSEC 0x1e27 /* VS1063, VS1053, 32 bits */ +#define PAR_RESYNC 0x1e29 /* VS1063, VS1053 */ + +/* The following addresses are shared between modes. */ +/* Generic pointer */ +#define PAR_GENERIC 0x1e2a /* VS1063, VS1053 */ + +/* Encoder mode */ +#define PAR_ENC_TX_UART_DIV 0x1e2a /* VS1063 */ +#define PAR_ENC_TX_UART_BYTE_SPEED 0x1e2b /* VS1063 */ +#define PAR_ENC_TX_PAUSE_GPIO 0x1e2c /* VS1063 */ +#define PAR_ENC_AEC_ADAPT_MULTIPLIER 0x1e2d /* VS1063 */ +#define PAR_ENC_RESERVED 0x1e2e /* VS1063 */ +#define PAR_ENC_CHANNEL_MAX 0x1e3c /* VS1063 */ +#define PAR_ENC_SERIAL_NUMBER 0x1e3e /* VS1063 */ + +/* Decoding WMA */ +#define PAR_WMA_CUR_PACKET_SIZE 0x1e2a /* VS1063, VS1053, 32 bits */ +#define PAR_WMA_PACKET_SIZE 0x1e2c /* VS1063, VS1053, 32 bits */ + +/* Decoding AAC */ +#define PAR_AAC_SCE_FOUND_MASK 0x1e2a /* VS1063, VS1053 */ +#define PAR_AAC_CPE_FOUND_MASK 0x1e2b /* VS1063, VS1053 */ +#define PAR_AAC_LFE_FOUND_MASK 0x1e2c /* VS1063, VS1053 */ +#define PAR_AAC_PLAY_SELECT 0x1e2d /* VS1063, VS1053 */ +#define PAR_AAC_DYN_COMPRESS 0x1e2e /* VS1063, VS1053 */ +#define PAR_AAC_DYN_BOOST 0x1e2f /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS 0x1e30 /* VS1063, VS1053 */ +#define PAR_AAC_SBR_PS_FLAGS 0x1e31 /* VS1063 */ + + +/* Decoding MIDI (VS1053) */ +#define PAR_MIDI_BYTES_LEFT 0x1e2a /* VS1053, 32 bits */ + +/* Decoding Vorbis */ +#define PAR_VORBIS_GAIN 0x1e2a 0x1e30 /* VS1063, VS1053 */ + + +/* Bit definitions for parametric registers with bitfields */ +#define PAR_CONFIG1_DIS_WMA_B 15 /* VS1063 */ +#define PAR_CONFIG1_DIS_AAC_B 14 /* VS1063 */ +#define PAR_CONFIG1_DIS_MP3_B 13 /* VS1063 */ +#define PAR_CONFIG1_DIS_FLAC_B 12 /* VS1063 */ +#define PAR_CONFIG1_DIS_CRC_B 8 /* VS1063 */ +#define PAR_CONFIG1_AAC_PS_B 6 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_B 4 /* VS1063, VS1053 */ +#define PAR_CONFIG1_MIDI_REVERB_B 0 /* VS1053 */ + +#define PAR_CONFIG1_DIS_WMA (1<<15) /* VS1063 */ +#define PAR_CONFIG1_DIS_AAC (1<<14) /* VS1063 */ +#define PAR_CONFIG1_DIS_MP3 (1<<13) /* VS1063 */ +#define PAR_CONFIG1_DIS_FLAC (1<<12) /* VS1063 */ +#define PAR_CONFIG1_DIS_CRC (1<< 8) /* VS1063 */ +#define PAR_CONFIG1_AAC_PS (1<< 6) /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR (1<< 4) /* VS1063, VS1053 */ +#define PAR_CONFIG1_MIDI_REVERB (1<< 0) /* VS1053 */ + +#define PAR_CONFIG1_AAC_PS_BITS 2 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_PS_MASK 0x00c0 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_BITS 2 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_MASK 0x0030 /* VS1063, VS1053 */ + +#define PAR_CONFIG1_AAC_SBR_ALWAYS_UPSAMPLE 0x0000 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_SELECTIVE_UPSAMPLE 0x0010 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_NEVER_UPSAMPLE 0x0020 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_SBR_DISABLE 0x0030 /* VS1063, VS1053 */ + +#define PAR_CONFIG1_AAC_PS_NORMAL 0x0000 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_PS_DOWNSAMPLED 0x0040 /* VS1063, VS1053 */ +#define PAR_CONFIG1_AAC_PS_DISABLE 0x00c0 /* VS1063, VS1053 */ + +#define PAR_PLAY_MODE_SPEED_SHIFTER_ENA_B 6 /* VS1063 */ +#define PAR_PLAY_MODE_EQ5_ENA_B 5 /* VS1063 */ +#define PAR_PLAY_MODE_PCM_MIXER_ENA_B 4 /* VS1063 */ +#define PAR_PLAY_MODE_AD_MIXER_ENA_B 3 /* VS1063 */ +#define PAR_PLAY_MODE_VU_METER_ENA_B 2 /* VS1063 */ +#define PAR_PLAY_MODE_PAUSE_ENA_B 1 /* VS1063 */ +#define PAR_PLAY_MODE_MONO_ENA_B 0 /* VS1063 */ + +#define PAR_PLAY_MODE_SPEED_SHIFTER_ENA (1<<6) /* VS1063 */ +#define PAR_PLAY_MODE_EQ5_ENA (1<<5) /* VS1063 */ +#define PAR_PLAY_MODE_PCM_MIXER_ENA (1<<4) /* VS1063 */ +#define PAR_PLAY_MODE_AD_MIXER_ENA (1<<3) /* VS1063 */ +#define PAR_PLAY_MODE_VU_METER_ENA (1<<2) /* VS1063 */ +#define PAR_PLAY_MODE_PAUSE_ENA (1<<1) /* VS1063 */ +#define PAR_PLAY_MODE_MONO_ENA (1<<0) /* VS1063 */ + +#define PAR_VU_METER_LEFT_BITS 8 /* VS1063 */ +#define PAR_VU_METER_LEFT_MASK 0xFF00 /* VS1063 */ +#define PAR_VU_METER_RIGHT_BITS 8 /* VS1063 */ +#define PAR_VU_METER_RIGHT_MASK 0x00FF /* VS1063 */ + +#define PAR_AD_MIXER_CONFIG_MODE_B 2 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_B 2 /* VS1063 */ + +#define PAR_AD_MIXER_CONFIG_MODE_BITS 2 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_MODE_MASK 0x000c /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_BITS 2 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_MASK 0x0003 /* VS1063 */ + +#define PAR_AD_MIXER_CONFIG_RATE_192K 0x0000 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_96K 0x0001 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_48K 0x0002 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_RATE_24K 0x0003 /* VS1063 */ + +#define PAR_AD_MIXER_CONFIG_MODE_STEREO 0x0000 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_MODE_MONO 0x0040 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_MODE_LEFT 0x0080 /* VS1063 */ +#define PAR_AD_MIXER_CONFIG_MODE_RIGHT 0x00c0 /* VS1063 */ + +#define PAR_AAC_SBR_AND_PS_STATUS_SBR_PRESENT_B 0 /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_UPSAMPLING_ACTIVE_B 1 /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_PS_PRESENT_B 2 /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_PS_ACTIVE_B 3 /* VS1063, VS1053 */ + +#define PAR_AAC_SBR_AND_PS_STATUS_SBR_PRESENT (1<<0) /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_UPSAMPLING_ACTIVE (1<<1) /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_PS_PRESENT (1<<2) /* VS1063, VS1053 */ +#define PAR_AAC_SBR_AND_PS_STATUS_PS_ACTIVE (1<<3) /* VS1063, VS1053 */ + + +#endif /* !VS10XX_MICROCONTROLLER_DEFINITIONS_H */ diff --git a/targets/esp32/components/VS1053/src/VS1053.cpp b/targets/esp32/components/VS1053/src/VS1053.cpp new file mode 100644 index 00000000..97b0a44f --- /dev/null +++ b/targets/esp32/components/VS1053/src/VS1053.cpp @@ -0,0 +1,666 @@ +#include "VS1053.h" + +#include +#include "esp_log.h" + +static const char* TAG = "VS_SINK"; +void vs_feed(void* track) { + ((VS1053_TRACK*)track)->run_track(1024); +} + +unsigned char pcm_wav_header[44] = { + 0x52, 0x49, 0x46, + 0x46, // RIFF + 0xFF, 0xFF, 0xFF, + 0xFF, // size + 0x57, 0x41, 0x56, + 0x45, // WAVE + 0x66, 0x6d, 0x74, + 0x20, // fmt + 0x10, 0x00, 0x00, + 0x00, // subchunk1size + 0x01, 0x00, // audio format - pcm + 0x02, 0x00, // numof channels + 0x44, 0xac, 0x00, + 0x00, //, //samplerate 44k1: 0x44, 0xac, 0x00, 0x00 48k: 48000: 0x80, 0xbb, 0x00, 0x00, + 0x10, 0xb1, 0x02, + 0x00, // byterate + 0x04, 0x00, // blockalign + 0x10, 0x00, // bits per sample - 16 + 0x64, 0x61, 0x74, + 0x61, // subchunk3id -"data" + 0xFF, 0xFF, 0xFF, + 0xFF // subchunk3size (endless) +}; +const char* afName[] = { + "unknown", "RIFF", "Ogg", "MP1", "MP2", "MP3", "AAC MP4", + "AAC ADTS", "AAC ADIF", "FLAC", "WMA", "MIDI", "DSD64", "LATM/LOAS", +}; +VS1053_SINK::VS1053_SINK() { + // PIN CONFIG + // DREQ + ESP_LOGI(TAG, "VS1053_DREQ=%d", CONFIG_GPIO_VS_DREQ); + gpio_config_t gpio_conf; + gpio_conf.mode = GPIO_MODE_INPUT; + gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE; + gpio_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; + gpio_conf.intr_type = GPIO_INTR_DISABLE; + gpio_conf.pin_bit_mask = ((uint64_t)(((uint64_t)1) << CONFIG_GPIO_VS_DREQ)); + ESP_ERROR_CHECK(gpio_config(&gpio_conf)); + // CS + ESP_LOGI(TAG, "VS1053_CS=%d", CONFIG_GPIO_VS_CS); + gpio_reset_pin((gpio_num_t)CONFIG_GPIO_VS_CS); + gpio_set_direction((gpio_num_t)CONFIG_GPIO_VS_CS, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)CONFIG_GPIO_VS_CS, 1); + // DCS + ESP_LOGI(TAG, "VS1053_DCS=%d", CONFIG_GPIO_VS_DCS); + gpio_reset_pin((gpio_num_t)CONFIG_GPIO_VS_DCS); + gpio_set_direction((gpio_num_t)CONFIG_GPIO_VS_DCS, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)CONFIG_GPIO_VS_DCS, 1); + // RESET + ESP_LOGI(TAG, "VS1053_RESET=%d", CONFIG_GPIO_VS_RESET); + if (CONFIG_GPIO_VS_RESET >= 0) { + gpio_reset_pin((gpio_num_t)CONFIG_GPIO_VS_RESET); + gpio_set_direction((gpio_num_t)CONFIG_GPIO_VS_RESET, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)CONFIG_GPIO_VS_RESET, 0); + vTaskDelay(100 / portTICK_PERIOD_MS); + gpio_set_level((gpio_num_t)CONFIG_GPIO_VS_RESET, 1); + } +} + +esp_err_t VS1053_SINK::init(spi_host_device_t SPI, + SemaphoreHandle_t* SPI_semaphore) { + esp_err_t ret; + this->SPI_semaphore = SPI_semaphore; + // SPI CONFIG + uint32_t freq = spi_get_actual_clock(APB_CLK_FREQ, 1400000, 128); + spi_device_interface_config_t devcfg; + memset(&devcfg, 0, sizeof(spi_device_interface_config_t)); + ESP_LOGI(TAG, "VS1053 LOWFreq: %d", freq); + + devcfg.clock_speed_hz = freq, devcfg.command_bits = 8, + devcfg.address_bits = 8, devcfg.dummy_bits = 0, devcfg.duty_cycle_pos = 0, + devcfg.cs_ena_pretrans = 0, devcfg.cs_ena_posttrans = 1, devcfg.flags = 0, + devcfg.mode = 0, devcfg.spics_io_num = CONFIG_GPIO_VS_CS, + devcfg.queue_size = 1, + devcfg.pre_cb = NULL, // Specify pre-transfer callback to handle D/C line + devcfg.post_cb = NULL; + + ESP_LOGI(TAG, "spi device interface config done, VERSION : %i", VERSION); + ret = spi_bus_add_device(SPI, &devcfg, &this->SPIHandleLow); + ESP_LOGI(TAG, "spi_bus_add_device=%d", ret); + assert(ret == ESP_OK); + // SPI TEST SLOW-/HIGH-SPEED + vTaskDelay(20 / portTICK_PERIOD_MS); + write_register(SCI_MODE, SM_SDINEW | SM_TESTS | SM_RESET); + ret = test_comm("Slow SPI,Testing VS1053 read/write registers...\n"); + if (ret != ESP_OK) + return ret; + { + freq = spi_get_actual_clock(APB_CLK_FREQ, 6670000, 128); + write_register( + SCI_CLOCKF, + HZ_TO_SC_FREQ(12288000) | SC_MULT_53_45X | + SC_ADD_53_00X); // Normal clock settings multiplyer 3.0 = 12.2 MHz + ESP_LOGI(TAG, "VS1053 HighFreq: %d", freq); + devcfg.clock_speed_hz = freq, devcfg.command_bits = 0, + devcfg.address_bits = 0, devcfg.spics_io_num = CONFIG_GPIO_VS_DCS; + ret = spi_bus_add_device(SPI, &devcfg, &this->SPIHandleFast); + ESP_LOGI(TAG, "spi_bus_add_device=%d", ret); + assert(ret == ESP_OK); + ret = test_comm("Slow SPI,Testing VS1053 read/write registers...\n"); + if (ret != ESP_OK) + return ret; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + + write_mem(PAR_CONFIG1, PAR_CONFIG1_AAC_SBR_SELECTIVE_UPSAMPLE); + write_register(SCI_VOL, 0x0c0c); +#ifndef CONFIG_VS1053_NO_PLUGIN + //load_user_code(PLUGIN, PLUGIN_SIZE); +#endif + vTaskDelay(100 / portTICK_PERIOD_MS); + return ESP_OK; +} + +VS1053_SINK::~VS1053_SINK() {} +VS1053_TRACK VS1053_SINK::newTrack(size_t track_id, size_t buffer_size) { + return VS1053_TRACK(this, track_id, buffer_size); +} +// LOOP +VS1053_TRACK::VS1053_TRACK(VS1053_SINK* vsSink, size_t track_id, + size_t buffer_size) { + this->track_id = track_id; + this->audioSink = vsSink; + this->dataBuffer = xStreamBufferCreate(buffer_size, 1); + // this->run_track(); +} +VS1053_TRACK::~VS1053_TRACK() { + if (this->track_state != tsStopped) + this->audioSink->new_state(tsCancel); + while (this->track_handle) + vTaskDelay(10 / portTICK_PERIOD_MS); + if (dataBuffer != NULL) + vStreamBufferDelete(dataBuffer); + dataBuffer = NULL; +} + +void runTrack() {} +void VS1053_SINK::start_track(std::shared_ptr track, + size_t buf_fill) { + this->track = track; + endFillByte = 0; + playMode = read_mem(PAR_PLAY_MODE); + endFillBytes = SDI_END_FILL_BYTES; // How many of those to send + sdi_send_fillers(endFillBytes); + write_register(SCI_DECODE_TIME, 0); // Reset DECODE_TIME + xTaskCreate(vs_feed, "track_feed", 4098, (void*)this->track.get(), 5, + &this->track->track_handle); + new_state(VS1053_TRACK::VS_TRACK_STATE::tsPlaybackStart); +} +void VS1053_SINK::new_track(std::shared_ptr track) { + if (this->track) + this->future_track = track; + else + this->start_track(track, 1024); +} +bool VS1053_SINK::is_seekable(VS1053_TRACK::VS_TRACK_STATE* state) { + if (read_register(SCI_STATUS) >> SS_DO_NOT_JUMP_B == 0) { + new_state(VS1053_TRACK::VS_TRACK_STATE::tsPlaybackSeekable); + return true; + } + return false; +} +size_t VS1053_SINK::track_seekable(size_t track_id) { + if (this->track) + if (this->track->track_id == track_id) + return this->track->header_size; + return 0; +} +void VS1053_SINK::cancel_track(VS1053_TRACK::VS_TRACK_STATE* state) { + unsigned short oldMode; + oldMode = read_register(SCI_MODE); + write_register(SCI_MODE, oldMode | SM_CANCEL); + new_state(VS1053_TRACK::VS_TRACK_STATE::tsCancelAwait); +} +bool VS1053_SINK::is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state) { + if (read_register(SCI_MODE) & SM_CANCEL) + sdi_send_fillers(2); + else { + sdi_send_fillers(endFillBytes); + new_state(VS1053_TRACK::VS_TRACK_STATE::tsStopped); + return true; + } + return false; +} +void VS1053_SINK::delete_track(void) { + if (this->future_track) { + this->track = this->future_track; + this->future_track = nullptr; + this->start_track(this->track, 1024); + } else { + this->remove_track(this->track); + } +} +size_t VS1053_SINK::get_track_info(size_t pos) { +#ifdef CONFIG_REPORT_ON_SCREEN + uint16_t sampleRate; + uint32_t byteRate; +#endif + get_audio_format(&audioFormat, &endFillBytes); + + /* It is important to collect endFillByte while still in normal + playback. If we need to later cancel playback or run into any + trouble with e.g. a broken file, we need to be able to repeatedly + send this byte until the decoder has been able to exit. */ + + endFillByte = read_mem(PAR_END_FILL_BYTE); +#ifdef CONFIG_REPORT_ON_SCREEN + + sampleRate = read_register(SCI_AUDATA); + byteRate = read_mem(PAR_BYTERATE); + /* FLAC: byteRate = bitRate / 32 + Others: byteRate = bitRate / 8 + Here we compensate for that difference. */ + if (audioFormat == afFlac) + byteRate *= 4; + + ESP_LOGI(TAG, + "%dKiB " + "%1ds %1.1f" + "kb/s %dHz %s %s", + pos / (1024 / VS1053_PACKET_SIZE), read_register(SCI_DECODE_TIME), + byteRate * (8.0 / 1000.0), sampleRate & 0xFFFE, + (sampleRate & 1) ? "stereo" : "mono", afName[audioFormat]); +#endif + return (audioFormat == afMidi || audioFormat == afUnknown) + ? REPORT_INTERVAL_MIDI + : REPORT_INTERVAL; +} + +size_t VS1053_TRACK::feed_data(uint8_t* data, size_t len, + bool STORAGE_VOLATILE) { + if (!len || xStreamBufferSpacesAvailable(this->dataBuffer) < len) + return 0; + if (STORAGE_VOLATILE) + if (this->header_size) + xStreamBufferReset(this->dataBuffer); + size_t res = + xStreamBufferSend(this->dataBuffer, (void*)data, len, pdMS_TO_TICKS(100)); + return res; +} +size_t VS1053_SINK::spaces_available(size_t track_id) { + if (this->track == nullptr) + return 0; + if (this->track->track_id == track_id) + return xStreamBufferSpacesAvailable(this->track->dataBuffer); + else + return xStreamBufferSpacesAvailable(this->future_track->dataBuffer); +} +void VS1053_TRACK::empty_feed() { + if (this->dataBuffer != NULL) + xStreamBufferReset(this->dataBuffer); +} +void VS1053_SINK::new_state(VS1053_TRACK::VS_TRACK_STATE state) { + this->track->track_state = state; + if (state_callback != NULL) { + state_callback(state); + } +} + +void VS1053_TRACK::run_track(size_t FILL_BUFFER_BEFORE_PLAYBACK) { + uint32_t pos = 0; + long nextReportPos = 0; // File pointer where to next collect/report + size_t itemSize = 0; + uint8_t* item = (uint8_t*)malloc(VS1053_PACKET_SIZE); + + if (FILL_BUFFER_BEFORE_PLAYBACK < + xStreamBufferBytesAvailable(this->dataBuffer)) + vTaskDelay(10 / portTICK_PERIOD_MS); + while (this->track_state != tsStopped) { + if (this->audioSink->command_callbacks.size()) { + this->audioSink->command_callbacks[0](track_id); + this->audioSink->command_callbacks.pop_front(); + } + switch (this->track_state) { + case tsPlaybackStart: + this->audioSink->new_state(tsPlayback); + goto tsPlaybackSeekable; + case tsPlayback: + if (this->audioSink->is_seekable(&this->track_state)) + if (!this->header_size) + this->header_size = VS1053_PACKET_SIZE * pos; + goto tsPlaybackSeekable; + case tsPlaybackSeekable: + + tsPlaybackSeekable: + itemSize = xStreamBufferReceive(this->dataBuffer, (void*)item, + VS1053_PACKET_SIZE, 10); + if (itemSize) { + this->audioSink->sdi_send_buffer(item, itemSize); + pos++; + } + break; + case tsSoftCancel: + if (xStreamBufferBytesAvailable(this->dataBuffer)) + goto tsPlaybackSeekable; + this->audioSink->new_state(tsCancel); + [[fallthrough]]; + case tsCancel: + free(item); + this->empty_feed(); + this->audioSink->cancel_track(&this->track_state); + [[fallthrough]]; + case tsCancelAwait: + if (this->audioSink->is_cancelled(&this->track_state)) {} + break; + default: + vTaskDelay(20 / portTICK_PERIOD_MS); + break; + } + if (pos >= nextReportPos) { + nextReportPos += this->audioSink->get_track_info(pos); + } + } + this->track_handle = NULL; + this->audioSink->delete_track(); + vTaskDelete(NULL); +} +// FEED FUNCTIONS + +size_t VS1053_SINK::data_request() { + return xStreamBufferSpacesAvailable(track->dataBuffer); +} + +void VS1053_SINK::stop_feed() { + if (this->future_track != nullptr) + this->future_track.reset(); // + if ((uint8_t)this->track->track_state < 3) + new_state(VS1053_TRACK::VS_TRACK_STATE::tsCancel); +} +void VS1053_SINK::soft_stop_feed() { + if (this->future_track != nullptr) + this->future_track.reset(); // + if ((uint8_t)this->track->track_state < 3) + new_state(VS1053_TRACK::VS_TRACK_STATE::tsSoftCancel); +} + +// COMMAND FUCNTIONS +/* The command pipeline recieves command in a structure of uint8_t[]. + */ +uint8_t VS1053_SINK::feed_command(command_callback commandCallback) { + if (this->track) { + command_callbacks.push_back(commandCallback); + } else + commandCallback(0); + return 0; +} +void VS1053_SINK::set_volume_logarithmic(size_t vol) { + float value = log10((float)vol / 0xFFFF * 100 + 1); + if (value >= 2.0) + value = 2.0; + size_t logVolume = value / 2 * 100; // *100 + + this->set_volume(logVolume); +} +/** + * set_volume accepts values from 0 to 100 + */ +void VS1053_SINK::set_volume(uint8_t vol) { + vol = vol > 100 ? 0 : 100 - vol; + uint16_t value = (vol << 8) | vol; + write_register(SCI_VOL, value); // Volume left and right +} + +void VS1053_SINK::set_volume(uint8_t left, uint8_t right) { + left = left > 100 ? 0 : 100 - left; + right = right > 100 ? 0 : 100 - right; + uint16_t value = (left << 8) | right; + write_register(SCI_VOL, value); // Volume left and right +} + +void VS1053_SINK::get_audio_format(Audio_Format* audioFormat, + size_t* endFillBytes) { + uint16_t h1 = read_register(SCI_HDAT1); + *audioFormat = afUnknown; + switch (h1) { + case 0x7665: + *audioFormat = afRiff; + goto sdi_end_fill_bytes; + case 0x4444: + *audioFormat = afDsd64; + goto sdi_end_fill_bytes_flac; + case 0x4c41: + *audioFormat = afLatm; + // set OUT_OF_WAV bit of SCI_MODE; + goto sdi_end_fill_bytes_flac; + case 0x4154: + *audioFormat = afAacAdts; + goto sdi_end_fill_bytes; + case 0x4144: + *audioFormat = afAacAdif; + goto sdi_end_fill_bytes; + case 0x574d: + *audioFormat = afWma; + goto sdi_end_fill_bytes; + case 0x4f67: + *audioFormat = afOggVorbis; + goto sdi_end_fill_bytes; + case 0x664c: + *audioFormat = afFlac; + goto sdi_end_fill_bytes_flac; + case 0x4d34: + *audioFormat = afAacMp4; + goto sdi_end_fill_bytes; + case 0x4d54: + *audioFormat = afMidi; + goto sdi_end_fill_bytes; + default: + h1 &= 0xffe6; + if (h1 == 0xffe2) + *audioFormat = afMp2; + else if (h1 == 0xffe4) + *audioFormat = afMp2; + else if (h1 == 0xffe6) + *audioFormat = afMp1; + if (*audioFormat == afUnknown) + goto sdi_end_fill_bytes_flac; + sdi_end_fill_bytes: + *endFillBytes = SDI_END_FILL_BYTES; + break; + sdi_end_fill_bytes_flac: + *endFillBytes = SDI_END_FILL_BYTES_FLAC; + break; + } +} + +// SPI COMMUNICATION TEST +const uint16_t chipNumber[16] = {1001, 1011, 1011, 1003, 1053, 1033, 1063, 1103, + 0, 0, 0, 0, 0, 0, 0, 0}; + +esp_err_t VS1053_SINK::test_comm(const char* header) { + // Test the communication with the VS1053 module. The result wille be returned. + // If DREQ is low, there is problably no VS1053 connected. Pull the line HIGH + // in order to prevent an endless loop waiting for this signal. The rest of the + // software will still work, but readbacks from VS1053 will fail. + + write_register(SCI_AICTRL1, 0xABAD); + write_register(SCI_AICTRL2, 0x7E57); + if (read_register(SCI_AICTRL1) != 0xABAD || + read_register(SCI_AICTRL2) != 0x7E57) { + ESP_LOGI(TAG, "There is something wrong with VS10xx SCI registers\n"); + return ESP_ERR_INVALID_RESPONSE; + } + write_register(SCI_AICTRL1, 0); + write_register(SCI_AICTRL2, 0); + uint16_t ssVer = ((read_register(SCI_STATUS) >> 4) & 15); + if (chipNumber[ssVer]) { + ESP_LOGI(TAG, "Chip is VS%d\n", chipNumber[ssVer]); + if (chipNumber[ssVer] != 1053) { + ESP_LOGI(TAG, "Incorrect chip\n"); + return ESP_ERR_NOT_SUPPORTED; + } + } else { + ESP_LOGI(TAG, "Unknown VS10xx SCI_MODE field SS_VER = %d\n", ssVer); + return ESP_ERR_NOT_FOUND; + } + + return ESP_OK; +} + +// PLUGIN FUNCTION + +void VS1053_SINK::load_user_code(const unsigned short* plugin, + uint16_t sizeofpatch) { + ESP_LOGI(TAG, "Loading patch"); + await_data_request(); + int i = 0; + while (i < sizeofpatch) { + unsigned short addr, n, val; + addr = plugin[i++]; + n = plugin[i++]; + if (n & 0x8000U) { /* RLE run, replicate n samples */ + n &= 0x7FFF; + val = plugin[i++]; + while (n--) { + write_register(addr, val); + } + } else { /* Copy run, copy n samples */ + while (n--) { + val = plugin[i++]; + write_register(addr, val); + } + } + } +} + +// GPIO FUNCTIONS + +void VS1053_SINK::await_data_request() { + while (!gpio_get_level((gpio_num_t)CONFIG_GPIO_VS_DREQ)) + vTaskDelay(1); +} +// WRITE/READ FUNCTIONS + +uint16_t VS1053_SINK::read_register(uint8_t _reg) { + spi_transaction_t SPITransaction; + esp_err_t ret; + await_data_request(); // Wait for DREQ to be HIGH + memset(&SPITransaction, 0, sizeof(spi_transaction_t)); + SPITransaction.length = 16; + SPITransaction.flags |= SPI_TRANS_USE_RXDATA; + SPITransaction.cmd = VS_READ_COMMAND; + SPITransaction.addr = _reg; + if (SPI_semaphore != NULL) + while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) + vTaskDelay(1); + ret = spi_device_transmit(this->SPIHandleLow, &SPITransaction); + assert(ret == ESP_OK); + uint16_t result = (((SPITransaction.rx_data[0] & 0xFF) << 8) | + ((SPITransaction.rx_data[1]) & 0xFF)); + await_data_request(); // Wait for DREQ to be HIGH again + if (SPI_semaphore != NULL) + xSemaphoreGive(*SPI_semaphore); + return result; +} + +bool VS1053_SINK::write_register(uint8_t _reg, uint16_t _value) { + spi_transaction_t SPITransaction; + esp_err_t ret; + + await_data_request(); // Wait for DREQ to be HIGH + memset(&SPITransaction, 0, sizeof(spi_transaction_t)); + SPITransaction.flags |= SPI_TRANS_USE_TXDATA; + SPITransaction.cmd = VS_WRITE_COMMAND; + SPITransaction.addr = _reg; + SPITransaction.tx_data[0] = (_value >> 8) & 0xFF; + SPITransaction.tx_data[1] = (_value & 0xFF); + SPITransaction.length = 16; + if (SPI_semaphore != NULL) + while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) + vTaskDelay(1); + ret = spi_device_transmit(this->SPIHandleLow, &SPITransaction); + assert(ret == ESP_OK); + await_data_request(); // Wait for DREQ to be HIGH again + if (SPI_semaphore != NULL) + xSemaphoreGive(*SPI_semaphore); + return true; +} + +uint32_t VS1053_SINK::read_mem32(uint16_t addr) { + uint16_t result; + + write_register(SCI_WRAMADDR, addr); + // Note: transfer16 does not seem to work + result = read_register(SCI_WRAM); + return result | ((uint32_t)read_register(SCI_WRAM) << 16); +} + +uint32_t VS1053_SINK::read_mem32_counter(uint16_t addr) { + uint16_t msbV1, lsb, msbV2; + uint32_t res; + write_register(SCI_WRAMADDR, addr); + msbV1 = read_register(SCI_WRAM); + write_register(SCI_WRAMADDR, addr); + lsb = read_register(SCI_WRAM); + msbV2 = read_register(SCI_WRAM); + if (lsb < 0x8000U) { + msbV1 = msbV2; + } + res = ((uint32_t)msbV1 << 16) | lsb; + + return res; +} + +uint16_t VS1053_SINK::read_mem(uint16_t addr) { + write_register(SCI_WRAMADDR, addr); + return read_register(SCI_WRAM); +} + +/* + Write 16-bit value to given VS10xx address +*/ +void VS1053_SINK::write_mem(uint16_t addr, uint16_t data) { + write_register(SCI_WRAMADDR, addr); + write_register(SCI_WRAM, data); +} + +/* + Write 32-bit value to given VS10xx address +*/ +void VS1053_SINK::write_mem32(uint16_t addr, uint32_t data) { + write_register(SCI_WRAMADDR, addr); + write_register(SCI_WRAM, (uint16_t)data); + write_register(SCI_WRAM, (uint16_t)(data >> 16)); +} +bool VS1053_SINK::sdi_send_buffer(uint8_t* data, size_t len) { + size_t chunk_length; // Length of chunk 32 byte or shorter + spi_transaction_t SPITransaction; + esp_err_t ret; + if (SPI_semaphore != NULL) + while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) + vTaskDelay(1); + while (len) // More to do? + { + await_data_request(); // Wait for space available + chunk_length = len; + if (len > VS1053_CHUNK_SIZE) { + chunk_length = VS1053_CHUNK_SIZE; + } + len -= chunk_length; + memset(&SPITransaction, 0, sizeof(spi_transaction_t)); + SPITransaction.length = chunk_length * 8; + SPITransaction.tx_buffer = data; + // while(spi_device_acquire_bus(this->SPIHandleFast,portMAX_DELAY)!=ESP_OK){}; + ret = spi_device_transmit(this->SPIHandleFast, &SPITransaction); + // spi_device_release_bus(this->SPIHandleFast); + assert(ret == ESP_OK); + data += chunk_length; + } + if (SPI_semaphore != NULL) + xSemaphoreGive(*SPI_semaphore); + + return true; +} + +bool VS1053_SINK::sdi_send_fillers(size_t len) { + size_t chunk_length; // Length of chunk 32 byte or shorter + spi_transaction_t SPITransaction; + esp_err_t ret; + uint8_t data[VS1053_CHUNK_SIZE]; + for (int i = 0; i < VS1053_CHUNK_SIZE; i++) + data[i] = this->endFillByte; + if (SPI_semaphore != NULL) + while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) + vTaskDelay(1); + while (len) // More to do? + { + await_data_request(); // Wait for space available + chunk_length = len; + if (len > VS1053_CHUNK_SIZE) { + chunk_length = VS1053_CHUNK_SIZE; + } + len -= chunk_length; + + memset(&SPITransaction, 0, sizeof(spi_transaction_t)); + SPITransaction.length = chunk_length * 8; + SPITransaction.tx_buffer = data; + spi_device_acquire_bus(this->SPIHandleFast, portMAX_DELAY); + ret = spi_device_transmit(this->SPIHandleFast, &SPITransaction); + spi_device_release_bus(this->SPIHandleFast); + assert(ret == ESP_OK); + } + if (SPI_semaphore != NULL) + xSemaphoreGive(*SPI_semaphore); + return true; +} + +void VS1053_SINK::wram_write(uint16_t address, uint16_t data) { + write_register(SCI_WRAMADDR, address); + write_register(SCI_WRAM, data); +} + +uint16_t VS1053_SINK::wram_read(uint16_t address) { + write_register(SCI_WRAMADDR, address); // Start reading from WRAM + return read_register(SCI_WRAM); // Read back result +} diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp index 4fdc2330..8a601ef5 100644 --- a/targets/esp32/main/EspPlayer.cpp +++ b/targets/esp32/main/EspPlayer.cpp @@ -26,17 +26,20 @@ EspPlayer::EspPlayer(std::unique_ptr sink, this->circularBuffer = std::make_shared(1024 * 128); - this->handler->getTrackPlayer()->setDataCallback( - [this](uint8_t* data, size_t bytes, size_t trackId) { - this->feedData(data, bytes, trackId); - return bytes; - }); + this->handler->getTrackPlayer()->setDataCallback([this](uint8_t* data, + size_t bytes, +#ifdef CONFIG_BELL_NOCODEC + bool STORAGE_VOLATILE, +#endif + size_t trackId) { + this->feedData(data, bytes, trackId); + return bytes; + }); this->isPaused = false; this->handler->setEventHandler( [this](std::unique_ptr event) { - switch (event->eventType) { case cspot::SpircHandler::EventType::PLAY_PAUSE: if (std::get(event->data)) { @@ -77,16 +80,19 @@ EspPlayer::EspPlayer(std::unique_ptr sink, void EspPlayer::feedData(uint8_t* data, size_t len, size_t trackId) { size_t toWrite = len; - while (toWrite > 0) { - this->current_hash = trackId; - size_t written = - this->circularBuffer->write(data + (len - toWrite), toWrite); - if (written == 0) { - BELL_SLEEP_MS(10); - } + if (!len) + this->handler->notifyAudioReachedPlaybackEnd(); + else + while (toWrite > 0) { + this->current_hash = trackId; + size_t written = + this->circularBuffer->write(data + (len - toWrite), toWrite); + if (written == 0) { + BELL_SLEEP_MS(10); + } - toWrite -= written; - } + toWrite -= written; + } } void EspPlayer::runTask() { diff --git a/targets/esp32/main/Kconfig.projbuild b/targets/esp32/main/Kconfig.projbuild index 64e164cb..54d700a6 100644 --- a/targets/esp32/main/Kconfig.projbuild +++ b/targets/esp32/main/Kconfig.projbuild @@ -8,10 +8,12 @@ menu "CSPOT Configuration" choice CSPOT_SINK prompt "Sink Device" - default CSPOT_SINK_AC101 + default CSPOT_SINK_INTERNAL help Select audio sink device + config BELL_NOCODEC + bool "VS1053" config CSPOT_SINK_INTERNAL bool "Built-in DAC" config CSPOT_SINK_AC101 @@ -28,17 +30,30 @@ menu "CSPOT Configuration" choice CSPOT_QUALITY prompt "Audio Quality (BPS)" - default CSPOT_QUALITY_320 + default VORBIS_160 help Audio quality (not used currently) - config CSPOT_QUALITY_320 + config VORBIS_320 bool "320 bps" - config CSPOT_QUALITY_160 + config VORBIS_160 bool "160 bps" - config CSPOT_QUALITY_96 + config VORBIS_96 bool "96 bps" endchoice + config CSPOT_AUDIO_FORMAT + int + default 0 if VORBIS_96 + default 1 if VORBIS_160 + default 2 if VORBIS_320 + default 3 if MP3_256 + default 4 if MP3_320 + default 5 if MP3_160 + default 6 if MP3_96 + default 7 if MP3_160_ENC + default 8 if AAC_24 + default 9 if AAC_48 + choice CSPOT_STATUS_LED_TYPE prompt "Status LED type" default CSPOT_STATUS_LED_TYPE_NONE diff --git a/targets/esp32/main/VSPlayer.cpp b/targets/esp32/main/VSPlayer.cpp new file mode 100644 index 00000000..f8836d49 --- /dev/null +++ b/targets/esp32/main/VSPlayer.cpp @@ -0,0 +1,100 @@ +#include "VSPlayer.h" + +#include // for uint8_t +#include // for operator<<, basic_ostream, endl, cout +#include // for shared_ptr, make_shared, make_unique +#include // for scoped_lock +#include // for get + +#include "TrackPlayer.h" // for TrackPlayer + +VSPlayer::VSPlayer(std::shared_ptr handler, + std::shared_ptr vsSink) { + this->handler = handler; + this->vsSink = vsSink; + this->vsSink->state_callback = [this](uint8_t state) { + this->state_callback(state); + }; + + this->handler->getTrackPlayer()->setDataCallback( + [this](uint8_t* data, size_t bytes, size_t trackId, + bool STORAGE_VOLATILE) { + if (!this->track) { + this->track = std::make_shared(this->vsSink.get(), + trackId, 4098 * 16); + this->vsSink->new_track(this->track); + } + if (trackId != this->track->track_id) { + this->vsSink->soft_stop_feed(); + this->track = std::make_shared(this->vsSink.get(), + trackId, 4098 * 16); + this->vsSink->new_track(this->track); + } + return this->track->feed_data(data, bytes, STORAGE_VOLATILE); + }, + [this](size_t trackId) { return this->vsSink->track_seekable(trackId); }, + [this](size_t trackId) { + return this->vsSink->spaces_available(trackId); + }); + + this->isPaused = false; + + this->handler->setEventHandler( + [this](std::unique_ptr event) { + switch (event->eventType) { + case cspot::SpircHandler::EventType::PLAY_PAUSE: + if (std::get(event->data)) { + if (this->track) + this->vsSink->new_state(VS1053_TRACK::tsPlaybackPaused); + } else { + if (this->track) + this->vsSink->new_state(VS1053_TRACK::tsPlaybackSeekable); + } + break; + case cspot::SpircHandler::EventType::DISC: + this->track = nullptr; + this->vsSink->stop_feed(); + break; + case cspot::SpircHandler::EventType::FLUSH: + this->track->empty_feed(); + break; + case cspot::SpircHandler::EventType::SEEK: + break; + case cspot::SpircHandler::EventType::PLAYBACK_START: + this->isPaused = true; + this->playlistEnd = false; + break; + case cspot::SpircHandler::EventType::DEPLETED: + this->playlistEnd = true; + this->track = nullptr; + this->vsSink->stop_feed(); + break; + case cspot::SpircHandler::EventType::VOLUME: { + this->volume = std::get(event->data); + this->vsSink->feed_command([this](uint8_t) { + this->vsSink->set_volume_logarithmic(this->volume); + }); + break; + } + default: + break; + } + }); +} + +void VSPlayer::state_callback(uint8_t state) { + if (state == 1) { + this->handler->notifyAudioReachedPlayback(); + } + if (state == 7) { + if (this->playlistEnd) + this->handler->notifyAudioEnded(); + else + this->handler->notifyAudioReachedPlaybackEnd(); + } +} + +void VSPlayer::disconnect() { + isRunning = false; + std::scoped_lock lock(runningMutex); +} diff --git a/targets/esp32/main/VSPlayer.h b/targets/esp32/main/VSPlayer.h new file mode 100644 index 00000000..c8db9a36 --- /dev/null +++ b/targets/esp32/main/VSPlayer.h @@ -0,0 +1,36 @@ +#pragma once + +#include // for size_t +#include // for uint8_t +#include // for atomic +#include // for shared_ptr, unique_ptr +#include // for mutex +#include // for string + +#include "SpircHandler.h" // for SpircHandler, SpircHandler::EventType +#include "VS1053.h" +namespace cspot { +class SpircHandler; +} // namespace cspot + +class VSPlayer { + public: + VSPlayer(std::shared_ptr spircHandler, + std::shared_ptr vsSink = NULL); + void disconnect(); + size_t volume = 0; + + private: + std::string currentTrackId; + std::shared_ptr vsSink; + std::shared_ptr handler; + std::shared_ptr track = nullptr; + VS1053_TRACK* futureTrack = NULL; + void state_callback(uint8_t state); + + std::atomic pauseRequested = false; + std::atomic isPaused = true; + std::atomic isRunning = true; + std::mutex runningMutex; + std::atomic playlistEnd = false; +}; diff --git a/targets/esp32/main/VSinit.h b/targets/esp32/main/VSinit.h new file mode 100644 index 00000000..cf438f18 --- /dev/null +++ b/targets/esp32/main/VSinit.h @@ -0,0 +1,30 @@ + +#include +#include +#include "esp_log.h" + +#include "VS1053.h" + +#define MOUNT_POINT "/sdcard" + +SemaphoreHandle_t SPI_semaphore; +#define TAG "INIT" +void initAudioSink(std::shared_ptr VS1053) { + esp_err_t ret; + // SPI SETUP + spi_bus_config_t bus_cfg; + memset(&bus_cfg, 0, sizeof(spi_bus_config_t)); + bus_cfg.sclk_io_num = CONFIG_GPIO_CLK; + bus_cfg.mosi_io_num = CONFIG_GPIO_MOSI; + bus_cfg.miso_io_num = CONFIG_GPIO_MISO; + bus_cfg.quadwp_io_num = -1; + bus_cfg.quadhd_io_num = -1; + ESP_LOGI("vsInit", "spi config done"); + ret = spi_bus_initialize(HSPI_HOST, &bus_cfg, 1); + assert(ret == ESP_OK); + SPI_semaphore = xSemaphoreCreateMutex(); + + // VS1053 SETUP + VS1053->init(HSPI_HOST, &SPI_semaphore); + VS1053->write_register(SCI_VOL, 10 | 10 << 8); +} \ No newline at end of file diff --git a/targets/esp32/main/main.cpp b/targets/esp32/main/main.cpp index d0ba2ba5..c95293bb 100644 --- a/targets/esp32/main/main.cpp +++ b/targets/esp32/main/main.cpp @@ -7,7 +7,7 @@ #include #include #include "BellHTTPServer.h" -#include "BellLogger.h" // for setDefaultLogger, AbstractLogger +#include "BellLogger.h" // for setDefaultLogger, AbstractLogger #include "BellTask.h" #include "civetweb.h" #include "esp_event.h" @@ -22,8 +22,6 @@ #include "protocol_examples_common.h" #include "sdkconfig.h" -#include "EspPlayer.h" - #include #include #include @@ -37,6 +35,11 @@ #define DEVICE_NAME CONFIG_CSPOT_DEVICE_NAME +#ifdef CONFIG_BELL_NOCODEC +#include "VSPlayer.h" +#include "VSinit.h" +#else +#include "EspPlayer.h" #ifdef CONFIG_CSPOT_SINK_INTERNAL #include #endif @@ -55,18 +58,16 @@ #ifdef CONFIG_CSPOT_SINK_TAS5711 #include #endif - -static const char* TAG = "cspot"; - +#endif extern "C" { - void app_main(void); +void app_main(void); } class ZeroconfAuthenticator { -public: - ZeroconfAuthenticator() {}; - ~ZeroconfAuthenticator() {}; + public: + ZeroconfAuthenticator(){}; + ~ZeroconfAuthenticator(){}; // Authenticator state int serverPort = 7864; @@ -83,14 +84,12 @@ class ZeroconfAuthenticator { server->registerGet("/spotify_info", [this](struct mg_connection* conn) { return this->server->makeJsonResponse(this->blob->buildZeroconfInfo()); - }); - + }); server->registerGet("/close", [this](struct mg_connection* conn) { this->onClose(); return this->server->makeEmptyResponse(); - }); - + }); server->registerPost("/spotify_info", [this](struct mg_connection* conn) { nlohmann::json obj; @@ -124,48 +123,57 @@ class ZeroconfAuthenticator { } return server->makeJsonResponse(obj.dump()); - }); - + }); // Register mdns service, for spotify to find us bell::MDNSService::registerService( - blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort, - { {"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"} }); + blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort, + {{"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"}}); std::cout << "Waiting for spotify app to connect..." << std::endl; } }; class CSpotTask : public bell::Task { -private: + private: std::unique_ptr handler; +#ifndef CONFIG_BELL_NOCODEC std::unique_ptr audioSink; +#endif -public: - CSpotTask() : bell::Task("cspot", 8 * 1024, 0, 0) { startTask(); } + public: + CSpotTask() : bell::Task("cspot", 8 * 1024, 0, 0) { + startTask(); + } void runTask() { mdns_init(); mdns_hostname_set("cspot"); +#ifdef CONFIG_BELL_NOCODEC + std::shared_ptr audioSink; + audioSink = std::make_shared(); + initAudioSink(audioSink); +#else #ifdef CONFIG_CSPOT_SINK_INTERNAL -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_AC101 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_ES8388 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_ES9018 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_PCM5102 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif #ifdef CONFIG_CSPOT_SINK_TAS5711 -auto audioSink = std::make_unique(); + auto audioSink = std::make_unique(); #endif audioSink->setParams(44100, 2, 16); audioSink->volumeChanged(160); +#endif auto loggedInSemaphore = std::make_shared(1); @@ -174,18 +182,19 @@ auto audioSink = std::make_unique(); zeroconfServer->onClose = [&isRunning]() { isRunning = false; - }; + }; auto loginBlob = std::make_shared(DEVICE_NAME); #ifdef CONFIG_CSPOT_LOGIN_PASS - loginBlob->loadUserPass(CONFIG_CSPOT_LOGIN_USERNAME, CONFIG_CSPOT_LOGIN_PASSWORD); + loginBlob->loadUserPass(CONFIG_CSPOT_LOGIN_USERNAME, + CONFIG_CSPOT_LOGIN_PASSWORD); loggedInSemaphore->give(); #else zeroconfServer->blob = loginBlob; zeroconfServer->onAuthSuccess = [loggedInSemaphore]() { loggedInSemaphore->give(); - }; + }; zeroconfServer->registerHandlers(); #endif loggedInSemaphore->wait(); @@ -202,8 +211,13 @@ auto audioSink = std::make_unique(); ctx->session->startTask(); // Create a player, pass the handler - auto player = std::make_shared(std::move(audioSink), std::move(handler)); - +#ifndef CONFIG_BELL_NOCODEC + auto player = + std::make_shared(std::move(audioSink), std::move(handler)); +#else + auto player = + std::make_shared(std::move(handler), std::move(audioSink)); +#endif // If we wanted to handle multiple devices, we would halt this loop // when a new zeroconf login is requested, and reinitialize the session while (isRunning) { @@ -213,27 +227,24 @@ auto audioSink = std::make_unique(); // Never happens, but required for above case handler->disconnect(); player->disconnect(); - } } }; void init_spiffs() { - esp_vfs_spiffs_conf_t conf = { .base_path = "/spiffs", + esp_vfs_spiffs_conf_t conf = {.base_path = "/spiffs", .partition_label = NULL, .max_files = 5, - .format_if_mount_failed = true }; + .format_if_mount_failed = true}; esp_err_t ret = esp_vfs_spiffs_register(&conf); if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount or format filesystem"); - } - else if (ret == ESP_ERR_NOT_FOUND) { + } else if (ret == ESP_ERR_NOT_FOUND) { ESP_LOGE(TAG, "Failed to find SPIFFS partition"); - } - else { + } else { ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); } return; @@ -243,9 +254,8 @@ void init_spiffs() { ret = esp_spiffs_info(conf.partition_label, &total, &used); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", - esp_err_to_name(ret)); - } - else { + esp_err_to_name(ret)); + } else { ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); } } @@ -256,7 +266,7 @@ void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || - ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } From d9b8373c226f5c85aed128d79d0d22a61e88a2d8 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Wed, 17 Jul 2024 00:10:59 +0200 Subject: [PATCH 24/41] adjusted some mistakes --- targets/esp32/main/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/esp32/main/main.cpp b/targets/esp32/main/main.cpp index c2b9c053..3fbd9647 100644 --- a/targets/esp32/main/main.cpp +++ b/targets/esp32/main/main.cpp @@ -257,7 +257,7 @@ void init_spiffs() { ESP_LOGE("SPIFFS", "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret)); } else { - CSPOT_LOG(info, "Partition size: total: %d, used: %d", total, used); + ESP_LOGE("SPIFFS", "Partition size: total: %d, used: %d", total, used); } } From 879197a5cbc12d4db066b666c743eb606a7805c2 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Wed, 17 Jul 2024 11:54:14 +0200 Subject: [PATCH 25/41] repeat is working - chnaged vs1053 structure to a constant stream - added sd-card support --- cspot/include/TrackQueue.h | 1 - cspot/src/SpircHandler.cpp | 1 - cspot/src/TrackQueue.cpp | 6 - .../esp32/components/VS1053/include/VS1053.h | 30 +-- .../esp32/components/VS1053/src/VS1053.cpp | 242 +++++++++--------- targets/esp32/main/VSPlayer.cpp | 13 +- targets/esp32/main/VSinit.h | 83 ++++++ 7 files changed, 223 insertions(+), 153 deletions(-) diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 2686077c..19a7ba8e 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -107,7 +107,6 @@ class TrackQueue : public bell::Task { void runTask() override; void stopTask(); - void prepareRepeat(); void shuffle_tracks(bool shuffleTracks); void update_ghost_tracks(int16_t offset = 0); bool hasTracks(); diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index 894809e0..aabc3d05 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -240,7 +240,6 @@ void SpircHandler::handleFrame(std::vector& data) { CSPOT_LOG(debug, "Got repeat frame"); playbackState->innerFrame.state.repeat = playbackState->remoteFrame.state.repeat; - trackQueue->prepareRepeat(); this->notify(); break; } diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 5a52b1c8..1937a1a7 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -711,12 +711,6 @@ bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { return true; } -void TrackQueue::prepareRepeat() { - if (currentTracksIndex > 0) - preloadedTracks.clear(); - queueNextTrack(0); -} - bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { bool skipped = true; std::scoped_lock lock(tracksMutex); diff --git a/targets/esp32/components/VS1053/include/VS1053.h b/targets/esp32/components/VS1053/include/VS1053.h index 35bcbc71..b22eea9d 100644 --- a/targets/esp32/components/VS1053/include/VS1053.h +++ b/targets/esp32/components/VS1053/include/VS1053.h @@ -55,8 +55,7 @@ class VS1053_SINK; class VS1053_TRACK { public: - VS1053_TRACK(VS1053_SINK* vsSink, size_t track_id = 0, - size_t buffer_size = BUF_SIZE_FEED); + VS1053_TRACK(size_t track_id = 0, size_t buffer_size = BUF_SIZE_FEED); ~VS1053_TRACK(); /** * feed data to dataBuffer @@ -68,8 +67,6 @@ class VS1053_TRACK { size_t feed_data(uint8_t* data, size_t len, bool STORAGE_VOLATILE = 0); void empty_feed(); void run_track(size_t FILL_BUFFER_BEFORE_PLAYSTART = 0); - VS1053_SINK* audioSink; - TaskHandle_t track_handle = NULL; enum VS_TRACK_STATE { tsPlaybackStart = 0, tsPlayback = 1, @@ -79,7 +76,7 @@ class VS1053_TRACK { tsCancel = 5, tsCancelAwait = 6, tsStopped = 7 - } track_state = tsStopped; + } state = tsPlaybackStart; size_t header_size = 0; size_t track_id; StreamBufferHandle_t dataBuffer; @@ -168,6 +165,9 @@ class VS1053_SINK { * @return `ESP_ERR_NOT_FOUND` if the chipNumber is not recognized. */ esp_err_t test_comm(const char* header); + + void run_feed(size_t); + std::function state_callback = nullptr; enum Audio_Format { afUnknown, @@ -203,37 +203,37 @@ class VS1053_SINK { this->track = nullptr; }; void start_track(std::shared_ptr, size_t); - bool is_seekable(VS1053_TRACK::VS_TRACK_STATE* state); size_t track_seekable(size_t); void cancel_track(VS1053_TRACK::VS_TRACK_STATE* state); - bool is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state); - size_t get_track_info(size_t); - void new_state(VS1053_TRACK::VS_TRACK_STATE); + bool is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state, uint8_t, size_t); + size_t get_track_info(size_t, uint8_t&, size_t&); + void new_state(VS1053_TRACK::VS_TRACK_STATE&, VS1053_TRACK::VS_TRACK_STATE); void new_track(std::shared_ptr track); - VS1053_TRACK newTrack(size_t track_id, size_t buffer_size = BUF_SIZE_FEED); - void delete_track(void); + void delete_all_tracks(void); size_t spaces_available(size_t); std::shared_ptr track = nullptr; std::shared_ptr future_track = nullptr; size_t command_pointer = 0, command_reader = 0; std::deque command_callbacks; + std::deque> tracks; + bool isRunning = false; private: spi_device_handle_t SPIHandleLow; spi_device_handle_t SPIHandleFast; - uint8_t curvol; // Current volume setting 0..100% - uint8_t endFillByte = 0; // Byte to send when stopping song - size_t endFillBytes = SDI_END_FILL_BYTES; + uint8_t curvol; // Current volume setting 0..100% int playMode = 0; uint8_t chipVersion; // Version of hardware SemaphoreHandle_t* SPI_semaphore = NULL; TaskHandle_t VS_TASK; void await_data_request(); - bool sdi_send_fillers(size_t len); + bool is_seekable(VS1053_TRACK::VS_TRACK_STATE* state); + bool sdi_send_fillers(uint8_t, size_t len); void wram_write(uint16_t address, uint16_t data); uint16_t wram_read(uint16_t address); size_t (*data_callback)(uint8_t*, size_t) = NULL; + TaskHandle_t task_handle = NULL; }; #endif \ No newline at end of file diff --git a/targets/esp32/components/VS1053/src/VS1053.cpp b/targets/esp32/components/VS1053/src/VS1053.cpp index 97b0a44f..34e35e7f 100644 --- a/targets/esp32/components/VS1053/src/VS1053.cpp +++ b/targets/esp32/components/VS1053/src/VS1053.cpp @@ -4,8 +4,8 @@ #include "esp_log.h" static const char* TAG = "VS_SINK"; -void vs_feed(void* track) { - ((VS1053_TRACK*)track)->run_track(1024); +void vs_feed(void* sink) { + ((VS1053_SINK*)sink)->run_feed(1024); } unsigned char pcm_wav_header[44] = { @@ -40,6 +40,7 @@ VS1053_SINK::VS1053_SINK() { // PIN CONFIG // DREQ ESP_LOGI(TAG, "VS1053_DREQ=%d", CONFIG_GPIO_VS_DREQ); + isRunning = true; gpio_config_t gpio_conf; gpio_conf.mode = GPIO_MODE_INPUT; gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE; @@ -120,89 +121,68 @@ esp_err_t VS1053_SINK::init(spi_host_device_t SPI, //load_user_code(PLUGIN, PLUGIN_SIZE); #endif vTaskDelay(100 / portTICK_PERIOD_MS); + xTaskCreate(vs_feed, "track_feed", 4098, (void*)this, 1, &task_handle); return ESP_OK; } -VS1053_SINK::~VS1053_SINK() {} -VS1053_TRACK VS1053_SINK::newTrack(size_t track_id, size_t buffer_size) { - return VS1053_TRACK(this, track_id, buffer_size); +VS1053_SINK::~VS1053_SINK() { + if (task_handle != NULL) + vTaskDelete(task_handle); + task_handle = NULL; + isRunning = false; } // LOOP -VS1053_TRACK::VS1053_TRACK(VS1053_SINK* vsSink, size_t track_id, - size_t buffer_size) { +VS1053_TRACK::VS1053_TRACK(size_t track_id, size_t buffer_size) { this->track_id = track_id; - this->audioSink = vsSink; this->dataBuffer = xStreamBufferCreate(buffer_size, 1); // this->run_track(); } VS1053_TRACK::~VS1053_TRACK() { - if (this->track_state != tsStopped) - this->audioSink->new_state(tsCancel); - while (this->track_handle) - vTaskDelay(10 / portTICK_PERIOD_MS); if (dataBuffer != NULL) vStreamBufferDelete(dataBuffer); dataBuffer = NULL; } -void runTrack() {} -void VS1053_SINK::start_track(std::shared_ptr track, - size_t buf_fill) { - this->track = track; - endFillByte = 0; - playMode = read_mem(PAR_PLAY_MODE); - endFillBytes = SDI_END_FILL_BYTES; // How many of those to send - sdi_send_fillers(endFillBytes); - write_register(SCI_DECODE_TIME, 0); // Reset DECODE_TIME - xTaskCreate(vs_feed, "track_feed", 4098, (void*)this->track.get(), 5, - &this->track->track_handle); - new_state(VS1053_TRACK::VS_TRACK_STATE::tsPlaybackStart); -} void VS1053_SINK::new_track(std::shared_ptr track) { - if (this->track) - this->future_track = track; - else - this->start_track(track, 1024); + tracks.push_back(track); } bool VS1053_SINK::is_seekable(VS1053_TRACK::VS_TRACK_STATE* state) { if (read_register(SCI_STATUS) >> SS_DO_NOT_JUMP_B == 0) { - new_state(VS1053_TRACK::VS_TRACK_STATE::tsPlaybackSeekable); + new_state(*state, VS1053_TRACK::VS_TRACK_STATE::tsPlaybackSeekable); return true; } return false; } size_t VS1053_SINK::track_seekable(size_t track_id) { - if (this->track) - if (this->track->track_id == track_id) - return this->track->header_size; + if (tracks.size()) + if (tracks[0]->track_id == track_id) + return tracks[0]->header_size; return 0; } void VS1053_SINK::cancel_track(VS1053_TRACK::VS_TRACK_STATE* state) { unsigned short oldMode; oldMode = read_register(SCI_MODE); write_register(SCI_MODE, oldMode | SM_CANCEL); - new_state(VS1053_TRACK::VS_TRACK_STATE::tsCancelAwait); + new_state(*state, VS1053_TRACK::VS_TRACK_STATE::tsCancelAwait); } -bool VS1053_SINK::is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state) { +bool VS1053_SINK::is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state, + uint8_t endFillByte, size_t endFillBytes) { if (read_register(SCI_MODE) & SM_CANCEL) - sdi_send_fillers(2); + sdi_send_fillers(endFillByte, 2); else { - sdi_send_fillers(endFillBytes); - new_state(VS1053_TRACK::VS_TRACK_STATE::tsStopped); + sdi_send_fillers(endFillByte, endFillBytes); + new_state(*state, VS1053_TRACK::VS_TRACK_STATE::tsStopped); return true; } return false; } -void VS1053_SINK::delete_track(void) { - if (this->future_track) { - this->track = this->future_track; - this->future_track = nullptr; - this->start_track(this->track, 1024); - } else { - this->remove_track(this->track); - } +void VS1053_SINK::delete_all_tracks(void) { + this->tracks.erase(tracks.begin() + 1, tracks.end()); + if (this->tracks[0]->state != VS1053_TRACK::VS_TRACK_STATE::tsStopped) + new_state(this->tracks[0]->state, VS1053_TRACK::VS_TRACK_STATE::tsCancel); } -size_t VS1053_SINK::get_track_info(size_t pos) { +size_t VS1053_SINK::get_track_info(size_t pos, uint8_t& endFillByte, + size_t& endFillBytes) { #ifdef CONFIG_REPORT_ON_SCREEN uint16_t sampleRate; uint32_t byteRate; @@ -210,9 +190,9 @@ size_t VS1053_SINK::get_track_info(size_t pos) { get_audio_format(&audioFormat, &endFillBytes); /* It is important to collect endFillByte while still in normal - playback. If we need to later cancel playback or run into any - trouble with e.g. a broken file, we need to be able to repeatedly - send this byte until the decoder has been able to exit. */ + playback. If we need to later cancel playback or run into any + trouble with e.g. a broken file, we need to be able to repeatedly + send this byte until the decoder has been able to exit. */ endFillByte = read_mem(PAR_END_FILL_BYTE); #ifdef CONFIG_REPORT_ON_SCREEN @@ -220,8 +200,8 @@ size_t VS1053_SINK::get_track_info(size_t pos) { sampleRate = read_register(SCI_AUDATA); byteRate = read_mem(PAR_BYTERATE); /* FLAC: byteRate = bitRate / 32 - Others: byteRate = bitRate / 8 - Here we compensate for that difference. */ + Others: byteRate = bitRate / 8 + Here we compensate for that difference. */ if (audioFormat == afFlac) byteRate *= 4; @@ -250,81 +230,98 @@ size_t VS1053_TRACK::feed_data(uint8_t* data, size_t len, return res; } size_t VS1053_SINK::spaces_available(size_t track_id) { - if (this->track == nullptr) - return 0; - if (this->track->track_id == track_id) - return xStreamBufferSpacesAvailable(this->track->dataBuffer); - else - return xStreamBufferSpacesAvailable(this->future_track->dataBuffer); + if (this->tracks.size()) + for (auto track : tracks) + if (track->track_id == track_id) + return xStreamBufferSpacesAvailable(track->dataBuffer); + return 0; } void VS1053_TRACK::empty_feed() { if (this->dataBuffer != NULL) xStreamBufferReset(this->dataBuffer); } -void VS1053_SINK::new_state(VS1053_TRACK::VS_TRACK_STATE state) { - this->track->track_state = state; +void VS1053_SINK::new_state(VS1053_TRACK::VS_TRACK_STATE& state, + VS1053_TRACK::VS_TRACK_STATE new_state) { + state = new_state; if (state_callback != NULL) { - state_callback(state); + state_callback((uint8_t)new_state); } } -void VS1053_TRACK::run_track(size_t FILL_BUFFER_BEFORE_PLAYBACK) { - uint32_t pos = 0; - long nextReportPos = 0; // File pointer where to next collect/report - size_t itemSize = 0; - uint8_t* item = (uint8_t*)malloc(VS1053_PACKET_SIZE); +void VS1053_SINK::run_feed(size_t FILL_BUFFER_BEFORE_PLAYBACK) { + while (isRunning) { + uint8_t* item = (uint8_t*)malloc(VS1053_PACKET_SIZE); + if (tracks.size()) { + size_t itemSize = 0; + uint32_t pos = 0; + long nextReportPos = 0; // File pointer where to next collect/report + std::shared_ptr track = tracks.front(); + uint8_t endFillByte = 0; // Byte to send when stopping song + size_t endFillBytes = SDI_END_FILL_BYTES; + playMode = read_mem(PAR_PLAY_MODE); + sdi_send_fillers(endFillByte, endFillBytes); + write_register(SCI_DECODE_TIME, 0); // Reset DECODE_TIME + new_state(track->state, VS1053_TRACK::VS_TRACK_STATE::tsPlaybackStart); + if (FILL_BUFFER_BEFORE_PLAYBACK < + xStreamBufferBytesAvailable(track->dataBuffer)) + vTaskDelay(10 / portTICK_PERIOD_MS); + while (track->state != VS1053_TRACK::VS_TRACK_STATE::tsStopped) { + if (this->command_callbacks.size()) { + this->command_callbacks[0](track->track_id); + this->command_callbacks.pop_front(); + } - if (FILL_BUFFER_BEFORE_PLAYBACK < - xStreamBufferBytesAvailable(this->dataBuffer)) - vTaskDelay(10 / portTICK_PERIOD_MS); - while (this->track_state != tsStopped) { - if (this->audioSink->command_callbacks.size()) { - this->audioSink->command_callbacks[0](track_id); - this->audioSink->command_callbacks.pop_front(); - } - switch (this->track_state) { - case tsPlaybackStart: - this->audioSink->new_state(tsPlayback); - goto tsPlaybackSeekable; - case tsPlayback: - if (this->audioSink->is_seekable(&this->track_state)) - if (!this->header_size) - this->header_size = VS1053_PACKET_SIZE * pos; - goto tsPlaybackSeekable; - case tsPlaybackSeekable: - - tsPlaybackSeekable: - itemSize = xStreamBufferReceive(this->dataBuffer, (void*)item, - VS1053_PACKET_SIZE, 10); - if (itemSize) { - this->audioSink->sdi_send_buffer(item, itemSize); - pos++; + switch (track->state) { + case VS1053_TRACK::VS_TRACK_STATE::tsPlaybackStart: + this->new_state( + track->state, + VS1053_TRACK::VS1053_TRACK::VS_TRACK_STATE::tsPlayback); + goto tsPlaybackSeekable; + case VS1053_TRACK::VS_TRACK_STATE::tsPlayback: + if (this->is_seekable(&track->state)) + if (!track->header_size) + track->header_size = VS1053_PACKET_SIZE * pos; + goto tsPlaybackSeekable; + case VS1053_TRACK::VS_TRACK_STATE::tsPlaybackSeekable: + + tsPlaybackSeekable: + itemSize = xStreamBufferReceive(track->dataBuffer, (void*)item, + VS1053_PACKET_SIZE, 10); + if (itemSize) { + this->sdi_send_buffer(item, itemSize); + pos++; + } } break; - case tsSoftCancel: - if (xStreamBufferBytesAvailable(this->dataBuffer)) - goto tsPlaybackSeekable; - this->audioSink->new_state(tsCancel); - [[fallthrough]]; - case tsCancel: - free(item); - this->empty_feed(); - this->audioSink->cancel_track(&this->track_state); - [[fallthrough]]; - case tsCancelAwait: - if (this->audioSink->is_cancelled(&this->track_state)) {} - break; - default: - vTaskDelay(20 / portTICK_PERIOD_MS); - break; - } - if (pos >= nextReportPos) { - nextReportPos += this->audioSink->get_track_info(pos); + case VS1053_TRACK::VS_TRACK_STATE::tsSoftCancel: + if (xStreamBufferBytesAvailable(track->dataBuffer)) + goto tsPlaybackSeekable; + this->new_state(track->state, VS1053_TRACK::VS_TRACK_STATE::tsCancel); + [[fallthrough]]; + case VS1053_TRACK::VS_TRACK_STATE::tsCancel: + free(item); + track->empty_feed(); + this->cancel_track(&track->state); + [[fallthrough]]; + case VS1053_TRACK::VS_TRACK_STATE::tsCancelAwait: + if (this->is_cancelled(&track->state, endFillByte, endFillBytes)) {} + break; + default: + vTaskDelay(20 / portTICK_PERIOD_MS); + break; + } + if (pos >= nextReportPos) { + nextReportPos += this->get_track_info(pos, endFillByte, endFillBytes); + } } + vStreamBufferDelete(track->dataBuffer); + track->dataBuffer = NULL; + tracks.pop_front(); } - this->track_handle = NULL; - this->audioSink->delete_track(); - vTaskDelete(NULL); + vTaskDelay(50 / portTICK_PERIOD_MS); +} +task_handle = NULL; +vTaskDelete(NULL); } // FEED FUNCTIONS @@ -333,23 +330,20 @@ size_t VS1053_SINK::data_request() { } void VS1053_SINK::stop_feed() { - if (this->future_track != nullptr) - this->future_track.reset(); // - if ((uint8_t)this->track->track_state < 3) - new_state(VS1053_TRACK::VS_TRACK_STATE::tsCancel); + if (this->tracks[0]->state < 3) + new_state(this->tracks[0]->state, VS1053_TRACK::VS_TRACK_STATE::tsCancel); } void VS1053_SINK::soft_stop_feed() { - if (this->future_track != nullptr) - this->future_track.reset(); // - if ((uint8_t)this->track->track_state < 3) - new_state(VS1053_TRACK::VS_TRACK_STATE::tsSoftCancel); + if (this->tracks[0]->state < 3) + new_state(this->tracks[0]->state, + VS1053_TRACK::VS_TRACK_STATE::tsSoftCancel); } // COMMAND FUCNTIONS /* The command pipeline recieves command in a structure of uint8_t[]. */ uint8_t VS1053_SINK::feed_command(command_callback commandCallback) { - if (this->track) { + if (this->tracks.size()) { command_callbacks.push_back(commandCallback); } else commandCallback(0); @@ -623,13 +617,13 @@ bool VS1053_SINK::sdi_send_buffer(uint8_t* data, size_t len) { return true; } -bool VS1053_SINK::sdi_send_fillers(size_t len) { +bool VS1053_SINK::sdi_send_fillers(uint8_t endFillByte, size_t len) { size_t chunk_length; // Length of chunk 32 byte or shorter spi_transaction_t SPITransaction; esp_err_t ret; uint8_t data[VS1053_CHUNK_SIZE]; for (int i = 0; i < VS1053_CHUNK_SIZE; i++) - data[i] = this->endFillByte; + data[i] = endFillByte; if (SPI_semaphore != NULL) while (xSemaphoreTake(*SPI_semaphore, 1) != pdTRUE) vTaskDelay(1); diff --git a/targets/esp32/main/VSPlayer.cpp b/targets/esp32/main/VSPlayer.cpp index f8836d49..26d55c33 100644 --- a/targets/esp32/main/VSPlayer.cpp +++ b/targets/esp32/main/VSPlayer.cpp @@ -20,14 +20,12 @@ VSPlayer::VSPlayer(std::shared_ptr handler, [this](uint8_t* data, size_t bytes, size_t trackId, bool STORAGE_VOLATILE) { if (!this->track) { - this->track = std::make_shared(this->vsSink.get(), - trackId, 4098 * 16); + this->track = std::make_shared(trackId, 4098 * 16); this->vsSink->new_track(this->track); } if (trackId != this->track->track_id) { this->vsSink->soft_stop_feed(); - this->track = std::make_shared(this->vsSink.get(), - trackId, 4098 * 16); + this->track = std::make_shared(trackId, 4098 * 16); this->vsSink->new_track(this->track); } return this->track->feed_data(data, bytes, STORAGE_VOLATILE); @@ -45,14 +43,17 @@ VSPlayer::VSPlayer(std::shared_ptr handler, case cspot::SpircHandler::EventType::PLAY_PAUSE: if (std::get(event->data)) { if (this->track) - this->vsSink->new_state(VS1053_TRACK::tsPlaybackPaused); + this->vsSink->new_state(this->vsSink->tracks[0]->state, + VS1053_TRACK::tsPlaybackPaused); } else { if (this->track) - this->vsSink->new_state(VS1053_TRACK::tsPlaybackSeekable); + this->vsSink->new_state(this->vsSink->tracks[0]->state, + VS1053_TRACK::tsPlaybackSeekable); } break; case cspot::SpircHandler::EventType::DISC: this->track = nullptr; + this->vsSink->delete_all_tracks(); this->vsSink->stop_feed(); break; case cspot::SpircHandler::EventType::FLUSH: diff --git a/targets/esp32/main/VSinit.h b/targets/esp32/main/VSinit.h index cf438f18..0682a4a1 100644 --- a/targets/esp32/main/VSinit.h +++ b/targets/esp32/main/VSinit.h @@ -1,7 +1,12 @@ #include +#include +#include #include +#include #include "esp_log.h" +#include "esp_vfs_fat.h" +#include "sdmmc_cmd.h" #include "VS1053.h" @@ -26,5 +31,83 @@ void initAudioSink(std::shared_ptr VS1053) { // VS1053 SETUP VS1053->init(HSPI_HOST, &SPI_semaphore); + if (CONFIG_GPIO_SD_CS >= 0) { + sdspi_device_config_t sd_device = SDSPI_DEVICE_CONFIG_DEFAULT(); + sd_device.gpio_cs = (gpio_num_t)CONFIG_GPIO_SD_CS; + sd_device.gpio_int = (gpio_num_t)-1; + gpio_install_isr_service(0); + sdspi_dev_handle_t sd_spi_handle; + ret = sdspi_host_init(); + ESP_ERROR_CHECK(ret); + ret = sdspi_host_init_device(&sd_device, &sd_spi_handle); + ESP_ERROR_CHECK(ret); + sdmmc_host_t host = SDSPI_HOST_DEFAULT(); + host.slot = sd_spi_handle; + gpio_reset_pin((gpio_num_t)CONFIG_GPIO_SD_CS); + gpio_set_direction((gpio_num_t)CONFIG_GPIO_SD_CS, GPIO_MODE_OUTPUT); + + esp_vfs_fat_sdmmc_mount_config_t mount_config = { +#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED + .format_if_mount_failed = true, +#else + .format_if_mount_failed = false, +#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED + .max_files = 5, + .allocation_unit_size = 16 * 1024}; + ESP_LOGI(TAG, "Initializing SD card"); + /* + ret = esp_vfs_fat_sdspi_mount("/sdcard", &host, &sd_device, &mount_config, &card); + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount filesystem. " + "If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option."); + } + else { + ESP_LOGE(TAG, "Failed to initialize the card (%s). " + "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); + } + } + */ + sdmmc_card_t* card = (sdmmc_card_t*)malloc(sizeof(sdmmc_card_t)); + + ESP_LOGI(TAG, "Filesystem mounted"); + if (ret == ESP_OK) + sdmmc_card_print_info(stdout, card); + ret = esp_vfs_fat_sdspi_mount("/sdcard", &host, &sd_device, &mount_config, + &card); + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + ESP_LOGE(TAG, + "Failed to mount filesystem. " + "If you want the card to be formatted, set the " + "CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option."); + } else { + ESP_LOGE(TAG, + "Failed to initialize the card (%s). " + "Make sure SD card lines have pull-up resistors in place.", + esp_err_to_name(ret)); + } + } + struct dirent* entry; + struct stat file_stat; + DIR* dir = opendir(MOUNT_POINT); + char n_name[280]; + if (!dir) + printf("no dir\n"); + while ((entry = readdir(dir)) != NULL) { + sprintf(n_name, "%s/%s", MOUNT_POINT, entry->d_name); + printf("%s\n", n_name); + printf("name:%s, ino: %i\n", entry->d_name, entry->d_ino); + printf("stat_return_value:%i\n", stat(n_name, &file_stat)); + printf("stat_mode:%i\n", file_stat.st_mode); + } + dir = opendir(MOUNT_POINT "/TRACKS"); + if (!dir) + printf("no dir\n"); + while ((entry = readdir(dir)) != NULL) { + printf("%s\n", entry->d_name); + } + closedir(dir); + } VS1053->write_register(SCI_VOL, 10 | 10 << 8); } \ No newline at end of file From e9906bcb16865c9f28bc3903569238305931c69b Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Wed, 17 Jul 2024 13:32:45 +0200 Subject: [PATCH 26/41] fixed vs1053.cpp --- .../esp32/components/VS1053/src/VS1053.cpp | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/targets/esp32/components/VS1053/src/VS1053.cpp b/targets/esp32/components/VS1053/src/VS1053.cpp index 34e35e7f..b710fa6b 100644 --- a/targets/esp32/components/VS1053/src/VS1053.cpp +++ b/targets/esp32/components/VS1053/src/VS1053.cpp @@ -291,37 +291,37 @@ void VS1053_SINK::run_feed(size_t FILL_BUFFER_BEFORE_PLAYBACK) { this->sdi_send_buffer(item, itemSize); pos++; } + break; + case VS1053_TRACK::VS_TRACK_STATE::tsSoftCancel: + if (xStreamBufferBytesAvailable(track->dataBuffer)) + goto tsPlaybackSeekable; + this->new_state(track->state, + VS1053_TRACK::VS_TRACK_STATE::tsCancel); + [[fallthrough]]; + case VS1053_TRACK::VS_TRACK_STATE::tsCancel: + free(item); + track->empty_feed(); + this->cancel_track(&track->state); + [[fallthrough]]; + case VS1053_TRACK::VS_TRACK_STATE::tsCancelAwait: + if (this->is_cancelled(&track->state, endFillByte, endFillBytes)) {} + break; + default: + vTaskDelay(20 / portTICK_PERIOD_MS); + break; + } + if (pos >= nextReportPos) { + nextReportPos += this->get_track_info(pos, endFillByte, endFillBytes); } - break; - case VS1053_TRACK::VS_TRACK_STATE::tsSoftCancel: - if (xStreamBufferBytesAvailable(track->dataBuffer)) - goto tsPlaybackSeekable; - this->new_state(track->state, VS1053_TRACK::VS_TRACK_STATE::tsCancel); - [[fallthrough]]; - case VS1053_TRACK::VS_TRACK_STATE::tsCancel: - free(item); - track->empty_feed(); - this->cancel_track(&track->state); - [[fallthrough]]; - case VS1053_TRACK::VS_TRACK_STATE::tsCancelAwait: - if (this->is_cancelled(&track->state, endFillByte, endFillBytes)) {} - break; - default: - vTaskDelay(20 / portTICK_PERIOD_MS); - break; - } - if (pos >= nextReportPos) { - nextReportPos += this->get_track_info(pos, endFillByte, endFillBytes); } + vStreamBufferDelete(track->dataBuffer); + track->dataBuffer = NULL; + tracks.pop_front(); } - vStreamBufferDelete(track->dataBuffer); - track->dataBuffer = NULL; - tracks.pop_front(); + vTaskDelay(50 / portTICK_PERIOD_MS); } - vTaskDelay(50 / portTICK_PERIOD_MS); -} -task_handle = NULL; -vTaskDelete(NULL); + task_handle = NULL; + vTaskDelete(NULL); } // FEED FUNCTIONS From 8f2b03e139d45f825049adfae08b9164f513061f Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Wed, 17 Jul 2024 17:54:07 +0200 Subject: [PATCH 27/41] added a deque for queued tracks --- cspot/include/TrackQueue.h | 6 +- cspot/src/MercurySession.cpp | 8 +- cspot/src/TrackQueue.cpp | 121 +++++++++++++++++---------- targets/esp32/main/Kconfig.projbuild | 7 ++ 4 files changed, 93 insertions(+), 49 deletions(-) diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 19a7ba8e..08623c77 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -5,7 +5,8 @@ #include #include #include -#include //for random_device and default_random_engine +#include //for random_device and default_random_engine +#include // for pair #include "BellTask.h" #include "EventManager.h" // for TrackMetrics @@ -16,8 +17,6 @@ #define inner_tracks_treshhold 10 #define SEND_OLD_TRACKS 2 -#define SEND_FUTURE_TRACKS 2 -#define GET_RADIO_TRACKS 10 namespace bell { class WrappedSemaphore; @@ -125,6 +124,7 @@ class TrackQueue : public bell::Task { std::shared_ptr processSemaphore; std::deque> preloadedTracks; + std::deque> queuedTracks; std::vector alt_index; std::vector currentTracks; std::vector ghostTracks; diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index e925e288..c768a90e 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -228,7 +228,7 @@ void MercurySession::failAllPending() { std::pair MercurySession::decodeResponse( const std::vector& data) { auto sequenceLength = ntohs(extract(data, 0)); - uint64_t sequenceId; + int64_t sequenceId; uint8_t flag; if (sequenceLength == 2) sequenceId = ntohs(extract(data, 2)); @@ -242,19 +242,19 @@ std::pair MercurySession::decodeResponse( size_t pos = 2 + sequenceLength; flag = (uint8_t)data[pos]; pos++; - auto parts = ntohs(extract(data, pos)); + uint16_t parts = ntohs(extract(data, pos)); pos += 2; auto partial = partials.find(sequenceId); if (partial == partials.end()) { CSPOT_LOG(debug, - "Creating new Mercury Response, seq: %llu, flags: %i, parts: %i", + "Creating new Mercury Response, seq: %lli, flags: %i, parts: %i", sequenceId, flag, parts); partial = this->partials.insert({sequenceId, Response()}).first; partial->second.parts = {}; partial->second.fail = false; } else CSPOT_LOG(debug, - "Adding to Mercury Response, seq: %llu, flags: %i, parts: %i", + "Adding to Mercury Response, seq: %lli, flags: %i, parts: %i", sequenceId, flag, parts); uint8_t index = 0; while (parts) { diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 1937a1a7..75331ac0 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -494,16 +494,29 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { else this->playbackState->innerFrame.state.index = currentTracksIndex + offset; ghostTracks.clear(); - uint16_t index = currentTracksIndex + offset > SEND_OLD_TRACKS - ? currentTracksIndex + offset - SEND_OLD_TRACKS - : 0; - uint16_t end = currentTracksIndex + offset + SEND_FUTURE_TRACKS + 1; - if (end >= currentTracks.size()) - end = currentTracks.size(); - for (uint16_t i = 0; i < end - index; i++) { - ghostTracks.push_back( - currentTracks[(index + i) >= alt_index.size() ? index + i - : alt_index[index + i]]); + //add SEND_OLD_TRACKS already played tracks + size_t ghostindex; + size_t index = currentTracksIndex + offset; + for (int i = 1; i <= this->playbackState->innerFrame.state.index; i++) { + ghostindex = index - i; + if (ghostindex < alt_index.size()) + ghostindex = alt_index[ghostindex]; + ghostTracks.push_back(currentTracks[ghostindex]); + } + if (queuedTracks.size()) { + if (index != queuedTracks[0].first) { + ghostTracks.push_back(currentTracks[index]); + index++; + } + for (auto track : queuedTracks) + ghostTracks.push_back(track.second); + } + ghostindex = index; + while (ghostTracks.size() < SEND_OLD_TRACKS + CONFIG_UPDATE_FUTURE_TRACKS && + index < currentTracks.size()) { + ghostindex = index < alt_index.size() ? index : alt_index[index]; + ghostTracks.push_back(currentTracks[ghostindex]); + index++; } } @@ -572,6 +585,8 @@ void TrackQueue::resolveContext() { string_format("hm://context-resolve/v1/%s", this->playbackState->innerFrame.state.context_uri); auto responseHandler = [this](MercurySession::Response& res) { + if (!res.parts.size()) + return; std::scoped_lock lock(tracksMutex); auto jsonResult = nlohmann::json::parse(res.parts[0]); //do nothing if last track is the same as last track in currentTracks @@ -686,6 +701,21 @@ void TrackQueue::processTrack(std::shared_ptr track) { bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { int requestedRefIndex = offset + currentTracksIndex; + if (queuedTracks.size()) { + for (auto track : queuedTracks) { + if (preloadedTracks.size() >= MAX_TRACKS_PRELOAD) + return true; + for (auto loaded_track : preloadedTracks) { + if (track.second.gid == loaded_track->ref.gid) + goto loadedTrackAlready; + } + preloadedTracks.push_back( + std::make_shared(track.second, ctx, 0)); + loadedTrackAlready:; + } + if (preloadedTracks.size() >= MAX_TRACKS_PRELOAD) + return true; + } if (playbackState->innerFrame.state.shuffle && requestedRefIndex < alt_index.size()) requestedRefIndex = alt_index[requestedRefIndex]; @@ -736,13 +766,37 @@ bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { } } else { if (currentTracks.size() > currentTracksIndex + 1) { - preloadedTracks.pop_front(); - - if (!queueNextTrack(preloadedTracks.size() + 1)) { - CSPOT_LOG(info, "Failed to queue next track"); + if (queuedTracks.size() > 0) { + if (currentTracksIndex == queuedTracks[0].first) { + queuedTracks.pop_front(); + preloadedTracks.pop_front(); + if (queuedTracks.size() <= 0) { + currentTracksIndex--; + queueNextTrack(1); + currentTracksIndex++; + } + } else { + preloadedTracks.pop_front(); + currentTracksIndex++; + } + for (auto track : queuedTracks) { + if (preloadedTracks.size() >= MAX_TRACKS_PRELOAD) + break; + for (auto loaded_track : preloadedTracks) { + if (track.second.gid == loaded_track->ref.gid) + goto loadedTrackAlready; + } + preloadedTracks.push_back( + std::make_shared(track.second, ctx, 0)); + loadedTrackAlready:; + } + } else { + preloadedTracks.pop_front(); + if (!queueNextTrack(preloadedTracks.size() + 1)) { + CSPOT_LOG(info, "Failed to queue next track"); + } + currentTracksIndex++; } - - currentTracksIndex++; } else { skipped = false; } @@ -773,6 +827,7 @@ bool TrackQueue::isFinished() { } void TrackQueue::shuffle_tracks(bool shuffleTracks) { + std::scoped_lock lock(tracksMutex); if (!shuffleTracks) currentTracksIndex = alt_index[currentTracksIndex]; alt_index.clear(); @@ -821,32 +876,14 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { playableSemaphore->give(); } else { - auto prevTrackIter = currentTracks.begin() + alt_index.size(); - alt_index.insert(alt_index.begin() + currentTracksIndex + 1, - alt_index.size()); - - currentTracks.insert( - prevTrackIter, - playbackState->remoteTracks[playbackState->innerFrame.state.index + 1]); - - if (preloadedTracks[0]->loading) { - // try to not re-load track if we are still loading it - - // remove everything except first track - preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); - - // Push a song on the preloaded queue - CSPOT_LOG(info, "Keeping current track %d", currentTracksIndex); - queueNextTrack(1); - cleared = false; - } else { - // Clear preloaded tracks - preloadedTracks.clear(); - - // Push a song on the preloaded queue - CSPOT_LOG(info, "Re-loading current track"); - queueNextTrack(0, requestedPosition); - } + std::cout << "insert" << std::endl; + queuedTracks.push_back(std::make_pair( + currentTracksIndex + 1, + playbackState->remoteTracks[playbackState->innerFrame.state.index + 1 + + queuedTracks.size()])); + preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); + queueNextTrack(1); + cleared = false; } update_ghost_tracks(); diff --git a/targets/esp32/main/Kconfig.projbuild b/targets/esp32/main/Kconfig.projbuild index 54d700a6..cd416e5a 100644 --- a/targets/esp32/main/Kconfig.projbuild +++ b/targets/esp32/main/Kconfig.projbuild @@ -93,6 +93,13 @@ menu "CSPOT Configuration" login with username and password endmenu + config UPDATE_FUTURE_TRACKS + int "Send tracks to spotify" + range 0 100 + default 10 + help + How many tracks are visible in the currently playing header + config CSPOT_STATUS_LED_GPIO int "Status LED GPIO number" range 0 48 From 8adac01c888a7958e494491c85218460fb620400 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Wed, 17 Jul 2024 20:30:27 +0200 Subject: [PATCH 28/41] a little tinkering for the queued tracks --- cspot/src/TrackQueue.cpp | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 75331ac0..6d70e25b 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -503,9 +503,10 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { ghostindex = alt_index[ghostindex]; ghostTracks.push_back(currentTracks[ghostindex]); } - if (queuedTracks.size()) { - if (index != queuedTracks[0].first) { - ghostTracks.push_back(currentTracks[index]); + if (queuedTracks.size() > 0) { + if (preloadedTracks[0]->ref.gid != queuedTracks[0].second.gid) { + ghostindex = index < alt_index.size() ? alt_index[index] : index; + ghostTracks.push_back(currentTracks[ghostindex]); index++; } for (auto track : queuedTracks) @@ -514,7 +515,7 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { ghostindex = index; while (ghostTracks.size() < SEND_OLD_TRACKS + CONFIG_UPDATE_FUTURE_TRACKS && index < currentTracks.size()) { - ghostindex = index < alt_index.size() ? index : alt_index[index]; + ghostindex = index < alt_index.size() ? alt_index[index] : index; ghostTracks.push_back(currentTracks[ghostindex]); index++; } @@ -767,29 +768,16 @@ bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { } else { if (currentTracks.size() > currentTracksIndex + 1) { if (queuedTracks.size() > 0) { - if (currentTracksIndex == queuedTracks[0].first) { + if (preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid) { queuedTracks.pop_front(); preloadedTracks.pop_front(); if (queuedTracks.size() <= 0) { - currentTracksIndex--; queueNextTrack(1); - currentTracksIndex++; } } else { preloadedTracks.pop_front(); currentTracksIndex++; } - for (auto track : queuedTracks) { - if (preloadedTracks.size() >= MAX_TRACKS_PRELOAD) - break; - for (auto loaded_track : preloadedTracks) { - if (track.second.gid == loaded_track->ref.gid) - goto loadedTrackAlready; - } - preloadedTracks.push_back( - std::make_shared(track.second, ctx, 0)); - loadedTrackAlready:; - } } else { preloadedTracks.pop_front(); if (!queueNextTrack(preloadedTracks.size() + 1)) { @@ -839,10 +827,10 @@ void TrackQueue::shuffle_tracks(bool shuffleTracks) { randomizeIndex(alt_index, 1, rng); currentTracksIndex = 0; } - update_ghost_tracks(); preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); // Push a song on the preloaded queue queueNextTrack(1, 0); + update_ghost_tracks(); } bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { @@ -876,7 +864,6 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { playableSemaphore->give(); } else { - std::cout << "insert" << std::endl; queuedTracks.push_back(std::make_pair( currentTracksIndex + 1, playbackState->remoteTracks[playbackState->innerFrame.state.index + 1 + From 326e9d7d7501e54587a6220c5a58295464fc4cb2 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Wed, 17 Jul 2024 21:22:47 +0200 Subject: [PATCH 29/41] Small changes for the cli player --- cspot/include/TrackQueue.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 08623c77..2072f264 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -15,6 +15,9 @@ #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode +#ifndef CONFIG_UPDATE_FUTURE_TRACKS +#define CONFIG_UPDATE_FUTURE_TRACKS 10 +#endif #define inner_tracks_treshhold 10 #define SEND_OLD_TRACKS 2 From 40d23838c05becbc59814d9ea113a22ffcbe287f Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Sun, 21 Jul 2024 11:25:51 +0200 Subject: [PATCH 30/41] PlayerContext.h, some structural changes, especially with EventManager, no Timestamp --- cspot/include/EventManager.h | 5 +- cspot/include/MercurySession.h | 2 +- cspot/include/PlayerContext.h | 52 ++++ cspot/include/TrackPlayer.h | 2 +- cspot/include/TrackQueue.h | 18 +- cspot/src/EventManager.cpp | 15 +- cspot/src/MercurySession.cpp | 40 ++- cspot/src/PlayerContext.cpp | 208 ++++++++++++++ cspot/src/SpircHandler.cpp | 8 +- cspot/src/TrackPlayer.cpp | 14 +- cspot/src/TrackQueue.cpp | 265 ++++-------------- .../esp32/components/VS1053/src/VS1053.cpp | 5 +- targets/esp32/main/main.cpp | 2 +- 13 files changed, 376 insertions(+), 260 deletions(-) create mode 100644 cspot/include/PlayerContext.h create mode 100644 cspot/src/PlayerContext.cpp diff --git a/cspot/include/EventManager.h b/cspot/include/EventManager.h index 63006599..d0b5156a 100644 --- a/cspot/include/EventManager.h +++ b/cspot/include/EventManager.h @@ -41,15 +41,16 @@ class TrackMetrics { uint64_t longestInterval = 0, totalAmountOfPlayTime = 0, totalMsOfPlayedTrack = 0, totalAmountPlayed = 0, audioKeyTime = 0, trackHeaderTime = 0, written_bytes = 0, track_size = 0, - timestamp = 0; + timestamp = 0, trackLatency = 0; std::vector> intervals; skip skipped_backward, skipped_forward; void newPosition(uint64_t pos); void endInterval(uint64_t pos); void endTrack(); + void startTrack(); void startTrackDecoding(); - void startTrack(uint64_t pos); + void startTrackPlaying(uint64_t pos); uint64_t getPosition(); private: diff --git a/cspot/include/MercurySession.h b/cspot/include/MercurySession.h index de53dd2a..c3dc55b1 100644 --- a/cspot/include/MercurySession.h +++ b/cspot/include/MercurySession.h @@ -114,7 +114,7 @@ class MercurySession : public bell::Task, public cspot::Session { void reconnect(); std::unordered_map callbacks; - std::unordered_map partials; + std::deque> partials; std::unordered_map subscriptions; std::unordered_map audioKeyCallbacks; diff --git a/cspot/include/PlayerContext.h b/cspot/include/PlayerContext.h new file mode 100644 index 00000000..1429a041 --- /dev/null +++ b/cspot/include/PlayerContext.h @@ -0,0 +1,52 @@ +#ifndef PLAYER_CONTEXT_H +#define PLAYER_CONTEXT_H + +#include +#include // for shared_ptr +#include //for scoped_loc, mutex... +#include //for random_device and default_random_engine +#include // for pair +#include //for vector + +#include "BellTask.h" +#include "CSpotContext.h" +#include "TrackReference.h" //for TrackReference + +#include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode +#define MAX_TRACKS 80 +namespace cspot { +class PlayerContext { + public: + PlayerContext( + bell::Task* queue, std::shared_ptr ctx, + std::vector* track_list, + std::deque>* queued_list, + std::mutex* trackMutex, uint32_t* index, bool shuffle, char* uri); + ~PlayerContext(); + void resolveContext(uint32_t index, bool shuffle, char* uri); + + private: + std::shared_ptr ctx; + std::mutex* trackMutex; + bell::Task* queue; + std::shared_ptr innerFrame; + void shuffleIndex(); + void getTracks(); + std::vector alternative_index; + uint32_t* index; + uint32_t last_index = 0; + uint32_t radio_offset = 0; + std::string context_uri; + std::vector* track_list; + std::deque>* queued_list; + bool last_resolve_shuffled = false; + bool resolveTracklist(uint32_t index, bool shuffle, + std::vector& data); + bool resolveInitial(uint32_t index, bool shuffle, std::vector& data); + bool resolveRadio(uint32_t index, std::vector& data); + std::random_device rd; + std::default_random_engine rng; +}; +}; // namespace cspot + +#endif \ No newline at end of file diff --git a/cspot/include/TrackPlayer.h b/cspot/include/TrackPlayer.h index 8dbeacd8..75bf736a 100644 --- a/cspot/include/TrackPlayer.h +++ b/cspot/include/TrackPlayer.h @@ -44,7 +44,7 @@ class TrackPlayer : bell::Task { #endif )> DataCallback; - typedef std::function EOFCallback; + typedef std::function EOFCallback; typedef std::function SeekableCallback; TrackPlayer(std::shared_ptr ctx, diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 2072f264..abf7a6e3 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -11,6 +11,7 @@ #include "BellTask.h" #include "EventManager.h" // for TrackMetrics #include "PlaybackState.h" +#include "PlayerContext.h" #include "TrackReference.h" #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode @@ -61,6 +62,9 @@ class QueuedTrack { TrackReference ref; // Holds GID, URI and Context TrackInfo trackInfo; // Full track information fetched from spotify, name etc + // PB data + Track pbTrack = Track_init_zero; + Episode pbEpisode = Episode_init_zero; uint32_t requestedPosition; uint64_t written_bytes = 0; std::string identifier; @@ -113,6 +117,7 @@ class TrackQueue : public bell::Task { void update_ghost_tracks(int16_t offset = 0); bool hasTracks(); bool isFinished(); + void reloadTracks(uint8_t offset = 1); bool skipTrack(SkipDirection dir, bool expectNotify = true); bool updateTracks(uint32_t requestedPosition = 0, bool initial = false); TrackInfo getTrackInfo(std::string_view identifier); @@ -120,28 +125,23 @@ class TrackQueue : public bell::Task { std::shared_ptr prevSong, int& offset); private: - static const int MAX_TRACKS_PRELOAD = 3; + static const int MAX_TRACKS_PRELOAD = 2; std::shared_ptr accessKeyFetcher; std::shared_ptr ctx; std::shared_ptr processSemaphore; + std::unique_ptr playerContext; std::deque> preloadedTracks; - std::deque> queuedTracks; - std::vector alt_index; + std::deque> queuedTracks = {}; std::vector currentTracks; std::vector ghostTracks; std::mutex tracksMutex, runningMutex; - // PB data - Track pbTrack; - Episode pbEpisode; - std::string accessKey; uint32_t radio_offset = 0; - int16_t currentTracksIndex = -1; - int16_t currentTracksSize = 0; + uint32_t currentTracksIndex = -1; bool isRunning = false; bool context_resolved = false; diff --git a/cspot/src/EventManager.cpp b/cspot/src/EventManager.cpp index f4faa1d5..f64d4130 100644 --- a/cspot/src/EventManager.cpp +++ b/cspot/src/EventManager.cpp @@ -42,13 +42,18 @@ uint64_t TrackMetrics::getPosition() { (this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start)); } -void TrackMetrics::startTrackDecoding() { +void TrackMetrics::startTrack() { trackHeaderTime = this->ctx->timeProvider->getSyncedTimestamp(); audioKeyTime = trackHeaderTime - timestamp; } -void TrackMetrics::startTrack(uint64_t pos) { - audioKeyTime = this->ctx->timeProvider->getSyncedTimestamp() - audioKeyTime; +void TrackMetrics::startTrackDecoding() { + trackHeaderTime = + this->ctx->timeProvider->getSyncedTimestamp() - trackHeaderTime; +} + +void TrackMetrics::startTrackPlaying(uint64_t pos) { + trackLatency = this->ctx->timeProvider->getSyncedTimestamp() - audioKeyTime; currentInterval = std::make_shared( this->ctx->timeProvider->getSyncedTimestamp(), pos); } @@ -151,7 +156,9 @@ std::vector PlaybackMetrics::sendEvent( .amount)); //total amount of time skipped forward append( &msg, - "15"); //randomNumber; biggest value so far 260, usually biggert than 1 //spotify says play latencie + std::to_string( + track->trackMetrics + ->trackLatency)); //randomNumber; biggest value so far 260, usually biggert than 1 //spotify says play latency append(&msg, "-1"); // usually -1, if paused positive, probablly in seconds append(&msg, "context"); append(&msg, std::to_string( diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index c768a90e..45c47137 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -176,15 +176,20 @@ void MercurySession::handlePacket() { auto response = this->decodeResponse(packet.data); if (response.first == static_cast(ResponseFlag::FINAL)) { - auto partial = this->partials.find(response.second); - //if the event-id is negative, they got sent without any request - if (response.first >= 0) { - if (this->callbacks.count(response.second)) { - this->callbacks[response.second](partial->second); - this->callbacks.erase(this->callbacks.find(response.second)); + + auto partial = partials.begin(); + while (partial != partials.end() && partial->first != response.second) + partial++; // if(partial.first == sequenceId) + if (partial != partials.end()) { + //if the event-id is negative, they got sent without any request + if (response.first >= 0) { + if (this->callbacks.count(response.second)) { + this->callbacks[response.second](partial->second); + this->callbacks.erase(this->callbacks.find(response.second)); + } } + this->partials.erase(partial); } - this->partials.erase(partial); } break; } @@ -192,12 +197,16 @@ void MercurySession::handlePacket() { auto response = decodeResponse(packet.data); if (response.first == static_cast(ResponseFlag::FINAL)) { - auto partial = this->partials.find(response.second); - auto uri = std::string(partial->second.mercuryHeader.uri); - if (this->subscriptions.count(uri) > 0) { - this->subscriptions[uri](partial->second); + auto partial = partials.begin(); + while (partial != partials.end() && partial->first != response.second) + partial++; // if(partial.first == sequenceId) + if (partial != partials.end()) { + auto uri = std::string(partial->second.mercuryHeader.uri); + if (this->subscriptions.count(uri) > 0) { + this->subscriptions[uri](partial->second); + } + this->partials.erase(partial); } - this->partials.erase(partial); } break; } @@ -244,12 +253,15 @@ std::pair MercurySession::decodeResponse( pos++; uint16_t parts = ntohs(extract(data, pos)); pos += 2; - auto partial = partials.find(sequenceId); + auto partial = partials.begin(); + while (partial != partials.end() && partial->first != sequenceId) + partial++; // if(partial.first == sequenceId) if (partial == partials.end()) { CSPOT_LOG(debug, "Creating new Mercury Response, seq: %lli, flags: %i, parts: %i", sequenceId, flag, parts); - partial = this->partials.insert({sequenceId, Response()}).first; + this->partials.push_back(std::make_pair(sequenceId, Response())); + partial = partials.end() - 1; partial->second.parts = {}; partial->second.fail = false; } else diff --git a/cspot/src/PlayerContext.cpp b/cspot/src/PlayerContext.cpp new file mode 100644 index 00000000..cb9c0a81 --- /dev/null +++ b/cspot/src/PlayerContext.cpp @@ -0,0 +1,208 @@ +#include "PlayerContext.h" +#include "MercurySession.h" +#include "TrackQueue.h" + +#ifdef BELL_ONLY_CJSON +#include "cJSON.h" +#else +#include "nlohmann/json.hpp" // for basic_json<>::object_t, basic_json +#include "nlohmann/json_fwd.hpp" // for json +#endif + +using namespace cspot; + +PlayerContext::PlayerContext( + bell::Task* queue, std::shared_ptr ctx, + std::vector* track_list, + std::deque>* queued_list, + std::mutex* trackMutex, uint32_t* index, bool shuffle, char* uri) { + this->queue = queue; + this->ctx = ctx; + this->track_list = track_list; + this->trackMutex = trackMutex; + this->queued_list = queued_list; + this->index = index; + rng = std::default_random_engine{rd()}; + std::string requestUrl = string_format("hm://context-resolve/v1/%s", uri); + auto responseHandler = [this, shuffle](MercurySession::Response& res) { + if (!res.parts.size()) + return; + if (!res.parts[0].size()) + return; + this->resolveInitial(*this->index, shuffle, res.parts[0]); + }; + + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); + if (track_list->size() < 30) + resolveContext(*this->index, shuffle, uri); +} + +static void randomizeIndex(std::vector& index, uint16_t offset, + std::default_random_engine rng) { + std::shuffle(index.begin() + offset, index.end(), rng); +} + +PlayerContext::~PlayerContext() {} + +void PlayerContext::resolveContext(uint32_t index, bool shuffle, char* uri) { + if ((last_index + track_list->size() >= alternative_index.size()) && + (last_resolve_shuffled == shuffle || + last_index + index >= alternative_index.size())) { + std::string requestUrl = + string_format("hm://autoplay-enabled/query?uri=%s", uri); + auto responseHandler = [this, index](MercurySession::Response& res) { + if (!res.parts.size()) + return; + std::string resolve_autoplay = + std::string(res.parts[0].begin(), res.parts[0].end()); + std::string requestUrl = string_format( + "hm://radio-apollo/v3/stations/%s?autoplay=true&offset=%i", + &resolve_autoplay[0], radio_offset); + auto responseHandler = [this, index](MercurySession::Response& res) { + if (!res.parts.size()) + return; + if (!res.parts[0].size()) + return; + this->resolveRadio(index, res.parts[0]); + }; + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); + }; + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); + } else { + std::string requestUrl = string_format("hm://context-resolve/v1/%s", uri); + auto responseHandler = [this, index, + shuffle](MercurySession::Response& res) { + if (!res.parts.size()) + return; + if (!res.parts[0].size()) + return; + this->resolveTracklist(index, shuffle, res.parts[0]); + }; + + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); + } +} + +bool PlayerContext::resolveRadio(uint32_t index, std::vector& data) { + std::scoped_lock lock(*trackMutex); + index = *this->index; + if (queued_list->size()) + if (queued_list->at(0).first == index || queued_list->at(0).first == -1) + index--; + auto jsonResult = nlohmann::json::parse(data); + radio_offset += jsonResult["tracks"].size(); + track_list->erase(track_list->begin(), track_list->begin() + index); + for (auto track : jsonResult["tracks"]) { + track_list->push_back(TrackReference(track["uri"])); + } + this->last_index += index; + this->ctx->playbackMetrics->correlation_id = jsonResult["correlation_id"]; + *this->index = 0; + static_cast(queue)->reloadTracks(); + return true; +} + +bool PlayerContext::resolveTracklist(uint32_t index, bool shuffle, + std::vector& data) { + index = *this->index; + std::scoped_lock lock(*trackMutex); + auto jsonResult = nlohmann::json::parse(data); + if (queued_list->at(0).first == 0 || queued_list->at(0).first == -1) + index--; + for (uint32_t i = 0; i < queued_list->size(); i++) + if (queued_list->at(i).first != -1) + queued_list->at(i).first -= index; + if (shuffle != last_resolve_shuffled) { + if (shuffle) { + alternative_index[0] = last_index + index; + alternative_index[index] = 0; + randomizeIndex(alternative_index, 1, rng); + last_index = 0; + } else { + last_index = alternative_index[index + last_index]; + for (uint32_t i = 0; i < alternative_index.size(); i++) + alternative_index[i] = i; + } + } else { + last_index += index; + } + track_list->erase(track_list->begin(), track_list->begin() + index); + track_list->erase(track_list->begin() + 1, track_list->end()); + uint32_t copyTracksSize = alternative_index.size() - last_index; + for (int i = 1; + i < (copyTracksSize < MAX_TRACKS ? copyTracksSize : MAX_TRACKS); i++) { + track_list->push_back( + TrackReference(jsonResult["pages"][0]["tracks"] + [alternative_index[i + last_index]]["uri"])); + } + last_resolve_shuffled = shuffle; + *this->index = 0; + static_cast(queue)->reloadTracks(); + return true; +} + +bool PlayerContext::resolveInitial(uint32_t index, bool shuffle, + std::vector& data) { + std::scoped_lock lock(*trackMutex); + index = *this->index; + auto jsonResult = nlohmann::json::parse(data); + if (jsonResult.find("pages") == jsonResult.end()) + return false; + // create a new_index based on track_list with all index -1 + std::vector new_index(track_list->size()); + std::fill(new_index.begin(), new_index.end(), -1); + alternative_index = {}; + TrackReference ref; + for (auto pages_itr : jsonResult["pages"]) { + if (pages_itr.find("tracks") == pages_itr.end()) + continue; + size_t alternative_offset = alternative_index.size(); + // add a index to alternative_index for each track in context + for (uint32_t i = alternative_offset; i < pages_itr["tracks"].size(); i++) + alternative_index.push_back(i); + // find tracks from track_list + for (const auto& track : pages_itr["tracks"]) { + ref = TrackReference(track["uri"]); + for (uint32_t i = 0; i < track_list->size(); i++) { + if (ref.gid == track_list->data()[i].gid) + new_index[i] = alternative_offset; + } + alternative_offset++; + } + } + if (new_index[index] == -1) + index--; + for (int64_t i = 0; i < new_index.size(); i++) { + if (new_index[i] == -1) { + if (i >= index) + queued_list->push_back( + std::make_pair(i - index, track_list->data()[i])); + track_list->erase(track_list->begin() + i); + new_index.erase(new_index.begin() + i); + i--; + } + } + if (shuffle) { + for (int i = 0; i < new_index.size(); i++) { + if (new_index[i] >= new_index.size()) { + alternative_index[new_index[i]] = alternative_index[i]; + alternative_index[i] = new_index[i]; + } else { + *std::find(alternative_index.begin(), alternative_index.end(), + new_index[i]) = alternative_index[i]; + alternative_index[i] = new_index[i]; + } + } + randomizeIndex(alternative_index, new_index.size(), rng); + } + track_list->erase(track_list->begin(), track_list->begin() + index); + last_index = shuffle ? index : new_index[index]; + last_resolve_shuffled = shuffle; + *this->index = 0; + //static_cast(queue)->reloadTracks(); + return true; +} \ No newline at end of file diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index aabc3d05..945d7b69 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -25,10 +25,12 @@ SpircHandler::SpircHandler(std::shared_ptr ctx) { this->playbackState = std::make_shared(ctx); this->trackQueue = std::make_shared(ctx, playbackState); - auto EOFCallback = [this]() { + auto EOFCallback = [this](bool loaded) { if (trackQueue->isFinished()) { sendEvent(EventType::DEPLETED); } + if (!loaded) + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); }; auto trackLoadedCallback = [this](std::shared_ptr track, @@ -98,6 +100,8 @@ void SpircHandler::notifyAudioReachedPlaybackEnd() { // Reset position in queued track currentTrack->requestedPosition = 0; } else if (!playbackState->innerFrame.state.repeat) { + currentTrack->trackMetrics->endTrack(); + ctx->playbackMetrics->sendEvent(currentTrack); trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); // we moved to next track, re-acquire currentTrack again currentTrack = trackQueue->consumeTrack(nullptr, offset); @@ -110,6 +114,8 @@ void SpircHandler::notifyAudioReachedPlayback() { // get HEAD track auto currentTrack = trackQueue->consumeTrack(nullptr, offset); + currentTrack->trackMetrics->startTrackPlaying( + currentTrack->requestedPosition); this->notify(); sendEvent(EventType::TRACK_INFO, currentTrack->trackInfo); diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index ff7a4b6f..0fb61e23 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -180,7 +180,7 @@ void TrackPlayer::runTask() { if (track->state != QueuedTrack::State::READY) { CSPOT_LOG(error, "Track failed to load, skipping it"); - this->eofCallback(); + this->eofCallback(false); continue; } } @@ -193,16 +193,17 @@ void TrackPlayer::runTask() { std::scoped_lock lock(playbackMutex); bool skipped = 0; + track->trackMetrics->startTrack(); currentTrackStream = track->getAudioFile(); - track->trackMetrics->startTrackDecoding(); - // Open the stream currentTrackStream->openStream(); if (pendingReset || !currentSongPlaying) { continue; } + track->trackMetrics->startTrackDecoding(); + track->trackMetrics->track_size = currentTrackStream->getSize(); #ifndef CONFIG_BELL_NOCODEC if (trackOffset == 0 && pendingSeekPositionMs == 0) { @@ -210,7 +211,6 @@ void TrackPlayer::runTask() { startPaused = false; } - track->trackMetrics->track_size = currentTrackStream->getSize(); int32_t r = ov_open_callbacks(this, &vorbisFile, NULL, 0, vorbisCallbacks); #else @@ -261,7 +261,6 @@ void TrackPlayer::runTask() { eof = false; track->loading = true; - track->trackMetrics->startTrack(track->requestedPosition); //in case of a repeatedtrack, set requested position to 0 track->requestedPosition = 0; @@ -347,9 +346,6 @@ void TrackPlayer::runTask() { // always move back to LOADING (ensure proper seeking after last track has been loaded) currentTrackStream = nullptr; track->loading = false; - track->trackMetrics->endTrack(); - std::vector result = - this->ctx->playbackMetrics->sendEvent(track); } if (eof) { @@ -357,7 +353,7 @@ void TrackPlayer::runTask() { endOfQueueReached = true; } - this->eofCallback(); + this->eofCallback(true); } } } diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 6d70e25b..732da6d1 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -25,10 +25,6 @@ using namespace cspot; -static void randomizeIndex(std::vector& index, uint16_t offset, - std::default_random_engine rng) { - std::shuffle(index.begin() + offset, index.end(), rng); -} namespace TrackDataUtils { bool countryListContains(char* countryList, const char* country) { @@ -148,6 +144,8 @@ QueuedTrack::~QueuedTrack() { if (pendingAudioKeyRequest != 0) { ctx->session->unregisterAudioKey(pendingAudioKeyRequest); } + pb_release(Track_fields, &pbTrack); + pb_release(Episode_fields, &pbEpisode); } std::shared_ptr QueuedTrack::getAudioFile() { @@ -383,8 +381,6 @@ TrackQueue::TrackQueue(std::shared_ptr ctx, playbackState->innerFrame.state.track.funcs.encode = &TrackReference::pbEncodeTrackList; playbackState->innerFrame.state.track.arg = &ghostTracks; - pbTrack = Track_init_zero; - pbEpisode = Episode_init_zero; // Start the task startTask(); @@ -394,9 +390,6 @@ TrackQueue::~TrackQueue() { stopTask(); std::scoped_lock lock(tracksMutex); - - pb_release(Track_fields, &pbTrack); - pb_release(Episode_fields, &pbEpisode); } TrackInfo TrackQueue::getTrackInfo(std::string_view identifier) { @@ -495,182 +488,43 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { this->playbackState->innerFrame.state.index = currentTracksIndex + offset; ghostTracks.clear(); //add SEND_OLD_TRACKS already played tracks - size_t ghostindex; - size_t index = currentTracksIndex + offset; - for (int i = 1; i <= this->playbackState->innerFrame.state.index; i++) { - ghostindex = index - i; - if (ghostindex < alt_index.size()) - ghostindex = alt_index[ghostindex]; - ghostTracks.push_back(currentTracks[ghostindex]); + size_t index = currentTracksIndex + offset - this->playbackState->innerFrame.state.index; + while(ghostTracks.size()playbackState->innerFrame.state.index){ + ghostTracks.push_back(currentTracks[index]); + index++; } if (queuedTracks.size() > 0) { - if (preloadedTracks[0]->ref.gid != queuedTracks[0].second.gid) { - ghostindex = index < alt_index.size() ? alt_index[index] : index; - ghostTracks.push_back(currentTracks[ghostindex]); + if (preloadedTracks[offset]->ref.gid != queuedTracks[0].second.gid) { + ghostTracks.push_back(currentTracks[index]); index++; } - for (auto track : queuedTracks) - ghostTracks.push_back(track.second); + else ghostTracks.push_back(queuedTracks[0].second); + for (auto track : queuedTracks){ + if(track.first != -1) break; + if(preloadedTracks[offset]->ref.gid != track.second.gid) { + ghostTracks.push_back(track.second); + } + } } - ghostindex = index; while (ghostTracks.size() < SEND_OLD_TRACKS + CONFIG_UPDATE_FUTURE_TRACKS && index < currentTracks.size()) { - ghostindex = index < alt_index.size() ? alt_index[index] : index; - ghostTracks.push_back(currentTracks[ghostindex]); - index++; - } -} - -void TrackQueue::loadRadio(std::string req) { - size_t keepTracks = currentTracks.size() - currentTracksIndex; - keepTracks = - keepTracks < inner_tracks_treshhold ? keepTracks : inner_tracks_treshhold; - if (keepTracks < inner_tracks_treshhold && continue_with_radio && - currentTracks.size()) { - - //if currentTrack is over the treshhold, remove some tracks from the front - if (currentTracks.size() > inner_tracks_treshhold * 3) { - uint32_t int_offset = currentTracks.size() - inner_tracks_treshhold; - currentTracks.erase(currentTracks.begin(), - currentTracks.begin() + int_offset); - currentTracksIndex -= int_offset; - } - - std::string requestUrl = string_format( - "hm://radio-apollo/v3/stations/%s?autoplay=true&offset=%i", &req[0], - radio_offset); - - auto responseHandler = [this](MercurySession::Response& res) { - std::scoped_lock lock(tracksMutex); - CSPOT_LOG(info, "Fetched new radio tracks"); - - if (res.parts[0].size() == 0) - return; - auto jsonResult = nlohmann::json::parse(res.parts[0]); - radio_offset += jsonResult["tracks"].size(); - std::string uri; - for (int i = 0; i < jsonResult["tracks"].size(); i++) { - currentTracks.push_back( - TrackReference(jsonResult["tracks"][i]["original_gid"], "radio")); - } - this->ctx->playbackMetrics->correlation_id = jsonResult["correlation_id"]; - if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { - queueNextTrack(preloadedTracks.size()); - } - }; - // Execute the request - ctx->session->execute(MercurySession::RequestType::GET, requestUrl, - responseHandler); - } -} - -void TrackQueue::resolveAutoplay() { - if (!this->playbackState->innerFrame.state.context_uri) - return; - std::string requestUrl = - string_format("hm://autoplay-enabled/query?uri=%s", - this->playbackState->innerFrame.state.context_uri); - auto responseHandler = [this](MercurySession::Response& res) { - if (res.parts.size()) { - loadRadio(std::string(res.parts[0].begin(), res.parts[0].end())); - } - }; - // Execute the request - ctx->session->execute(MercurySession::RequestType::GET, requestUrl, - responseHandler); -} - -void TrackQueue::resolveContext() { - std::scoped_lock lock(tracksMutex); - std::string requestUrl = - string_format("hm://context-resolve/v1/%s", - this->playbackState->innerFrame.state.context_uri); - auto responseHandler = [this](MercurySession::Response& res) { - if (!res.parts.size()) - return; - std::scoped_lock lock(tracksMutex); - auto jsonResult = nlohmann::json::parse(res.parts[0]); - //do nothing if last track is the same as last track in currentTracks - for (auto pages_itr : jsonResult["pages"]) { - TrackReference _ref; - int32_t front = 0; - if (pages_itr.find("tracks") == pages_itr.end()) - continue; - if (this->playbackState->innerFrame.state.shuffle) { - std::vector new_index = {}; - std::vector new_tracks = {}; - for (const auto& track : pages_itr["tracks"]) { - new_tracks.push_back(TrackReference(track["uri"])); - } - for (const auto& itr : currentTracks) { - auto currentTracksIter = - std::find(new_tracks.begin(), new_tracks.end(), itr); - if (currentTracksIter != new_tracks.end()) { - int32_t old_index = - std::distance(new_tracks.begin(), currentTracksIter); - new_index.push_back(old_index); - } else { - int newIndex = new_tracks.size(); - new_tracks.push_back(itr); - new_index.push_back(newIndex); - } - } - for (uint32_t i = 0; i < new_index.size(); i++) - if (std::find(new_index.begin(), new_index.end(), i) == - new_index.end()) - new_index.push_back(i); - randomizeIndex(new_index, currentTracks.size(), rng); - alt_index = new_index; - currentTracks = new_tracks; - } else { - auto altref = currentTracks.front().gid; - uint8_t loop_pointer = 0; - for (auto itr : pages_itr["tracks"]) { - _ref = TrackReference(itr["uri"]); - switch (loop_pointer) { - case 0: - if (_ref.gid == altref) { - loop_pointer++; - altref = currentTracks.back().gid; - if (altref == base62Decode(pages_itr["tracks"].back()["uri"])) - goto exit_loop; - } else { - //for completion of the trasklist in case of shuffle, add missing item too the front - currentTracks.insert(currentTracks.begin() + front, _ref); - front++; - } - break; - case 1: - if (_ref.gid == altref) - loop_pointer++; - break; - case 2: - //add missing tracks to the back - currentTracks.push_back(_ref); - break; - default: - break; - } + if (queuedTracks.size() > 0) { + for (auto track : queuedTracks){ + if(track.first == index && preloadedTracks[offset]->ref.gid != track.second.gid) { + ghostTracks.push_back(track.second); } - exit_loop:; - currentTracksIndex += front; - alt_index.clear(); - for (int32_t i = 0; i < currentTracks.size(); i++) - alt_index.push_back(i); + else break; } - currentTracksSize = currentTracks.size(); - CSPOT_LOG(info, "Resolved context, new currentTracks-size = %i", - currentTracksSize); } - }; - ctx->session->execute(MercurySession::RequestType::GET, requestUrl, - responseHandler); + ghostTracks.push_back(currentTracks[index]); + index++; + } } void TrackQueue::processTrack(std::shared_ptr track) { switch (track->state) { case QueuedTrack::State::QUEUED: - track->stepLoadMetadata(&pbTrack, &pbEpisode, tracksMutex, + track->stepLoadMetadata(&track->pbTrack, &track->pbEpisode, tracksMutex, processSemaphore); break; case QueuedTrack::State::KEY_REQUIRED: @@ -680,14 +534,9 @@ void TrackQueue::processTrack(std::shared_ptr track) { track->stepLoadCDNUrl(accessKey); if (track->state == QueuedTrack::State::READY) { - if (!context_resolved) { - resolveContext(); - context_resolved = true; - } - if (continue_with_radio) - if (preloadedTracks.size() + currentTracksIndex >= + if (preloadedTracks.size() + currentTracksIndex + 1>= currentTracks.size()) - resolveAutoplay(); + playerContext->resolveContext(currentTracksIndex, this->playbackState->innerFrame.state.shuffle, this->playbackState->innerFrame.state.context_uri); if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { // Queue a new track to preload queueNextTrack(preloadedTracks.size()); @@ -703,23 +552,21 @@ void TrackQueue::processTrack(std::shared_ptr track) { bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { int requestedRefIndex = offset + currentTracksIndex; if (queuedTracks.size()) { + if (requestedRefIndex != queuedTracks[0].first && queuedTracks[0].first != -1) goto queueNext; for (auto track : queuedTracks) { - if (preloadedTracks.size() >= MAX_TRACKS_PRELOAD) - return true; for (auto loaded_track : preloadedTracks) { - if (track.second.gid == loaded_track->ref.gid) - goto loadedTrackAlready; + if (track.second.gid == loaded_track->ref.gid ) goto noNeedToLoadTrack; + else if (requestedRefIndex != queuedTracks[0].first && queuedTracks[0].first != -1) goto queueNext; } preloadedTracks.push_back( std::make_shared(track.second, ctx, 0)); - loadedTrackAlready:; + return true; + noNeedToLoadTrack:; } - if (preloadedTracks.size() >= MAX_TRACKS_PRELOAD) - return true; } - if (playbackState->innerFrame.state.shuffle && - requestedRefIndex < alt_index.size()) - requestedRefIndex = alt_index[requestedRefIndex]; + queueNext:; + if (preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid ) + requestedRefIndex--; if (requestedRefIndex < 0 || requestedRefIndex >= currentTracks.size()) { return false; @@ -745,7 +592,6 @@ bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { bool skipped = true; std::scoped_lock lock(tracksMutex); - if (dir == SkipDirection::PREV) { uint64_t position = !playbackState->innerFrame.state.has_position_ms @@ -767,16 +613,16 @@ bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { } } else { if (currentTracks.size() > currentTracksIndex + 1) { - if (queuedTracks.size() > 0) { + if (queuedTracks.size() > 0 && (currentTracksIndex == queuedTracks[0].first || queuedTracks[0].first == -1)) { if (preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid) { queuedTracks.pop_front(); preloadedTracks.pop_front(); - if (queuedTracks.size() <= 0) { - queueNextTrack(1); + if (queuedTracks.size() <= 0 || currentTracksIndex != queuedTracks[0].first) { + queueNextTrack(preloadedTracks.size()); } } else { preloadedTracks.pop_front(); - currentTracksIndex++; + queueNextTrack(preloadedTracks.size()+1); } } else { preloadedTracks.pop_front(); @@ -815,24 +661,16 @@ bool TrackQueue::isFinished() { } void TrackQueue::shuffle_tracks(bool shuffleTracks) { - std::scoped_lock lock(tracksMutex); - if (!shuffleTracks) - currentTracksIndex = alt_index[currentTracksIndex]; - alt_index.clear(); - for (int i = 0; i < currentTracksSize; i++) - alt_index.push_back(i); - if (shuffleTracks) { - alt_index[currentTracksIndex] = 0; - alt_index[0] = currentTracksIndex; - randomizeIndex(alt_index, 1, rng); - currentTracksIndex = 0; - } - preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); - // Push a song on the preloaded queue - queueNextTrack(1, 0); - update_ghost_tracks(); + playerContext->resolveContext(currentTracksIndex, this->playbackState->innerFrame.state.shuffle, this->playbackState->innerFrame.state.context_uri); } +void TrackQueue::reloadTracks(uint8_t offset){ + preloadedTracks.erase(preloadedTracks.begin() + offset, preloadedTracks.end()); + //preloadedTracks.clear(); + queueNextTrack(1); + update_ghost_tracks(); + //this->ctx->handler->notify(); +} bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { std::scoped_lock lock(tracksMutex); bool cleared = true; @@ -841,14 +679,10 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { // initialize new random_engine rng = std::default_random_engine{rd()}; // Copy requested track list + queuedTracks = {}; currentTracks = playbackState->remoteTracks; currentTracksIndex = playbackState->innerFrame.state.playing_track_index; - currentTracksSize = currentTracks.size(); - - // Revert the alternative Index to it's inital Index structure - alt_index.clear(); - for (int i = 0; i < playbackState->remoteTracks.size(); i++) - alt_index.push_back(i); + playerContext = std::make_unique(this, ctx, ¤tTracks, &queuedTracks, &tracksMutex, ¤tTracksIndex, playbackState->innerFrame.state.shuffle, playbackState->innerFrame.state.context_uri); // Clear preloaded tracks preloadedTracks.clear(); @@ -864,8 +698,7 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { playableSemaphore->give(); } else { - queuedTracks.push_back(std::make_pair( - currentTracksIndex + 1, + queuedTracks.push_back(std::make_pair( -1, playbackState->remoteTracks[playbackState->innerFrame.state.index + 1 + queuedTracks.size()])); preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); diff --git a/targets/esp32/components/VS1053/src/VS1053.cpp b/targets/esp32/components/VS1053/src/VS1053.cpp index b710fa6b..d1fb1a3d 100644 --- a/targets/esp32/components/VS1053/src/VS1053.cpp +++ b/targets/esp32/components/VS1053/src/VS1053.cpp @@ -121,7 +121,7 @@ esp_err_t VS1053_SINK::init(spi_host_device_t SPI, //load_user_code(PLUGIN, PLUGIN_SIZE); #endif vTaskDelay(100 / portTICK_PERIOD_MS); - xTaskCreate(vs_feed, "track_feed", 4098, (void*)this, 1, &task_handle); + xTaskCreate(vs_feed, "track_feed", 4098, (void*)this, 10, &task_handle); return ESP_OK; } @@ -177,7 +177,8 @@ bool VS1053_SINK::is_cancelled(VS1053_TRACK::VS_TRACK_STATE* state, return false; } void VS1053_SINK::delete_all_tracks(void) { - this->tracks.erase(tracks.begin() + 1, tracks.end()); + if (this->tracks.size() > 1) + this->tracks.erase(tracks.begin() + 1, tracks.end()); if (this->tracks[0]->state != VS1053_TRACK::VS_TRACK_STATE::tsStopped) new_state(this->tracks[0]->state, VS1053_TRACK::VS_TRACK_STATE::tsCancel); } diff --git a/targets/esp32/main/main.cpp b/targets/esp32/main/main.cpp index 3fbd9647..f26cf449 100644 --- a/targets/esp32/main/main.cpp +++ b/targets/esp32/main/main.cpp @@ -289,7 +289,7 @@ void app_main(void) { //auto taskHandle = xTaskCreatePinnedToCore(&cspotTask, "cspot", 12*1024, NULL, 5, NULL, 1); /*auto taskHandle = */ bell::setDefaultLogger(); - bell::enableTimestampLogging(); + //bell::enableTimestampLogging(); auto task = std::make_unique(); vTaskSuspend(NULL); } From b0c62c0835bc78e7bcb639a477279f7f231b117a Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Sun, 21 Jul 2024 11:32:12 +0200 Subject: [PATCH 31/41] minor changes --- cspot/src/TrackQueue.cpp | 89 ++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 732da6d1..8e245ffb 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -25,7 +25,6 @@ using namespace cspot; - namespace TrackDataUtils { bool countryListContains(char* countryList, const char* country) { uint16_t countryList_length = strlen(countryList); @@ -488,8 +487,9 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { this->playbackState->innerFrame.state.index = currentTracksIndex + offset; ghostTracks.clear(); //add SEND_OLD_TRACKS already played tracks - size_t index = currentTracksIndex + offset - this->playbackState->innerFrame.state.index; - while(ghostTracks.size()playbackState->innerFrame.state.index){ + size_t index = + currentTracksIndex + offset - this->playbackState->innerFrame.state.index; + while (ghostTracks.size() < this->playbackState->innerFrame.state.index) { ghostTracks.push_back(currentTracks[index]); index++; } @@ -497,11 +497,12 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { if (preloadedTracks[offset]->ref.gid != queuedTracks[0].second.gid) { ghostTracks.push_back(currentTracks[index]); index++; - } - else ghostTracks.push_back(queuedTracks[0].second); - for (auto track : queuedTracks){ - if(track.first != -1) break; - if(preloadedTracks[offset]->ref.gid != track.second.gid) { + } else + ghostTracks.push_back(queuedTracks[0].second); + for (auto track : queuedTracks) { + if (track.first != -1) + break; + if (preloadedTracks[offset]->ref.gid != track.second.gid) { ghostTracks.push_back(track.second); } } @@ -509,11 +510,12 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { while (ghostTracks.size() < SEND_OLD_TRACKS + CONFIG_UPDATE_FUTURE_TRACKS && index < currentTracks.size()) { if (queuedTracks.size() > 0) { - for (auto track : queuedTracks){ - if(track.first == index && preloadedTracks[offset]->ref.gid != track.second.gid) { + for (auto track : queuedTracks) { + if (track.first == index && + preloadedTracks[offset]->ref.gid != track.second.gid) { ghostTracks.push_back(track.second); - } - else break; + } else + break; } } ghostTracks.push_back(currentTracks[index]); @@ -534,9 +536,11 @@ void TrackQueue::processTrack(std::shared_ptr track) { track->stepLoadCDNUrl(accessKey); if (track->state == QueuedTrack::State::READY) { - if (preloadedTracks.size() + currentTracksIndex + 1>= - currentTracks.size()) - playerContext->resolveContext(currentTracksIndex, this->playbackState->innerFrame.state.shuffle, this->playbackState->innerFrame.state.context_uri); + if (preloadedTracks.size() + currentTracksIndex + 1 >= + currentTracks.size()) + playerContext->resolveContext( + currentTracksIndex, this->playbackState->innerFrame.state.shuffle, + this->playbackState->innerFrame.state.context_uri); if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { // Queue a new track to preload queueNextTrack(preloadedTracks.size()); @@ -552,20 +556,25 @@ void TrackQueue::processTrack(std::shared_ptr track) { bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { int requestedRefIndex = offset + currentTracksIndex; if (queuedTracks.size()) { - if (requestedRefIndex != queuedTracks[0].first && queuedTracks[0].first != -1) goto queueNext; + if (requestedRefIndex != queuedTracks[0].first && + queuedTracks[0].first != -1) + goto queueNext; for (auto track : queuedTracks) { for (auto loaded_track : preloadedTracks) { - if (track.second.gid == loaded_track->ref.gid ) goto noNeedToLoadTrack; - else if (requestedRefIndex != queuedTracks[0].first && queuedTracks[0].first != -1) goto queueNext; + if (track.second.gid == loaded_track->ref.gid) + goto noNeedToLoadTrack; + else if (requestedRefIndex != queuedTracks[0].first && + queuedTracks[0].first != -1) + goto queueNext; } preloadedTracks.push_back( std::make_shared(track.second, ctx, 0)); - return true; + return true; noNeedToLoadTrack:; } } - queueNext:; - if (preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid ) +queueNext:; + if (preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid) requestedRefIndex--; if (requestedRefIndex < 0 || requestedRefIndex >= currentTracks.size()) { @@ -613,16 +622,19 @@ bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { } } else { if (currentTracks.size() > currentTracksIndex + 1) { - if (queuedTracks.size() > 0 && (currentTracksIndex == queuedTracks[0].first || queuedTracks[0].first == -1)) { + if (queuedTracks.size() > 0 && + (currentTracksIndex == queuedTracks[0].first || + queuedTracks[0].first == -1)) { if (preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid) { queuedTracks.pop_front(); preloadedTracks.pop_front(); - if (queuedTracks.size() <= 0 || currentTracksIndex != queuedTracks[0].first) { + if (queuedTracks.size() <= 0 || + currentTracksIndex != queuedTracks[0].first) { queueNextTrack(preloadedTracks.size()); } } else { preloadedTracks.pop_front(); - queueNextTrack(preloadedTracks.size()+1); + queueNextTrack(preloadedTracks.size() + 1); } } else { preloadedTracks.pop_front(); @@ -661,15 +673,17 @@ bool TrackQueue::isFinished() { } void TrackQueue::shuffle_tracks(bool shuffleTracks) { - playerContext->resolveContext(currentTracksIndex, this->playbackState->innerFrame.state.shuffle, this->playbackState->innerFrame.state.context_uri); + playerContext->resolveContext( + currentTracksIndex, this->playbackState->innerFrame.state.shuffle, + this->playbackState->innerFrame.state.context_uri); } -void TrackQueue::reloadTracks(uint8_t offset){ - preloadedTracks.erase(preloadedTracks.begin() + offset, preloadedTracks.end()); - //preloadedTracks.clear(); - queueNextTrack(1); - update_ghost_tracks(); - //this->ctx->handler->notify(); - +void TrackQueue::reloadTracks(uint8_t offset) { + preloadedTracks.erase(preloadedTracks.begin() + offset, + preloadedTracks.end()); + //preloadedTracks.clear(); + queueNextTrack(1); + update_ghost_tracks(); + //this->ctx->handler->notify(); } bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { std::scoped_lock lock(tracksMutex); @@ -682,7 +696,10 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { queuedTracks = {}; currentTracks = playbackState->remoteTracks; currentTracksIndex = playbackState->innerFrame.state.playing_track_index; - playerContext = std::make_unique(this, ctx, ¤tTracks, &queuedTracks, &tracksMutex, ¤tTracksIndex, playbackState->innerFrame.state.shuffle, playbackState->innerFrame.state.context_uri); + playerContext = std::make_unique( + this, ctx, ¤tTracks, &queuedTracks, &tracksMutex, + ¤tTracksIndex, playbackState->innerFrame.state.shuffle, + playbackState->innerFrame.state.context_uri); // Clear preloaded tracks preloadedTracks.clear(); @@ -698,9 +715,9 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { playableSemaphore->give(); } else { - queuedTracks.push_back(std::make_pair( -1, - playbackState->remoteTracks[playbackState->innerFrame.state.index + 1 + - queuedTracks.size()])); + queuedTracks.push_back(std::make_pair( + -1, playbackState->remoteTracks[playbackState->innerFrame.state.index + + 1 + queuedTracks.size()])); preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); queueNextTrack(1); cleared = false; From 4fc99ce88f30f227e959af2d232ea43fb34fffc1 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Sun, 21 Jul 2024 11:49:09 +0200 Subject: [PATCH 32/41] changed the track feedback a little, so it'll skip to the next track if there are any missreads in the stream --- cspot/src/TrackPlayer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index 0fb61e23..4e542ac0 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -132,6 +132,7 @@ void TrackPlayer::runTask() { bool endOfQueueReached = false; while (isRunning) { + bool properStream = true; // Ensure we even have any tracks to play if (!this->trackQueue->hasTracks() || (!pendingReset && endOfQueueReached && trackQueue->isFinished())) { @@ -297,6 +298,7 @@ void TrackPlayer::runTask() { if (ret < 0) { CSPOT_LOG(error, "An error has occured in the stream %d", ret); currentSongPlaying = false; + properStream = false; } else { if (ret == 0) { CSPOT_LOG(info, "EOF"); @@ -352,9 +354,8 @@ void TrackPlayer::runTask() { if (trackQueue->isFinished()) { endOfQueueReached = true; } - - this->eofCallback(true); } + this->eofCallback(properStream); } } From 050cb324a6bf5fb7443da1e44ad382b72c94c090 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 22 Jul 2024 16:39:43 +0200 Subject: [PATCH 33/41] finally a proper track loading process --- cspot/include/TrackQueue.h | 2 +- cspot/src/PlayerContext.cpp | 2 +- cspot/src/SpircHandler.cpp | 22 +++++++++--------- cspot/src/TrackPlayer.cpp | 4 ++-- cspot/src/TrackQueue.cpp | 46 ++++++++++++++----------------------- 5 files changed, 32 insertions(+), 44 deletions(-) diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index abf7a6e3..8c2437e2 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -125,7 +125,7 @@ class TrackQueue : public bell::Task { std::shared_ptr prevSong, int& offset); private: - static const int MAX_TRACKS_PRELOAD = 2; + static const int MAX_TRACKS_PRELOAD = 3; std::shared_ptr accessKeyFetcher; std::shared_ptr ctx; diff --git a/cspot/src/PlayerContext.cpp b/cspot/src/PlayerContext.cpp index cb9c0a81..d190625f 100644 --- a/cspot/src/PlayerContext.cpp +++ b/cspot/src/PlayerContext.cpp @@ -203,6 +203,6 @@ bool PlayerContext::resolveInitial(uint32_t index, bool shuffle, last_index = shuffle ? index : new_index[index]; last_resolve_shuffled = shuffle; *this->index = 0; - //static_cast(queue)->reloadTracks(); + static_cast(queue)->reloadTracks(); return true; } \ No newline at end of file diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index 945d7b69..e27e26cc 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -30,7 +30,7 @@ SpircHandler::SpircHandler(std::shared_ptr ctx) { sendEvent(EventType::DEPLETED); } if (!loaded) - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, true); }; auto trackLoadedCallback = [this](std::shared_ptr track, @@ -92,21 +92,13 @@ void SpircHandler::notifyAudioReachedPlaybackEnd() { // get HEAD track auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - if (trackQueue->notifyPending) { - trackQueue->notifyPending = false; - - playbackState->updatePositionMs(currentTrack->requestedPosition); - - // Reset position in queued track - currentTrack->requestedPosition = 0; - } else if (!playbackState->innerFrame.state.repeat) { + if (!playbackState->innerFrame.state.repeat) { currentTrack->trackMetrics->endTrack(); ctx->playbackMetrics->sendEvent(currentTrack); - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, true); // we moved to next track, re-acquire currentTrack again currentTrack = trackQueue->consumeTrack(nullptr, offset); } - playbackState->updatePositionMs(0); } void SpircHandler::notifyAudioReachedPlayback() { @@ -116,6 +108,14 @@ void SpircHandler::notifyAudioReachedPlayback() { auto currentTrack = trackQueue->consumeTrack(nullptr, offset); currentTrack->trackMetrics->startTrackPlaying( currentTrack->requestedPosition); + if (trackQueue->notifyPending) { + trackQueue->notifyPending = false; + + playbackState->updatePositionMs(currentTrack->requestedPosition); + + // Reset position in queued track + currentTrack->requestedPosition = 0; + } this->notify(); sendEvent(EventType::TRACK_INFO, currentTrack->trackInfo); diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index 4e542ac0..e82d8d6a 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -158,7 +158,6 @@ void TrackPlayer::runTask() { } newTrack = trackQueue->consumeTrack(track, trackOffset); - this->trackQueue->update_ghost_tracks(trackOffset); if (newTrack == nullptr) { if (trackOffset == -1) { @@ -299,6 +298,7 @@ void TrackPlayer::runTask() { CSPOT_LOG(error, "An error has occured in the stream %d", ret); currentSongPlaying = false; properStream = false; + eof = true; } else { if (ret == 0) { CSPOT_LOG(info, "EOF"); @@ -354,8 +354,8 @@ void TrackPlayer::runTask() { if (trackQueue->isFinished()) { endOfQueueReached = true; } + this->eofCallback(properStream); } - this->eofCallback(properStream); } } diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 8e245ffb..08b01dc6 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -424,6 +424,7 @@ void TrackQueue::runTask() { } for (auto& track : trackQueue) { + std::scoped_lock lock(tracksMutex); if (track) { this->processTrack(track); } @@ -494,7 +495,7 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { index++; } if (queuedTracks.size() > 0) { - if (preloadedTracks[offset]->ref.gid != queuedTracks[0].second.gid) { + if (preloadedTracks[0]->ref.gid != queuedTracks[0].second.gid) { ghostTracks.push_back(currentTracks[index]); index++; } else @@ -502,7 +503,7 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { for (auto track : queuedTracks) { if (track.first != -1) break; - if (preloadedTracks[offset]->ref.gid != track.second.gid) { + if (preloadedTracks[0]->ref.gid != track.second.gid) { ghostTracks.push_back(track.second); } } @@ -514,7 +515,7 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { if (track.first == index && preloadedTracks[offset]->ref.gid != track.second.gid) { ghostTracks.push_back(track.second); - } else + } else if (track.first > index) break; } } @@ -556,16 +557,14 @@ void TrackQueue::processTrack(std::shared_ptr track) { bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { int requestedRefIndex = offset + currentTracksIndex; if (queuedTracks.size()) { - if (requestedRefIndex != queuedTracks[0].first && - queuedTracks[0].first != -1) - goto queueNext; for (auto track : queuedTracks) { + if (track.first > requestedRefIndex) + goto queueNext; for (auto loaded_track : preloadedTracks) { - if (track.second.gid == loaded_track->ref.gid) + if (track.second.gid == loaded_track->ref.gid) { + requestedRefIndex--; goto noNeedToLoadTrack; - else if (requestedRefIndex != queuedTracks[0].first && - queuedTracks[0].first != -1) - goto queueNext; + } } preloadedTracks.push_back( std::make_shared(track.second, ctx, 0)); @@ -574,8 +573,6 @@ bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { } } queueNext:; - if (preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid) - requestedRefIndex--; if (requestedRefIndex < 0 || requestedRefIndex >= currentTracks.size()) { return false; @@ -622,21 +619,12 @@ bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { } } else { if (currentTracks.size() > currentTracksIndex + 1) { - if (queuedTracks.size() > 0 && - (currentTracksIndex == queuedTracks[0].first || - queuedTracks[0].first == -1)) { - if (preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid) { + { + if (queuedTracks.size() > 0 && + preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid) { + currentTracksIndex--; queuedTracks.pop_front(); - preloadedTracks.pop_front(); - if (queuedTracks.size() <= 0 || - currentTracksIndex != queuedTracks[0].first) { - queueNextTrack(preloadedTracks.size()); - } - } else { - preloadedTracks.pop_front(); - queueNextTrack(preloadedTracks.size() + 1); } - } else { preloadedTracks.pop_front(); if (!queueNextTrack(preloadedTracks.size() + 1)) { CSPOT_LOG(info, "Failed to queue next track"); @@ -657,6 +645,7 @@ bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { notifyPending = true; } } + update_ghost_tracks(); return skipped; } @@ -678,10 +667,10 @@ void TrackQueue::shuffle_tracks(bool shuffleTracks) { this->playbackState->innerFrame.state.context_uri); } void TrackQueue::reloadTracks(uint8_t offset) { - preloadedTracks.erase(preloadedTracks.begin() + offset, - preloadedTracks.end()); + if (preloadedTracks.size()) + preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); //preloadedTracks.clear(); - queueNextTrack(1); + queueNextTrack(preloadedTracks.size()); update_ghost_tracks(); //this->ctx->handler->notify(); } @@ -710,7 +699,6 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { } // We already updated track meta, mark it - notifyPending = true; radio_offset = 0; playableSemaphore->give(); From c6a5c4d920c0c3a8738b3fd202059e0349beeeee Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Mon, 22 Jul 2024 22:01:45 +0200 Subject: [PATCH 34/41] moved trackmetrics playStart back to TrackPlayer because needed --- cspot/src/SpircHandler.cpp | 2 -- cspot/src/TrackPlayer.cpp | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index e27e26cc..4b92dbe9 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -106,8 +106,6 @@ void SpircHandler::notifyAudioReachedPlayback() { // get HEAD track auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - currentTrack->trackMetrics->startTrackPlaying( - currentTrack->requestedPosition); if (trackQueue->notifyPending) { trackQueue->notifyPending = false; diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index e82d8d6a..6014f6bb 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -263,6 +263,7 @@ void TrackPlayer::runTask() { track->loading = true; //in case of a repeatedtrack, set requested position to 0 track->requestedPosition = 0; + track->trackMetrics->startTrackPlaying(track->requestedPosition); CSPOT_LOG(info, "Playing"); From ff981b1731ef00e79304a5405d8676f01f6645c7 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 30 Jul 2024 22:06:15 +0200 Subject: [PATCH 35/41] changes in track queueing --- cspot/include/TrackQueue.h | 7 ++-- cspot/protobuf/spirc.options | 2 ++ cspot/protobuf/spirc.proto | 2 ++ cspot/src/PlaybackState.cpp | 11 +++++++ cspot/src/PlayerContext.cpp | 12 +++---- cspot/src/SpircHandler.cpp | 33 +++++++------------ cspot/src/TrackPlayer.cpp | 10 ++++-- cspot/src/TrackQueue.cpp | 32 +++++++++++++----- .../esp32/components/VS1053/src/VS1053.cpp | 6 ++-- 9 files changed, 69 insertions(+), 46 deletions(-) diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 8c2437e2..31ac58c6 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -109,6 +109,7 @@ class TrackQueue : public bell::Task { std::shared_ptr playableSemaphore; std::shared_ptr playbackState; std::atomic notifyPending = false; + std::function notifyCallback; void runTask() override; void stopTask(); @@ -123,6 +124,7 @@ class TrackQueue : public bell::Task { TrackInfo getTrackInfo(std::string_view identifier); std::shared_ptr consumeTrack( std::shared_ptr prevSong, int& offset); + std::deque> preloadedTracks; private: static const int MAX_TRACKS_PRELOAD = 3; @@ -132,9 +134,8 @@ class TrackQueue : public bell::Task { std::shared_ptr processSemaphore; std::unique_ptr playerContext; - std::deque> preloadedTracks; std::deque> queuedTracks = {}; - std::vector currentTracks; + std::vector currentTracks = {}; std::vector ghostTracks; std::mutex tracksMutex, runningMutex; @@ -144,7 +145,7 @@ class TrackQueue : public bell::Task { uint32_t currentTracksIndex = -1; bool isRunning = false; - bool context_resolved = false; + bool contextResolved = false; bool continue_with_radio = true; std::random_device rd; diff --git a/cspot/protobuf/spirc.options b/cspot/protobuf/spirc.options index b7331f53..1804712a 100644 --- a/cspot/protobuf/spirc.options +++ b/cspot/protobuf/spirc.options @@ -7,4 +7,6 @@ DeviceState.sw_version type:FT_POINTER DeviceState.name type:FT_POINTER DeviceState.capabilities max_count:17, fixed_count:false State.context_uri type:FT_POINTER +State.last_command_ident type:FT_POINTER +State.context_description type:FT_POINTER TrackRef.queued type:FT_CALLBACK \ No newline at end of file diff --git a/cspot/protobuf/spirc.proto b/cspot/protobuf/spirc.proto index 5d54bd26..fcd3a512 100644 --- a/cspot/protobuf/spirc.proto +++ b/cspot/protobuf/spirc.proto @@ -43,6 +43,8 @@ message State { optional string context_description = 0x8; optional bool shuffle = 0xd; optional bool repeat = 0xe; + optional string last_command_ident = 0x14; + optional uint32 last_command_msgid = 0x15; optional uint32 playing_track_index = 0x1a; repeated TrackRef track = 0x1b; } diff --git a/cspot/src/PlaybackState.cpp b/cspot/src/PlaybackState.cpp index 56cca32e..de5863c7 100644 --- a/cspot/src/PlaybackState.cpp +++ b/cspot/src/PlaybackState.cpp @@ -116,6 +116,17 @@ void PlaybackState::syncWithRemote() { strcpy(innerFrame.state.context_uri, remoteFrame.state.context_uri); + if (remoteFrame.state.context_description != NULL) { + innerFrame.state.context_description = + (char*)realloc(innerFrame.state.context_description, + strlen(remoteFrame.state.context_description) + 1); + strcpy(innerFrame.state.context_description, + remoteFrame.state.context_description); + } else { + free(innerFrame.state.context_description); + innerFrame.state.context_description = NULL; + } + innerFrame.state.has_playing_track_index = true; innerFrame.state.playing_track_index = remoteFrame.state.playing_track_index; innerFrame.state.has_shuffle = remoteFrame.state.has_shuffle; diff --git a/cspot/src/PlayerContext.cpp b/cspot/src/PlayerContext.cpp index d190625f..726a1214 100644 --- a/cspot/src/PlayerContext.cpp +++ b/cspot/src/PlayerContext.cpp @@ -24,18 +24,18 @@ PlayerContext::PlayerContext( this->index = index; rng = std::default_random_engine{rd()}; std::string requestUrl = string_format("hm://context-resolve/v1/%s", uri); - auto responseHandler = [this, shuffle](MercurySession::Response& res) { + auto responseHandler = [this, shuffle, uri](MercurySession::Response& res) { if (!res.parts.size()) return; if (!res.parts[0].size()) return; this->resolveInitial(*this->index, shuffle, res.parts[0]); + if (this->track_list->size() < 30) + resolveContext(*this->index, shuffle, uri); }; ctx->session->execute(MercurySession::RequestType::GET, requestUrl, responseHandler); - if (track_list->size() < 30) - resolveContext(*this->index, shuffle, uri); } static void randomizeIndex(std::vector& index, uint16_t offset, @@ -111,8 +111,6 @@ bool PlayerContext::resolveTracklist(uint32_t index, bool shuffle, index = *this->index; std::scoped_lock lock(*trackMutex); auto jsonResult = nlohmann::json::parse(data); - if (queued_list->at(0).first == 0 || queued_list->at(0).first == -1) - index--; for (uint32_t i = 0; i < queued_list->size(); i++) if (queued_list->at(i).first != -1) queued_list->at(i).first -= index; @@ -199,10 +197,8 @@ bool PlayerContext::resolveInitial(uint32_t index, bool shuffle, } randomizeIndex(alternative_index, new_index.size(), rng); } - track_list->erase(track_list->begin(), track_list->begin() + index); - last_index = shuffle ? index : new_index[index]; + last_index = shuffle ? 0 : new_index[0]; last_resolve_shuffled = shuffle; - *this->index = 0; static_cast(queue)->reloadTracks(); return true; } \ No newline at end of file diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index 4b92dbe9..a52f857f 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -25,12 +25,16 @@ SpircHandler::SpircHandler(std::shared_ptr ctx) { this->playbackState = std::make_shared(ctx); this->trackQueue = std::make_shared(ctx, playbackState); + trackQueue->notifyCallback = [this]() { + this->notify(); + }; + auto EOFCallback = [this](bool loaded) { if (trackQueue->isFinished()) { sendEvent(EventType::DEPLETED); } if (!loaded) - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, true); + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); }; auto trackLoadedCallback = [this](std::shared_ptr track, @@ -39,8 +43,6 @@ SpircHandler::SpircHandler(std::shared_ptr ctx) { : PlaybackState::State::Playing); playbackState->updatePositionMs(track->requestedPosition); - this->notify(); - // Send playback start event, pause/unpause per request sendEvent(EventType::PLAYBACK_START, (int)track->requestedPosition); sendEvent(EventType::PLAY_PAUSE, paused); @@ -95,10 +97,13 @@ void SpircHandler::notifyAudioReachedPlaybackEnd() { if (!playbackState->innerFrame.state.repeat) { currentTrack->trackMetrics->endTrack(); ctx->playbackMetrics->sendEvent(currentTrack); - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, true); - // we moved to next track, re-acquire currentTrack again - currentTrack = trackQueue->consumeTrack(nullptr, offset); + if (!trackQueue->notifyPending) + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); + else + trackQueue->notifyPending = false; } + trackQueue->update_ghost_tracks(); + notify(); } void SpircHandler::notifyAudioReachedPlayback() { @@ -106,16 +111,6 @@ void SpircHandler::notifyAudioReachedPlayback() { // get HEAD track auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - if (trackQueue->notifyPending) { - trackQueue->notifyPending = false; - - playbackState->updatePositionMs(currentTrack->requestedPosition); - - // Reset position in queued track - currentTrack->requestedPosition = 0; - } - this->notify(); - sendEvent(EventType::TRACK_INFO, currentTrack->trackInfo); } @@ -148,16 +143,12 @@ void SpircHandler::handleFrame(std::vector& data) { ctx->playbackMetrics->end_source = influence; this->trackPlayer->stop(); sendEvent(EventType::DISC); + trackQueue->preloadedTracks.clear(); } break; } case MessageType_kMessageTypeSeek: { this->trackPlayer->seekMs(playbackState->remoteFrame.position); - - playbackState->updatePositionMs(playbackState->remoteFrame.position); - - notify(); - sendEvent(EventType::SEEK, (int)playbackState->remoteFrame.position); break; } diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index 6014f6bb..871865a0 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -205,12 +205,12 @@ void TrackPlayer::runTask() { track->trackMetrics->startTrackDecoding(); track->trackMetrics->track_size = currentTrackStream->getSize(); -#ifndef CONFIG_BELL_NOCODEC if (trackOffset == 0 && pendingSeekPositionMs == 0) { this->trackLoaded(track, startPaused); startPaused = false; } +#ifndef CONFIG_BELL_NOCODEC int32_t r = ov_open_callbacks(this, &vorbisFile, NULL, 0, vorbisCallbacks); #else @@ -262,8 +262,11 @@ void TrackPlayer::runTask() { eof = false; track->loading = true; //in case of a repeatedtrack, set requested position to 0 - track->requestedPosition = 0; track->trackMetrics->startTrackPlaying(track->requestedPosition); + this->trackQueue->playbackState->updatePositionMs( + track->requestedPosition); + this->trackQueue->notifyCallback(); + track->requestedPosition = 0; CSPOT_LOG(info, "Playing"); @@ -281,6 +284,9 @@ void TrackPlayer::runTask() { track->trackMetrics->newPosition(pendingSeekPositionMs); skipped = true; #endif + this->trackQueue->playbackState->updatePositionMs( + pendingSeekPositionMs); + this->trackQueue->notifyCallback(); // Reset the pending seek position pendingSeekPositionMs = 0; diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 08b01dc6..19d8b83a 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -444,7 +444,8 @@ std::shared_ptr TrackQueue::consumeTrack( std::shared_ptr prevTrack, int& offset) { std::scoped_lock lock(tracksMutex); - if (currentTracksIndex == -1 || currentTracksIndex >= currentTracks.size()) { + if ((currentTracksIndex == -1 && !currentTracks.size()) || + currentTracksIndex >= currentTracks.size()) { return nullptr; } @@ -495,7 +496,7 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { index++; } if (queuedTracks.size() > 0) { - if (preloadedTracks[0]->ref.gid != queuedTracks[0].second.gid) { + if (preloadedTracks[offset]->ref.gid != queuedTracks[0].second.gid) { ghostTracks.push_back(currentTracks[index]); index++; } else @@ -503,7 +504,7 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { for (auto track : queuedTracks) { if (track.first != -1) break; - if (preloadedTracks[0]->ref.gid != track.second.gid) { + if (preloadedTracks[offset]->ref.gid != track.second.gid) { ghostTracks.push_back(track.second); } } @@ -538,10 +539,13 @@ void TrackQueue::processTrack(std::shared_ptr track) { if (track->state == QueuedTrack::State::READY) { if (preloadedTracks.size() + currentTracksIndex + 1 >= - currentTracks.size()) + currentTracks.size() && + !contextResolved) { playerContext->resolveContext( currentTracksIndex, this->playbackState->innerFrame.state.shuffle, this->playbackState->innerFrame.state.context_uri); + contextResolved = true; + } if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { // Queue a new track to preload queueNextTrack(preloadedTracks.size()); @@ -672,13 +676,16 @@ void TrackQueue::reloadTracks(uint8_t offset) { //preloadedTracks.clear(); queueNextTrack(preloadedTracks.size()); update_ghost_tracks(); - //this->ctx->handler->notify(); + this->notifyCallback(); + contextResolved = false; } bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { std::scoped_lock lock(tracksMutex); bool cleared = true; if (initial) { + if (preloadedTracks.size()) + notifyPending = true; // initialize new random_engine rng = std::default_random_engine{rd()}; // Copy requested track list @@ -703,9 +710,18 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { playableSemaphore->give(); } else { - queuedTracks.push_back(std::make_pair( - -1, playbackState->remoteTracks[playbackState->innerFrame.state.index + - 1 + queuedTracks.size()])); + auto track_it = queuedTracks.begin(); + uint32_t offset = 0; + while (track_it->first < 0) { + track_it++; + offset++; + } + queuedTracks.insert( + track_it, + std::make_pair( + -1, + playbackState->remoteTracks[playbackState->innerFrame.state.index + + 1 + offset])); preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); queueNextTrack(1); cleared = false; diff --git a/targets/esp32/components/VS1053/src/VS1053.cpp b/targets/esp32/components/VS1053/src/VS1053.cpp index d1fb1a3d..59d82eb8 100644 --- a/targets/esp32/components/VS1053/src/VS1053.cpp +++ b/targets/esp32/components/VS1053/src/VS1053.cpp @@ -121,7 +121,8 @@ esp_err_t VS1053_SINK::init(spi_host_device_t SPI, //load_user_code(PLUGIN, PLUGIN_SIZE); #endif vTaskDelay(100 / portTICK_PERIOD_MS); - xTaskCreate(vs_feed, "track_feed", 4098, (void*)this, 10, &task_handle); + xTaskCreatePinnedToCore(vs_feed, "track_feed", 4098, (void*)this, 10, + &task_handle, 0); return ESP_OK; } @@ -263,9 +264,6 @@ void VS1053_SINK::run_feed(size_t FILL_BUFFER_BEFORE_PLAYBACK) { sdi_send_fillers(endFillByte, endFillBytes); write_register(SCI_DECODE_TIME, 0); // Reset DECODE_TIME new_state(track->state, VS1053_TRACK::VS_TRACK_STATE::tsPlaybackStart); - if (FILL_BUFFER_BEFORE_PLAYBACK < - xStreamBufferBytesAvailable(track->dataBuffer)) - vTaskDelay(10 / portTICK_PERIOD_MS); while (track->state != VS1053_TRACK::VS_TRACK_STATE::tsStopped) { if (this->command_callbacks.size()) { this->command_callbacks[0](track->track_id); From b489cc93a3045c9814b48834b66ba0b3c0c7ea68 Mon Sep 17 00:00:00 2001 From: tobiasguyer <154328661+tobiasguyer@users.noreply.github.com> Date: Thu, 1 Aug 2024 09:43:32 +0200 Subject: [PATCH 36/41] Event manager (#2) * moved trackmetrics playStart back to TrackPlayer because needed * changes in track queueing --- cspot/include/TrackQueue.h | 7 ++-- cspot/protobuf/spirc.options | 2 ++ cspot/protobuf/spirc.proto | 2 ++ cspot/src/PlaybackState.cpp | 11 ++++++ cspot/src/PlayerContext.cpp | 12 +++---- cspot/src/SpircHandler.cpp | 35 +++++++------------ cspot/src/TrackPlayer.cpp | 9 ++++- cspot/src/TrackQueue.cpp | 32 ++++++++++++----- .../esp32/components/VS1053/src/VS1053.cpp | 6 ++-- 9 files changed, 69 insertions(+), 47 deletions(-) diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 8c2437e2..31ac58c6 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -109,6 +109,7 @@ class TrackQueue : public bell::Task { std::shared_ptr playableSemaphore; std::shared_ptr playbackState; std::atomic notifyPending = false; + std::function notifyCallback; void runTask() override; void stopTask(); @@ -123,6 +124,7 @@ class TrackQueue : public bell::Task { TrackInfo getTrackInfo(std::string_view identifier); std::shared_ptr consumeTrack( std::shared_ptr prevSong, int& offset); + std::deque> preloadedTracks; private: static const int MAX_TRACKS_PRELOAD = 3; @@ -132,9 +134,8 @@ class TrackQueue : public bell::Task { std::shared_ptr processSemaphore; std::unique_ptr playerContext; - std::deque> preloadedTracks; std::deque> queuedTracks = {}; - std::vector currentTracks; + std::vector currentTracks = {}; std::vector ghostTracks; std::mutex tracksMutex, runningMutex; @@ -144,7 +145,7 @@ class TrackQueue : public bell::Task { uint32_t currentTracksIndex = -1; bool isRunning = false; - bool context_resolved = false; + bool contextResolved = false; bool continue_with_radio = true; std::random_device rd; diff --git a/cspot/protobuf/spirc.options b/cspot/protobuf/spirc.options index b7331f53..1804712a 100644 --- a/cspot/protobuf/spirc.options +++ b/cspot/protobuf/spirc.options @@ -7,4 +7,6 @@ DeviceState.sw_version type:FT_POINTER DeviceState.name type:FT_POINTER DeviceState.capabilities max_count:17, fixed_count:false State.context_uri type:FT_POINTER +State.last_command_ident type:FT_POINTER +State.context_description type:FT_POINTER TrackRef.queued type:FT_CALLBACK \ No newline at end of file diff --git a/cspot/protobuf/spirc.proto b/cspot/protobuf/spirc.proto index 5d54bd26..fcd3a512 100644 --- a/cspot/protobuf/spirc.proto +++ b/cspot/protobuf/spirc.proto @@ -43,6 +43,8 @@ message State { optional string context_description = 0x8; optional bool shuffle = 0xd; optional bool repeat = 0xe; + optional string last_command_ident = 0x14; + optional uint32 last_command_msgid = 0x15; optional uint32 playing_track_index = 0x1a; repeated TrackRef track = 0x1b; } diff --git a/cspot/src/PlaybackState.cpp b/cspot/src/PlaybackState.cpp index 56cca32e..de5863c7 100644 --- a/cspot/src/PlaybackState.cpp +++ b/cspot/src/PlaybackState.cpp @@ -116,6 +116,17 @@ void PlaybackState::syncWithRemote() { strcpy(innerFrame.state.context_uri, remoteFrame.state.context_uri); + if (remoteFrame.state.context_description != NULL) { + innerFrame.state.context_description = + (char*)realloc(innerFrame.state.context_description, + strlen(remoteFrame.state.context_description) + 1); + strcpy(innerFrame.state.context_description, + remoteFrame.state.context_description); + } else { + free(innerFrame.state.context_description); + innerFrame.state.context_description = NULL; + } + innerFrame.state.has_playing_track_index = true; innerFrame.state.playing_track_index = remoteFrame.state.playing_track_index; innerFrame.state.has_shuffle = remoteFrame.state.has_shuffle; diff --git a/cspot/src/PlayerContext.cpp b/cspot/src/PlayerContext.cpp index d190625f..726a1214 100644 --- a/cspot/src/PlayerContext.cpp +++ b/cspot/src/PlayerContext.cpp @@ -24,18 +24,18 @@ PlayerContext::PlayerContext( this->index = index; rng = std::default_random_engine{rd()}; std::string requestUrl = string_format("hm://context-resolve/v1/%s", uri); - auto responseHandler = [this, shuffle](MercurySession::Response& res) { + auto responseHandler = [this, shuffle, uri](MercurySession::Response& res) { if (!res.parts.size()) return; if (!res.parts[0].size()) return; this->resolveInitial(*this->index, shuffle, res.parts[0]); + if (this->track_list->size() < 30) + resolveContext(*this->index, shuffle, uri); }; ctx->session->execute(MercurySession::RequestType::GET, requestUrl, responseHandler); - if (track_list->size() < 30) - resolveContext(*this->index, shuffle, uri); } static void randomizeIndex(std::vector& index, uint16_t offset, @@ -111,8 +111,6 @@ bool PlayerContext::resolveTracklist(uint32_t index, bool shuffle, index = *this->index; std::scoped_lock lock(*trackMutex); auto jsonResult = nlohmann::json::parse(data); - if (queued_list->at(0).first == 0 || queued_list->at(0).first == -1) - index--; for (uint32_t i = 0; i < queued_list->size(); i++) if (queued_list->at(i).first != -1) queued_list->at(i).first -= index; @@ -199,10 +197,8 @@ bool PlayerContext::resolveInitial(uint32_t index, bool shuffle, } randomizeIndex(alternative_index, new_index.size(), rng); } - track_list->erase(track_list->begin(), track_list->begin() + index); - last_index = shuffle ? index : new_index[index]; + last_index = shuffle ? 0 : new_index[0]; last_resolve_shuffled = shuffle; - *this->index = 0; static_cast(queue)->reloadTracks(); return true; } \ No newline at end of file diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index e27e26cc..a52f857f 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -25,12 +25,16 @@ SpircHandler::SpircHandler(std::shared_ptr ctx) { this->playbackState = std::make_shared(ctx); this->trackQueue = std::make_shared(ctx, playbackState); + trackQueue->notifyCallback = [this]() { + this->notify(); + }; + auto EOFCallback = [this](bool loaded) { if (trackQueue->isFinished()) { sendEvent(EventType::DEPLETED); } if (!loaded) - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, true); + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); }; auto trackLoadedCallback = [this](std::shared_ptr track, @@ -39,8 +43,6 @@ SpircHandler::SpircHandler(std::shared_ptr ctx) { : PlaybackState::State::Playing); playbackState->updatePositionMs(track->requestedPosition); - this->notify(); - // Send playback start event, pause/unpause per request sendEvent(EventType::PLAYBACK_START, (int)track->requestedPosition); sendEvent(EventType::PLAY_PAUSE, paused); @@ -95,10 +97,13 @@ void SpircHandler::notifyAudioReachedPlaybackEnd() { if (!playbackState->innerFrame.state.repeat) { currentTrack->trackMetrics->endTrack(); ctx->playbackMetrics->sendEvent(currentTrack); - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, true); - // we moved to next track, re-acquire currentTrack again - currentTrack = trackQueue->consumeTrack(nullptr, offset); + if (!trackQueue->notifyPending) + trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); + else + trackQueue->notifyPending = false; } + trackQueue->update_ghost_tracks(); + notify(); } void SpircHandler::notifyAudioReachedPlayback() { @@ -106,18 +111,6 @@ void SpircHandler::notifyAudioReachedPlayback() { // get HEAD track auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - currentTrack->trackMetrics->startTrackPlaying( - currentTrack->requestedPosition); - if (trackQueue->notifyPending) { - trackQueue->notifyPending = false; - - playbackState->updatePositionMs(currentTrack->requestedPosition); - - // Reset position in queued track - currentTrack->requestedPosition = 0; - } - this->notify(); - sendEvent(EventType::TRACK_INFO, currentTrack->trackInfo); } @@ -150,16 +143,12 @@ void SpircHandler::handleFrame(std::vector& data) { ctx->playbackMetrics->end_source = influence; this->trackPlayer->stop(); sendEvent(EventType::DISC); + trackQueue->preloadedTracks.clear(); } break; } case MessageType_kMessageTypeSeek: { this->trackPlayer->seekMs(playbackState->remoteFrame.position); - - playbackState->updatePositionMs(playbackState->remoteFrame.position); - - notify(); - sendEvent(EventType::SEEK, (int)playbackState->remoteFrame.position); break; } diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index e82d8d6a..871865a0 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -205,12 +205,12 @@ void TrackPlayer::runTask() { track->trackMetrics->startTrackDecoding(); track->trackMetrics->track_size = currentTrackStream->getSize(); -#ifndef CONFIG_BELL_NOCODEC if (trackOffset == 0 && pendingSeekPositionMs == 0) { this->trackLoaded(track, startPaused); startPaused = false; } +#ifndef CONFIG_BELL_NOCODEC int32_t r = ov_open_callbacks(this, &vorbisFile, NULL, 0, vorbisCallbacks); #else @@ -262,6 +262,10 @@ void TrackPlayer::runTask() { eof = false; track->loading = true; //in case of a repeatedtrack, set requested position to 0 + track->trackMetrics->startTrackPlaying(track->requestedPosition); + this->trackQueue->playbackState->updatePositionMs( + track->requestedPosition); + this->trackQueue->notifyCallback(); track->requestedPosition = 0; CSPOT_LOG(info, "Playing"); @@ -280,6 +284,9 @@ void TrackPlayer::runTask() { track->trackMetrics->newPosition(pendingSeekPositionMs); skipped = true; #endif + this->trackQueue->playbackState->updatePositionMs( + pendingSeekPositionMs); + this->trackQueue->notifyCallback(); // Reset the pending seek position pendingSeekPositionMs = 0; diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 08b01dc6..19d8b83a 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -444,7 +444,8 @@ std::shared_ptr TrackQueue::consumeTrack( std::shared_ptr prevTrack, int& offset) { std::scoped_lock lock(tracksMutex); - if (currentTracksIndex == -1 || currentTracksIndex >= currentTracks.size()) { + if ((currentTracksIndex == -1 && !currentTracks.size()) || + currentTracksIndex >= currentTracks.size()) { return nullptr; } @@ -495,7 +496,7 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { index++; } if (queuedTracks.size() > 0) { - if (preloadedTracks[0]->ref.gid != queuedTracks[0].second.gid) { + if (preloadedTracks[offset]->ref.gid != queuedTracks[0].second.gid) { ghostTracks.push_back(currentTracks[index]); index++; } else @@ -503,7 +504,7 @@ void TrackQueue::update_ghost_tracks(int16_t offset) { for (auto track : queuedTracks) { if (track.first != -1) break; - if (preloadedTracks[0]->ref.gid != track.second.gid) { + if (preloadedTracks[offset]->ref.gid != track.second.gid) { ghostTracks.push_back(track.second); } } @@ -538,10 +539,13 @@ void TrackQueue::processTrack(std::shared_ptr track) { if (track->state == QueuedTrack::State::READY) { if (preloadedTracks.size() + currentTracksIndex + 1 >= - currentTracks.size()) + currentTracks.size() && + !contextResolved) { playerContext->resolveContext( currentTracksIndex, this->playbackState->innerFrame.state.shuffle, this->playbackState->innerFrame.state.context_uri); + contextResolved = true; + } if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { // Queue a new track to preload queueNextTrack(preloadedTracks.size()); @@ -672,13 +676,16 @@ void TrackQueue::reloadTracks(uint8_t offset) { //preloadedTracks.clear(); queueNextTrack(preloadedTracks.size()); update_ghost_tracks(); - //this->ctx->handler->notify(); + this->notifyCallback(); + contextResolved = false; } bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { std::scoped_lock lock(tracksMutex); bool cleared = true; if (initial) { + if (preloadedTracks.size()) + notifyPending = true; // initialize new random_engine rng = std::default_random_engine{rd()}; // Copy requested track list @@ -703,9 +710,18 @@ bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { playableSemaphore->give(); } else { - queuedTracks.push_back(std::make_pair( - -1, playbackState->remoteTracks[playbackState->innerFrame.state.index + - 1 + queuedTracks.size()])); + auto track_it = queuedTracks.begin(); + uint32_t offset = 0; + while (track_it->first < 0) { + track_it++; + offset++; + } + queuedTracks.insert( + track_it, + std::make_pair( + -1, + playbackState->remoteTracks[playbackState->innerFrame.state.index + + 1 + offset])); preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); queueNextTrack(1); cleared = false; diff --git a/targets/esp32/components/VS1053/src/VS1053.cpp b/targets/esp32/components/VS1053/src/VS1053.cpp index d1fb1a3d..59d82eb8 100644 --- a/targets/esp32/components/VS1053/src/VS1053.cpp +++ b/targets/esp32/components/VS1053/src/VS1053.cpp @@ -121,7 +121,8 @@ esp_err_t VS1053_SINK::init(spi_host_device_t SPI, //load_user_code(PLUGIN, PLUGIN_SIZE); #endif vTaskDelay(100 / portTICK_PERIOD_MS); - xTaskCreate(vs_feed, "track_feed", 4098, (void*)this, 10, &task_handle); + xTaskCreatePinnedToCore(vs_feed, "track_feed", 4098, (void*)this, 10, + &task_handle, 0); return ESP_OK; } @@ -263,9 +264,6 @@ void VS1053_SINK::run_feed(size_t FILL_BUFFER_BEFORE_PLAYBACK) { sdi_send_fillers(endFillByte, endFillBytes); write_register(SCI_DECODE_TIME, 0); // Reset DECODE_TIME new_state(track->state, VS1053_TRACK::VS_TRACK_STATE::tsPlaybackStart); - if (FILL_BUFFER_BEFORE_PLAYBACK < - xStreamBufferBytesAvailable(track->dataBuffer)) - vTaskDelay(10 / portTICK_PERIOD_MS); while (track->state != VS1053_TRACK::VS_TRACK_STATE::tsStopped) { if (this->command_callbacks.size()) { this->command_callbacks[0](track->track_id); From b399b03dc637c0c1d6214226457c4b4faacf69c1 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 24 Sep 2024 16:32:29 +0200 Subject: [PATCH 37/41] Changed structural from spirc to connectState --- cspot/include/CSpotContext.h | 4 + cspot/include/ConstantParameters.h | 2 +- cspot/include/DeviceStateHandler.h | 110 ++ cspot/include/EventManager.h | 3 +- cspot/include/MercurySession.h | 15 +- cspot/include/PlaybackState.h | 97 -- cspot/include/PlayerContext.h | 74 +- cspot/include/SpircHandler.h | 82 -- cspot/include/TrackPlayer.h | 6 +- cspot/include/TrackQueue.h | 75 +- cspot/include/TrackReference.h | 32 +- cspot/include/Utils.h | 12 +- cspot/protobuf/connect.options | 79 ++ cspot/protobuf/connect.proto | 345 +++++ cspot/protobuf/mercury.options | 6 +- cspot/src/DeviceStateHandler.cpp | 1145 +++++++++++++++++ cspot/src/EventManager.cpp | 49 +- cspot/src/LoginBlob.cpp | 28 +- cspot/src/MercurySession.cpp | 38 +- cspot/src/PlaybackState.cpp | 222 ---- cspot/src/PlayerContext.cpp | 620 ++++++--- cspot/src/Session.cpp | 4 +- cspot/src/SpircHandler.cpp | 317 ----- cspot/src/TrackPlayer.cpp | 43 +- cspot/src/TrackQueue.cpp | 322 +---- cspot/src/TrackReference.cpp | 128 +- cspot/src/Utils.cpp | 47 +- targets/cli/CliPlayer.cpp | 95 +- targets/cli/CliPlayer.h | 12 +- targets/cli/main.cpp | 31 +- .../esp32/components/VS1053/include/VS1053.h | 15 +- .../esp32/components/VS1053/src/VS1053.cpp | 28 +- targets/esp32/main/EspPlayer.cpp | 101 +- targets/esp32/main/EspPlayer.h | 12 +- targets/esp32/main/VSPlayer.cpp | 75 +- targets/esp32/main/VSPlayer.h | 11 +- targets/esp32/main/VSinit.h | 41 +- targets/esp32/main/main.cpp | 12 +- 38 files changed, 2727 insertions(+), 1611 deletions(-) create mode 100644 cspot/include/DeviceStateHandler.h delete mode 100644 cspot/include/PlaybackState.h delete mode 100644 cspot/include/SpircHandler.h create mode 100644 cspot/protobuf/connect.options create mode 100644 cspot/protobuf/connect.proto create mode 100644 cspot/src/DeviceStateHandler.cpp delete mode 100644 cspot/src/PlaybackState.cpp delete mode 100644 cspot/src/SpircHandler.cpp diff --git a/cspot/include/CSpotContext.h b/cspot/include/CSpotContext.h index be20940d..d39f7dc3 100644 --- a/cspot/include/CSpotContext.h +++ b/cspot/include/CSpotContext.h @@ -2,6 +2,7 @@ #include #include +#include //for random_device and default_random_engine #include "Crypto.h" #include "EventManager.h" @@ -37,6 +38,8 @@ struct Context { std::shared_ptr timeProvider; std::shared_ptr session; std::shared_ptr playbackMetrics; + std::random_device rd; + std::default_random_engine rng; std::string getCredentialsJson() { #ifdef BELL_ONLY_CJSON cJSON* json_obj = cJSON_CreateObject(); @@ -68,6 +71,7 @@ struct Context { std::shared_ptr blob) { auto ctx = std::make_shared(); ctx->timeProvider = std::make_shared(); + ctx->rng = std::default_random_engine{ctx->rd()}; ctx->session = std::make_shared(ctx->timeProvider); ctx->playbackMetrics = std::make_shared(ctx); diff --git a/cspot/include/ConstantParameters.h b/cspot/include/ConstantParameters.h index 12ebac30..f57bc717 100644 --- a/cspot/include/ConstantParameters.h +++ b/cspot/include/ConstantParameters.h @@ -12,6 +12,6 @@ const char* const brandName = "cspot"; const char* const versionString = "cspot-1.1"; const char* const protocolVersion = "2.7.1"; const char* const defaultDeviceName = "CSpot"; -const char* const swVersion = "1.0.0"; +const char* const swVersion = "1.1.0"; } // namespace cspot \ No newline at end of file diff --git a/cspot/include/DeviceStateHandler.h b/cspot/include/DeviceStateHandler.h new file mode 100644 index 00000000..6f839648 --- /dev/null +++ b/cspot/include/DeviceStateHandler.h @@ -0,0 +1,110 @@ +/** + * TO DO + * + * autoplay doesn't work for episodes + * + */ +#pragma once + +#include // for uint8_t, uint32_t +#include //for deque.. +#include //for function +#include // for shared_ptr +#include // for string +#include // for pair +#include // for variant +#include // for vector + +#include "PlayerContext.h" // for PlayerContext::resolveTracklist, jsonToTracklist... +#include "TrackPlayer.h" // for TrackPlayer +#include "TrackQueue.h" +#include "TrackReference.h" +#include "protobuf/connect.pb.h" // for PutStateRequest, DeviceState, PlayerState... + +namespace cspot { +struct Context; +struct PlayerContext; + +class DeviceStateHandler { + public: + //Command Callback Structure + enum CommandType { + STOP, + PLAY, + PAUSE, + DISC, + DEPLETED, + FLUSH, + PLAYBACK_START, + PLAYBACK, + SKIP_NEXT, + SKIP_PREV, + SEEK, + SET_SHUFFLE, + SET_REPEAT, + VOLUME, + TRACK_INFO, + }; + + typedef std::variant, int32_t, bool> + CommandData; + + struct Command { + CommandType commandType; + CommandData data; + }; + + typedef std::function StateCallback; + + DeviceStateHandler(std::shared_ptr); + ~DeviceStateHandler(); + + void disconnect(); + + void putDeviceState(PutStateReason member_type = + PutStateReason::PutStateReason_PLAYER_STATE_CHANGED); + void putPlayerState(PutStateReason member_type = + PutStateReason::PutStateReason_PLAYER_STATE_CHANGED); + void handleConnectState(); + void sendCommand(CommandType, CommandData data = {}); + + Device device = Device_init_zero; + + std::vector currentTracks = {}; + StateCallback stateCallback; + + uint64_t started_playing_at = 0; + uint32_t last_message_id = -1; + uint8_t offset = 0; + int64_t offsetFromStartInMillis = 0; + + bool is_active = false; + bool reloadPreloadedTracks = true; + bool needsToBeSkipped = true; + bool playerStateChanged = false; + + std::shared_ptr trackPlayer; + std::shared_ptr trackQueue; + std::shared_ptr ctx; + + private: + std::shared_ptr playerContext; + + std::pair*> queuePacket = { + &offset, ¤tTracks}; + std::vector> metadata_map = {}; + std::vector> context_metadata_map = {}; + std::mutex playerStateMutex; + std::string context_uri, context_url; + void parseCommand(std::vector& data); + void skip(CommandType dir, bool notify); + + void unreference(char* string) { + if (string != NULL) + free(string); + string = NULL; + } + + static void reloadTrackList(void*); +}; +} // namespace cspot \ No newline at end of file diff --git a/cspot/include/EventManager.h b/cspot/include/EventManager.h index d0b5156a..975c849c 100644 --- a/cspot/include/EventManager.h +++ b/cspot/include/EventManager.h @@ -47,11 +47,12 @@ class TrackMetrics { void newPosition(uint64_t pos); void endInterval(uint64_t pos); + void pauseInterval(uint64_t pos, bool pause); void endTrack(); void startTrack(); void startTrackDecoding(); void startTrackPlaying(uint64_t pos); - uint64_t getPosition(); + uint64_t getPosition(bool paused = false); private: std::shared_ptr ctx; diff --git a/cspot/include/MercurySession.h b/cspot/include/MercurySession.h index c3dc55b1..f01ee02f 100644 --- a/cspot/include/MercurySession.h +++ b/cspot/include/MercurySession.h @@ -39,7 +39,9 @@ class MercurySession : public bell::Task, public cspot::Session { UNSUB = 0xb4, SUBRES = 0xb5, SEND = 0xb2, - GET = 0xFF, // Shitty workaround, it's value is actually same as SEND + GET = 0xFF, // Shitty workaround, it's value is actually same as SEND + POST = 0xb6, //?? + PUT = 0xb7, //?? PING = 0x04, PONG_ACK = 0x4a, AUDIO_CHUNK_REQUEST_COMMAND = 0x08, @@ -57,14 +59,16 @@ class MercurySession : public bell::Task, public cspot::Session { }; std::unordered_map RequestTypeMap = { - {RequestType::GET, "GET"}, - {RequestType::SEND, "SEND"}, - {RequestType::SUB, "SUB"}, - {RequestType::UNSUB, "UNSUB"}, + {RequestType::GET, "GET"}, {RequestType::SEND, "SEND"}, + {RequestType::SUB, "SUB"}, {RequestType::UNSUB, "UNSUB"}, + {RequestType::POST, "POST"}, {RequestType::PUT, "PUT"}, }; void handlePacket(); + void addSubscriptionListener(const std::string& uri, + ResponseCallback subscription); + uint64_t executeSubscription(RequestType type, const std::string& uri, ResponseCallback callback, ResponseCallback subscription, DataParts& parts); @@ -129,6 +133,7 @@ class MercurySession : public bell::Task, public cspot::Session { std::atomic isRunning = false; std::atomic isReconnecting = false; std::atomic executeEstabilishedCallback = false; + std::atomic connection_lost = false; void failAllPending(); diff --git a/cspot/include/PlaybackState.h b/cspot/include/PlaybackState.h deleted file mode 100644 index a79eab01..00000000 --- a/cspot/include/PlaybackState.h +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once - -#include // for uint8_t, uint32_t -#include // for shared_ptr -#include // for string -#include // for vector - -#include "TrackReference.h" -#include "protobuf/spirc.pb.h" // for Frame, TrackRef, CapabilityType, Mess... - -namespace cspot { -struct Context; - -class PlaybackState { - private: - std::shared_ptr ctx; - - uint32_t seqNum = 0; - uint8_t capabilityIndex = 0; - - std::vector frameData; - - void addCapability( - CapabilityType typ, int intValue = -1, - std::vector stringsValue = std::vector()); - - public: - Frame innerFrame; - Frame remoteFrame; - - std::vector remoteTracks; - - enum class State { Playing, Stopped, Loading, Paused }; - - /** - * @brief Player state represents the current state of player. - * - * Responsible for keeping track of player's state. Doesn't control the playback itself. - * - * @param timeProvider synced time provider - */ - PlaybackState(std::shared_ptr ctx); - - ~PlaybackState(); - - /** - * @brief Updates state according to current playback state. - * - * @param state playback state - */ - void setPlaybackState(const PlaybackState::State state); - - /** - * @brief Sets player activity - * - * @param isActive activity status - */ - void setActive(bool isActive); - - /** - * @brief Simple getter - * - * @return true player is active - * @return false player is inactive - */ - bool isActive(); - - /** - * @brief Updates local track position. - * - * @param position position in milliseconds - */ - void updatePositionMs(uint32_t position); - - /** - * @brief Sets local volume on internal state. - * - * @param volume volume between 0 and UINT16 max - */ - void setVolume(uint32_t volume); - - /** - * @brief Updates local track queue from remote data. - */ - void syncWithRemote(); - - /** - * @brief Encodes current frame into binary data via protobuf. - * - * @param typ message type to include in frame type - * @return std::vector binary frame data - */ - std::vector encodeCurrentFrame(MessageType typ); - - bool decodeRemoteFrame(std::vector& data); -}; -} // namespace cspot diff --git a/cspot/include/PlayerContext.h b/cspot/include/PlayerContext.h index 1429a041..59019c8c 100644 --- a/cspot/include/PlayerContext.h +++ b/cspot/include/PlayerContext.h @@ -2,50 +2,62 @@ #define PLAYER_CONTEXT_H #include -#include // for shared_ptr -#include //for scoped_loc, mutex... +#include // for shared_ptr +#include //for scoped_loc, mutex... +#include #include //for random_device and default_random_engine #include // for pair #include //for vector #include "BellTask.h" #include "CSpotContext.h" -#include "TrackReference.h" //for TrackReference +#include "TrackReference.h" //for TrackReference +#include "nlohmann/json.hpp" // for basic_json<>::object_t, basic_json +#include "nlohmann/json_fwd.hpp" // for json #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode #define MAX_TRACKS 80 namespace cspot { -class PlayerContext { - public: - PlayerContext( - bell::Task* queue, std::shared_ptr ctx, - std::vector* track_list, - std::deque>* queued_list, - std::mutex* trackMutex, uint32_t* index, bool shuffle, char* uri); - ~PlayerContext(); - void resolveContext(uint32_t index, bool shuffle, char* uri); +struct PlayerContext { + PlayerContext(std::shared_ptr ctx, PlayerState* playerState, + std::vector* tracks, uint8_t* index) { + this->ctx = ctx; + this->playerState = playerState; + this->tracks = tracks; + this->index = index; + } + void resolveRadio( + std::vector> metadata_map, + void (*responseFunction)(void*), bool secondTry = false); - private: + void resolveTracklist( + std::vector> metadata_map, + void (*responseFunction)(void*), bool state_changed = false); + uint8_t jsonToTracklist( + std::vector* tracks, + std::vector> metadata_map, + nlohmann::json::value_type& json_tracks, const char* provider, + int64_t offset = 0, uint8_t page = 0, bool shuffle = false, + bool preloadedTrack = false); + void createIndexBasedOnTracklist(std::vector* tracks, + nlohmann::json::value_type& json_tracks, + bool shuffle, uint8_t page); + //void jsonToPlayerStateContext(PlayerState* playerState, std::vector* tracks, uint8_t* index, std::vector> metadata_map,nlohmann::json::object_t context); + static char* createStringReferenceIfFound( + nlohmann::json::value_type& jsonObject, const char* key); + uint64_t radio_offset = 0; + std::mutex trackListMutex; std::shared_ptr ctx; - std::mutex* trackMutex; - bell::Task* queue; - std::shared_ptr innerFrame; - void shuffleIndex(); - void getTracks(); - std::vector alternative_index; - uint32_t* index; - uint32_t last_index = 0; - uint32_t radio_offset = 0; + PlayerState* playerState; + std::vector* tracks; + uint8_t* index; + std::vector alternative_index; + char* next_page_url = NULL; std::string context_uri; - std::vector* track_list; - std::deque>* queued_list; - bool last_resolve_shuffled = false; - bool resolveTracklist(uint32_t index, bool shuffle, - std::vector& data); - bool resolveInitial(uint32_t index, bool shuffle, std::vector& data); - bool resolveRadio(uint32_t index, std::vector& data); - std::random_device rd; - std::default_random_engine rng; + ~PlayerContext() { + if (next_page_url != NULL) + free(next_page_url); + } }; }; // namespace cspot diff --git a/cspot/include/SpircHandler.h b/cspot/include/SpircHandler.h deleted file mode 100644 index 9baa7658..00000000 --- a/cspot/include/SpircHandler.h +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include // for uint32_t, uint8_t -#include // for function -#include // for shared_ptr, unique_ptr -#include // for string -#include // for variant -#include // for vector - -#include "CDNAudioFile.h" // for CDNTrackStream, CDNTrackStream::Track... -#include "TrackQueue.h" -#include "protobuf/spirc.pb.h" // for MessageType - -namespace cspot { -class TrackPlayer; -struct Context; - -class SpircHandler { - public: - SpircHandler(std::shared_ptr ctx); - - enum class EventType { - PLAY_PAUSE, - VOLUME, - TRACK_INFO, - DISC, - NEXT, - PREV, - SEEK, - DEPLETED, - FLUSH, - PLAYBACK_START - }; - - typedef std::variant EventData; - - struct Event { - EventType eventType; - EventData data; - }; - - typedef std::function)> EventHandler; - - void subscribeToMercury(); - std::shared_ptr getTrackPlayer(); - - void setEventHandler(EventHandler handler); - - void setPause(bool pause); - - bool previousSong(); - - bool nextSong(); - - void notifyAudioReachedPlaybackEnd(); - void notifyAudioReachedPlayback(); - void notifyAudioEnded(); - void updatePositionMs(uint32_t position); - void setRemoteVolume(int volume); - void loadTrackFromURI(const std::string& uri); - std::shared_ptr getTrackQueue() { return trackQueue; } - std::shared_ptr trackPlayer; - std::shared_ptr trackQueue; - std::shared_ptr playbackState; - - void disconnect(); - - private: - std::shared_ptr ctx; - - EventHandler eventHandler = nullptr; - - void sendCmd(MessageType typ); - - void sendEvent(EventType type); - void sendEvent(EventType type, EventData data); - - bool skipSong(TrackQueue::SkipDirection dir); - void handleFrame(std::vector& data); - void notify(); -}; -} // namespace cspot diff --git a/cspot/include/TrackPlayer.h b/cspot/include/TrackPlayer.h index 75bf736a..aa738ce9 100644 --- a/cspot/include/TrackPlayer.h +++ b/cspot/include/TrackPlayer.h @@ -46,6 +46,7 @@ class TrackPlayer : bell::Task { DataCallback; typedef std::function EOFCallback; typedef std::function SeekableCallback; + EOFCallback eofCallback; TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, @@ -82,7 +83,6 @@ class TrackPlayer : bell::Task { TrackLoadedCallback trackLoaded; DataCallback dataCallback = nullptr; - EOFCallback eofCallback; #ifdef CONFIG_BELL_NOCODEC SeekableCallback spaces_available = nullptr; SeekableCallback seekable_callback; @@ -101,7 +101,11 @@ class TrackPlayer : bell::Task { int currentSection; #endif +#ifndef CONFIG_BELL_NOCODEC std::vector pcmBuffer = std::vector(1024); +#else + std::vector pcmBuffer = std::vector(128); +#endif bool autoStart = false; diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 31ac58c6..513026ba 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -5,23 +5,16 @@ #include #include #include -#include //for random_device and default_random_engine #include // for pair #include "BellTask.h" #include "EventManager.h" // for TrackMetrics -#include "PlaybackState.h" -#include "PlayerContext.h" #include "TrackReference.h" +#include "Utils.h" +#include "protobuf/connect.pb.h" // for ProvidedTrack #include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode -#ifndef CONFIG_UPDATE_FUTURE_TRACKS -#define CONFIG_UPDATE_FUTURE_TRACKS 10 -#endif -#define inner_tracks_treshhold 10 -#define SEND_OLD_TRACKS 2 - namespace bell { class WrappedSemaphore; }; @@ -42,8 +35,8 @@ struct TrackInfo { class QueuedTrack { public: - QueuedTrack(TrackReference& ref, std::shared_ptr ctx, - uint32_t requestedPosition = 0); + QueuedTrack(ProvidedTrack& ref, std::shared_ptr ctx, + int64_t requestedPosition = 0); ~QueuedTrack(); enum class State { @@ -59,17 +52,21 @@ class QueuedTrack { std::shared_ptr loadedSemaphore; State state = State::QUEUED; // Current state of the track - TrackReference ref; // Holds GID, URI and Context TrackInfo trackInfo; // Full track information fetched from spotify, name etc + ProvidedTrack ref; + std::string identifier; + uint32_t playingTrackIndex; + uint32_t requestedPosition; + bool loading = false; // PB data Track pbTrack = Track_init_zero; Episode pbEpisode = Episode_init_zero; - uint32_t requestedPosition; - uint64_t written_bytes = 0; - std::string identifier; - bool loading = false; + + // EventManager data + int64_t written_bytes = 0; std::shared_ptr trackMetrics; + // Will return nullptr if the track is not ready std::shared_ptr getAudioFile(); @@ -96,65 +93,41 @@ class QueuedTrack { std::vector trackId, fileId, audioKey; std::string cdnUrl; + std::pair> gid = { + SpotifyFileType::UNKNOWN, + {}}; }; class TrackQueue : public bell::Task { public: - TrackQueue(std::shared_ptr ctx, - std::shared_ptr playbackState); + TrackQueue(std::shared_ptr ctx); ~TrackQueue(); enum class SkipDirection { NEXT, PREV }; std::shared_ptr playableSemaphore; - std::shared_ptr playbackState; + std::shared_ptr accessKeyFetcher; std::atomic notifyPending = false; - std::function notifyCallback; + std::deque> preloadedTracks; + bool repeat = false; void runTask() override; void stopTask(); - void shuffle_tracks(bool shuffleTracks); - void update_ghost_tracks(int16_t offset = 0); - bool hasTracks(); - bool isFinished(); - void reloadTracks(uint8_t offset = 1); - bool skipTrack(SkipDirection dir, bool expectNotify = true); - bool updateTracks(uint32_t requestedPosition = 0, bool initial = false); + bool skipTrack(SkipDirection dir, bool expectNotify = false); TrackInfo getTrackInfo(std::string_view identifier); std::shared_ptr consumeTrack( std::shared_ptr prevSong, int& offset); - std::deque> preloadedTracks; + std::mutex tracksMutex, runningMutex; private: - static const int MAX_TRACKS_PRELOAD = 3; - - std::shared_ptr accessKeyFetcher; std::shared_ptr ctx; std::shared_ptr processSemaphore; - std::unique_ptr playerContext; - - std::deque> queuedTracks = {}; - std::vector currentTracks = {}; - std::vector ghostTracks; - std::mutex tracksMutex, runningMutex; - - std::string accessKey; - uint32_t radio_offset = 0; - - uint32_t currentTracksIndex = -1; bool isRunning = false; - bool contextResolved = false; - bool continue_with_radio = true; - std::random_device rd; - std::default_random_engine rng; + std::string accessKey; - void resolveAutoplay(); - void resolveContext(); void processTrack(std::shared_ptr track); - bool queueNextTrack(int offset = 0, uint32_t positionMs = 0); - void loadRadio(std::string req); }; -} // namespace cspot +} // namespace cspot \ No newline at end of file diff --git a/cspot/include/TrackReference.h b/cspot/include/TrackReference.h index d303224b..a5688d4b 100644 --- a/cspot/include/TrackReference.h +++ b/cspot/include/TrackReference.h @@ -7,25 +7,25 @@ #include "NanoPBHelper.h" #include "Utils.h" //for base62decode #include "pb_decode.h" -#include "protobuf/spirc.pb.h" +#include "protobuf/connect.pb.h" + +#define TRACK_SEND_LIMIT 10 namespace cspot { struct TrackReference { TrackReference(); TrackReference(std::string uri, std::string context) : type(Type::TRACK) { - this->gid = base62Decode(uri); + this->gid = base62Decode(uri).second; //this->uri=uri; this->context = context; } TrackReference(std::string uri) : type(Type::TRACK) { - gid = base62Decode(uri); + gid = base62Decode(uri).second; if (uri.find("episode:") != std::string::npos) { type = Type::EPISODE; } - if (uri.find("track:") == std::string::npos) { - this->uri = uri; - } + this->uri = uri; } // Resolved track GID @@ -43,10 +43,22 @@ struct TrackReference { bool operator==(const TrackReference& other) const; // Encodes list of track references into a pb structure, used by nanopb - static bool pbEncodeTrackList(pb_ostream_t* stream, const pb_field_t* field, - void* const* arg); + static bool pbEncodeProvidedTracks(pb_ostream_t* stream, + const pb_field_t* field, void* const* arg); + + static bool pbDecodeProvidedTracks(pb_istream_t* stream, + const pb_field_t* field, void** arg); - static bool pbDecodeTrackList(pb_istream_t* stream, const pb_field_t* field, - void** arg); + static void clearProvidedTracklist(std::vector* tracklist) { + for (auto& track : *tracklist) + pbReleaseProvidedTrack(&track); + tracklist->clear(); + } + + static void pbReleaseProvidedTrack(ProvidedTrack* track) { + if (track->metadata_count < track->full_metadata_count) + track->metadata_count = track->full_metadata_count; + pb_release(ProvidedTrack_fields, track); + } }; } // namespace cspot diff --git a/cspot/include/Utils.h b/cspot/include/Utils.h index a657e5b6..e2ce70ca 100644 --- a/cspot/include/Utils.h +++ b/cspot/include/Utils.h @@ -15,8 +15,10 @@ #include // for unique_ptr #include // for runtime_error #include // for string +#include // for pair #define HMAC_SHA1_BLOCKSIZE 64 +enum class SpotifyFileType { TRACK, EPISODE, UNKNOWN }; /** * @brief Returns current timestamp @@ -33,6 +35,14 @@ unsigned long long getCurrentTimestamp(); */ uint64_t hton64(uint64_t value); +/** + * @brief Encodes a bytestream to a base64 string + * + * @param v std::vector + * @return std::string + */ +std::string base64Encode(const std::vector& v); + std::vector bigNumDivide(std::vector num, int n); /** @@ -61,7 +71,7 @@ unsigned char h2int(char c); * @param uri spotify uri/spotify id(base62) string * @return std::vector gid */ -std::vector base62Decode(std::string uri); +std::pair> base62Decode(std::string uri); std::string urlDecode(std::string str); diff --git a/cspot/protobuf/connect.options b/cspot/protobuf/connect.options new file mode 100644 index 00000000..63c63f89 --- /dev/null +++ b/cspot/protobuf/connect.options @@ -0,0 +1,79 @@ +DeviceInfo.name type:FT_POINTER +DeviceInfo.device_id type:FT_POINTER +DeviceInfo.client_id type:FT_POINTER +DeviceInfo.spirc_version type:FT_POINTER +//DeviceInfo.supported_types type:FT_POINTER +DeviceInfo.device_software_version type:FT_POINTER +DeviceInfo.capabilities max_count:27, fixed_count:false +DeviceInfo.model type:FT_POINTER +DeviceInfo.brand type:FT_POINTER +PutStateRequest.callback_url type:FT_POINTER +PutStateRequest.last_command_sent_by_device_id type:FT_POINTER +Capabilities.stringValue max_count:50, max_size: 50 +Capabilities.intValue max_count:50 +Capabilities.supported_types type:FT_POINTER +Capabilities.Supported_typesEntry type:FT_POINTER +Cluster.device max_count:10 fixed_count:false +Cluster.DeviceEntry.key type:FT_POINTER +Cluster.active_device_id type:FT_POINTER +ProvidedTrack.uri type:FT_POINTER +ProvidedTrack.uid type:FT_POINTER +ProvidedTrack.metadata max_count:30, fixed_count:false +ProvidedTrack.MetadataEntry type:FT_POINTER +ProvidedTrack.removed type:FT_POINTER +ProvidedTrack.blocked type:FT_POINTER +ProvidedTrack.provider type:FT_POINTER +ProvidedTrack.album_uri type:FT_POINTER +ProvidedTrack.disallow_reasons type:FT_POINTER +ProvidedTrack.artist_uri type:FT_POINTER +ProvidedTrack.disallow_undecided type:FT_POINTER +PlayOrigin.feature_identifier type:FT_POINTER +PlayOrigin.feature_version type:FT_POINTER +PlayOrigin.view_uri type:FT_POINTER +PlayOrigin.external_referrer type:FT_POINTER +PlayOrigin.referrer_identifier type:FT_POINTER +PlayOrigin.device_identifier type:FT_POINTER +PlayOrigin.feature_classes type:FT_POINTER +PlayerState.playback_id type:FT_POINTER + +ContextPlayerOptions.context_enhancement max_count:2, fixed_count:false +ContextPlayerOptions.ContextEnhancementEntry type:FT_POINTER + +Restrictions type:FT_POINTER + +PlayerState.context_uri type:FT_POINTER +PlayerState.context_url type:FT_POINTER +PlayerState.context_metadata type:FT_POINTER +PlayerState.ContextMetadataEntry type:FT_POINTER +PlayerState.page_metadata type:FT_POINTER +PlayerState.PageMetadataEntry type:FT_POINTER +PlayerState.session_id type:FT_POINTER +PlayerState.queue_revision type:FT_POINTER +PlayerState.entity_uri type:FT_POINTER +PlayerState.playback_provider type:FT_POINTER +PlayerState.random_message type:FT_POINTER + +Restrictions.disallow_pausing_reasons type:FT_POINTER +Restrictions.disallow_resuming_reasons type:FT_POINTER +Restrictions.disallow_seeking_reasons type:FT_POINTER +Restrictions.disallow_peeking_prev_reasons type:FT_POINTER +Restrictions.disallow_peeking_next_reasons type:FT_POINTER +Restrictions.disallow_skipping_prev_reasons type:FT_POINTER +Restrictions.disallow_skipping_next_reasons type:FT_POINTER +Restrictions.disallow_toggling_repeat_context_reasons type:FT_POINTER +Restrictions.disallow_toggling_repeat_track_reasons type:FT_POINTER +Restrictions.disallow_toggling_shuffle_reasons type:FT_POINTER +Restrictions.disallow_set_queue_reasons type:FT_POINTER +Restrictions.disallow_interrupting_playback_reasons type:FT_POINTER +Restrictions.disallow_transferring_playback_reasons type:FT_POINTER +Restrictions.disallow_remote_control_reasons type:FT_POINTER +Restrictions.disallow_inserting_into_next_tracks_reasons type:FT_POINTER +Restrictions.disallow_inserting_into_context_tracks_reasons type:FT_POINTER +Restrictions.disallow_reordering_in_next_tracks_reasons type:FT_POINTER +Restrictions.disallow_reordering_in_context_tracks_reasons type:FT_POINTER +Restrictions.disallow_removing_from_next_tracks_reasons type:FT_POINTER +Restrictions.disallow_removing_from_context_tracks_reasons type:FT_POINTER +Restrictions.disallow_updating_context_reasons type:FT_POINTER +Restrictions.disallow_playing_reasons type:FT_POINTER +Restrictions.disallow_stopping_reasons type:FT_POINTER +Restrictions.disallow_loading_context_reasons type:FT_POINTER \ No newline at end of file diff --git a/cspot/protobuf/connect.proto b/cspot/protobuf/connect.proto new file mode 100644 index 00000000..c27b843f --- /dev/null +++ b/cspot/protobuf/connect.proto @@ -0,0 +1,345 @@ +syntax = "proto2"; + +message PlayerState { + optional int64 timestamp = 1; + optional string context_uri = 2; + optional string context_url = 3; + optional Restrictions context_restrictions = 4; + optional PlayOrigin play_origin = 5; + optional ContextIndex index = 6; + optional ProvidedTrack track = 7; + optional string playback_id = 8; + optional double playback_speed = 9; + optional int64 position_as_of_timestamp = 10; + optional int64 duration = 11; + optional bool is_playing = 12; + optional bool is_paused = 13; + optional bool is_buffering = 14; + optional bool is_system_initiated = 15; + optional ContextPlayerOptions options = 16; + optional Restrictions restrictions = 17; + optional Suppressions suppressions = 18; + repeated ProvidedTrack prev_tracks = 19; + repeated ProvidedTrack next_tracks = 20; + map context_metadata = 21; + map page_metadata = 22; + optional string session_id = 23; + optional string queue_revision = 24; + optional int64 position = 25; + optional string entity_uri = 26; + repeated ProvidedTrack reverse = 27; + repeated ProvidedTrack future = 28; + optional PlaybackQuality playback_quality = 32; + optional string playback_provider = 33; + optional string random_message = 35; +} + +message ProvidedTrack { + optional string uri = 1; + optional string uid = 2; + map metadata = 3; + optional string removed = 4; + repeated string blocked = 5; + optional string provider = 6; + optional Restrictions restrictions = 7; + optional string album_uri = 8; + repeated string disallow_reasons = 9; + optional string artist_uri = 10; + repeated string disallow_undecided = 11; + optional uint32 page = 253; + optional uint32 original_index = 254; + optional uint32 full_metadata_count = 255; +} + +message ContextIndex { + optional uint32 page = 1; + optional uint32 track = 2; +} + +message Restrictions { + repeated string disallow_pausing_reasons = 1; + repeated string disallow_resuming_reasons = 2; + repeated string disallow_seeking_reasons = 3; + repeated string disallow_peeking_prev_reasons = 4; + repeated string disallow_peeking_next_reasons = 5; + repeated string disallow_skipping_prev_reasons = 6; + repeated string disallow_skipping_next_reasons = 7; + repeated string disallow_toggling_repeat_context_reasons = 8; + repeated string disallow_toggling_repeat_track_reasons = 9; + repeated string disallow_toggling_shuffle_reasons = 10; + repeated string disallow_set_queue_reasons = 11; + repeated string disallow_interrupting_playback_reasons = 12; + repeated string disallow_transferring_playback_reasons = 13; + repeated string disallow_remote_control_reasons = 14; + repeated string disallow_inserting_into_next_tracks_reasons = 15; + repeated string disallow_inserting_into_context_tracks_reasons = 16; + repeated string disallow_reordering_in_next_tracks_reasons = 17; + repeated string disallow_reordering_in_context_tracks_reasons = 18; + repeated string disallow_removing_from_next_tracks_reasons = 19; + repeated string disallow_removing_from_context_tracks_reasons = 20; + repeated string disallow_updating_context_reasons = 21; + repeated string disallow_playing_reasons = 22; + repeated string disallow_stopping_reasons = 23; + repeated string disallow_loading_context_reasons = 25; +} + +message PlayOrigin { + optional string feature_identifier = 1; + optional string feature_version = 2; + optional string view_uri = 3; + optional string external_referrer = 4; + optional string referrer_identifier = 5; + optional string device_identifier = 6; + optional string feature_classes = 7; +} + +message ContextEnhancement{ + optional string key = 1; + optional string value = 2; +} + +message ContextPlayerOptions { + optional bool shuffling_context = 1; + optional bool repeating_context = 2; + optional bool repeating_track = 3; + + map context_enhancement = 5; +} + +message Suppressions { + repeated string providers = 1; +} + +enum BitrateLevel { + unknown = 0; + low = 1; + normal = 2; + high = 3; + veryhigh = 4; + normalized = 5; +} + +enum BitrateStrategy { + unknown_strategy = 0; + best_matching = 1; + backend_advised = 2; + offlined_file = 3; + cached_file = 4; + local_file = 5; +} + +enum HiFiStatus { + none = 0; + off = 1; + on = 2; +} + +message PlaybackQuality { + optional BitrateLevel bitrate_level = 1; + optional BitrateStrategy strategy = 2; + optional BitrateLevel target_bitrate_level = 3; + optional bool target_bitrate_available = 4; + optional HiFiStatus hifi_status = 5; +} + +message ClusterUpdate { + optional Cluster cluster = 1; + optional ClusterUpdateReason update_reason = 2; + optional string ack_id = 3; + repeated string devices_that_changed = 4; +} + +message Device { + optional DeviceInfo device_info = 1; + optional PlayerState player_state = 2; + optional PrivateDeviceInfo private_device_info = 3; + optional bytes transfer_data = 4; // TransferState +} + +message Cluster { + optional uint64 timestamp = 1; + optional string active_device_id = 2; + optional PlayerState player_state = 3; + map device = 4; + optional bytes transfer_data = 5; + optional uint64 transfer_data_timestamp = 6; + optional int64 not_playing_since_timestamp = 7; + optional bool need_full_player_state = 8; + optional int64 server_timestamp_ms = 9; +} + +message PutStateRequest { + optional string callback_url = 1; + optional Device device = 2; + optional MemberType member_type = 3; + optional bool is_active = 4; + optional PutStateReason put_state_reason = 5; + optional uint32 message_id = 6; + optional string last_command_sent_by_device_id = 7; + optional uint32 last_command_message_id = 8; + optional uint64 started_playing_at = 9; + optional uint64 has_been_playing_for_ms = 11; + optional uint64 client_side_timestamp = 12; + optional bool only_write_player_state = 13; +} + +message PrivateDeviceInfo { + optional string platform = 1; +} + +message SubscribeRequest { + optional string callback_url = 1; +} + +message DeviceInfo { + message DeviceAliasesEntry { + optional uint32 key = 1; + optional DeviceAlias value = 2; + } + optional bool can_play = 1; + optional uint32 volume = 2; + optional string name = 3; + optional Capabilities capabilities = 4; + optional string device_software_version = 6; + optional DeviceType device_type = 7; + optional string spirc_version = 9; + optional string device_id = 10; + optional bool is_private_session = 11; + optional bool is_social_connect = 12; + optional string client_id = 13; + optional string brand = 14; + optional string model = 15; + map metadata_map = 16; + optional string product_id = 17; + optional string deduplication_id = 18; + optional uint32 selected_alias_id = 19; + repeated DeviceAliasesEntry device_aliases = 20; + optional bool is_offline = 21; + optional string public_ip = 22; + optional string license = 23; +} + +message DeviceAlias { + optional uint32 id = 1; + optional string name = 2; + optional bool is_group = 3; +} + +message Capabilities { + optional bool can_be_player = 2; + optional bool restrict_to_local = 3; + optional bool gaia_eq_connect_id = 5; + optional bool supports_logout = 6; + optional bool is_observable = 7; + optional int32 volume_steps = 8; + repeated string supported_types = 9; + optional bool command_acks = 10; + optional bool supports_rename = 11; + optional bool hidden = 12; + optional bool disable_volume = 13; + optional bool connect_disabled = 14; + optional bool supports_playlist_v2 = 15; + optional bool is_controllable = 16; + optional bool supports_external_episodes = 17; + optional bool supports_set_backend_metadata = 18; + optional bool supports_transfer_command = 19; + optional bool supports_command_request = 20; + optional bool is_voice_enabled = 21; + optional bool needs_full_player_state = 22; + optional bool supports_gzip_pushes = 23; + optional bool supports_lossless_audio = 24; + optional bool supports_set_options_command = 25; + optional CapabilitySupportDetails supports_hifi = 26; + // reserved 1, "supported_contexts"; +} + +message CapabilitySupportDetails { + optional bool fully_supported = 1; + optional bool user_eligible = 2; + optional bool device_supported = 3; +} + +message ConnectCommandOptions { + optional int32 message_id = 1; +} + +message LogoutCommand { + optional ConnectCommandOptions command_options = 1; +} + +message SetVolumeCommand { + optional int32 volume = 1; + optional ConnectCommandOptions command_options = 2; +} + +message RenameCommand { + optional string rename_to = 1; + optional ConnectCommandOptions command_options = 2; +} + +message SetBackendMetadataCommand { + map metadata = 1; +} + +enum SendCommandResult { + UNKNOWN_SEND_COMMAND_RESULT = 0; + SUCCESS = 1; + DEVICE_NOT_FOUND = 2; + CONTEXT_PLAYER_ERROR = 3; + DEVICE_DISAPPEARED = 4; + UPSTREAM_ERROR = 5; + DEVICE_DOES_NOT_SUPPORT_COMMAND = 6; + RATE_LIMITED = 7; +} + +enum PutStateReason { + UNKNOWN_PUT_STATE_REASON = 0; + SPIRC_HELLO = 1; + SPIRC_NOTIFY = 2; + NEW_DEVICE = 3; + PLAYER_STATE_CHANGED = 4; + VOLUME_CHANGED = 5; + PICKER_OPENED = 6; + BECAME_INACTIVE = 7; + ALIAS_CHANGED = 8; +} + +enum MemberType { + SPIRC_V2 = 0; + SPIRC_V3 = 1; + CONNECT_STATE = 2; + CONNECT_STATE_EXTENDED = 5; + ACTIVE_DEVICE_TRACKER = 6; + PLAY_TOKEN = 7; +} + +enum ClusterUpdateReason { + UNKNOWN_CLUSTER_UPDATE_REASON = 0; + DEVICES_DISAPPEARED = 1; + DEVICE_STATE_CHANGED = 2; + NEW_DEVICE_APPEARED = 3; + DEVICE_VOLUME_CHANGED = 4; + DEVICE_ALIAS_CHANGED = 5; +} + +enum DeviceType { + UNKNOWN = 0; + COMPUTER = 1; + TABLET = 2; + SMARTPHONE = 3; + SPEAKER = 4; + TV = 5; + AVR = 6; + STB = 7; + AUDIO_DONGLE = 8; + GAME_CONSOLE = 9; + CAST_VIDEO = 10; + CAST_AUDIO = 11; + AUTOMOBILE = 12; + SMARTWATCH = 13; + CHROMEBOOK = 14; + UNKNOWN_SPOTIFY = 100; + CAR_THING = 101; + OBSERVER = 102; + HOME_THING = 103; +} diff --git a/cspot/protobuf/mercury.options b/cspot/protobuf/mercury.options index d0fb231b..071a17b9 100644 --- a/cspot/protobuf/mercury.options +++ b/cspot/protobuf/mercury.options @@ -1,5 +1,5 @@ -Header.uri max_size:256, fixed_length:false -Header.method max_size:64, fixed_length:false +Header.uri type:FT_POINTER +Header.method type:FT_POINTER UserField.key type:FT_POINTER UserField.value type:FT_POINTER -Header.user_fields max_count:64, fixed_count:false \ No newline at end of file +Header.user_fields max_count:10, fixed_count:false \ No newline at end of file diff --git a/cspot/src/DeviceStateHandler.cpp b/cspot/src/DeviceStateHandler.cpp new file mode 100644 index 00000000..b3b0a322 --- /dev/null +++ b/cspot/src/DeviceStateHandler.cpp @@ -0,0 +1,1145 @@ +#include "DeviceStateHandler.h" + +#include // for strdup, memcpy, strcpy, strlen +#include // for uint8_t +#include // for unreference, NULL, realloc, rand +#include +#include // for shared_ptr +#include // for remove_extent_t +#include // for swap + +#include "BellLogger.h" // for AbstractLogger +#include "BellUtils.h" // for BELL_SLEEP_MS +#include "CSpotContext.h" // for Context::ConfigState, Context (ptr o... +#include "ConstantParameters.h" // for protocolVersion, swVersion +#include "Logger.h" // for CSPOT_LOG +#include "NanoPBHelper.h" // for pbEncode, pbPutString +#include "Packet.h" // for cspot +#include "TrackReference.h" // for cspot +#include "nlohmann/json.hpp" // for basic_json<>::object_t, basic_json +#include "nlohmann/json_fwd.hpp" // for json +#include "pb.h" // for pb_bytes_array_t, PB_BYTES_ARRAY_T_A... +#include "pb_decode.h" // for pb_release + +using namespace cspot; + +static DeviceStateHandler* handler; + +void DeviceStateHandler::reloadTrackList(void*) { + if (strcmp(handler->currentTracks[handler->offset - 1].uri, + "spotify:delimiter") == 0 && + handler->device.player_state.is_playing) { + handler->ctx->playbackMetrics->end_reason = cspot::PlaybackMetrics::REMOTE; + handler->ctx->playbackMetrics->end_source = "unknown"; + handler->trackPlayer->stop(); + handler->device.player_state.has_is_playing = true; + handler->device.player_state.is_playing = false; + handler->device.player_state.track = ProvidedTrack_init_zero; + handler->device.player_state.has_track = false; + if (handler->device.player_state.has_restrictions) + pb_release(Restrictions_fields, + &handler->device.player_state.restrictions); + handler->device.player_state.restrictions = Restrictions_init_zero; + handler->device.player_state.has_restrictions = false; + handler->putPlayerState(); + handler->sendCommand(CommandType::DISC); + return; + } + if (!handler->trackQueue->preloadedTracks.size()) { + handler->trackQueue->preloadedTracks.push_back( + std::make_shared( + handler->currentTracks[handler->offset - 1], handler->ctx, + handler->offsetFromStartInMillis)); + handler->offsetFromStartInMillis = 0; + } + if (handler->currentTracks.size() > + handler->trackQueue->preloadedTracks.size() + handler->offset) { + while (handler->currentTracks.size() > + handler->trackQueue->preloadedTracks.size() + handler->offset && + handler->trackQueue->preloadedTracks.size() < 3) { + handler->trackQueue->preloadedTracks.push_back( + std::make_shared( + handler + ->currentTracks[handler->offset + + handler->trackQueue->preloadedTracks.size() - + 1], + handler->ctx, 0)); + } + } + if (handler->reloadPreloadedTracks) { + handler->needsToBeSkipped = true; + handler->trackPlayer->start(); + handler->trackPlayer->resetState(); + handler->reloadPreloadedTracks = false; + handler->sendCommand(CommandType::PLAYBACK_START); + } + if (handler->playerStateChanged) { + handler->putPlayerState( + PutStateReason::PutStateReason_PLAYER_STATE_CHANGED); + handler->playerStateChanged = false; + } +} +DeviceStateHandler::DeviceStateHandler(std::shared_ptr ctx) { + handler = this; + this->ctx = ctx; + this->trackQueue = std::make_shared(ctx); + this->playerContext = std::make_shared( + ctx, &this->device.player_state, ¤tTracks, &offset); + + auto EOFCallback = [this](bool loaded) { + CSPOT_LOG(debug, "Ended track, needs_to_be_skipped = %s", + needsToBeSkipped ? "true" : "false"); + if (needsToBeSkipped) { + if (this->device.player_state.options.repeating_track) + this->trackQueue->preloadedTracks[0]->requestedPosition = 0; + else if (this->trackQueue->preloadedTracks.size()) + skip(CommandType::SKIP_NEXT, true); + } + this->device.player_state.timestamp = + this->ctx->timeProvider->getSyncedTimestamp(); + needsToBeSkipped = true; + if (!this->trackQueue->preloadedTracks.size()) + sendCommand(CommandType::DEPLETED); + }; + + auto playerStateChangedCallback = [this](std::shared_ptr track, + bool new_track = false) { + CSPOT_LOG(debug, "Track loaded, new_track = %s", + new_track ? "true" : "false"); + if (new_track) { + this->device.player_state.timestamp = + this->ctx->timeProvider->getSyncedTimestamp(); + //putPlayerState(); + sendCommand(CommandType::PLAYBACK, trackQueue->preloadedTracks[0]); + } else + putPlayerState(); + }; + + this->trackPlayer = std::make_shared( + ctx, trackQueue, EOFCallback, playerStateChangedCallback); + CSPOT_LOG(info, "Started player"); + + auto connectStateSubscription = [this](MercurySession::Response& res) { + if (res.fail || !res.parts.size()) + return; + if (strstr(res.mercuryHeader.uri, "player/command")) { + if (res.parts[0].size()) + parseCommand(res.parts[0]); + } else if (strstr(res.mercuryHeader.uri, "volume")) { + if (res.parts[0].size()) { + SetVolumeCommand newVolume; + pbDecode(newVolume, SetVolumeCommand_fields, res.parts[0]); + device.device_info.volume = newVolume.volume; + device.device_info.has_volume = true; + sendCommand(CommandType::VOLUME, newVolume.volume); + pb_release(SetVolumeCommand_fields, &newVolume); + } + } else if (strstr(res.mercuryHeader.uri, "cluster")) { + } else + CSPOT_LOG(debug, "Unknown connect_state, uri : %s", + res.mercuryHeader.uri); + }; + + this->ctx->session->addSubscriptionListener("hm://connect-state/", + connectStateSubscription); + CSPOT_LOG(info, "Added connect-state subscrription"); + + // the device connection status gets reported trough "hm://social-connect",if active + auto socialConnectSubscription = [this](MercurySession::Response& res) { + if (res.fail || !res.parts.size()) + return; + if (res.parts[0].size()) { + auto jsonResult = nlohmann::json::parse(res.parts[0]); + if (jsonResult.find("deviceBroadcastStatus") != jsonResult.end()) { + if (jsonResult.find("deviceBroadcastStatus")->find("device_id") != + jsonResult.find("deviceBroadcastStatus")->end()) { + if (jsonResult.find("deviceBroadcastStatus") + ->at("device_id") + .get() != this->ctx->config.deviceId) + goto changePlayerState; + } + } else if (jsonResult.find("reason") != jsonResult.end() && + jsonResult.at("reason") == "SESSION_DELETED") + goto changePlayerState; + return; + changePlayerState: + if (this->is_active) { + this->ctx->playbackMetrics->end_reason = PlaybackMetrics::REMOTE; + this->ctx->playbackMetrics->end_source = "unknown"; + this->trackPlayer->stop(); + this->is_active = false; + if (device.player_state.has_restrictions) + pb_release(Restrictions_fields, &device.player_state.restrictions); + device.player_state.restrictions = Restrictions_init_zero; + device.player_state.has_restrictions = false; + this->putDeviceState(PutStateReason::PutStateReason_BECAME_INACTIVE); + CSPOT_LOG(debug, "Device changed"); + sendCommand(CommandType::DISC); + } + } + }; + + this->ctx->session->addSubscriptionListener("social-connect", + socialConnectSubscription); + CSPOT_LOG(info, "Added social-connect supscription"); + + ctx->session->setConnectedHandler([this]() { + CSPOT_LOG(info, "Registered new device"); + this->putDeviceState(PutStateReason::PutStateReason_NEW_DEVICE); + // Assign country code + this->ctx->config.countryCode = this->ctx->session->getCountryCode(); + }); + + device = {}; + + // Prepare default device state + device.has_device_info = true; + + // Prepare device info + device.device_info.can_play = true; + device.device_info.has_can_play = true; + + device.device_info.has_volume = true; + device.device_info.volume = ctx->config.volume; + + device.device_info.name = strdup(ctx->config.deviceName.c_str()); + + device.device_info.has_capabilities = true; + device.device_info.capabilities = Capabilities{ + true, + 1, //can_be_player + false, + 0, //restrict_to_local + true, + 1, //gaia_eq_connect_id + true, + 0, //supports_logout + true, + 1, //is_observable + true, + 64, //volume_steps + 0, + NULL, //{"audio/track", "audio/episode", "audio/episode+track"}, //supported_types + true, + 1, //command_acks + false, + 0, //supports_rename + false, + 0, //hidden + false, + 0, //disable_volume + false, + 0, //connect_disabled + true, + 1, //supports_playlist_v2 + true, + 1, //is_controllable + true, + 1, //supports_external_episodes + true, + 0, //supports_set_backend_metadata + true, + 1, //supports_transfer_command + false, + 0, //supports_command_request + false, + 0, //is_voice_enabled + true, + 1, //needs_full_player_state + false, + 1, //supports_gzip_pushes + false, + 0, //supports_lossless_audio + true, + 1, //supports_set_options_command + true, + {false, 0, false, 0, true, 1}}; + device.device_info.capabilities.supported_types = + (char**)calloc(5, sizeof(char*)); + device.device_info.capabilities.supported_types[0] = strdup("audio/track"); + device.device_info.capabilities.supported_types[1] = strdup("audio/episode"); + device.device_info.capabilities.supported_types[2] = + strdup("audio/episode+track"); + device.device_info.capabilities.supported_types[3] = + strdup("audio/interruption"); + device.device_info.capabilities.supported_types[4] = strdup("audio/local"); + device.device_info.capabilities.supported_types_count = 5; + device.device_info.device_software_version = strdup(swVersion); + device.device_info.has_device_type = true; + device.device_info.device_type = DeviceType::DeviceType_SPEAKER; + device.device_info.spirc_version = strdup(protocolVersion); + device.device_info.device_id = strdup(ctx->config.deviceId.c_str()); + //device.device_info.client_id + device.device_info.brand = strdup(brandName); + device.device_info.model = strdup(informationString); + //device.device_info.metadata_map = {{"debug_level","1"},{"tier1_port","0"},{"device_address_mask",local_ip}}; + //device.device_info.public_ip = ; // gets added trough server + //device.device_info.license = ; +} + +DeviceStateHandler::~DeviceStateHandler() { + TrackReference::clearProvidedTracklist(¤tTracks); + currentTracks.clear(); + pb_release(Device_fields, &device); +} + +void DeviceStateHandler::putDeviceState(PutStateReason put_state_reason) { + std::scoped_lock lock(playerStateMutex); + std::string uri = + "hm://connect-state/v1/devices/" + this->ctx->config.deviceId + "/"; + + std::vector send_tracks = {}; + PutStateRequest tempPutReq = PutStateRequest_init_zero; + tempPutReq.has_device = true; + tempPutReq.has_member_type = true; + tempPutReq.member_type = MemberType::MemberType_CONNECT_STATE; + tempPutReq.has_is_active = true; + tempPutReq.is_active = is_active; + tempPutReq.has_put_state_reason = true; + tempPutReq.put_state_reason = put_state_reason; + tempPutReq.has_message_id = true; + tempPutReq.message_id = last_message_id; + tempPutReq.has_has_been_playing_for_ms = true; + tempPutReq.has_been_playing_for_ms = (uint64_t)-1; + tempPutReq.has_client_side_timestamp = true; + tempPutReq.client_side_timestamp = + this->ctx->timeProvider->getSyncedTimestamp(); + tempPutReq.has_only_write_player_state = true; + tempPutReq.only_write_player_state = false; + + if (is_active) { + tempPutReq.has_started_playing_at = true; + tempPutReq.started_playing_at = this->started_playing_at; + tempPutReq.has_been_playing_for_ms = + this->ctx->timeProvider->getSyncedTimestamp() - + this->started_playing_at; + device.has_player_state = true; + device.player_state.has_position_as_of_timestamp = true; + device.player_state.position_as_of_timestamp = + this->ctx->timeProvider->getSyncedTimestamp() - + device.player_state.timestamp; + } else + device.has_player_state = false; + device.player_state.next_tracks.funcs.encode = + &cspot::TrackReference::pbEncodeProvidedTracks; + device.player_state.next_tracks.arg = &queuePacket; + tempPutReq.device = this->device; + + auto putStateRequest = pbEncode(PutStateRequest_fields, &tempPutReq); + tempPutReq.device = Device_init_zero; + pb_release(PutStateRequest_fields, &tempPutReq); + auto parts = MercurySession::DataParts({putStateRequest}); + auto responseLambda = [this](MercurySession::Response& res) { + if (res.fail || !res.parts.size()) + return; + }; + this->ctx->session->execute(MercurySession::RequestType::PUT, uri, + responseLambda, parts); +} + +void DeviceStateHandler::putPlayerState(PutStateReason put_state_reason) { + std::scoped_lock lock(playerStateMutex); + std::string uri = + "hm://connect-state/v1/devices/" + this->ctx->config.deviceId + "/"; + PutStateRequest tempPutReq = {}; + pb_release(PutStateRequest_fields, &tempPutReq); + tempPutReq = PutStateRequest_init_zero; + tempPutReq.has_device = true; + tempPutReq.has_member_type = false; + tempPutReq.member_type = MemberType::MemberType_CONNECT_STATE; + tempPutReq.has_is_active = true; + tempPutReq.is_active = true; + tempPutReq.has_put_state_reason = true; + tempPutReq.put_state_reason = put_state_reason; + tempPutReq.last_command_message_id = last_message_id; + tempPutReq.has_started_playing_at = true; + tempPutReq.started_playing_at = this->started_playing_at; + tempPutReq.has_has_been_playing_for_ms = true; + tempPutReq.has_been_playing_for_ms = + this->ctx->timeProvider->getSyncedTimestamp() - this->started_playing_at; + tempPutReq.has_client_side_timestamp = true; + tempPutReq.client_side_timestamp = + this->ctx->timeProvider->getSyncedTimestamp(); + tempPutReq.has_only_write_player_state = true; + tempPutReq.only_write_player_state = true; + device.player_state.has_position_as_of_timestamp = true; + device.player_state.position_as_of_timestamp = + (int64_t)trackQueue->preloadedTracks[0]->trackMetrics->getPosition(); + device.has_player_state = true; + device.player_state.has_position_as_of_timestamp = true; + device.player_state.position_as_of_timestamp = + trackQueue->preloadedTracks[0]->trackMetrics->getPosition(); + queuePacket = {&offset, ¤tTracks}; + device.player_state.next_tracks.funcs.encode = + &cspot::TrackReference::pbEncodeProvidedTracks; + device.player_state.next_tracks.arg = &queuePacket; + if (device.player_state.track.provider && + strcmp(device.player_state.track.provider, "autoplay") == 0) { + if (device.player_state.has_restrictions) + pb_release(Restrictions_fields, &device.player_state.restrictions); + pb_release(ContextIndex_fields, &device.player_state.index); + device.player_state.index = ContextIndex_init_zero; + device.player_state.has_index = false; + device.player_state.restrictions = Restrictions_init_zero; + if (!device.player_state.is_paused) { + device.player_state.restrictions.disallow_resuming_reasons = + (char**)calloc(1, sizeof(char*)); + device.player_state.restrictions.disallow_resuming_reasons_count = 1; + device.player_state.restrictions.disallow_resuming_reasons[0] = + strdup("not_paused"); + } else { + device.player_state.restrictions.disallow_pausing_reasons = + (char**)calloc(1, sizeof(char*)); + device.player_state.restrictions.disallow_pausing_reasons_count = 1; + device.player_state.restrictions.disallow_pausing_reasons[0] = + strdup("not_playing"); + } + + device.player_state.restrictions.disallow_toggling_repeat_context_reasons = + (char**)calloc(3, sizeof(char*)); + device.player_state.restrictions + .disallow_toggling_repeat_context_reasons_count = 3; + device.player_state.restrictions + .disallow_toggling_repeat_context_reasons[0] = strdup("autoplay"); + device.player_state.restrictions + .disallow_toggling_repeat_context_reasons[1] = + strdup("endless_context"); + device.player_state.restrictions + .disallow_toggling_repeat_context_reasons[2] = strdup("radio"); + + device.player_state.restrictions.disallow_toggling_repeat_track_reasons = + (char**)calloc(1, sizeof(char*)); + device.player_state.restrictions + .disallow_toggling_repeat_track_reasons_count = 1; + device.player_state.restrictions.disallow_toggling_repeat_track_reasons[0] = + strdup("autoplay"); + + device.player_state.restrictions.disallow_toggling_shuffle_reasons = + (char**)calloc(3, sizeof(char*)); + device.player_state.restrictions.disallow_toggling_shuffle_reasons_count = + 3; + device.player_state.restrictions.disallow_toggling_shuffle_reasons[0] = + strdup("autoplay"); + device.player_state.restrictions.disallow_toggling_shuffle_reasons[1] = + strdup("endless_context"); + device.player_state.restrictions.disallow_toggling_shuffle_reasons[2] = + strdup("radio"); + + device.player_state.restrictions.disallow_loading_context_reasons = + (char**)calloc(1, sizeof(char*)); + device.player_state.restrictions.disallow_loading_context_reasons_count = 1; + device.player_state.restrictions.disallow_loading_context_reasons[0] = + strdup("not_supported_by_content_type"); + + device.player_state.has_index = false; + device.player_state.has_restrictions = true; + } else { + device.player_state.index = + ContextIndex{true, device.player_state.track.page, true, + device.player_state.track.original_index}; + if (device.player_state.has_restrictions) + pb_release(Restrictions_fields, &device.player_state.restrictions); + device.player_state.restrictions = Restrictions_init_zero; + if (!device.player_state.is_paused) { + device.player_state.restrictions.disallow_resuming_reasons = + (char**)calloc(1, sizeof(char*)); + device.player_state.restrictions.disallow_resuming_reasons_count = 1; + device.player_state.restrictions.disallow_resuming_reasons[0] = + strdup("not_paused"); + } else { + device.player_state.restrictions.disallow_pausing_reasons = + (char**)calloc(1, sizeof(char*)); + device.player_state.restrictions.disallow_pausing_reasons_count = 1; + device.player_state.restrictions.disallow_pausing_reasons[0] = + strdup("not_playing"); + } + device.player_state.restrictions.disallow_loading_context_reasons = + (char**)calloc(1, sizeof(char*)); + device.player_state.restrictions.disallow_loading_context_reasons_count = 1; + device.player_state.restrictions.disallow_loading_context_reasons[0] = + strdup("not_supported_by_content_type"); + + device.player_state.has_restrictions = true; + } + tempPutReq.device = this->device; + auto putStateRequest = pbEncode(PutStateRequest_fields, &tempPutReq); + tempPutReq.device = Device_init_zero; + pb_release(PutStateRequest_fields, &tempPutReq); + auto parts = MercurySession::DataParts({putStateRequest}); + + auto responseLambda = [this](MercurySession::Response& res) { + if (res.fail || !res.parts.size()) + return; + }; + this->ctx->session->execute(MercurySession::RequestType::PUT, uri, + responseLambda, parts); +} + +void DeviceStateHandler::disconnect() { + this->trackQueue->stopTask(); + this->trackPlayer->stop(); + this->ctx->session->disconnect(); +} + +void DeviceStateHandler::skip(CommandType dir, bool notify) { + if (dir == CommandType::SKIP_NEXT) { + std::scoped_lock lock(trackQueue->tracksMutex); + this->device.player_state.track = currentTracks[offset]; + if (this->device.player_state.track.full_metadata_count > + this->device.player_state.track.metadata_count) + this->device.player_state.track.metadata_count = + this->device.player_state.track.full_metadata_count; + if (trackQueue->preloadedTracks.size()) { + trackQueue->preloadedTracks.pop_front(); + if (currentTracks.size() > + (trackQueue->preloadedTracks.size() + offset)) { + while (currentTracks.size() > + trackQueue->preloadedTracks.size() + offset && + trackQueue->preloadedTracks.size() < 3) { + trackQueue->preloadedTracks.push_back( + std::make_shared( + currentTracks[offset + trackQueue->preloadedTracks.size()], + this->ctx, 0)); + } + } + offset++; + } + } else if (trackQueue->preloadedTracks[0]->trackMetrics->getPosition() >= + 3000 && + offset > 1) { + std::scoped_lock lock(trackQueue->tracksMutex); + trackQueue->preloadedTracks.pop_back(); + offset--; + trackQueue->preloadedTracks.push_front(std::make_shared( + currentTracks[offset - 1], this->ctx, 0)); + } else { + if (trackQueue->preloadedTracks.size()) + trackQueue->preloadedTracks[0]->requestedPosition = 0; + } + if (trackQueue->preloadedTracks.size() && + currentTracks.size() < offset + trackQueue->preloadedTracks.size()) { + playerContext->resolveTracklist(metadata_map, reloadTrackList); + } + if (!trackQueue->preloadedTracks.size()) + this->trackPlayer->stop(); + else if (!notify) + trackPlayer->resetState(); +} + +void DeviceStateHandler::parseCommand(std::vector& data) { + if (data.size() <= 2) + return; + auto jsonResult = nlohmann::json::parse(data); + + if (jsonResult.find("message_id") != jsonResult.end()) + last_message_id = jsonResult["message_id"].get(); + + auto command = jsonResult.find("command"); + if (command != jsonResult.end()) { + if (command->find("endpoint") == command->end()) + return; + CSPOT_LOG(debug, "Parsing new command, endpoint : %s", + command->at("endpoint").get().c_str()); + + auto options = command->find("options"); + + if (command->at("endpoint") == "transfer") { + if (is_active) + return; + if (options != command->end()) { + if (options->find("restore_paused") != + options->end()) { //"restore"==play + if (!is_active && options->at("restore_paused") == "restore") { + started_playing_at = this->ctx->timeProvider->getSyncedTimestamp(); + is_active = true; + } + } + } + this->playerContext->radio_offset = 0; + this->device.player_state.has_is_playing = true; + this->device.player_state.is_playing = true; + this->device.player_state.has_timestamp = true; + this->device.player_state.timestamp = + this->ctx->timeProvider->getSyncedTimestamp(); + if (!is_active) { + started_playing_at = this->ctx->timeProvider->getSyncedTimestamp(); + is_active = true; + } + auto logging_params = command->find("logging_params"); + if (logging_params != command->end()) { + metadata_map.clear(); + if (logging_params->find("page_instance_ids") != + logging_params->end()) { + metadata_map.push_back(std::make_pair( + "page_instance_id", + logging_params->at("page_instance_ids")[0].get())); + } + + if (logging_params->find("interaction_ids") != logging_params->end()) { + metadata_map.push_back(std::make_pair( + "interaction_id", + logging_params->at("interaction_ids")[0].get())); + } + } + auto responseHandler = [this](MercurySession::Response& res) { + if (res.fail || !res.parts.size()) + return; + std::scoped_lock lock(trackQueue->tracksMutex); + cspot::TrackReference::clearProvidedTracklist(¤tTracks); + currentTracks = {}; + Cluster cluster = {}; + for (int i = this->device.player_state.context_metadata_count - 1; + i >= 0; i--) { + unreference(this->device.player_state.context_metadata[i].key); + unreference(this->device.player_state.context_metadata[i].value); + } + free(this->device.player_state.context_metadata); + this->device.player_state.context_metadata = NULL; + this->device.player_state.context_metadata_count = 0; + device.player_state.track = ProvidedTrack_init_zero; + device.player_state.next_tracks.arg = NULL; + if (device.player_state.has_restrictions) + pb_release(Restrictions_fields, &device.player_state.restrictions); + device.player_state.restrictions = Restrictions_init_zero; + device.player_state.has_restrictions = false; + pb_release(PlayerState_fields, &this->device.player_state); + this->device.player_state = PlayerState_init_zero; + pb_release(Cluster_fields, &cluster); + cluster.player_state.next_tracks.funcs.decode = + &cspot::TrackReference::pbDecodeProvidedTracks; + cluster.player_state.next_tracks.arg = &this->currentTracks; + + pbDecode(cluster, Cluster_fields, res.parts[0]); + this->device.player_state = cluster.player_state; + cluster.player_state = PlayerState_init_zero; + pb_release(Cluster_fields, &cluster); + offsetFromStartInMillis = device.player_state.position_as_of_timestamp; + + std::vector random_bytes; + static std::uniform_int_distribution d(0, 255); + for (int i = 0; i < 16; i++) { + random_bytes.push_back(d(ctx->rng)); + } + unreference(this->device.player_state.session_id); + this->device.player_state.session_id = + strdup(bytesToHexString(random_bytes).c_str()); + + unreference(this->device.player_state.playback_id); + random_bytes.clear(); + for (int i = 0; i < 16; i++) { + random_bytes.push_back(d(ctx->rng)); + } + this->device.player_state.playback_id = + strdup(base64Encode(random_bytes).c_str()); + + this->currentTracks.insert(this->currentTracks.begin(), + this->device.player_state.track); + offset = 1; + + queuePacket = {&offset, ¤tTracks}; + this->putDeviceState( + PutStateReason::PutStateReason_PLAYER_STATE_CHANGED); + + trackQueue->preloadedTracks.clear(); + reloadPreloadedTracks = true; + playerContext->resolveTracklist(metadata_map, reloadTrackList, true); + }; + this->ctx->session->execute(MercurySession::RequestType::GET, + "hm://connect-state/v1/cluster", + responseHandler); + } else if (this->is_active) { + if (command->at("endpoint") == "play") { + handler->trackPlayer->stop(); + sendCommand(CommandType::DEPLETED); + playerContext->radio_offset = 0; + std::scoped_lock lock(trackQueue->tracksMutex); + trackQueue->preloadedTracks.clear(); + uint8_t queued = 0; + ProvidedTrack track = ProvidedTrack_init_zero; + if (!this->device.player_state.is_playing) { + this->device.player_state.is_playing = true; + this->device.player_state.has_track = true; + } + for (int i = 0; i < currentTracks.size(); i++) { + if (i > this->offset || + strcmp(currentTracks[i].provider, "queue") != 0) { + if (currentTracks[i].full_metadata_count > + currentTracks[i].metadata_count) + currentTracks[i].metadata_count = + currentTracks[i].full_metadata_count; + pb_release(ProvidedTrack_fields, ¤tTracks[i]); + } else + queued++; + } + if (queued) { + currentTracks.erase(currentTracks.begin()); + currentTracks.erase(currentTracks.begin() + queued, + currentTracks.end()); + } else + currentTracks.clear(); + + auto logging_params = command->find("logging_params"); + if (logging_params != command->end()) { + metadata_map.clear(); + if (logging_params->find("page_instance_ids") != + logging_params->end()) { + metadata_map.push_back(std::make_pair( + "page_instance_ids", + logging_params->at("page_instance_ids")[0].get())); + } + if (logging_params->find("interaction_ids") != + logging_params->end()) { + metadata_map.push_back(std::make_pair( + "interaction_id", + logging_params->at("interaction_ids")[0].get())); + } + } + + if (command->find("play_origin") != command->end()) { + pb_release(PlayOrigin_fields, &device.player_state.play_origin); + device.player_state.play_origin = PlayOrigin_init_zero; + device.player_state.play_origin.feature_identifier = + PlayerContext::createStringReferenceIfFound( + command->at("play_origin"), "feature_identifier"); + device.player_state.play_origin.feature_version = + PlayerContext::createStringReferenceIfFound( + command->at("play_origin"), "feature_version"); + device.player_state.play_origin.referrer_identifier = + PlayerContext::createStringReferenceIfFound( + command->at("play_origin"), "referrer_identifier"); + } + + auto options = command->find("options"); + int64_t playlist_offset = 0; + if (options != command->end()) { + if (options->find("player_options_override") != options->end()) + device.player_state.options.shuffling_context = + options->at("player_options_override").at("shuffling_context"); + if (options->find("skip_to") != options->end()) { + if (options->at("skip_to").size()) { + if (options->at("skip_to").find("track_index") != + options->at("skip_to").end()) + playlist_offset = options->at("skip_to").at("track_index"); + track.uri = PlayerContext::createStringReferenceIfFound( + options->at("skip_to"), "track_uri"); + track.uid = PlayerContext::createStringReferenceIfFound( + options->at("skip_to"), "track_uid"); + } + } + } + + auto metadata = command->at("context").find("metadata"); + if (metadata != command->at("context").end()) { + if (metadata->find("enhanced_context") != metadata->end()) { + this->device.player_state.options.context_enhancement[0].key = + strdup("context_enhancement"); + this->device.player_state.options.context_enhancement[0].value = + strdup("NONE"); + this->device.player_state.options.context_enhancement_count = 1; + } else if (this->device.player_state.options + .context_enhancement_count) { + for (auto& enhamcement : + this->device.player_state.options.context_enhancement) { + this->unreference(enhamcement.key); + this->unreference(enhamcement.value); + } + this->device.player_state.options.context_enhancement_count = 0; + } + + context_metadata_map.clear(); + for (auto element : metadata->items()) { + if (element.value().size() && element.value() != "" && + element.key() != "canContainArtists.uris") { + context_metadata_map.push_back(std::make_pair( + element.key(), element.value().get())); + } + } + for (int i = this->device.player_state.context_metadata_count - 1; + i >= 0; i--) { + unreference(this->device.player_state.context_metadata[i].key); + unreference(this->device.player_state.context_metadata[i].value); + } + free(this->device.player_state.context_metadata); + this->device.player_state.context_metadata = + (PlayerState_ContextMetadataEntry*)calloc( + context_metadata_map.size(), + sizeof(PlayerState_ContextMetadataEntry)); + for (int i = 0; i < context_metadata_map.size(); i++) { + this->device.player_state.context_metadata[i].key = + strdup(context_metadata_map[i].first.c_str()); + this->device.player_state.context_metadata[i].value = + strdup(context_metadata_map[i].second.c_str()); + } + this->device.player_state.context_metadata_count = + context_metadata_map.size(); + } + + unreference(this->device.player_state.context_uri); + this->device.player_state.context_uri = + PlayerContext::createStringReferenceIfFound(command->at("context"), + "uri"); + unreference(this->device.player_state.context_url); + this->device.player_state.context_url = + PlayerContext::createStringReferenceIfFound(command->at("context"), + "url"); + + reloadPreloadedTracks = true; + this->trackPlayer->start(); + uint8_t metadata_offset = 0; + for (auto metadata_entry : metadata_map) { + track.metadata[metadata_offset].key = + strdup(metadata_entry.first.c_str()); + track.metadata[metadata_offset].value = + strdup(metadata_entry.second.c_str()); + metadata_offset++; + } + + if (command->at("context").find("pages") != + command->at("context").end() && + command->at("context").at("pages")[0]["tracks"].size() > + playlist_offset) { + //populate first tarck + if (track.uri == NULL) { + track.uri = PlayerContext::createStringReferenceIfFound( + command->at("context")["pages"][0]["tracks"][playlist_offset], + "uri"); + track.uid = PlayerContext::createStringReferenceIfFound( + command->at("context")["pages"][0]["tracks"][playlist_offset], + "uid"); + } + if (command->at("context")["pages"][0]["tracks"][playlist_offset] + .find("metadata") != + command->at("context")["pages"][0]["tracks"][playlist_offset] + .end()) { + for (auto metadata_entry : + command->at("context")["pages"][0]["tracks"][playlist_offset] + .at("metadata") + .items()) { + track.metadata[metadata_offset].key = + strdup(metadata_entry.key().c_str()); + track.metadata[metadata_offset].value = + strdup(((std::string)metadata_entry.value()).c_str()); + metadata_offset++; + } + } + } + track.full_metadata_count = metadata_offset; + track.metadata_count = metadata_offset; + track.provider = strdup("context"); + currentTracks.insert(currentTracks.begin(), track); + device.player_state.track = track; + offset = 1; + playerContext->resolveTracklist(context_metadata_map, reloadTrackList, + true); + } else if (command->at("endpoint") == "pause") { + device.player_state.is_paused = true; + device.player_state.has_is_paused = true; + this->putPlayerState(); + sendCommand(CommandType::PAUSE); + } else if (command->at("endpoint") == "resume") { + device.player_state.is_paused = false; + device.player_state.has_is_paused = true; + this->putPlayerState(); + sendCommand(CommandType::PLAY); + } else if (command->at("endpoint") == "skip_next") { + ctx->playbackMetrics->end_reason = PlaybackMetrics::FORWARD_BTN; + needsToBeSkipped = false; + if (command->find("track") == command->end()) + skip(CommandType::SKIP_NEXT, false); + else { + std::scoped_lock lock(playerContext->trackListMutex); + offset = 0; + for (auto track : currentTracks) { + if (strcmp(command->find("track") + ->at("uri") + .get() + .c_str(), + track.uri) == 0) + break; + offset++; + } + trackQueue->preloadedTracks.clear(); + + this->device.player_state.track = currentTracks[offset]; + for (auto i = offset; + i < (currentTracks.size() < 3 + offset ? currentTracks.size() + : 3 + offset) + + offset; + i++) { + trackQueue->preloadedTracks.push_back( + std::make_shared(currentTracks[i], + this->ctx, 0)); + } + offset++; + trackPlayer->resetState(); + } + sendCommand(CommandType::SKIP_NEXT); + } else if (command->at("endpoint") == "skip_prev") { + ctx->playbackMetrics->end_reason = PlaybackMetrics::BACKWARD_BTN; + needsToBeSkipped = false; + skip(CommandType::SKIP_PREV, false); + sendCommand(CommandType::SKIP_PREV); + + } else if (command->at("endpoint") == "seek_to") { + if (command->at("relative") == "beginning") { //relative + this->device.player_state.has_position_as_of_timestamp = true; + this->device.player_state.position_as_of_timestamp = + command->at("value").get(); + this->device.player_state.timestamp = + this->ctx->timeProvider->getSyncedTimestamp(); + this->trackPlayer->seekMs(command->at("value").get()); + } else if (command->at("relative") == "current") { + this->device.player_state.has_position_as_of_timestamp = true; + this->device.player_state.position_as_of_timestamp = + command->at("value").get() + + command->at("position").get(); + this->trackPlayer->seekMs( + this->device.player_state.position_as_of_timestamp); + this->device.player_state.timestamp = + this->ctx->timeProvider->getSyncedTimestamp(); + } + sendCommand( + CommandType::SEEK, + (int32_t)this->device.player_state.position_as_of_timestamp); + this->putPlayerState(); + } else if (command->at("endpoint") == "add_to_queue") { + std::scoped_lock lock(trackQueue->tracksMutex); + uint8_t queuedOffset = 0; + //look up already queued tracks + for (uint8_t i = offset; i < currentTracks.size(); i++) { + if (strcmp(currentTracks[i].provider, "queue") != 0) + break; + queuedOffset++; + } + + ProvidedTrack track = {}; + track.uri = strdup( + command->find("track")->at("uri").get().c_str()); + track.provider = strdup("queue"); + this->currentTracks.insert( + this->currentTracks.begin() + offset + queuedOffset, track); + if (queuedOffset < 2) { + trackQueue->preloadedTracks.pop_back(); + trackQueue->preloadedTracks.insert( + trackQueue->preloadedTracks.begin() + 1 + queuedOffset, + std::make_shared( + currentTracks[offset + queuedOffset], this->ctx, 0)); + } + this->putPlayerState(); + } else if (command->at("endpoint") == "set_queue") { + std::scoped_lock lock(trackQueue->tracksMutex); + uint8_t queuedOffset = 0, newQueuedOffset = 0; + //look up already queued tracks + for (uint8_t i = offset; i < currentTracks.size(); i++) { + if (strcmp(currentTracks[i].provider, "queue") != 0) + break; + queuedOffset++; + } + auto tracks = command->find("next_tracks"); + if (!command->at("next_tracks").size()) { + for (uint8_t i = offset; i < currentTracks.size(); i++) { + if (strcmp(currentTracks[i].provider, "queue") != 0) + break; + pb_release(ProvidedTrack_fields, ¤tTracks[i]); + currentTracks.erase(currentTracks.begin() + i); + i--; + } + } + if (command->find("next_tracks") != command->end()) { + for (int i = 0; i < command->at("next_tracks").size(); i++) { + if (strcmp(command->at("next_tracks")[i]["uri"] + .get() + .c_str(), + currentTracks[offset + i].uri) != 0) { + if (newQueuedOffset < queuedOffset) { + queuedOffset--; + goto removeTrack; + } else if (command->at("next_tracks")[i]["provider"] == "queue") { + ProvidedTrack track = {}; + track.uri = strdup(command->at("next_tracks")[i]["uri"] + .get() + .c_str()); + track.provider = strdup("queue"); + this->currentTracks.insert( + this->currentTracks.begin() + offset + i, track); + continue; + } + removeTrack:; + pb_release(ProvidedTrack_fields, ¤tTracks[offset + i]); + currentTracks.erase(currentTracks.begin() + offset + i); + if (strcmp(currentTracks[offset + i].provider, "queue") != 0 || + strcmp(command->at("next_tracks")[i]["uri"] + .get() + .c_str(), + currentTracks[offset + i].uri) == 0) + break; + i--; + } else if (command->at("next_tracks")[i]["provider"] == "queue") + newQueuedOffset++; + } + } + if (queuedOffset < 2 || newQueuedOffset < 2) { + trackQueue->preloadedTracks.clear(); + while (trackQueue->preloadedTracks.size() < 3) + trackQueue->preloadedTracks.push_back( + std::make_shared( + currentTracks[offset + trackQueue->preloadedTracks.size() - + 1], + this->ctx, 0)); + } + this->putPlayerState(); + } else if (command->at("endpoint") == "update_context") { + unreference(this->device.player_state.session_id); + this->device.player_state.session_id = + PlayerContext::createStringReferenceIfFound(*command, "session_id"); + + auto context = command->find("context"); + if (context != command->end()) { + if (context_metadata_map.size()) + context_metadata_map.clear(); + context_uri = context->find("uri") != context->end() + ? context->at("uri").get() + : " "; + context_url = context->find("url") != context->end() + ? context->at("url").get() + : " "; + auto metadata = context->find("metadata"); + if (metadata != context->end()) { + for (auto element : metadata->items()) { + if (element.value().size() && element.value() != "") { + context_metadata_map.push_back(std::make_pair( + element.key(), element.value().get())); + } + } + } + } + } else if (command->at("endpoint") == "set_shuffling_context") { + if (context_uri.size()) { + unreference(this->device.player_state.context_uri); + this->device.player_state.context_uri = strdup(context_uri.c_str()); + } + if (context_url.size()) { + unreference(this->device.player_state.context_url); + this->device.player_state.context_url = strdup(context_url.c_str()); + } + for (int i = this->device.player_state.context_metadata_count - 1; + i >= 0; i--) { + unreference(this->device.player_state.context_metadata[i].key); + unreference(this->device.player_state.context_metadata[i].value); + } + free(this->device.player_state.context_metadata); + this->device.player_state.context_metadata = + (PlayerState_ContextMetadataEntry*)calloc( + context_metadata_map.size(), + sizeof(PlayerState_ContextMetadataEntry)); + for (int i = 0; i < context_metadata_map.size(); i++) { + this->device.player_state.context_metadata[i].key = + strdup(context_metadata_map[i].first.c_str()); + this->device.player_state.context_metadata[i].value = + strdup(context_metadata_map[i].second.c_str()); + } + this->device.player_state.context_metadata_count = + context_metadata_map.size(); + + this->device.player_state.has_options = true; + this->device.player_state.options.has_shuffling_context = true; + if (command->find("value").value()) + this->device.player_state.options.shuffling_context = true; + else + this->device.player_state.options.shuffling_context = false; + if (strchr(this->device.player_state.context_url, '?') != NULL) { + this->device.player_state.options.context_enhancement[0].key = + strdup("context_enhancement"); + this->device.player_state.options.context_enhancement[0].value = + strdup("NONE"); + this->device.player_state.options.context_enhancement_count = 1; + } else { + if (this->device.player_state.options.context_enhancement_count) { + unreference( + this->device.player_state.options.context_enhancement[0].key); + unreference( + this->device.player_state.options.context_enhancement[0].value); + this->device.player_state.options.context_enhancement_count = 0; + } + } + std::scoped_lock lock(trackQueue->tracksMutex); + playerStateChanged = true; + this->trackQueue->preloadedTracks.erase( + this->trackQueue->preloadedTracks.begin(), + this->trackQueue->preloadedTracks.end()); + uint8_t queued = 0; + for (int i = offset; i < currentTracks.size(); i++) { + if (strcmp(currentTracks[i].provider, "queue") != 0) { + if (currentTracks[i].full_metadata_count > + currentTracks[i].metadata_count) + currentTracks[i].metadata_count = + currentTracks[i].full_metadata_count; + pb_release(ProvidedTrack_fields, ¤tTracks[i]); + } else + queued++; + } + currentTracks.erase(currentTracks.begin() + offset + queued, + currentTracks.end()); + playerContext->resolveTracklist(metadata_map, reloadTrackList, true); + sendCommand(CommandType::SET_SHUFFLE, + (int32_t)(this->device.player_state.options + .context_enhancement_count + ? 2 + : this->device.player_state.options + .shuffling_context)); + } else if (command->at("endpoint") == "set_options") { + + if (this->device.player_state.options.repeating_context != + command->at("repeating_context").get()) { + uint8_t release = 0; + for (int i = offset; i < currentTracks.size(); i++) + if (strcmp(currentTracks[i].uri, "spotify:delimiter") == 0 || + strcmp(currentTracks[i].provider, "autoplay") == 0) { + release = i; + break; + } + if (release) { + for (int i = release; i < currentTracks.size(); i++) + cspot::TrackReference::pbReleaseProvidedTrack(¤tTracks[i]); + currentTracks.erase(currentTracks.begin() + release, + currentTracks.end()); + } + + this->device.player_state.options.has_repeating_context = true; + this->device.player_state.options.repeating_context = + command->at("repeating_context").get(); + this->device.player_state.options.repeating_track = + command->at("repeating_track").get(); + this->device.player_state.options.has_repeating_track = true; + playerStateChanged = true; + this->playerContext->resolveTracklist(metadata_map, reloadTrackList, + true); + } else { + this->device.player_state.options.has_repeating_context = true; + this->device.player_state.options.repeating_context = + command->at("repeating_context").get(); + this->device.player_state.options.repeating_track = + command->at("repeating_track").get(); + this->device.player_state.options.has_repeating_track = true; + this->putPlayerState(); + } + if (this->device.player_state.options.repeating_context) + sendCommand( + CommandType::SET_REPEAT, + (int32_t)(this->device.player_state.options.repeating_context + ? 2 + : this->device.player_state.options + .repeating_track)); + } else + CSPOT_LOG(error, "Unknown command: %s", + &command->at("endpoint").get()[0]); + return; + } + } +} +void DeviceStateHandler::sendCommand(CommandType type, CommandData data) { + Command command; + command.commandType = type; + command.data = data; + stateCallback(command); +} \ No newline at end of file diff --git a/cspot/src/EventManager.cpp b/cspot/src/EventManager.cpp index f64d4130..3b292fe7 100644 --- a/cspot/src/EventManager.cpp +++ b/cspot/src/EventManager.cpp @@ -36,10 +36,37 @@ void TrackMetrics::endInterval(uint64_t pos) { addInterval(intervals, {currentInterval->position, currentInterval->end}); } -uint64_t TrackMetrics::getPosition() { - return ( - currentInterval->position + - (this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start)); +void TrackMetrics::pauseInterval(uint64_t pos, bool pause) { + // end Interval + if (pause) { + currentInterval->length = + this->ctx->timeProvider->getSyncedTimestamp() - currentInterval->start; + currentInterval->end = currentInterval->position + currentInterval->length; + totalAmountPlayed += currentInterval->length; + // add skipped time + if (pos != 0) { + if (pos > currentInterval->position + currentInterval->length) + skipped_forward.add( + pos - (currentInterval->position + currentInterval->length)); + else + skipped_backward.add( + (currentInterval->position + currentInterval->length) - pos); + } + if (currentInterval->length > longestInterval) + longestInterval = currentInterval->length; + intervals = addInterval(intervals, + {currentInterval->position, currentInterval->end}); + } else { + currentInterval = std::make_shared( + this->ctx->timeProvider->getSyncedTimestamp(), pos); + } +} + +uint64_t TrackMetrics::getPosition(bool paused) { + return (currentInterval->position + + (paused ? currentInterval->length + : (this->ctx->timeProvider->getSyncedTimestamp() - + currentInterval->start))); } void TrackMetrics::startTrack() { @@ -197,7 +224,7 @@ std::vector PlaybackMetrics::sendEvent( std::to_string(track->trackMetrics ->timestamp)); // unix timestamp when track started append(&msg, "0"); //?? usually 0 - append(&msg, track->ref.context == "radio" ? "autoplay" : "context"); + append(&msg, track->ref.provider); append( &msg, (end_source == "playlist" || end_source == "your_library") @@ -225,11 +252,15 @@ std::vector PlaybackMetrics::sendEvent( append(&msg, ""); append(&msg, "5003900000000146"); append(&msg, ""); + for (int i = 0; i < track->ref.full_metadata_count; i++) + if (strcmp(track->ref.metadata[i].key, "decision_id") == 0) { + append(&msg, track->ref.metadata[i].value); + goto appended_decision_id; + } append( &msg, - track->ref.context == "radio" - ? correlation_id - : ""); //ssp~061a6236e23e1a9847bd9b6ad4cd942eac8d //allways the same , only when radio? / autoplay + ""); // decision_id ssp~061a6236e23e1a9847bd9b6ad4cd942eac8d //allways the same , only when radio? / autoplay +appended_decision_id:; append(&msg, ""); append(&msg, "0"); //?? usually 0 append(&msg, "0"); //?? usually 0 @@ -246,7 +277,7 @@ std::vector PlaybackMetrics::sendEvent( auto parts = MercurySession::DataParts({msg}); // Execute the request - ctx->session->execute(MercurySession::RequestType::SEND, requestUrl, + ctx->session->execute(MercurySession::RequestType::POST, requestUrl, responseLambda, parts); #endif return msg; diff --git a/cspot/src/LoginBlob.cpp b/cspot/src/LoginBlob.cpp index 62c9df14..232a8a90 100644 --- a/cspot/src/LoginBlob.cpp +++ b/cspot/src/LoginBlob.cpp @@ -4,6 +4,7 @@ #include // for initializer_list #include "BellLogger.h" // for AbstractLogger +#include "BellUtils.h" // for getMacAddress #include "ConstantParameters.h" // for brandName, cspot, protoc... #include "Logger.h" // for CSPOT_LOG #include "protobuf/authentication.pb.h" // for AuthenticationType_AUTHE... @@ -15,13 +16,38 @@ #include "nlohmann/json_fwd.hpp" // for json #endif +#include //(for generating unique device id) + using namespace cspot; +std::string sha1_digest(const std::vector& message) { + std::vector digest(20); // SHA1 digest size (160 bits) + mbedtls_sha1_context sha1Context; + + mbedtls_sha1_init(&sha1Context); + mbedtls_sha1_starts(&sha1Context); + mbedtls_sha1_update(&sha1Context, message.data(), message.size()); + mbedtls_sha1_finish(&sha1Context, digest.data()); + mbedtls_sha1_free(&sha1Context); + + // Convert digest to a hex string + std::ostringstream oss; + for (const auto& byte : digest) { + oss << std::hex << std::setw(2) << std::setfill('0') + << static_cast(byte); + } + + return oss.str(); // Return the hex string +} + LoginBlob::LoginBlob(std::string name) { char hash[32]; sprintf(hash, "%016zu", std::hash{}(name)); // base is 142137fd329622137a14901634264e6f332e2411 - this->deviceId = std::string("142137fd329622137a149016") + std::string(hash); + std::string mac_string = bell::getMacAddress(); + CSPOT_LOG(info, "new mac : %s", mac_string.c_str()); + std::vector mac(mac_string.begin(), mac_string.end()); + this->deviceId = sha1_digest(mac); this->crypto = std::make_unique(); this->name = name; diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index 45c47137..9d33a51e 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -51,12 +51,14 @@ void MercurySession::runTask() { } } catch (const std::runtime_error& e) { CSPOT_LOG(error, "Error while receiving packet: %s", e.what()); + connection_lost = true; failAllPending(); if (!isRunning) return; reconnect(); + connection_lost = false; continue; } } @@ -138,7 +140,8 @@ std::string MercurySession::getCountryCode() { void MercurySession::handlePacket() { Packet packet = {}; - + if (connection_lost) + return; this->packetQueue.wtpop(packet, 200); if (executeEstabilishedCallback && this->connectionReadyCallback != nullptr) { @@ -188,6 +191,7 @@ void MercurySession::handlePacket() { this->callbacks.erase(this->callbacks.find(response.second)); } } + pb_release(Header_fields, &partial->second.mercuryHeader); this->partials.erase(partial); } } @@ -202,9 +206,13 @@ void MercurySession::handlePacket() { partial++; // if(partial.first == sequenceId) if (partial != partials.end()) { auto uri = std::string(partial->second.mercuryHeader.uri); - if (this->subscriptions.count(uri) > 0) { - this->subscriptions[uri](partial->second); - } + for (auto& it : this->subscriptions) + if (uri.find(it.first) != std::string::npos) { + it.second(partial->second); + goto found_subscription; + } + found_subscription:; + pb_release(Header_fields, &partial->second.mercuryHeader); this->partials.erase(partial); } } @@ -274,7 +282,7 @@ std::pair MercurySession::decodeResponse( break; auto partSize = ntohs(extract(data, pos)); pos += 2; - if (!partial->second.mercuryHeader.has_uri) { + if (partial->second.mercuryHeader.uri == NULL) { partial->second.fail = false; auto headerBytes = std::vector(data.begin() + pos, data.begin() + pos + partSize); @@ -293,6 +301,11 @@ std::pair MercurySession::decodeResponse( return std::make_pair(flag, sequenceId); } +void MercurySession::addSubscriptionListener(const std::string& uri, + ResponseCallback subscription) { + this->subscriptions.insert({uri, subscription}); +} + uint64_t MercurySession::executeSubscription(RequestType method, const std::string& uri, ResponseCallback callback, @@ -302,15 +315,14 @@ uint64_t MercurySession::executeSubscription(RequestType method, RequestTypeMap[method].c_str()); // Encode header - pbPutString(uri, tempMercuryHeader.uri); - pbPutString(RequestTypeMap[method], tempMercuryHeader.method); - - tempMercuryHeader.has_method = true; - tempMercuryHeader.has_uri = true; + pb_release(Header_fields, &tempMercuryHeader); + tempMercuryHeader.uri = strdup(uri.c_str()); + tempMercuryHeader.method = strdup(RequestTypeMap[method].c_str()); // GET and SEND are actually the same. Therefore the override // The difference between them is only in header's method - if (method == RequestType::GET) { + if (method == RequestType::GET || method == RequestType::POST || + method == RequestType::PUT) { method = RequestType::SEND; } @@ -319,8 +331,10 @@ uint64_t MercurySession::executeSubscription(RequestType method, } auto headerBytes = pbEncode(Header_fields, &tempMercuryHeader); + pb_release(Header_fields, &tempMercuryHeader); - this->callbacks.insert({sequenceId, callback}); + if (callback != nullptr) + this->callbacks.insert({sequenceId, callback}); // Structure: [Sequence size] [SequenceId] [0x1] [Payloads number] // [Header size] [Header] [Payloads (size + data)] diff --git a/cspot/src/PlaybackState.cpp b/cspot/src/PlaybackState.cpp deleted file mode 100644 index de5863c7..00000000 --- a/cspot/src/PlaybackState.cpp +++ /dev/null @@ -1,222 +0,0 @@ -#include "PlaybackState.h" - -#include // for strdup, memcpy, strcpy, strlen -#include // for uint8_t -#include // for free, NULL, realloc, rand -#include -#include // for shared_ptr -#include // for remove_extent_t -#include // for swap - -#include "BellLogger.h" // for AbstractLogger -#include "CSpotContext.h" // for Context::ConfigState, Context (ptr o... -#include "ConstantParameters.h" // for protocolVersion, swVersion -#include "Logger.h" // for CSPOT_LOG -#include "NanoPBHelper.h" // for pbEncode, pbPutString -#include "Packet.h" // for cspot -#include "pb.h" // for pb_bytes_array_t, PB_BYTES_ARRAY_T_A... -#include "pb_decode.h" // for pb_release -#include "protobuf/spirc.pb.h" - -using namespace cspot; - -PlaybackState::PlaybackState(std::shared_ptr ctx) { - this->ctx = ctx; - innerFrame = {}; - remoteFrame = {}; - - // Prepare callbacks for decoding of remote frame track data - remoteFrame.state.track.funcs.decode = &TrackReference::pbDecodeTrackList; - remoteFrame.state.track.arg = &remoteTracks; - - innerFrame.ident = strdup(ctx->config.deviceId.c_str()); - innerFrame.protocol_version = strdup(protocolVersion); - - // Prepare default state - innerFrame.state.has_position_ms = true; - innerFrame.state.position_ms = 0; - - innerFrame.state.status = PlayStatus_kPlayStatusStop; - innerFrame.state.has_status = true; - - innerFrame.state.position_measured_at = 0; - innerFrame.state.has_position_measured_at = true; - - innerFrame.state.shuffle = false; - innerFrame.state.has_shuffle = true; - - innerFrame.state.repeat = false; - innerFrame.state.has_repeat = true; - - innerFrame.device_state.sw_version = strdup(swVersion); - - innerFrame.device_state.is_active = false; - innerFrame.device_state.has_is_active = true; - - innerFrame.device_state.can_play = true; - innerFrame.device_state.has_can_play = true; - - innerFrame.device_state.volume = ctx->config.volume; - innerFrame.device_state.has_volume = true; - - innerFrame.device_state.name = strdup(ctx->config.deviceName.c_str()); - - // Prepare player's capabilities - addCapability(CapabilityType_kCanBePlayer, 1); - addCapability(CapabilityType_kDeviceType, 4); - addCapability(CapabilityType_kGaiaEqConnectId, 1); - addCapability(CapabilityType_kSupportsLogout, 0); - addCapability(CapabilityType_kSupportsPlaylistV2, 1); - addCapability(CapabilityType_kIsObservable, 1); - addCapability(CapabilityType_kVolumeSteps, 64); - addCapability(CapabilityType_kSupportedContexts, -1, - std::vector({"album", "playlist", "search", - "inbox", "toplist", "starred", - "publishedstarred", "track"})); - addCapability(CapabilityType_kSupportedTypes, -1, - std::vector( - {"audio/track", "audio/episode", "audio/episode+track"})); - innerFrame.device_state.capabilities_count = 8; -} - -PlaybackState::~PlaybackState() { - pb_release(Frame_fields, &innerFrame); - pb_release(Frame_fields, &remoteFrame); -} - -void PlaybackState::setPlaybackState(const PlaybackState::State state) { - switch (state) { - case State::Loading: - // Prepare the playback at position 0 - innerFrame.state.status = PlayStatus_kPlayStatusPause; - innerFrame.state.position_ms = 0; - innerFrame.state.position_measured_at = - ctx->timeProvider->getSyncedTimestamp(); - break; - case State::Playing: - innerFrame.state.status = PlayStatus_kPlayStatusPlay; - innerFrame.state.position_measured_at = - ctx->timeProvider->getSyncedTimestamp(); - break; - case State::Stopped: - break; - case State::Paused: - // Update state and recalculate current song position - innerFrame.state.status = PlayStatus_kPlayStatusPause; - uint32_t diff = ctx->timeProvider->getSyncedTimestamp() - - innerFrame.state.position_measured_at; - this->updatePositionMs(innerFrame.state.position_ms + diff); - break; - } -} - -void PlaybackState::syncWithRemote() { - innerFrame.state.context_uri = (char*)realloc( - innerFrame.state.context_uri, strlen(remoteFrame.state.context_uri) + 1); - - strcpy(innerFrame.state.context_uri, remoteFrame.state.context_uri); - - if (remoteFrame.state.context_description != NULL) { - innerFrame.state.context_description = - (char*)realloc(innerFrame.state.context_description, - strlen(remoteFrame.state.context_description) + 1); - strcpy(innerFrame.state.context_description, - remoteFrame.state.context_description); - } else { - free(innerFrame.state.context_description); - innerFrame.state.context_description = NULL; - } - - innerFrame.state.has_playing_track_index = true; - innerFrame.state.playing_track_index = remoteFrame.state.playing_track_index; - innerFrame.state.has_shuffle = remoteFrame.state.has_shuffle; - innerFrame.state.shuffle = remoteFrame.state.shuffle; - innerFrame.state.has_repeat = remoteFrame.state.has_repeat; - innerFrame.state.repeat = remoteFrame.state.repeat; - innerFrame.state.has_index = true; - innerFrame.state.index = remoteFrame.state.index; -} - -bool PlaybackState::isActive() { - return innerFrame.device_state.is_active; -} - -void PlaybackState::setActive(bool isActive) { - innerFrame.device_state.is_active = isActive; - if (isActive) { - innerFrame.device_state.became_active_at = - ctx->timeProvider->getSyncedTimestamp(); - innerFrame.device_state.has_became_active_at = true; - } -} - -void PlaybackState::updatePositionMs(uint32_t position) { - innerFrame.state.position_ms = position; - innerFrame.state.position_measured_at = - ctx->timeProvider->getSyncedTimestamp(); -} - -void PlaybackState::setVolume(uint32_t volume) { - innerFrame.device_state.volume = volume; - ctx->config.volume = volume; -} - -bool PlaybackState::decodeRemoteFrame(std::vector& data) { - pb_release(Frame_fields, &remoteFrame); - - remoteTracks.clear(); - - pbDecode(remoteFrame, Frame_fields, data); - - return true; -} - -std::vector PlaybackState::encodeCurrentFrame(MessageType typ) { - // Prepare current frame info - innerFrame.version = 1; - innerFrame.seq_nr = this->seqNum; - innerFrame.typ = typ; - innerFrame.state_update_id = ctx->timeProvider->getSyncedTimestamp(); - innerFrame.has_version = true; - innerFrame.has_seq_nr = true; - innerFrame.recipient_count = 0; - innerFrame.has_state = true; - innerFrame.has_device_state = true; - innerFrame.has_typ = true; - innerFrame.has_state_update_id = true; - innerFrame.state.playing_track_index = innerFrame.state.index; - innerFrame.state.has_playing_track_index = true; - innerFrame.state.has_index = true; - - this->seqNum += 1; - - return pbEncode(Frame_fields, &innerFrame); -} - -// Wraps messy nanopb setters. @TODO: find a better way to handle this -void PlaybackState::addCapability(CapabilityType typ, int intValue, - std::vector stringValue) { - innerFrame.device_state.capabilities[capabilityIndex].has_typ = true; - this->innerFrame.device_state.capabilities[capabilityIndex].typ = typ; - - if (intValue != -1) { - this->innerFrame.device_state.capabilities[capabilityIndex].intValue[0] = - intValue; - this->innerFrame.device_state.capabilities[capabilityIndex].intValue_count = - 1; - } else { - this->innerFrame.device_state.capabilities[capabilityIndex].intValue_count = - 0; - } - - for (int x = 0; x < stringValue.size(); x++) { - pbPutString(stringValue[x], - this->innerFrame.device_state.capabilities[capabilityIndex] - .stringValue[x]); - } - - this->innerFrame.device_state.capabilities[capabilityIndex] - .stringValue_count = stringValue.size(); - - this->capabilityIndex += 1; -} diff --git a/cspot/src/PlayerContext.cpp b/cspot/src/PlayerContext.cpp index 726a1214..e8da0b59 100644 --- a/cspot/src/PlayerContext.cpp +++ b/cspot/src/PlayerContext.cpp @@ -1,7 +1,12 @@ #include "PlayerContext.h" +#include +#include +#include #include "MercurySession.h" -#include "TrackQueue.h" +#include "protobuf/connect.pb.h" // for PutStateRequest, DeviceState, PlayerState... +#include "BellLogger.h" // for AbstractLogger +#include "Logger.h" // for CSPOT_LOG #ifdef BELL_ONLY_CJSON #include "cJSON.h" #else @@ -10,195 +15,472 @@ #endif using namespace cspot; - -PlayerContext::PlayerContext( - bell::Task* queue, std::shared_ptr ctx, - std::vector* track_list, - std::deque>* queued_list, - std::mutex* trackMutex, uint32_t* index, bool shuffle, char* uri) { - this->queue = queue; - this->ctx = ctx; - this->track_list = track_list; - this->trackMutex = trackMutex; - this->queued_list = queued_list; - this->index = index; - rng = std::default_random_engine{rd()}; - std::string requestUrl = string_format("hm://context-resolve/v1/%s", uri); - auto responseHandler = [this, shuffle, uri](MercurySession::Response& res) { - if (!res.parts.size()) - return; - if (!res.parts[0].size()) - return; - this->resolveInitial(*this->index, shuffle, res.parts[0]); - if (this->track_list->size() < 30) - resolveContext(*this->index, shuffle, uri); - }; - - ctx->session->execute(MercurySession::RequestType::GET, requestUrl, - responseHandler); -} - -static void randomizeIndex(std::vector& index, uint16_t offset, - std::default_random_engine rng) { - std::shuffle(index.begin() + offset, index.end(), rng); +char* PlayerContext::createStringReferenceIfFound( + nlohmann::json::value_type& jsonObject, const char* key) { + if (jsonObject.find(key) != jsonObject.end()) { + std::string value = jsonObject.at(key).get(); + if (value.size()) + return strdup(value.c_str()); + } + return NULL; } - -PlayerContext::~PlayerContext() {} - -void PlayerContext::resolveContext(uint32_t index, bool shuffle, char* uri) { - if ((last_index + track_list->size() >= alternative_index.size()) && - (last_resolve_shuffled == shuffle || - last_index + index >= alternative_index.size())) { - std::string requestUrl = - string_format("hm://autoplay-enabled/query?uri=%s", uri); - auto responseHandler = [this, index](MercurySession::Response& res) { - if (!res.parts.size()) - return; - std::string resolve_autoplay = - std::string(res.parts[0].begin(), res.parts[0].end()); - std::string requestUrl = string_format( - "hm://radio-apollo/v3/stations/%s?autoplay=true&offset=%i", - &resolve_autoplay[0], radio_offset); - auto responseHandler = [this, index](MercurySession::Response& res) { - if (!res.parts.size()) - return; - if (!res.parts[0].size()) - return; - this->resolveRadio(index, res.parts[0]); - }; - ctx->session->execute(MercurySession::RequestType::GET, requestUrl, - responseHandler); - }; - ctx->session->execute(MercurySession::RequestType::GET, requestUrl, - responseHandler); - } else { - std::string requestUrl = string_format("hm://context-resolve/v1/%s", uri); - auto responseHandler = [this, index, - shuffle](MercurySession::Response& res) { - if (!res.parts.size()) - return; +void PlayerContext::resolveRadio( + std::vector> metadata_map, + void (*responseFunction)(void*), bool secondTry) { + CSPOT_LOG(debug, "Resolve autoplay context: %s", + secondTry ? tracks->at(0).uri : playerState->context_uri); + std::string requestUrl = + string_format("hm://autoplay-enabled/query?uri=%s", + secondTry ? tracks->at(0).uri : playerState->context_uri); + auto responseHandler = [this, metadata_map, responseFunction, + secondTry](MercurySession::Response& res) { + if (res.fail || !res.parts.size()) { + if (secondTry) + resolveRadio(metadata_map, responseFunction, true); + else + return responseFunction(NULL); + } + std::string resolve_autoplay = + std::string(res.parts[0].begin(), res.parts[0].end()); + std::string requestUrl; + if (radio_offset) + requestUrl = (std::string)next_page_url; + else { + auto trackRef = tracks->end() - 1; + while ( + trackRef != tracks->begin() && + (!trackRef->provider || strcmp(trackRef->provider, "context") != 0)) { + trackRef--; + } + if (strcmp(trackRef->provider, "context") == 0) + requestUrl = string_format( + "hm://radio-apollo/v3/stations/%s?autoplay=true&offset=%i", + &resolve_autoplay[0], trackRef->original_index); + else { + requestUrl = "hm://radio-apollo/v3/tracks/" + + (std::string)playerState->context_uri + + "?autoplay=true&count=50&isVideo=false&prev_tracks="; + uint8_t copiedTracks = 0; + while (trackRef != tracks->end()) { + if (strcmp(trackRef->provider, "autoplay") == 0 && + (trackRef->uri && strrchr(trackRef->uri, ':'))) { + if (copiedTracks) + requestUrl += ","; + requestUrl += (std::string)(strrchr(trackRef->uri, ':') + 1); + copiedTracks++; + } + trackRef++; + } + } + } + auto responseHandler = [this, metadata_map, + responseFunction](MercurySession::Response& res) { + if (res.fail || !res.parts.size()) + return responseFunction(NULL); if (!res.parts[0].size()) - return; - this->resolveTracklist(index, shuffle, res.parts[0]); + return responseFunction(NULL); + std::scoped_lock lock(trackListMutex); + // remove old_tracks, keep 5 tracks in memory + int remove_tracks = ((int)*index) - 5; + if (remove_tracks > 0) { + for (int i = 0; i < remove_tracks; i++) { + if (tracks->at(i).full_metadata_count) + tracks->at(i).metadata_count = tracks->at(i).full_metadata_count; + pb_release(ProvidedTrack_fields, &tracks->at(i)); + } + tracks->erase(tracks->begin(), tracks->begin() + remove_tracks); + } + *index = (uint8_t)(remove_tracks < 0 ? 5 + remove_tracks : 5); + auto jsonResult = nlohmann::json::parse(res.parts[0]); + if (jsonResult.find("uri") != jsonResult.end()) + context_uri = jsonResult.at("uri").get(); + if (next_page_url != NULL) + free(next_page_url); + next_page_url = createStringReferenceIfFound(jsonResult, "next_page_url"); + std::vector> metadata = metadata_map; + metadata.push_back(std::make_pair("context_uri", context_uri)); + metadata.push_back(std::make_pair("entity_uri", context_uri)); + metadata.push_back(std::make_pair("iteration", "0")); + metadata.insert(metadata.begin(), + std::make_pair("autoplay.is_autoplay", "true")); + metadata.push_back(std::make_pair("track_player", "audio")); + metadata.push_back( + std::make_pair("actions.skipping_next_past_track", "resume")); + metadata.push_back( + std::make_pair("actions.skipping_prev_past_track", "resume")); + jsonToTracklist(tracks, metadata, jsonResult["tracks"], "autoplay", 0); + radio_offset++; + responseFunction(NULL); }; - ctx->session->execute(MercurySession::RequestType::GET, requestUrl, responseHandler); - } + }; + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); } -bool PlayerContext::resolveRadio(uint32_t index, std::vector& data) { - std::scoped_lock lock(*trackMutex); - index = *this->index; - if (queued_list->size()) - if (queued_list->at(0).first == index || queued_list->at(0).first == -1) - index--; - auto jsonResult = nlohmann::json::parse(data); - radio_offset += jsonResult["tracks"].size(); - track_list->erase(track_list->begin(), track_list->begin() + index); - for (auto track : jsonResult["tracks"]) { - track_list->push_back(TrackReference(track["uri"])); - } - this->last_index += index; - this->ctx->playbackMetrics->correlation_id = jsonResult["correlation_id"]; - *this->index = 0; - static_cast(queue)->reloadTracks(); - return true; +static unsigned long distributionToIndex(std::string d) { + return strtoul(&d[d.find("(") + 1], nullptr, 10); } -bool PlayerContext::resolveTracklist(uint32_t index, bool shuffle, - std::vector& data) { - index = *this->index; - std::scoped_lock lock(*trackMutex); - auto jsonResult = nlohmann::json::parse(data); - for (uint32_t i = 0; i < queued_list->size(); i++) - if (queued_list->at(i).first != -1) - queued_list->at(i).first -= index; - if (shuffle != last_resolve_shuffled) { - if (shuffle) { - alternative_index[0] = last_index + index; - alternative_index[index] = 0; - randomizeIndex(alternative_index, 1, rng); - last_index = 0; - } else { - last_index = alternative_index[index + last_index]; - for (uint32_t i = 0; i < alternative_index.size(); i++) - alternative_index[i] = i; +void PlayerContext::createIndexBasedOnTracklist( + std::vector* tracks, nlohmann::json::value_type& json_tracks, + bool shuffle, uint8_t page) { + //create new index + alternative_index.clear(); + std::vector shuffle_index; + bool smart_shuffle = + (json_tracks.at(0).find("metadata") == json_tracks.at(0).end() || + json_tracks.at(0).find("metadata")->find("shuffle.distribution") == + json_tracks.at(0).find("metadata")->end()) + ? false + : true; + for (int i = 0; i < tracks->size(); i++) { + if (strstr(tracks->at(i).uri, "spotify:delimiter")) { + uint8_t release_offset = 1; + while (i + release_offset < tracks->size()) { + cspot::TrackReference::pbReleaseProvidedTrack( + std::addressof(tracks->at(i + release_offset))); + release_offset++; + } + tracks->erase(tracks->begin() + i, tracks->end()); + break; + } + } + if (smart_shuffle) + alternative_index = std::vector(json_tracks.size()); + for (int i = 0; i < json_tracks.size(); i++) { + if (smart_shuffle) { + alternative_index[distributionToIndex(json_tracks.at(i) + .find("metadata") + ->find("shuffle.distribution") + ->get()) - + 1] = i; + } else if (!shuffle) + alternative_index.push_back(i); + for (auto& track : *tracks) { + if (strcmp(track.uri, + json_tracks.at(i).at("uri").get().c_str()) == 0) { + track.original_index = i; + track.page = page; + if (shuffle && !smart_shuffle) + alternative_index.push_back(i); + goto found_track; + } } - } else { - last_index += index; + if (shuffle && !smart_shuffle) + shuffle_index.push_back(i); + found_track:; } - track_list->erase(track_list->begin(), track_list->begin() + index); - track_list->erase(track_list->begin() + 1, track_list->end()); - uint32_t copyTracksSize = alternative_index.size() - last_index; - for (int i = 1; - i < (copyTracksSize < MAX_TRACKS ? copyTracksSize : MAX_TRACKS); i++) { - track_list->push_back( - TrackReference(jsonResult["pages"][0]["tracks"] - [alternative_index[i + last_index]]["uri"])); + if (shuffle && !smart_shuffle) { + if (shuffle_index.size()) + ctx->rng = std::default_random_engine{ctx->rd()}; + std::shuffle(shuffle_index.begin(), shuffle_index.end(), ctx->rng); + alternative_index.insert(strstr(tracks->back().uri, "spotify:delimiter") + ? alternative_index.end() + : alternative_index.begin(), + shuffle_index.begin(), shuffle_index.end()); } - last_resolve_shuffled = shuffle; - *this->index = 0; - static_cast(queue)->reloadTracks(); - return true; } +uint8_t PlayerContext::jsonToTracklist( + std::vector* tracks, + std::vector> metadata_map, + nlohmann::json::value_type& json_tracks, const char* provider, + int64_t offset, uint8_t page, bool shuffle, bool preloadedTrack) { + if (offset >= json_tracks.size()) + return 0; + bool radio = (strcmp("autoplay", provider) == 0) ? true : false; + uint8_t copiedTracks = 0; + if (!radio && json_tracks.size() != alternative_index.size()) + createIndexBasedOnTracklist(tracks, json_tracks, shuffle, page); + if (shuffle) { + for (int i = 0; i < alternative_index.size(); i++) + if (alternative_index[i] == offset) { + offset = i; + break; + } + } + if (preloadedTrack) + offset++; + while (tracks->size() < MAX_TRACKS && offset < json_tracks.size()) { -bool PlayerContext::resolveInitial(uint32_t index, bool shuffle, - std::vector& data) { - std::scoped_lock lock(*trackMutex); - index = *this->index; - auto jsonResult = nlohmann::json::parse(data); - if (jsonResult.find("pages") == jsonResult.end()) - return false; - // create a new_index based on track_list with all index -1 - std::vector new_index(track_list->size()); - std::fill(new_index.begin(), new_index.end(), -1); - alternative_index = {}; - TrackReference ref; - for (auto pages_itr : jsonResult["pages"]) { - if (pages_itr.find("tracks") == pages_itr.end()) + ProvidedTrack new_track = ProvidedTrack_init_zero; + int64_t index = radio ? offset : alternative_index[offset]; + if (index >= json_tracks.size() || index < 0) { + offset++; continue; - size_t alternative_offset = alternative_index.size(); - // add a index to alternative_index for each track in context - for (uint32_t i = alternative_offset; i < pages_itr["tracks"].size(); i++) - alternative_index.push_back(i); - // find tracks from track_list - for (const auto& track : pages_itr["tracks"]) { - ref = TrackReference(track["uri"]); - for (uint32_t i = 0; i < track_list->size(); i++) { - if (ref.gid == track_list->data()[i].gid) - new_index[i] = alternative_offset; + } + auto track = json_tracks.at(index); + new_track.uri = createStringReferenceIfFound(track, "uri"); + new_track.uid = createStringReferenceIfFound(track, "uid"); + new_track.provider = strdup(provider); + uint8_t metadata_offset = 0; + for (auto metadata : metadata_map) { + new_track.metadata[metadata_offset].key = strdup(metadata.first.c_str()); + new_track.metadata[metadata_offset].value = + strdup(metadata.second.c_str()); + metadata_offset++; + } + if (track.find("metadata") != track.end()) { + if (track.at("metadata").find("decision_id") != + track.at("metadata").end()) { + new_track.metadata[metadata_offset].key = strdup("decision_id"); + new_track.metadata[metadata_offset].value = + strdup(std::string(track.at("metadata").at("decision_id")).c_str()); + metadata_offset++; + } + new_track.metadata_count = metadata_offset; + for (auto metadata : track.at("metadata").items()) { + if (metadata.key() != "decision_id" && + metadata.key() != "is_promotional" && + metadata.key() != "is_explicit") { + new_track.metadata[metadata_offset].key = + strdup(metadata.key().c_str()); + new_track.metadata[metadata_offset].value = + strdup(((std::string)metadata.value()).c_str()); + metadata_offset++; + } } - alternative_offset++; } + new_track.full_metadata_count = metadata_offset; + if (!radio) + new_track.metadata_count = metadata_offset; + new_track.original_index = index; + new_track.page = page; + tracks->push_back(new_track); + copiedTracks++; + offset++; } - if (new_index[index] == -1) - index--; - for (int64_t i = 0; i < new_index.size(); i++) { - if (new_index[i] == -1) { - if (i >= index) - queued_list->push_back( - std::make_pair(i - index, track_list->data()[i])); - track_list->erase(track_list->begin() + i); - new_index.erase(new_index.begin() + i); - i--; + if (offset == json_tracks.size()) { + ProvidedTrack new_track = ProvidedTrack_init_zero; + new_track.uri = strdup("spotify:delimiter"); + new_track.uid = strdup("delimiter0"); + new_track.provider = strdup("context"); + new_track.removed = strdup("context/delimiter"); + metadata_map.insert(metadata_map.begin(), std::make_pair("hidden", "true")); + metadata_map.push_back( + std::make_pair("actions.skipping_next_past_track", "resume")); + metadata_map.push_back( + std::make_pair("actions.advancing_past_track", "resume")); + metadata_map.push_back(std::make_pair("iteration", "0")); + for (auto metadata : metadata_map) { + new_track.metadata[new_track.metadata_count].key = + strdup(metadata.first.c_str()); + new_track.metadata[new_track.metadata_count].value = + strdup(metadata.second.c_str()); + new_track.metadata_count++; } + tracks->push_back(new_track); } - if (shuffle) { - for (int i = 0; i < new_index.size(); i++) { - if (new_index[i] >= new_index.size()) { - alternative_index[new_index[i]] = alternative_index[i]; - alternative_index[i] = new_index[i]; - } else { - *std::find(alternative_index.begin(), alternative_index.end(), - new_index[i]) = alternative_index[i]; - alternative_index[i] = new_index[i]; + return copiedTracks; +} +void PlayerContext::resolveTracklist( + std::vector> metadata_map, + void (*responseFunction)(void*), bool changed_state) { + //if last track was no radio track, resolve tracklist + //CSPOT_LOG() + CSPOT_LOG(debug, "Resolve tracklist"); + if (changed_state) { + for (int i = 0; i < tracks->size(); i++) { + if (strstr(tracks->at(i).uri, "spotify:delimiter")) { + uint8_t release_offset = 0; + while (i + release_offset < tracks->size()) { + cspot::TrackReference::pbReleaseProvidedTrack( + std::addressof(tracks->at(i + release_offset))); + release_offset++; + } + tracks->erase(tracks->begin() + i, tracks->end()); + break; } } - randomizeIndex(alternative_index, new_index.size(), rng); } - last_index = shuffle ? 0 : new_index[0]; - last_resolve_shuffled = shuffle; - static_cast(queue)->reloadTracks(); - return true; + if ((playerState->track.provider == NULL || + strcmp(playerState->track.provider, "autoplay")) != 0 && + playerState->context_uri != NULL) { + std::string requestUrl = string_format( + "hm://context-resolve/v1/%s", + (playerState->options.shuffling_context && playerState->context_url) + ? &playerState->context_url[10] + : playerState->context_uri); + auto responseHandler = [this, metadata_map, responseFunction, + changed_state](MercurySession::Response& res) { + if (res.fail || !res.parts.size()) + return; + if (!res.parts[0].size()) + return; + auto jsonResult = nlohmann::json::parse(res.parts[0]); + std::scoped_lock lock(trackListMutex); + uint8_t copy_tracks = 0; + if (tracks->size()) { + // remove old_tracks, keep 5 tracks in memory + int remove_tracks = ((int)*index) - 5; + if (remove_tracks > 0) { + for (int i = 0; i < remove_tracks; i++) { + if (tracks->at(i).full_metadata_count > + tracks->at(i).metadata_count) + tracks->at(i).metadata_count = tracks->at(i).full_metadata_count; + pb_release(ProvidedTrack_fields, &tracks->at(i)); + } + tracks->erase(tracks->begin(), tracks->begin() + remove_tracks); + } + *index = (uint8_t)(remove_tracks < 0 ? 5 + remove_tracks : 5); + + auto trackref = tracks->end() - 1; + //if last track was a queued track/delimiter, try to look for a normal track as lookup reference + while (trackref != tracks->begin() && + (strcmp(trackref->provider, "context") != 0 || + trackref->removed != NULL)) { + trackref--; + } + //if no normal track was found, resolve radio + if (strcmp(trackref->provider, "queue") == 0) + return resolveRadio(metadata_map, responseFunction); + looking_for_playlisttrack:; + //if last track was a smart_shuffled track + if (trackref != tracks->begin()) { + if (trackref->removed != NULL || + strcmp(trackref->provider, "context") != + 0) { //is a delimiter || is queued + trackref--; + goto looking_for_playlisttrack; + } + for (int i = 0; i < trackref->full_metadata_count; i++) + if (trackref->metadata[i].key && + strcmp(trackref->metadata[i].key, "provider") == 0 && + !playerState->options + .context_enhancement_count) { //was a smart_shuffle-track, but smart_shuffle is no more + trackref--; + goto looking_for_playlisttrack; + } + } + if (trackref == tracks->begin() && + strcmp(trackref->uri, "spotify:delimiter") == 0) + return; + //if track available were all smart_shuffle_tracks, load Tracklist from 0; + if (trackref == tracks->begin()) { + + for (int i = 0; + i < (trackref->full_metadata_count > trackref->metadata_count + ? trackref->full_metadata_count + : trackref->metadata_count); + i++) + if ((strcmp(trackref->metadata[i].key, "provider") == 0 && + !playerState->options.context_enhancement_count)) { + jsonToTracklist(tracks, metadata_map, + jsonResult["pages"][0]["tracks"], "context", 0, 0, + playerState->options.shuffling_context, false); + return responseFunction(NULL); + } + } + + //look for trackreference + for (int i = 0; i < jsonResult["pages"].size(); i++) { + int64_t offset = 0; + if (!copy_tracks) { + for (auto track : jsonResult["pages"][i]["tracks"]) { + if (strcmp(track["uri"].get().c_str(), + trackref->uri) == 0) { + copy_tracks = 1; + break; + } + offset++; + } + } + //if trackreference was found + if (copy_tracks) { + if (changed_state) { + createIndexBasedOnTracklist( + tracks, jsonResult["pages"][i]["tracks"], + playerState->options.shuffling_context, i); + if (jsonResult["pages"][i]["tracks"].at(0).find("metadata") != + jsonResult["pages"][i]["tracks"].at(0).end() && + jsonResult["pages"][i]["tracks"] + .at(0) + .find("metadata") + ->find("shuffle.distribution") != + jsonResult["pages"][i]["tracks"] + .at(0) + .find("metadata") + ->end()) { + if (playerState->options.shuffling_context) { + if (alternative_index[0] != offset) { + for (auto& index : alternative_index) + if (index == offset) { + index = alternative_index[0]; + alternative_index[0] = offset; + break; + } + } + } + } + } + copy_tracks = jsonToTracklist( + tracks, metadata_map, jsonResult["pages"][i]["tracks"], + "context", offset, i, playerState->options.shuffling_context, + true); + if (copy_tracks) + break; + } + } + } + if (!copy_tracks) { + if (this->playerState->options.repeating_context || !tracks->size()) { + if (*index >= tracks->size()) { + for (int i = 0; i < tracks->size(); i++) + cspot::TrackReference::pbReleaseProvidedTrack(&tracks->at(i)); + tracks->clear(); + *index = 0; + } else + *index = 1; + createIndexBasedOnTracklist(tracks, jsonResult["pages"][0]["tracks"], + playerState->options.shuffling_context, + 0); + jsonToTracklist(tracks, metadata_map, + jsonResult["pages"][0]["tracks"], "context", 0, 0, + playerState->options.shuffling_context, false); + playerState->track = tracks->back(); + + if (*index >= tracks->size() && tracks->size()) { + ProvidedTrack new_track = ProvidedTrack_init_zero; + new_track.uri = strdup("spotify:delimiter"); + new_track.uid = strdup("uiddelimiter0"); + new_track.provider = strdup("context"); + new_track.removed = strdup("context/delimiter"); + new_track.metadata[new_track.metadata_count].key = strdup("hidden"); + new_track.metadata[new_track.metadata_count].value = strdup("true"); + new_track.metadata_count++; + new_track.metadata[new_track.metadata_count].key = + strdup("actions.skipping_next_past_track"); + new_track.metadata[new_track.metadata_count].value = + strdup("resume"); + new_track.metadata_count++; + new_track.metadata[new_track.metadata_count].key = + strdup("actions.advancing_past_track"); + new_track.metadata[new_track.metadata_count].value = + strdup("resume"); + new_track.metadata_count++; + new_track.metadata[new_track.metadata_count].key = + strdup("iteration"); + new_track.metadata[new_track.metadata_count].value = strdup("0"); + new_track.metadata_count++; + for (auto metadata : metadata_map) { + new_track.metadata[new_track.metadata_count].key = + strdup(metadata.first.c_str()); + new_track.metadata[new_track.metadata_count].value = + strdup(metadata.second.c_str()); + new_track.metadata_count++; + } + + tracks->insert(tracks->begin(), new_track); + } + } else + return resolveRadio(metadata_map, responseFunction); + } + responseFunction(NULL); + }; + ctx->session->execute(MercurySession::RequestType::GET, requestUrl, + responseHandler); + + } else + resolveRadio(metadata_map, responseFunction); } \ No newline at end of file diff --git a/cspot/src/Session.cpp b/cspot/src/Session.cpp index 74bd0633..8700d33a 100644 --- a/cspot/src/Session.cpp +++ b/cspot/src/Session.cpp @@ -74,8 +74,8 @@ std::vector Session::authenticate(std::shared_ptr blob) { // save auth blob for reconnection purposes authBlob = blob; // prepare authentication request proto - auto data = challenges->prepareAuthPacket(blob->authData, blob->authType, - deviceId, blob->username); + auto data = challenges->prepareAuthPacket( + blob->authData, blob->authType, blob->getDeviceId(), blob->username); // Send login request this->shanConn->sendPacket(LOGIN_REQUEST_COMMAND, data); diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp deleted file mode 100644 index a52f857f..00000000 --- a/cspot/src/SpircHandler.cpp +++ /dev/null @@ -1,317 +0,0 @@ -#include "SpircHandler.h" - -#include // for uint8_t -#include // for shared_ptr, make_unique, unique_ptr -#include // for remove_extent_t -#include // for move - -#include "BellLogger.h" // for AbstractLogger -#include "CSpotContext.h" // for Context::ConfigState, Context (ptr only) -#include "Logger.h" // for CSPOT_LOG -#include "MercurySession.h" // for MercurySession, MercurySession::Response -#include "NanoPBHelper.h" // for pbDecode -#include "Packet.h" // for cspot -#include "PlaybackState.h" // for PlaybackState, PlaybackState::State -#include "TrackPlayer.h" // for TrackPlayer -#include "TrackQueue.h" -#include "TrackReference.h" // for TrackReference -#include "Utils.h" // for stringHexToBytes -#include "pb_decode.h" // for pb_release -#include "protobuf/spirc.pb.h" // for Frame, State, Frame_fields, MessageTy... - -using namespace cspot; - -SpircHandler::SpircHandler(std::shared_ptr ctx) { - this->playbackState = std::make_shared(ctx); - this->trackQueue = std::make_shared(ctx, playbackState); - - trackQueue->notifyCallback = [this]() { - this->notify(); - }; - - auto EOFCallback = [this](bool loaded) { - if (trackQueue->isFinished()) { - sendEvent(EventType::DEPLETED); - } - if (!loaded) - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); - }; - - auto trackLoadedCallback = [this](std::shared_ptr track, - bool paused = false) { - playbackState->setPlaybackState(paused ? PlaybackState::State::Paused - : PlaybackState::State::Playing); - playbackState->updatePositionMs(track->requestedPosition); - - // Send playback start event, pause/unpause per request - sendEvent(EventType::PLAYBACK_START, (int)track->requestedPosition); - sendEvent(EventType::PLAY_PAUSE, paused); - }; - - this->ctx = ctx; - this->trackPlayer = std::make_shared( - ctx, trackQueue, EOFCallback, trackLoadedCallback); - - // Subscribe to mercury on session ready - ctx->session->setConnectedHandler([this]() { this->subscribeToMercury(); }); -} - -void SpircHandler::subscribeToMercury() { - auto responseLambda = [this](MercurySession::Response& res) { - if (res.fail) - return; - - sendCmd(MessageType_kMessageTypeHello); - CSPOT_LOG(debug, "Sent kMessageTypeHello!"); - - // Assign country code - this->ctx->config.countryCode = this->ctx->session->getCountryCode(); - }; - auto subscriptionLambda = [this](MercurySession::Response& res) { - if (res.fail) - return; - CSPOT_LOG(debug, "Received subscription response"); - - this->handleFrame(res.parts[0]); - }; - - ctx->session->executeSubscription( - MercurySession::RequestType::SUB, - "hm://remote/user/" + ctx->config.username + "/", responseLambda, - subscriptionLambda); -} - -void SpircHandler::loadTrackFromURI(const std::string& uri) {} - -void SpircHandler::notifyAudioEnded() { - playbackState->updatePositionMs(0); - notify(); - trackPlayer->resetState(true); -} -void SpircHandler::notifyAudioReachedPlaybackEnd() { - int offset = 0; - - // get HEAD track - auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - - if (!playbackState->innerFrame.state.repeat) { - currentTrack->trackMetrics->endTrack(); - ctx->playbackMetrics->sendEvent(currentTrack); - if (!trackQueue->notifyPending) - trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false); - else - trackQueue->notifyPending = false; - } - trackQueue->update_ghost_tracks(); - notify(); -} - -void SpircHandler::notifyAudioReachedPlayback() { - int offset = 0; - - // get HEAD track - auto currentTrack = trackQueue->consumeTrack(nullptr, offset); - sendEvent(EventType::TRACK_INFO, currentTrack->trackInfo); -} - -void SpircHandler::updatePositionMs(uint32_t position) { - playbackState->updatePositionMs(position); - notify(); -} - -void SpircHandler::disconnect() { - this->trackQueue->stopTask(); - this->trackPlayer->stop(); - this->ctx->session->disconnect(); -} - -void SpircHandler::handleFrame(std::vector& data) { - // Decode received spirc frame - playbackState->decodeRemoteFrame(data); - - std::string influence = "unknown"; - switch (playbackState->remoteFrame.typ) { - case MessageType_kMessageTypeNotify: { - CSPOT_LOG(debug, "Notify frame"); - - // Pause the playback if another player took control - if (playbackState->isActive() && - playbackState->remoteFrame.device_state.is_active) { - CSPOT_LOG(debug, "Another player took control, pausing playback"); - playbackState->setActive(false); - ctx->playbackMetrics->end_reason = PlaybackMetrics::REMOTE; - ctx->playbackMetrics->end_source = influence; - this->trackPlayer->stop(); - sendEvent(EventType::DISC); - trackQueue->preloadedTracks.clear(); - } - break; - } - case MessageType_kMessageTypeSeek: { - this->trackPlayer->seekMs(playbackState->remoteFrame.position); - sendEvent(EventType::SEEK, (int)playbackState->remoteFrame.position); - break; - } - case MessageType_kMessageTypeVolume: - playbackState->setVolume(playbackState->remoteFrame.volume); - this->notify(); - sendEvent(EventType::VOLUME, (int)playbackState->remoteFrame.volume); - break; - case MessageType_kMessageTypePause: - setPause(true); - break; - case MessageType_kMessageTypePlay: - setPause(false); - break; - case MessageType_kMessageTypeNext: - if (nextSong()) { - sendEvent(EventType::NEXT); - ctx->playbackMetrics->end_reason = PlaybackMetrics::FORWARD_BTN; - } - break; - case MessageType_kMessageTypePrev: - if (previousSong()) { - sendEvent(EventType::PREV); - ctx->playbackMetrics->end_reason = PlaybackMetrics::BACKWARD_BTN; - } - break; - case MessageType_kMessageTypeLoad: { - this->trackPlayer->start(); - - CSPOT_LOG(debug, "Load frame %d!", playbackState->remoteTracks.size()); - - if (playbackState->remoteTracks.size() == 0) { - CSPOT_LOG(info, "No tracks in frame, stopping playback"); - break; - } - - playbackState->setActive(true); - - playbackState->updatePositionMs(playbackState->remoteFrame.position); - playbackState->setPlaybackState(PlaybackState::State::Playing); - - playbackState->syncWithRemote(); - - // Update track list in case we have a new one - trackQueue->updateTracks(playbackState->remoteFrame.state.position_ms, - true); - - this->notify(); - - // Stop the current track, if any - trackPlayer->resetState(); - break; - } - case MessageType_kMessageTypeReplace: { - CSPOT_LOG(debug, "Got replace frame %d", - playbackState->remoteTracks.size()); - playbackState->syncWithRemote(); - - // 1st track is the current one, but update the position - bool cleared = trackQueue->updateTracks( - playbackState->remoteFrame.state.position_ms + - ctx->timeProvider->getSyncedTimestamp() - - playbackState->innerFrame.state.position_measured_at, - false); - - this->notify(); - - // need to re-load all if streaming track is completed - if (cleared) { - sendEvent(EventType::FLUSH); - trackPlayer->resetState(); - } - break; - } - case MessageType_kMessageTypeShuffle: { - CSPOT_LOG(debug, "Got shuffle frame"); - playbackState->innerFrame.state.shuffle = - playbackState->remoteFrame.state.shuffle; - trackQueue->shuffle_tracks(playbackState->remoteFrame.state.shuffle); - this->notify(); - break; - } - case MessageType_kMessageTypeRepeat: { - CSPOT_LOG(debug, "Got repeat frame"); - playbackState->innerFrame.state.repeat = - playbackState->remoteFrame.state.repeat; - this->notify(); - break; - } - default: - break; - } -} - -void SpircHandler::setRemoteVolume(int volume) { - playbackState->setVolume(volume); - notify(); -} - -void SpircHandler::notify() { - this->sendCmd(MessageType_kMessageTypeNotify); -} - -bool SpircHandler::skipSong(TrackQueue::SkipDirection dir) { - bool skipped = trackQueue->skipTrack(dir); - - // Reset track state - trackPlayer->resetState(!skipped); - - // send NEXT or PREV event only when successful - return skipped; -} - -bool SpircHandler::nextSong() { - return skipSong(TrackQueue::SkipDirection::NEXT); -} - -bool SpircHandler::previousSong() { - return skipSong(TrackQueue::SkipDirection::PREV); -} - -std::shared_ptr SpircHandler::getTrackPlayer() { - return this->trackPlayer; -} - -void SpircHandler::sendCmd(MessageType typ) { - // Serialize current player state - auto encodedFrame = playbackState->encodeCurrentFrame(typ); - - auto responseLambda = [=](MercurySession::Response& res) { - }; - auto parts = MercurySession::DataParts({encodedFrame}); - ctx->session->execute(MercurySession::RequestType::SEND, - "hm://remote/user/" + ctx->config.username + "/", - responseLambda, parts); -} -void SpircHandler::setEventHandler(EventHandler handler) { - this->eventHandler = handler; -} - -void SpircHandler::setPause(bool isPaused) { - if (isPaused) { - CSPOT_LOG(debug, "External pause command"); - playbackState->setPlaybackState(PlaybackState::State::Paused); - } else { - CSPOT_LOG(debug, "External play command"); - - playbackState->setPlaybackState(PlaybackState::State::Playing); - } - notify(); - sendEvent(EventType::PLAY_PAUSE, isPaused); -} - -void SpircHandler::sendEvent(EventType type) { - auto event = std::make_unique(); - event->eventType = type; - event->data = {}; - eventHandler(std::move(event)); -} - -void SpircHandler::sendEvent(EventType type, EventData data) { - auto event = std::make_unique(); - event->eventType = type; - event->data = data; - eventHandler(std::move(event)); -} diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index 871865a0..e5d6622e 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -8,6 +8,7 @@ #include "BellLogger.h" // for AbstractLogger #include "BellUtils.h" // for BELL_SLEEP_MS #include "CSpotContext.h" +#include "EventManager.h" #include "Logger.h" // for CSPOT_LOG #include "Packet.h" // for cspot #include "TrackQueue.h" // for CDNTrackStream, CDNTrackStream::TrackInfo @@ -57,7 +58,7 @@ static long vorbisTellCb(TrackPlayer* self) { TrackPlayer::TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, EOFCallback eof, TrackLoadedCallback trackLoaded) - : bell::Task("cspot_player", 48 * 1024, 5, 1) { + : bell::Task("cspot_player", 56 * 1024, 5, 1) { this->ctx = ctx; this->eofCallback = eof; this->trackLoaded = trackLoaded; @@ -134,8 +135,9 @@ void TrackPlayer::runTask() { while (isRunning) { bool properStream = true; // Ensure we even have any tracks to play - if (!this->trackQueue->hasTracks() || - (!pendingReset && endOfQueueReached && trackQueue->isFinished())) { + if (!this->trackQueue->preloadedTracks.size() || + (!pendingReset && endOfQueueReached && + this->trackQueue->preloadedTracks.size() == 1)) { this->trackQueue->playableSemaphore->twait(300); continue; } @@ -170,7 +172,6 @@ void TrackPlayer::runTask() { } track = newTrack; - track->trackMetrics = std::make_shared(this->ctx); this->ctx->playbackMetrics->trackMetrics = track->trackMetrics; inFuture = trackOffset > 0; @@ -185,8 +186,6 @@ void TrackPlayer::runTask() { } } - CSPOT_LOG(info, "Got track ID=%s", track->identifier.c_str()); - currentSongPlaying = true; { @@ -205,10 +204,8 @@ void TrackPlayer::runTask() { track->trackMetrics->startTrackDecoding(); track->trackMetrics->track_size = currentTrackStream->getSize(); - if (trackOffset == 0 && pendingSeekPositionMs == 0) { - this->trackLoaded(track, startPaused); - startPaused = false; - } + this->trackLoaded(track, true); + startPaused = false; #ifndef CONFIG_BELL_NOCODEC int32_t r = @@ -221,6 +218,8 @@ void TrackPlayer::runTask() { pcmBuffer.size()); size_t written = 0; size_t toWrite = ret; + if (!ret) + continue; while (toWrite) { written = dataCallback(pcmBuffer.data() + (ret - toWrite), toWrite, tracksPlayed, 0); @@ -261,35 +260,27 @@ void TrackPlayer::runTask() { eof = false; track->loading = true; - //in case of a repeatedtrack, set requested position to 0 - track->trackMetrics->startTrackPlaying(track->requestedPosition); - this->trackQueue->playbackState->updatePositionMs( - track->requestedPosition); - this->trackQueue->notifyCallback(); - track->requestedPosition = 0; CSPOT_LOG(info, "Playing"); while (!eof && currentSongPlaying) { // Execute seek if needed if (pendingSeekPositionMs > 0) { - uint32_t seekPosition = pendingSeekPositionMs; + track->requestedPosition = pendingSeekPositionMs; // Seek to the new position #ifndef CONFIG_BELL_NOCODEC - VORBIS_SEEK(&vorbisFile, seekPosition); + VORBIS_SEEK(&vorbisFile, track->requestedPosition); #else - seekPosition = seekPosition * duration_lambda + start_offset; + uint32_t seekPosition = + track->requestedPosition * duration_lambda + start_offset; currentTrackStream->seek(seekPosition); - track->trackMetrics->newPosition(pendingSeekPositionMs); skipped = true; #endif - this->trackQueue->playbackState->updatePositionMs( - pendingSeekPositionMs); - this->trackQueue->notifyCallback(); - + track->trackMetrics->newPosition(pendingSeekPositionMs); // Reset the pending seek position pendingSeekPositionMs = 0; + this->trackLoaded(track, false); } long ret = @@ -358,10 +349,12 @@ void TrackPlayer::runTask() { } if (eof) { - if (trackQueue->isFinished()) { + if (this->trackQueue->preloadedTracks.size() <= 1) { endOfQueueReached = true; } +#ifdef CONFIG_BELL_NOCODEC this->eofCallback(properStream); +#endif } } } diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index 19d8b83a..b81c2b59 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -9,6 +9,7 @@ #include "AccessKeyFetcher.h" #include "BellTask.h" +#include "BellUtils.h" // for BELL_SLEEP_MS #include "CDNAudioFile.h" #include "CSpotContext.h" #include "HTTPClient.h" @@ -122,14 +123,20 @@ void TrackInfo::loadPbEpisode(Episode* pbEpisode, duration = pbEpisode->duration; } -QueuedTrack::QueuedTrack(TrackReference& ref, +QueuedTrack::QueuedTrack(ProvidedTrack& ref, std::shared_ptr ctx, - uint32_t requestedPosition) - : requestedPosition(requestedPosition), ctx(ctx) { - this->ref = ref; - + int64_t requestedPosition) + : requestedPosition((uint32_t)requestedPosition), ctx(ctx) { + trackMetrics = std::make_shared(ctx, requestedPosition); loadedSemaphore = std::make_shared(); - state = State::QUEUED; + this->ref = ref; + if (ref.uid == NULL || !strstr(ref.uri, "spotify:delimiter")) { + this->gid = base62Decode(ref.uri); + state = State::QUEUED; + } else { + state = State::FAILED; + loadedSemaphore->give(); + } } QueuedTrack::~QueuedTrack() { @@ -162,7 +169,7 @@ void QueuedTrack::stepParseMetadata(Track* pbTrack, Episode* pbEpisode) { const char* countryCode = ctx->config.countryCode.c_str(); - if (ref.type == TrackReference::Type::TRACK) { + if (gid.first == SpotifyFileType::TRACK) { CSPOT_LOG(info, "Track name: %s", pbTrack->name); CSPOT_LOG(info, "Track duration: %d", pbTrack->duration); @@ -239,8 +246,6 @@ void QueuedTrack::stepParseMetadata(Track* pbTrack, Episode* pbEpisode) { loadedSemaphore->give(); return; } - - // Assign track identifier identifier = bytesToHexString(fileId); state = State::KEY_REQUIRED; @@ -286,9 +291,8 @@ void QueuedTrack::stepLoadCDNUrl(const std::string& accessKey) { std::string requestUrl = string_format( "https://api.spotify.com/v1/storage-resolve/files/audio/interactive/" - "%s?alt=json&product=9", + "%s?alt=json", bytesToHexString(fileId).c_str()); - auto req = bell::HTTPClient::get( requestUrl, {bell::HTTPClient::ValueHeader( {"Authorization", "Bearer " + accessKey})}); @@ -306,7 +310,7 @@ void QueuedTrack::stepLoadCDNUrl(const std::string& accessKey) { cdnUrl = jsonResult["cdnurl"][0]; #endif - CSPOT_LOG(info, "Received CDN URL, %s", cdnUrl.c_str()); + // CSPOT_LOG(info, "Received CDN URL, %s", cdnUrl.c_str()); state = State::READY; loadedSemaphore->give(); } catch (...) { @@ -326,12 +330,11 @@ void QueuedTrack::expire() { void QueuedTrack::stepLoadMetadata( Track* pbTrack, Episode* pbEpisode, std::mutex& trackListMutex, std::shared_ptr updateSemaphore) { - // Prepare request ID - std::string requestUrl = string_format( - "hm://metadata/3/%s/%s", - ref.type == TrackReference::Type::TRACK ? "track" : "episode", - bytesToHexString(ref.gid).c_str()); + std::string requestUrl = + string_format("hm://metadata/3/%s/%s", + gid.first == SpotifyFileType::TRACK ? "track" : "episode", + bytesToHexString(gid.second).c_str()); auto responseHandler = [this, pbTrack, pbEpisode, &trackListMutex, updateSemaphore](MercurySession::Response& res) { @@ -346,7 +349,7 @@ void QueuedTrack::stepLoadMetadata( } // Parse the metadata - if (ref.type == TrackReference::Type::TRACK) { + if (gid.first == SpotifyFileType::TRACK) { pb_release(Track_fields, pbTrack); pbDecode(*pbTrack, Track_fields, res.parts[0]); } else { @@ -360,27 +363,20 @@ void QueuedTrack::stepLoadMetadata( updateSemaphore->give(); }; // Execute the request - pendingMercuryRequest = ctx->session->execute( - MercurySession::RequestType::GET, requestUrl, responseHandler); + if (pbTrack != NULL || pbEpisode != NULL) + pendingMercuryRequest = ctx->session->execute( + MercurySession::RequestType::GET, requestUrl, responseHandler); // Set the state to pending state = State::PENDING_META; } -TrackQueue::TrackQueue(std::shared_ptr ctx, - std::shared_ptr state) - : bell::Task("CSpotTrackQueue", 1024 * 32, 2, 1), - playbackState(state), - ctx(ctx) { +TrackQueue::TrackQueue(std::shared_ptr ctx) + : bell::Task("CSpotTrackQueue", 1024 * 32, 2, 1), ctx(ctx) { accessKeyFetcher = std::make_shared(ctx); processSemaphore = std::make_shared(); playableSemaphore = std::make_shared(); - // Assign encode callback to track list - playbackState->innerFrame.state.track.funcs.encode = - &TrackReference::pbEncodeTrackList; - playbackState->innerFrame.state.track.arg = &ghostTracks; - // Start the task startTask(); }; @@ -391,14 +387,6 @@ TrackQueue::~TrackQueue() { std::scoped_lock lock(tracksMutex); } -TrackInfo TrackQueue::getTrackInfo(std::string_view identifier) { - for (auto& track : preloadedTracks) { - if (track->identifier == identifier) - return track->trackInfo; - } - return TrackInfo{}; -} - void TrackQueue::runTask() { isRunning = true; @@ -412,10 +400,9 @@ void TrackQueue::runTask() { // Make sure we have the newest access key accessKey = accessKeyFetcher->getAccessKey(); - int loadedIndex = currentTracksIndex; - // No tracks loaded yet - if (loadedIndex < 0) { + if (!preloadedTracks.size()) { + BELL_SLEEP_MS(50); continue; } else { std::scoped_lock lock(tracksMutex); @@ -444,25 +431,11 @@ std::shared_ptr TrackQueue::consumeTrack( std::shared_ptr prevTrack, int& offset) { std::scoped_lock lock(tracksMutex); - if ((currentTracksIndex == -1 && !currentTracks.size()) || - currentTracksIndex >= currentTracks.size()) { + if (!preloadedTracks.size()) { + offset = -1; return nullptr; } - // No previous track, return head - if (prevTrack == nullptr || playbackState->innerFrame.state.repeat) { - offset = 0; - - return preloadedTracks[0]; - } - - // if (currentTracksIndex + preloadedTracks.size() >= currentTracks.size()) { - // offset = -1; - - // // Last track in queue - // return nullptr; - // } - auto prevTrackIter = std::find(preloadedTracks.begin(), preloadedTracks.end(), prevTrack); @@ -472,59 +445,13 @@ std::shared_ptr TrackQueue::consumeTrack( } else { offset = 0; } - if (offset >= preloadedTracks.size()) { // Last track in preloaded queue return nullptr; } - - // Return the current track return preloadedTracks[offset]; } -void TrackQueue::update_ghost_tracks(int16_t offset) { - if (currentTracksIndex + offset >= SEND_OLD_TRACKS) - this->playbackState->innerFrame.state.index = SEND_OLD_TRACKS; - else - this->playbackState->innerFrame.state.index = currentTracksIndex + offset; - ghostTracks.clear(); - //add SEND_OLD_TRACKS already played tracks - size_t index = - currentTracksIndex + offset - this->playbackState->innerFrame.state.index; - while (ghostTracks.size() < this->playbackState->innerFrame.state.index) { - ghostTracks.push_back(currentTracks[index]); - index++; - } - if (queuedTracks.size() > 0) { - if (preloadedTracks[offset]->ref.gid != queuedTracks[0].second.gid) { - ghostTracks.push_back(currentTracks[index]); - index++; - } else - ghostTracks.push_back(queuedTracks[0].second); - for (auto track : queuedTracks) { - if (track.first != -1) - break; - if (preloadedTracks[offset]->ref.gid != track.second.gid) { - ghostTracks.push_back(track.second); - } - } - } - while (ghostTracks.size() < SEND_OLD_TRACKS + CONFIG_UPDATE_FUTURE_TRACKS && - index < currentTracks.size()) { - if (queuedTracks.size() > 0) { - for (auto track : queuedTracks) { - if (track.first == index && - preloadedTracks[offset]->ref.gid != track.second.gid) { - ghostTracks.push_back(track.second); - } else if (track.first > index) - break; - } - } - ghostTracks.push_back(currentTracks[index]); - index++; - } -} - void TrackQueue::processTrack(std::shared_ptr track) { switch (track->state) { case QueuedTrack::State::QUEUED: @@ -536,197 +463,8 @@ void TrackQueue::processTrack(std::shared_ptr track) { break; case QueuedTrack::State::CDN_REQUIRED: track->stepLoadCDNUrl(accessKey); - - if (track->state == QueuedTrack::State::READY) { - if (preloadedTracks.size() + currentTracksIndex + 1 >= - currentTracks.size() && - !contextResolved) { - playerContext->resolveContext( - currentTracksIndex, this->playbackState->innerFrame.state.shuffle, - this->playbackState->innerFrame.state.context_uri); - contextResolved = true; - } - if (preloadedTracks.size() < MAX_TRACKS_PRELOAD) { - // Queue a new track to preload - queueNextTrack(preloadedTracks.size()); - } - } - break; default: // Do not perform any action break; } } - -bool TrackQueue::queueNextTrack(int offset, uint32_t positionMs) { - int requestedRefIndex = offset + currentTracksIndex; - if (queuedTracks.size()) { - for (auto track : queuedTracks) { - if (track.first > requestedRefIndex) - goto queueNext; - for (auto loaded_track : preloadedTracks) { - if (track.second.gid == loaded_track->ref.gid) { - requestedRefIndex--; - goto noNeedToLoadTrack; - } - } - preloadedTracks.push_back( - std::make_shared(track.second, ctx, 0)); - return true; - noNeedToLoadTrack:; - } - } -queueNext:; - - if (requestedRefIndex < 0 || requestedRefIndex >= currentTracks.size()) { - return false; - } - - // in case we re-queue current track, make sure position is updated (0) - if (offset == 0 && preloadedTracks.size() && - preloadedTracks[0]->ref == currentTracks[currentTracksIndex]) { - preloadedTracks.pop_front(); - } - - if (offset <= 0) { - preloadedTracks.push_front(std::make_shared( - currentTracks[requestedRefIndex], ctx, positionMs)); - } else { - preloadedTracks.push_back(std::make_shared( - currentTracks[requestedRefIndex], ctx, positionMs)); - } - - return true; -} - -bool TrackQueue::skipTrack(SkipDirection dir, bool expectNotify) { - bool skipped = true; - std::scoped_lock lock(tracksMutex); - if (dir == SkipDirection::PREV) { - uint64_t position = - !playbackState->innerFrame.state.has_position_ms - ? 0 - : playbackState->innerFrame.state.position_ms + - ctx->timeProvider->getSyncedTimestamp() - - playbackState->innerFrame.state.position_measured_at; - - if (currentTracksIndex > 0 && position < 3000) { - queueNextTrack(-1); - - if (preloadedTracks.size() > MAX_TRACKS_PRELOAD) { - preloadedTracks.pop_back(); - } - - currentTracksIndex--; - } else { - queueNextTrack(0); - } - } else { - if (currentTracks.size() > currentTracksIndex + 1) { - { - if (queuedTracks.size() > 0 && - preloadedTracks[0]->ref.gid == queuedTracks[0].second.gid) { - currentTracksIndex--; - queuedTracks.pop_front(); - } - preloadedTracks.pop_front(); - if (!queueNextTrack(preloadedTracks.size() + 1)) { - CSPOT_LOG(info, "Failed to queue next track"); - } - currentTracksIndex++; - } - } else { - skipped = false; - } - } - - if (skipped) { - // Update frame data - playbackState->innerFrame.state.playing_track_index = currentTracksIndex; - - if (expectNotify) { - // Reset position to zero - notifyPending = true; - } - } - update_ghost_tracks(); - - return skipped; -} - -bool TrackQueue::hasTracks() { - std::scoped_lock lock(tracksMutex); - - return currentTracks.size() > 0; -} - -bool TrackQueue::isFinished() { - std::scoped_lock lock(tracksMutex); - return currentTracksIndex >= currentTracks.size() - 1; -} - -void TrackQueue::shuffle_tracks(bool shuffleTracks) { - playerContext->resolveContext( - currentTracksIndex, this->playbackState->innerFrame.state.shuffle, - this->playbackState->innerFrame.state.context_uri); -} -void TrackQueue::reloadTracks(uint8_t offset) { - if (preloadedTracks.size()) - preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); - //preloadedTracks.clear(); - queueNextTrack(preloadedTracks.size()); - update_ghost_tracks(); - this->notifyCallback(); - contextResolved = false; -} -bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { - std::scoped_lock lock(tracksMutex); - bool cleared = true; - - if (initial) { - if (preloadedTracks.size()) - notifyPending = true; - // initialize new random_engine - rng = std::default_random_engine{rd()}; - // Copy requested track list - queuedTracks = {}; - currentTracks = playbackState->remoteTracks; - currentTracksIndex = playbackState->innerFrame.state.playing_track_index; - playerContext = std::make_unique( - this, ctx, ¤tTracks, &queuedTracks, &tracksMutex, - ¤tTracksIndex, playbackState->innerFrame.state.shuffle, - playbackState->innerFrame.state.context_uri); - - // Clear preloaded tracks - preloadedTracks.clear(); - - if (currentTracksIndex < currentTracks.size()) { - // Push a song on the preloaded queue - queueNextTrack(0, requestedPosition); - } - - // We already updated track meta, mark it - radio_offset = 0; - - playableSemaphore->give(); - } else { - auto track_it = queuedTracks.begin(); - uint32_t offset = 0; - while (track_it->first < 0) { - track_it++; - offset++; - } - queuedTracks.insert( - track_it, - std::make_pair( - -1, - playbackState->remoteTracks[playbackState->innerFrame.state.index + - 1 + offset])); - preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); - queueNextTrack(1); - cleared = false; - } - update_ghost_tracks(); - - return cleared; -} diff --git a/cspot/src/TrackReference.cpp b/cspot/src/TrackReference.cpp index e978d9f3..e83e55b3 100644 --- a/cspot/src/TrackReference.cpp +++ b/cspot/src/TrackReference.cpp @@ -1,7 +1,7 @@ #include "TrackReference.h" #include "NanoPBExtensions.h" -#include "protobuf/spirc.pb.h" +#include "protobuf/connect.pb.h" using namespace cspot; @@ -12,7 +12,7 @@ TrackReference::TrackReference() : type(Type::TRACK) {} void TrackReference::decodeURI() { if (gid.size() == 0) { // Episode GID is being fetched via base62 encoded URI - gid = base62Decode(uri); + gid = base62Decode(uri).second; if (uri.find("episode:") != std::string::npos) { type = Type::EPISODE; @@ -24,119 +24,41 @@ bool TrackReference::operator==(const TrackReference& other) const { return other.gid == gid && other.uri == uri; } -bool TrackReference::pbEncodeTrackList(pb_ostream_t* stream, - const pb_field_t* field, - void* const* arg) { - auto trackQueue = *static_cast*>(*arg); - static TrackRef msg = TrackRef_init_zero; - - // Prepare nanopb callbacks - msg.context.funcs.encode = &bell::nanopb::encodeString; - msg.uri.funcs.encode = &bell::nanopb::encodeString; - msg.gid.funcs.encode = &bell::nanopb::encodeVector; - msg.queued.funcs.encode = &bell::nanopb::encodeBoolean; - - for (auto trackRef : trackQueue) { +bool TrackReference::pbEncodeProvidedTracks(pb_ostream_t* stream, + const pb_field_t* field, + void* const* arg) { + auto trackPacket = (std::pair*>*)(*arg); + if (*trackPacket->first >= trackPacket->second->size() || + !trackPacket->second->size()) + return true; + for (int i = *trackPacket->first; i < trackPacket->second->size(); i++) { if (!pb_encode_tag_for_field(stream, field)) { return false; } - - msg.gid.arg = &trackRef.gid; - msg.uri.arg = &trackRef.uri; - msg.context.arg = &empty_string; //&trackRef.context; - msg.queued.arg = &trackRef.queued; - - if (!pb_encode_submessage(stream, TrackRef_fields, &msg)) { + if (!pb_encode_submessage(stream, ProvidedTrack_fields, + &(trackPacket->second->at(i)))) return false; - } + //if there's a delimiter, or the tracks are over the track treshhold + if (trackPacket->second->at(i).removed != NULL || + i - *trackPacket->first >= TRACK_SEND_LIMIT) + return true; } - return true; } -bool TrackReference::pbDecodeTrackList(pb_istream_t* stream, - const pb_field_t* field, void** arg) { - auto trackQueue = static_cast*>(*arg); +bool TrackReference::pbDecodeProvidedTracks(pb_istream_t* stream, + const pb_field_t* field, + void** arg) { + auto trackQueue = static_cast*>(*arg); // Push a new reference - trackQueue->push_back(TrackReference()); + trackQueue->push_back(ProvidedTrack()); auto& track = trackQueue->back(); - bool eof = false; - pb_wire_type_t wire_type; - pb_istream_t substream; - uint32_t tag; - - while (!eof) { - if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) { - // Decoding failed and not eof - if (!eof) { - return false; - } - // EOF - } else { - switch (tag) { - case TrackRef_uri_tag: - case TrackRef_context_tag: - case TrackRef_gid_tag: { - // Make substream - if (!pb_make_string_substream(stream, &substream)) { - - return false; - } - - uint8_t* destBuffer = nullptr; - - // Handle GID - if (tag == TrackRef_gid_tag) { - track.gid.resize(substream.bytes_left); - destBuffer = &track.gid[0]; - } else if (tag == TrackRef_context_tag) { - track.context.resize(substream.bytes_left); - - destBuffer = reinterpret_cast(&track.context[0]); - } else if (tag == TrackRef_uri_tag) { - track.uri.resize(substream.bytes_left); - - destBuffer = reinterpret_cast(&track.uri[0]); - } - - if (!pb_read(&substream, destBuffer, substream.bytes_left)) { - return false; - } - - // Close substream - if (!pb_close_string_substream(stream, &substream)) { - return false; - } - - break; - } - case TrackRef_queued_tag: { - uint32_t queuedValue; - - // Decode boolean - if (!pb_decode_varint32(stream, &queuedValue)) { - return false; - } - - // Cast down to bool - track.queued = (bool)queuedValue; - - break; - } - default: - // Field not known, skip - pb_skip_field(stream, wire_type); - - break; - } - } - } - - // Fill in GID when only URI is provided - track.decodeURI(); + if (!pb_decode(stream, ProvidedTrack_fields, &track)) + return false; + track.full_metadata_count = track.metadata_count; return true; -} +} \ No newline at end of file diff --git a/cspot/src/Utils.cpp b/cspot/src/Utils.cpp index 74c0c0d7..dfdd588e 100644 --- a/cspot/src/Utils.cpp +++ b/cspot/src/Utils.cpp @@ -11,8 +11,10 @@ #include #endif -static std::string alphabet = +static std::string Base62Alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static char Base64Alphabet[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; unsigned long long getCurrentTimestamp() { return std::chrono::duration_cast( @@ -31,6 +33,34 @@ uint64_t hton64(uint64_t value) { } } +std::string base64Encode(const std::vector& v) { + std::string ss; + int nLenOut = 0; + int index = 0; + while (index < v.size()) { + size_t decode_size = v.size() - index; + unsigned long n = v[index]; + n <<= 8; + n |= (decode_size > 1) ? v[index + 1] : 0; + n <<= 8; + n |= (decode_size > 2) ? v[index + 2] : 0; + uint8_t m4 = n & 0x3f; + n >>= 6; + uint8_t m3 = n & 0x3f; + n >>= 6; + uint8_t m2 = n & 0x3f; + n >>= 6; + uint8_t m1 = n & 0x3f; + + ss.push_back(Base64Alphabet[m1]); + ss.push_back(Base64Alphabet[m2]); + ss.push_back(decode_size > 1 ? Base64Alphabet[m3] : '='); + ss.push_back(decode_size > 2 ? Base64Alphabet[m4] : '='); + index += 3; + } + return ss; +} + std::vector stringHexToBytes(const std::string& s) { std::vector v; v.reserve(s.length() / 2); @@ -156,17 +186,24 @@ std::string urlDecode(std::string str) { return encodedString; } -std::vector base62Decode(std::string uri) { +std::pair> base62Decode(std::string uri) { std::vector n = std::vector({0}); + SpotifyFileType type = SpotifyFileType::UNKNOWN; auto it = uri.begin(); - if (uri.find(":") != std::string::npos) + if (uri.find(":") != std::string::npos) { + if (uri.find("episode:") != std::string::npos) { + type = SpotifyFileType::EPISODE; + } else if (uri.find("track:") != std::string::npos) { + type = SpotifyFileType::TRACK; + } it += uri.rfind(":") + 1; + } while (it != uri.end()) { - size_t d = alphabet.find(*it); + size_t d = Base62Alphabet.find(*it); n = bigNumMultiply(n, 62); n = bigNumAdd(n, d); it++; } - return n; + return std::make_pair(type, n); } \ No newline at end of file diff --git a/targets/cli/CliPlayer.cpp b/targets/cli/CliPlayer.cpp index 766574cf..a3a56e32 100644 --- a/targets/cli/CliPlayer.cpp +++ b/targets/cli/CliPlayer.cpp @@ -14,13 +14,13 @@ #include "BellDSP.h" // for BellDSP, BellDSP::FadeEffect, BellDS... #include "BellUtils.h" // for BELL_SLEEP_MS #include "CentralAudioBuffer.h" // for CentralAudioBuffer::AudioChunk, Cent... +#include "DeviceStateHandler.h" // for DeviceStateHandler, DeviceStateHandler::CommandType #include "Logger.h" -#include "SpircHandler.h" // for SpircHandler, SpircHandler::EventType -#include "StreamInfo.h" // for BitWidth, BitWidth::BW_16 -#include "TrackPlayer.h" // for TrackPlayer +#include "StreamInfo.h" // for BitWidth, BitWidth::BW_16 +#include "TrackPlayer.h" // for TrackPlayer CliPlayer::CliPlayer(std::unique_ptr sink, - std::shared_ptr handler) + std::shared_ptr handler) : bell::Task("player", 1024, 0, 0) { this->handler = handler; this->audioSink = std::move(sink); @@ -32,52 +32,70 @@ CliPlayer::CliPlayer(std::unique_ptr sink, this->dsp = std::make_shared(this->centralAudioBuffer); #endif - this->handler->getTrackPlayer()->setDataCallback( - [this](uint8_t* data, size_t bytes, size_t trackId) { - if (!bytes) - this->handler->notifyAudioReachedPlaybackEnd(); - return this->centralAudioBuffer->writePCM(data, bytes, trackId); - }); + this->handler->trackPlayer->setDataCallback([this](uint8_t* data, + size_t bytes, +#ifdef CONFIG_BELL_NOCODEC + bool STORAGE_VOLATILE, +#endif + size_t trackId) { + return this->centralAudioBuffer->writePCM(data, bytes, trackId); + }); this->isPaused = false; - this->handler->setEventHandler( - [this](std::unique_ptr event) { - switch (event->eventType) { - case cspot::SpircHandler::EventType::PLAY_PAUSE: - if (std::get(event->data)) { - this->pauseRequested = true; - } else { - this->isPaused = false; - this->pauseRequested = false; - } + this->handler->stateCallback = + [this](cspot::DeviceStateHandler::Command event) { + switch (event.commandType) { + case cspot::DeviceStateHandler::CommandType::PAUSE: + this->pauseRequested = true; + break; + case cspot::DeviceStateHandler::CommandType::PLAY: + this->isPaused = false; + this->pauseRequested = false; break; - case cspot::SpircHandler::EventType::FLUSH: { + case cspot::DeviceStateHandler::CommandType::FLUSH: { this->centralAudioBuffer->clearBuffer(); break; } - case cspot::SpircHandler::EventType::DISC: + case cspot::DeviceStateHandler::CommandType::DISC: + this->centralAudioBuffer->clearBuffer(); + tracks.at(0)->trackMetrics->endTrack(); + this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + tracks.clear(); + this->playlistEnd = true; + break; + case cspot::DeviceStateHandler::CommandType::SEEK: this->centralAudioBuffer->clearBuffer(); break; - case cspot::SpircHandler::EventType::SEEK: + case cspot::DeviceStateHandler::CommandType::SKIP_NEXT: + case cspot::DeviceStateHandler::CommandType::SKIP_PREV: this->centralAudioBuffer->clearBuffer(); break; - case cspot::SpircHandler::EventType::PLAYBACK_START: - this->isPaused = true; - this->playlistEnd = false; + case cspot::DeviceStateHandler::CommandType::PLAYBACK_START: this->centralAudioBuffer->clearBuffer(); + if (tracks.size()) + tracks.clear(); + this->isPaused = false; + this->playlistEnd = false; + break; + case cspot::DeviceStateHandler::CommandType::PLAYBACK: + tracks.push_back( + std::get>(event.data)); + this->isPaused = false; + this->playlistEnd = false; break; - case cspot::SpircHandler::EventType::DEPLETED: + case cspot::DeviceStateHandler::CommandType::DEPLETED: + this->centralAudioBuffer->clearBuffer(); this->playlistEnd = true; break; - case cspot::SpircHandler::EventType::VOLUME: { - int volume = std::get(event->data); + case cspot::DeviceStateHandler::CommandType::VOLUME: { + int volume = std::get(event.data); break; } default: break; } - }); + }; startTask(); } @@ -109,15 +127,28 @@ void CliPlayer::runTask() { if (!chunk || chunk->pcmSize == 0) { if (this->playlistEnd) { - this->handler->notifyAudioEnded(); this->playlistEnd = false; + if (tracks.size()) { + tracks.at(0)->trackMetrics->endTrack(); + this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + tracks.clear(); + } + lastHash = 0; } BELL_SLEEP_MS(10); continue; } else { if (lastHash != chunk->trackHash) { + if (lastHash) { + this->handler->trackPlayer->eofCallback(true); + tracks.pop_front(); + tracks.at(0)->trackMetrics->endTrack(); + this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + } lastHash = chunk->trackHash; - this->handler->notifyAudioReachedPlayback(); + tracks.at(0)->trackMetrics->startTrackPlaying( + tracks.at(0)->requestedPosition); + this->handler->putPlayerState(); } #ifndef BELL_DISABLE_CODECS diff --git a/targets/cli/CliPlayer.h b/targets/cli/CliPlayer.h index 0857a640..65b7f122 100644 --- a/targets/cli/CliPlayer.h +++ b/targets/cli/CliPlayer.h @@ -7,29 +7,31 @@ #include // for mutex #include // for string -#include "AudioSink.h" // for AudioSink -#include "BellTask.h" // for Task +#include "AudioSink.h" // for AudioSink +#include "BellTask.h" // for Task +#include "DeviceStateHandler.h" // for DeviceStateHandler namespace bell { class BellDSP; class CentralAudioBuffer; } // namespace bell namespace cspot { -class SpircHandler; +class DeviceStateHandler; } // namespace cspot class CliPlayer : public bell::Task { public: CliPlayer(std::unique_ptr sink, - std::shared_ptr spircHandler); + std::shared_ptr handler); void disconnect(); private: std::string currentTrackId; - std::shared_ptr handler; + std::shared_ptr handler; std::shared_ptr dsp; std::unique_ptr audioSink; std::shared_ptr centralAudioBuffer; + std::deque> tracks = {}; void feedData(uint8_t* data, size_t len); diff --git a/targets/cli/main.cpp b/targets/cli/main.cpp index a4249875..536d959b 100644 --- a/targets/cli/main.cpp +++ b/targets/cli/main.cpp @@ -1,18 +1,18 @@ -#include // for __base, function +#include +#include // for __base, function +#include #include // for operator!=, map, map<>::mapped_type +#include // for std::osstringstream #include // for invalid_argument #include // for remove_extent_t #include // for vector -#include -#include -#include // for std::osstringstream #include "BellHTTPServer.h" // for BellHTTPServer #include "BellLogger.h" // for setDefaultLogger, AbstractLogger #include "CSpotContext.h" // for Context, Context::ConfigState #include "CliPlayer.h" // for CliPlayer +#include "DeviceStateHandler.h" // for DeviceStateHandler #include "MDNSService.h" // for MDNSService -#include "SpircHandler.h" // for SpircHandler #include "WrappedSemaphore.h" // for WrappedSemaphore #include "civetweb.h" // for mg_header, mg_get_request_info #include "nlohmann/json.hpp" // for basic_json<>::object_t, basic_json @@ -151,7 +151,8 @@ int main(int argc, char** argv) { std::cout << "-p, --password your spotify password, note that " "if you use facebook login you can set a password in your " "account settings\n"; - std::cout << "-c, --credentials json file to store/load reusable credentials\n"; + std::cout << "-c, --credentials json file to store/load reusable " + "credentials\n"; std::cout << "-b, --bitrate bitrate (320, 160, 96)\n"; std::cout << "\n"; std::cout << "ddd 2022\n"; @@ -168,11 +169,11 @@ int main(int argc, char** argv) { } // reusable credentials else if (!args->credentials.empty()) { - std::ifstream file(args->credentials); - std::ostringstream credentials; - credentials << file.rdbuf(); - loginBlob->loadJson(credentials.str()); - loggedInSemaphore->give(); + std::ifstream file(args->credentials); + std::ostringstream credentials; + credentials << file.rdbuf(); + loginBlob->loadJson(credentials.str()); + loggedInSemaphore->give(); } // ZeroconfAuthenticator else { @@ -200,12 +201,12 @@ int main(int argc, char** argv) { if (ctx->config.authData.size() > 0) { // when credentials file is set, then store reusable credentials if (!args->credentials.empty()) { - std::ofstream file(args->credentials); - file << ctx->getCredentialsJson(); + std::ofstream file(args->credentials); + file << ctx->getCredentialsJson(); } - // Start spirc task - auto handler = std::make_shared(ctx); + // Start DeviceStateHandler + auto handler = std::make_shared(ctx); // Start handling mercury messages ctx->session->startTask(); diff --git a/targets/esp32/components/VS1053/include/VS1053.h b/targets/esp32/components/VS1053/include/VS1053.h index b22eea9d..78acd468 100644 --- a/targets/esp32/components/VS1053/include/VS1053.h +++ b/targets/esp32/components/VS1053/include/VS1053.h @@ -150,7 +150,7 @@ class VS1053_SINK { * get available Space in dataBuffer * @return free space available in dataBuffer */ - size_t data_request(); + size_t data_request(std::shared_ptr track); /** * loads Usercode(PATCH) * @param plugin uint8_t * to plugin array @@ -185,6 +185,10 @@ class VS1053_SINK { afDsd64, afLatm } audioFormat = afUnknown; + + std::deque command_callbacks; + std::deque> tracks; + void get_audio_format(Audio_Format* audioFormat, size_t* endFillBytes); void control_mode_on(); void control_mode_off(); @@ -199,8 +203,9 @@ class VS1053_SINK { void write_mem32(uint16_t addr, uint32_t data); bool sdi_send_buffer(uint8_t* data, size_t len); void remove_track(std::shared_ptr track) { - if (this->track->track_id == track->track_id) - this->track = nullptr; + for (int i = 0; i < tracks.size(); i++) + if (tracks[i]->track_id == track->track_id) + tracks.erase(tracks.begin() + i); }; void start_track(std::shared_ptr, size_t); size_t track_seekable(size_t); @@ -212,11 +217,7 @@ class VS1053_SINK { void delete_all_tracks(void); size_t spaces_available(size_t); - std::shared_ptr track = nullptr; - std::shared_ptr future_track = nullptr; size_t command_pointer = 0, command_reader = 0; - std::deque command_callbacks; - std::deque> tracks; bool isRunning = false; private: diff --git a/targets/esp32/components/VS1053/src/VS1053.cpp b/targets/esp32/components/VS1053/src/VS1053.cpp index 59d82eb8..1d86ebf8 100644 --- a/targets/esp32/components/VS1053/src/VS1053.cpp +++ b/targets/esp32/components/VS1053/src/VS1053.cpp @@ -118,17 +118,18 @@ esp_err_t VS1053_SINK::init(spi_host_device_t SPI, write_mem(PAR_CONFIG1, PAR_CONFIG1_AAC_SBR_SELECTIVE_UPSAMPLE); write_register(SCI_VOL, 0x0c0c); #ifndef CONFIG_VS1053_NO_PLUGIN - //load_user_code(PLUGIN, PLUGIN_SIZE); + load_user_code(PLUGIN, PLUGIN_SIZE); #endif vTaskDelay(100 / portTICK_PERIOD_MS); - xTaskCreatePinnedToCore(vs_feed, "track_feed", 4098, (void*)this, 10, - &task_handle, 0); + xTaskCreate(vs_feed, "track_feed", 1028 * 20, (void*)this, 1, &task_handle); + //xTaskCreatePinnedToCore(vs_feed, "track_feed", 1028 * 20, (void*)this, 1, &task_handle, 1); return ESP_OK; } VS1053_SINK::~VS1053_SINK() { if (task_handle != NULL) vTaskDelete(task_handle); + command_callbacks.clear(); task_handle = NULL; isRunning = false; } @@ -208,12 +209,14 @@ size_t VS1053_SINK::get_track_info(size_t pos, uint8_t& endFillByte, byteRate *= 4; ESP_LOGI(TAG, + "Track %i, " "%dKiB " "%1ds %1.1f" "kb/s %dHz %s %s", - pos / (1024 / VS1053_PACKET_SIZE), read_register(SCI_DECODE_TIME), - byteRate * (8.0 / 1000.0), sampleRate & 0xFFFE, - (sampleRate & 1) ? "stereo" : "mono", afName[audioFormat]); + tracks[0]->track_id, pos / (1024 / VS1053_PACKET_SIZE), + read_register(SCI_DECODE_TIME), byteRate * (8.0 / 1000.0), + sampleRate & 0xFFFE, (sampleRate & 1) ? "stereo" : "mono", + afName[audioFormat]); #endif return (audioFormat == afMidi || audioFormat == afUnknown) ? REPORT_INTERVAL_MIDI @@ -222,7 +225,8 @@ size_t VS1053_SINK::get_track_info(size_t pos, uint8_t& endFillByte, size_t VS1053_TRACK::feed_data(uint8_t* data, size_t len, bool STORAGE_VOLATILE) { - if (!len || xStreamBufferSpacesAvailable(this->dataBuffer) < len) + if (this->dataBuffer == NULL || !len || + xStreamBufferSpacesAvailable(this->dataBuffer) < len) return 0; if (STORAGE_VOLATILE) if (this->header_size) @@ -245,6 +249,7 @@ void VS1053_TRACK::empty_feed() { void VS1053_SINK::new_state(VS1053_TRACK::VS_TRACK_STATE& state, VS1053_TRACK::VS_TRACK_STATE new_state) { state = new_state; + ESP_LOGI(TAG, "New state %i", new_state); if (state_callback != NULL) { state_callback((uint8_t)new_state); } @@ -313,7 +318,8 @@ void VS1053_SINK::run_feed(size_t FILL_BUFFER_BEFORE_PLAYBACK) { nextReportPos += this->get_track_info(pos, endFillByte, endFillBytes); } } - vStreamBufferDelete(track->dataBuffer); + if (track->dataBuffer != NULL) + vStreamBufferDelete(track->dataBuffer); track->dataBuffer = NULL; tracks.pop_front(); } @@ -324,16 +330,16 @@ void VS1053_SINK::run_feed(size_t FILL_BUFFER_BEFORE_PLAYBACK) { } // FEED FUNCTIONS -size_t VS1053_SINK::data_request() { +size_t VS1053_SINK::data_request(std::shared_ptr track) { return xStreamBufferSpacesAvailable(track->dataBuffer); } void VS1053_SINK::stop_feed() { - if (this->tracks[0]->state < 3) + if (this->tracks[0]->state <= 4) new_state(this->tracks[0]->state, VS1053_TRACK::VS_TRACK_STATE::tsCancel); } void VS1053_SINK::soft_stop_feed() { - if (this->tracks[0]->state < 3) + if (this->tracks[0]->state <= 3) new_state(this->tracks[0]->state, VS1053_TRACK::VS_TRACK_STATE::tsSoftCancel); } diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp index 8a601ef5..68ce80e6 100644 --- a/targets/esp32/main/EspPlayer.cpp +++ b/targets/esp32/main/EspPlayer.cpp @@ -13,76 +13,96 @@ #include "BellUtils.h" // for BELL_SLEEP_MS #include "CircularBuffer.h" +#include "DeviceStateHandler.h" // for SpircHandler, DeviceStateHandler::CommandType #include "Logger.h" -#include "SpircHandler.h" // for SpircHandler, SpircHandler::EventType -#include "StreamInfo.h" // for BitWidth, BitWidth::BW_16 -#include "TrackPlayer.h" // for TrackPlayer +#include "StreamInfo.h" // for BitWidth, BitWidth::BW_16 +#include "TrackPlayer.h" // for TrackPlayer EspPlayer::EspPlayer(std::unique_ptr sink, - std::shared_ptr handler) + std::shared_ptr handler) : bell::Task("player", 32 * 1024, 0, 1) { this->handler = handler; this->audioSink = std::move(sink); this->circularBuffer = std::make_shared(1024 * 128); - this->handler->getTrackPlayer()->setDataCallback([this](uint8_t* data, - size_t bytes, + this->handler->trackPlayer->setDataCallback([this](uint8_t* data, + size_t bytes, #ifdef CONFIG_BELL_NOCODEC - bool STORAGE_VOLATILE, + bool STORAGE_VOLATILE, #endif - size_t trackId) { + size_t trackId) { this->feedData(data, bytes, trackId); return bytes; }); this->isPaused = false; - this->handler->setEventHandler( - [this](std::unique_ptr event) { - switch (event->eventType) { - case cspot::SpircHandler::EventType::PLAY_PAUSE: - if (std::get(event->data)) { - this->pauseRequested = true; - } else { - this->isPaused = false; - this->pauseRequested = false; - } + this->handler->stateCallback = + [this](cspot::DeviceStateHandler::Command event) { + switch (event.commandType) { + case cspot::DeviceStateHandler::CommandType::PAUSE: + this->pauseRequested = true; break; - case cspot::SpircHandler::EventType::DISC: + case cspot::DeviceStateHandler::CommandType::PLAY: + this->isPaused = false; + this->pauseRequested = false; + break; + case cspot::DeviceStateHandler::CommandType::DISC: this->circularBuffer->emptyBuffer(); + tracks.at(0)->trackMetrics->endTrack(); + this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + tracks.clear(); + this->playlistEnd = true; break; - case cspot::SpircHandler::EventType::FLUSH: + case cspot::DeviceStateHandler::CommandType::FLUSH: this->circularBuffer->emptyBuffer(); break; - case cspot::SpircHandler::EventType::SEEK: + case cspot::DeviceStateHandler::CommandType::SEEK: this->circularBuffer->emptyBuffer(); break; - case cspot::SpircHandler::EventType::PLAYBACK_START: - this->isPaused = true; - this->playlistEnd = false; + case cspot::DeviceStateHandler::CommandType::SKIP_NEXT: + case cspot::DeviceStateHandler::CommandType::SKIP_PREV: this->circularBuffer->emptyBuffer(); break; - case cspot::SpircHandler::EventType::DEPLETED: + case cspot::DeviceStateHandler::CommandType::PLAYBACK_START: + this->circularBuffer->emptyBuffer(); + this->isPaused = false; + this->playlistEnd = false; + if (tracks.size()) + tracks.clear(); + break; + case cspot::DeviceStateHandler::CommandType::PLAYBACK: + tracks.push_back( + std::get>(event.data)); + this->isPaused = false; + this->playlistEnd = false; + break; + case cspot::DeviceStateHandler::CommandType::DEPLETED: + this->circularBuffer->emptyBuffer(); this->playlistEnd = true; break; - case cspot::SpircHandler::EventType::VOLUME: { - int volume = std::get(event->data); + case cspot::DeviceStateHandler::CommandType::VOLUME: { + int volume = std::get(event.data); break; } default: break; } - }); + }; startTask(); } void EspPlayer::feedData(uint8_t* data, size_t len, size_t trackId) { size_t toWrite = len; - if (!len) - this->handler->notifyAudioReachedPlaybackEnd(); - else + if (!len) { + tracks.at(0)->trackMetrics->endTrack(); + this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + if (this->playlistEnd) { + tracks.clear(); + } + } else while (toWrite > 0) { this->current_hash = trackId; size_t written = @@ -114,15 +134,28 @@ void EspPlayer::runTask() { if (read == 0) { if (this->playlistEnd) { - this->handler->notifyAudioEnded(); this->playlistEnd = false; + if (tracks.size()) { + tracks.at(0)->trackMetrics->endTrack(); + this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + tracks.clear(); + } + lastHash = 0; } BELL_SLEEP_MS(10); continue; } else { if (lastHash != current_hash) { - lastHash = current_hash; - this->handler->notifyAudioReachedPlayback(); + if (lastHash) { + this->handler->trackPlayer->eofCallback(true); + tracks.pop_front(); + tracks.at(0)->trackMetrics->endTrack(); + this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + } + lastHash = chunk->trackHash; + tracks.at(0)->trackMetrics->startTrackPlaying( + tracks.at(0)->requestedPosition); + this->handler->putPlayerState(); } } } else { diff --git a/targets/esp32/main/EspPlayer.h b/targets/esp32/main/EspPlayer.h index 47189231..dfcc2bbf 100644 --- a/targets/esp32/main/EspPlayer.h +++ b/targets/esp32/main/EspPlayer.h @@ -7,27 +7,29 @@ #include // for mutex #include // for string -#include "AudioSink.h" // for AudioSink -#include "BellTask.h" // for Task +#include "AudioSink.h" // for AudioSink +#include "BellTask.h" // for Task +#include "DeviceStateHandler.h" // for DeviceStateHandler namespace bell { class CircularBuffer; } // namespace bell namespace cspot { -class SpircHandler; +class DeviceStateHandler; } // namespace cspot class EspPlayer : public bell::Task { public: EspPlayer(std::unique_ptr sink, - std::shared_ptr spircHandler); + std::shared_ptr handler); void disconnect(); private: std::string currentTrackId; - std::shared_ptr handler; + std::shared_ptr handler; std::unique_ptr audioSink; std::shared_ptr circularBuffer; + std::deque> tracks = {}; void feedData(uint8_t* data, size_t len, size_t); std::atomic pauseRequested = false; diff --git a/targets/esp32/main/VSPlayer.cpp b/targets/esp32/main/VSPlayer.cpp index 26d55c33..7df9e5b2 100644 --- a/targets/esp32/main/VSPlayer.cpp +++ b/targets/esp32/main/VSPlayer.cpp @@ -8,7 +8,7 @@ #include "TrackPlayer.h" // for TrackPlayer -VSPlayer::VSPlayer(std::shared_ptr handler, +VSPlayer::VSPlayer(std::shared_ptr handler, std::shared_ptr vsSink) { this->handler = handler; this->vsSink = vsSink; @@ -16,7 +16,7 @@ VSPlayer::VSPlayer(std::shared_ptr handler, this->state_callback(state); }; - this->handler->getTrackPlayer()->setDataCallback( + this->handler->trackPlayer->setDataCallback( [this](uint8_t* data, size_t bytes, size_t trackId, bool STORAGE_VOLATILE) { if (!this->track) { @@ -37,41 +37,49 @@ VSPlayer::VSPlayer(std::shared_ptr handler, this->isPaused = false; - this->handler->setEventHandler( - [this](std::unique_ptr event) { - switch (event->eventType) { - case cspot::SpircHandler::EventType::PLAY_PAUSE: - if (std::get(event->data)) { - if (this->track) - this->vsSink->new_state(this->vsSink->tracks[0]->state, - VS1053_TRACK::tsPlaybackPaused); - } else { - if (this->track) - this->vsSink->new_state(this->vsSink->tracks[0]->state, - VS1053_TRACK::tsPlaybackSeekable); - } + this->handler->stateCallback = + [this](cspot::DeviceStateHandler::Command event) { + switch (event.commandType) { + case cspot::DeviceStateHandler::CommandType::PAUSE: + if (this->track) + this->vsSink->new_state(this->vsSink->tracks[0]->state, + VS1053_TRACK::tsPlaybackPaused); break; - case cspot::SpircHandler::EventType::DISC: + case cspot::DeviceStateHandler::CommandType::PLAY: + if (this->track) + this->vsSink->new_state(this->vsSink->tracks[0]->state, + VS1053_TRACK::tsPlaybackSeekable); + break; + case cspot::DeviceStateHandler::CommandType::DISC: this->track = nullptr; this->vsSink->delete_all_tracks(); this->vsSink->stop_feed(); + //this->currentTrack = nullptr; + this->futureTrack = nullptr; break; - case cspot::SpircHandler::EventType::FLUSH: + case cspot::DeviceStateHandler::CommandType::FLUSH: this->track->empty_feed(); break; - case cspot::SpircHandler::EventType::SEEK: + //case cspot::DeviceStateHandler::CommandType::SEEK: + //break; + case cspot::DeviceStateHandler::CommandType::PLAYBACK_START: break; - case cspot::SpircHandler::EventType::PLAYBACK_START: + case cspot::DeviceStateHandler::CommandType::PLAYBACK: this->isPaused = true; this->playlistEnd = false; + if (this->currentTrack != nullptr) + this->futureTrack = + std::get>(event.data); + else + this->currentTrack = + std::get>(event.data); break; - case cspot::SpircHandler::EventType::DEPLETED: - this->playlistEnd = true; - this->track = nullptr; + case cspot::DeviceStateHandler::CommandType::DEPLETED: + this->futureTrack = nullptr; this->vsSink->stop_feed(); break; - case cspot::SpircHandler::EventType::VOLUME: { - this->volume = std::get(event->data); + case cspot::DeviceStateHandler::CommandType::VOLUME: { + this->volume = std::get(event.data); this->vsSink->feed_command([this](uint8_t) { this->vsSink->set_volume_logarithmic(this->volume); }); @@ -80,18 +88,25 @@ VSPlayer::VSPlayer(std::shared_ptr handler, default: break; } - }); + }; } void VSPlayer::state_callback(uint8_t state) { if (state == 1) { - this->handler->notifyAudioReachedPlayback(); + currentTrack->trackMetrics->startTrackPlaying( + currentTrack->requestedPosition); + this->handler->putPlayerState(); } if (state == 7) { - if (this->playlistEnd) - this->handler->notifyAudioEnded(); - else - this->handler->notifyAudioReachedPlaybackEnd(); + currentTrack->trackMetrics->endTrack(); + this->handler->ctx->playbackMetrics->sendEvent(currentTrack); + if (futureTrack != nullptr) { + currentTrack = futureTrack; + futureTrack = nullptr; + } else { + currentTrack = nullptr; + this->track = nullptr; + } } } diff --git a/targets/esp32/main/VSPlayer.h b/targets/esp32/main/VSPlayer.h index c8db9a36..8dd27bcc 100644 --- a/targets/esp32/main/VSPlayer.h +++ b/targets/esp32/main/VSPlayer.h @@ -7,15 +7,15 @@ #include // for mutex #include // for string -#include "SpircHandler.h" // for SpircHandler, SpircHandler::EventType +#include "DeviceStateHandler.h" // for DeviceStateHandler, DeviceStateHandler::CommandType #include "VS1053.h" namespace cspot { -class SpircHandler; +class DeviceStateHandler; } // namespace cspot class VSPlayer { public: - VSPlayer(std::shared_ptr spircHandler, + VSPlayer(std::shared_ptr handler, std::shared_ptr vsSink = NULL); void disconnect(); size_t volume = 0; @@ -23,9 +23,10 @@ class VSPlayer { private: std::string currentTrackId; std::shared_ptr vsSink; - std::shared_ptr handler; + std::shared_ptr handler; std::shared_ptr track = nullptr; - VS1053_TRACK* futureTrack = NULL; + std::shared_ptr futureTrack = nullptr, + currentTrack = nullptr; void state_callback(uint8_t state); std::atomic pauseRequested = false; diff --git a/targets/esp32/main/VSinit.h b/targets/esp32/main/VSinit.h index 0682a4a1..1b08bd01 100644 --- a/targets/esp32/main/VSinit.h +++ b/targets/esp32/main/VSinit.h @@ -87,27 +87,28 @@ void initAudioSink(std::shared_ptr VS1053) { "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); } + } else { + struct dirent* entry; + struct stat file_stat; + DIR* dir = opendir(MOUNT_POINT); + char n_name[280]; + if (!dir) + printf("no dir\n"); + while ((entry = readdir(dir)) != NULL) { + sprintf(n_name, "%s/%s", MOUNT_POINT, entry->d_name); + printf("%s\n", n_name); + printf("name:%s, ino: %i\n", entry->d_name, entry->d_ino); + printf("stat_return_value:%i\n", stat(n_name, &file_stat)); + printf("stat_mode:%i\n", file_stat.st_mode); + } + dir = opendir(MOUNT_POINT "/TRACKS"); + if (!dir) + printf("no dir\n"); + while ((entry = readdir(dir)) != NULL) { + printf("%s\n", entry->d_name); + } + closedir(dir); } - struct dirent* entry; - struct stat file_stat; - DIR* dir = opendir(MOUNT_POINT); - char n_name[280]; - if (!dir) - printf("no dir\n"); - while ((entry = readdir(dir)) != NULL) { - sprintf(n_name, "%s/%s", MOUNT_POINT, entry->d_name); - printf("%s\n", n_name); - printf("name:%s, ino: %i\n", entry->d_name, entry->d_ino); - printf("stat_return_value:%i\n", stat(n_name, &file_stat)); - printf("stat_mode:%i\n", file_stat.st_mode); - } - dir = opendir(MOUNT_POINT "/TRACKS"); - if (!dir) - printf("no dir\n"); - while ((entry = readdir(dir)) != NULL) { - printf("%s\n", entry->d_name); - } - closedir(dir); } VS1053->write_register(SCI_VOL, 10 | 10 << 8); } \ No newline at end of file diff --git a/targets/esp32/main/main.cpp b/targets/esp32/main/main.cpp index f26cf449..e1ab2983 100644 --- a/targets/esp32/main/main.cpp +++ b/targets/esp32/main/main.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include "BellTask.h" @@ -135,7 +134,7 @@ class ZeroconfAuthenticator { class CSpotTask : public bell::Task { private: - std::unique_ptr handler; + //std::unique_ptr handler; #ifndef CONFIG_BELL_NOCODEC std::unique_ptr audioSink; #endif @@ -204,8 +203,8 @@ class CSpotTask : public bell::Task { if (ctx->config.authData.size() > 0) { // when credentials file is set, then store reusable credentials - // Start spirc task - auto handler = std::make_shared(ctx); + // Start device handler task + auto handler = std::make_shared(ctx); // Start handling mercury messages ctx->session->startTask(); @@ -246,7 +245,7 @@ void init_spiffs() { ESP_LOGE("SPIFFS", "Failed to find SPIFFS partition"); } else { ESP_LOGE("SPIFFS", "Failed to initialize SPIFFS (%s)", - esp_err_to_name(ret)); + esp_err_to_name(ret)); } return; } @@ -255,7 +254,7 @@ void init_spiffs() { ret = esp_spiffs_info(conf.partition_label, &total, &used); if (ret != ESP_OK) { ESP_LOGE("SPIFFS", "Failed to get SPIFFS partition information (%s)", - esp_err_to_name(ret)); + esp_err_to_name(ret)); } else { ESP_LOGE("SPIFFS", "Partition size: total: %d, used: %d", total, used); } @@ -284,7 +283,6 @@ void app_main(void) { // statusLed->setStatus(StatusLed::WIFI_CONNECTED); - ESP_LOGI("MAIN", "Connected to AP, start spotify receiver"); //auto taskHandle = xTaskCreatePinnedToCore(&cspotTask, "cspot", 12*1024, NULL, 5, NULL, 1); /*auto taskHandle = */ From 7db50678c1cdb18e660ea1cd7889287e91715f84 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 24 Sep 2024 16:44:37 +0200 Subject: [PATCH 38/41] minor changes --- cspot/include/DeviceStateHandler.h | 2 +- cspot/src/DeviceStateHandler.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cspot/include/DeviceStateHandler.h b/cspot/include/DeviceStateHandler.h index 6f839648..28b23dc6 100644 --- a/cspot/include/DeviceStateHandler.h +++ b/cspot/include/DeviceStateHandler.h @@ -104,7 +104,7 @@ class DeviceStateHandler { free(string); string = NULL; } - + static void reloadTrackList(void*); }; } // namespace cspot \ No newline at end of file diff --git a/cspot/src/DeviceStateHandler.cpp b/cspot/src/DeviceStateHandler.cpp index b3b0a322..203362a9 100644 --- a/cspot/src/DeviceStateHandler.cpp +++ b/cspot/src/DeviceStateHandler.cpp @@ -252,8 +252,7 @@ DeviceStateHandler::DeviceStateHandler(std::shared_ptr ctx) { 0, //supports_lossless_audio true, 1, //supports_set_options_command - true, - {false, 0, false, 0, true, 1}}; + true, {false, 0, false, 0, true, 1}}; device.device_info.capabilities.supported_types = (char**)calloc(5, sizeof(char*)); device.device_info.capabilities.supported_types[0] = strdup("audio/track"); From 7b152de64ec80319f27da6a0c1ab750b26bbbc57 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 24 Sep 2024 16:47:13 +0200 Subject: [PATCH 39/41] minor clang-format changes --- cspot/src/DeviceStateHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cspot/src/DeviceStateHandler.cpp b/cspot/src/DeviceStateHandler.cpp index 203362a9..f01fb642 100644 --- a/cspot/src/DeviceStateHandler.cpp +++ b/cspot/src/DeviceStateHandler.cpp @@ -252,7 +252,7 @@ DeviceStateHandler::DeviceStateHandler(std::shared_ptr ctx) { 0, //supports_lossless_audio true, 1, //supports_set_options_command - true, {false, 0, false, 0, true, 1}}; + true, {false, 0, false, 0, true, 1}}; device.device_info.capabilities.supported_types = (char**)calloc(5, sizeof(char*)); device.device_info.capabilities.supported_types[0] = strdup("audio/track"); From d6e1e6fb4b90903b41b0e931e23557366c0640a2 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Tue, 24 Sep 2024 20:50:36 +0200 Subject: [PATCH 40/41] Seeking now supported on all devices --- cspot/src/DeviceStateHandler.cpp | 4 ++++ targets/esp32/main/EspPlayer.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cspot/src/DeviceStateHandler.cpp b/cspot/src/DeviceStateHandler.cpp index f01fb642..08f9a0e6 100644 --- a/cspot/src/DeviceStateHandler.cpp +++ b/cspot/src/DeviceStateHandler.cpp @@ -880,6 +880,10 @@ void DeviceStateHandler::parseCommand(std::vector& data) { sendCommand(CommandType::SKIP_PREV); } else if (command->at("endpoint") == "seek_to") { + +#ifdef CONFIG_BELL_NOCODEC + needsToBeSkipped = false; +#endif if (command->at("relative") == "beginning") { //relative this->device.player_state.has_position_as_of_timestamp = true; this->device.player_state.position_as_of_timestamp = diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp index 68ce80e6..f1c57ded 100644 --- a/targets/esp32/main/EspPlayer.cpp +++ b/targets/esp32/main/EspPlayer.cpp @@ -152,7 +152,7 @@ void EspPlayer::runTask() { tracks.at(0)->trackMetrics->endTrack(); this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); } - lastHash = chunk->trackHash; + lastHash = current_hash; tracks.at(0)->trackMetrics->startTrackPlaying( tracks.at(0)->requestedPosition); this->handler->putPlayerState(); From 209d27814b3c2d812f82f6db2f02780bec793093 Mon Sep 17 00:00:00 2001 From: Tobias Guyer Date: Sun, 29 Sep 2024 16:10:03 +0200 Subject: [PATCH 41/41] adjusting stack-sizes to new structure, minor adjustments for bell_nocodec --- cspot/include/MercurySession.h | 7 +-- cspot/include/TrackReference.h | 2 +- cspot/src/DeviceStateHandler.cpp | 27 +++++++++-- cspot/src/MercurySession.cpp | 81 ++++++++++++++------------------ targets/cli/CliPlayer.cpp | 4 +- targets/esp32/main/EspPlayer.cpp | 4 +- targets/esp32/main/main.cpp | 2 +- 7 files changed, 70 insertions(+), 57 deletions(-) diff --git a/cspot/include/MercurySession.h b/cspot/include/MercurySession.h index f01ee02f..4359e0a0 100644 --- a/cspot/include/MercurySession.h +++ b/cspot/include/MercurySession.h @@ -27,7 +27,8 @@ class MercurySession : public bell::Task, public cspot::Session { struct Response { Header mercuryHeader; DataParts parts; - bool fail; + int64_t sequenceId; + bool fail = true; }; typedef std::function ResponseCallback; typedef std::function&)> @@ -118,7 +119,7 @@ class MercurySession : public bell::Task, public cspot::Session { void reconnect(); std::unordered_map callbacks; - std::deque> partials; + std::deque partials; std::unordered_map subscriptions; std::unordered_map audioKeyCallbacks; @@ -137,6 +138,6 @@ class MercurySession : public bell::Task, public cspot::Session { void failAllPending(); - std::pair decodeResponse(const std::vector& data); + MercurySession::Response decodeResponse(const std::vector& data); }; } // namespace cspot diff --git a/cspot/include/TrackReference.h b/cspot/include/TrackReference.h index a5688d4b..70b04e0a 100644 --- a/cspot/include/TrackReference.h +++ b/cspot/include/TrackReference.h @@ -9,7 +9,7 @@ #include "pb_decode.h" #include "protobuf/connect.pb.h" -#define TRACK_SEND_LIMIT 10 +#define TRACK_SEND_LIMIT 25 namespace cspot { struct TrackReference { diff --git a/cspot/src/DeviceStateHandler.cpp b/cspot/src/DeviceStateHandler.cpp index 08f9a0e6..e6c1cfa7 100644 --- a/cspot/src/DeviceStateHandler.cpp +++ b/cspot/src/DeviceStateHandler.cpp @@ -142,7 +142,7 @@ DeviceStateHandler::DeviceStateHandler(std::shared_ptr ctx) { this->ctx->session->addSubscriptionListener("hm://connect-state/", connectStateSubscription); - CSPOT_LOG(info, "Added connect-state subscrription"); + CSPOT_LOG(info, "Added connect-state subscription"); // the device connection status gets reported trough "hm://social-connect",if active auto socialConnectSubscription = [this](MercurySession::Response& res) { @@ -880,8 +880,8 @@ void DeviceStateHandler::parseCommand(std::vector& data) { sendCommand(CommandType::SKIP_PREV); } else if (command->at("endpoint") == "seek_to") { - -#ifdef CONFIG_BELL_NOCODEC + +#ifndef CONFIG_BELL_NOCODEC needsToBeSkipped = false; #endif if (command->at("relative") == "beginning") { //relative @@ -928,6 +928,13 @@ void DeviceStateHandler::parseCommand(std::vector& data) { std::make_shared( currentTracks[offset + queuedOffset], this->ctx, 0)); } +#ifndef CONFIG_BELL_NOCODEC + this->trackPlayer->seekMs( + trackQueue->preloadedTracks[0]->trackMetrics->getPosition()); + sendCommand( + CommandType::SEEK, + (int32_t)this->device.player_state.position_as_of_timestamp); +#endif this->putPlayerState(); } else if (command->at("endpoint") == "set_queue") { std::scoped_lock lock(trackQueue->tracksMutex); @@ -990,6 +997,13 @@ void DeviceStateHandler::parseCommand(std::vector& data) { 1], this->ctx, 0)); } +#ifndef CONFIG_BELL_NOCODEC + this->trackPlayer->seekMs( + trackQueue->preloadedTracks[0]->trackMetrics->getPosition()); + sendCommand( + CommandType::SEEK, + (int32_t)this->device.player_state.position_as_of_timestamp); +#endif this->putPlayerState(); } else if (command->at("endpoint") == "update_context") { unreference(this->device.player_state.session_id); @@ -1090,6 +1104,13 @@ void DeviceStateHandler::parseCommand(std::vector& data) { ? 2 : this->device.player_state.options .shuffling_context)); +#ifndef CONFIG_BELL_NOCODEC + this->trackPlayer->seekMs( + trackQueue->preloadedTracks[0]->trackMetrics->getPosition()); + sendCommand( + CommandType::SEEK, + (int32_t)this->device.player_state.position_as_of_timestamp); +#endif } else if (command->at("endpoint") == "set_options") { if (this->device.player_state.options.repeating_context != diff --git a/cspot/src/MercurySession.cpp b/cspot/src/MercurySession.cpp index 9d33a51e..3db327d9 100644 --- a/cspot/src/MercurySession.cpp +++ b/cspot/src/MercurySession.cpp @@ -22,7 +22,7 @@ using namespace cspot; MercurySession::MercurySession(std::shared_ptr timeProvider) - : bell::Task("mercury_dispatcher", 4 * 1024, 3, 1) { + : bell::Task("mercury_dispatcher", 32 * 1024, 3, 1) { this->timeProvider = timeProvider; } @@ -178,43 +178,29 @@ void MercurySession::handlePacket() { CSPOT_LOG(debug, "Received mercury packet"); auto response = this->decodeResponse(packet.data); - if (response.first == static_cast(ResponseFlag::FINAL)) { - - auto partial = partials.begin(); - while (partial != partials.end() && partial->first != response.second) - partial++; // if(partial.first == sequenceId) - if (partial != partials.end()) { - //if the event-id is negative, they got sent without any request - if (response.first >= 0) { - if (this->callbacks.count(response.second)) { - this->callbacks[response.second](partial->second); - this->callbacks.erase(this->callbacks.find(response.second)); - } + if (!response.fail) { + if (response.sequenceId >= 0) { + if (this->callbacks.count(response.sequenceId)) { + this->callbacks[response.sequenceId](response); + this->callbacks.erase(this->callbacks.find(response.sequenceId)); } - pb_release(Header_fields, &partial->second.mercuryHeader); - this->partials.erase(partial); } + pb_release(Header_fields, &response.mercuryHeader); } break; } case RequestType::SUBRES: { auto response = decodeResponse(packet.data); - if (response.first == static_cast(ResponseFlag::FINAL)) { - auto partial = partials.begin(); - while (partial != partials.end() && partial->first != response.second) - partial++; // if(partial.first == sequenceId) - if (partial != partials.end()) { - auto uri = std::string(partial->second.mercuryHeader.uri); - for (auto& it : this->subscriptions) - if (uri.find(it.first) != std::string::npos) { - it.second(partial->second); - goto found_subscription; - } - found_subscription:; - pb_release(Header_fields, &partial->second.mercuryHeader); - this->partials.erase(partial); + if (!response.fail) { + std::string uri(response.mercuryHeader.uri); + for (auto& it : this->subscriptions) { + if (uri.find(it.first) != std::string::npos) { + it.second(response); + break; // Exit loop once subscription is found + } } + pb_release(Header_fields, &response.mercuryHeader); } break; } @@ -242,11 +228,12 @@ void MercurySession::failAllPending() { this->callbacks = {}; } -std::pair MercurySession::decodeResponse( +MercurySession::Response MercurySession::decodeResponse( const std::vector& data) { auto sequenceLength = ntohs(extract(data, 0)); int64_t sequenceId; uint8_t flag; + Response resp; if (sequenceLength == 2) sequenceId = ntohs(extract(data, 2)); else if (sequenceLength == 4) @@ -254,7 +241,7 @@ std::pair MercurySession::decodeResponse( else if (sequenceLength == 8) sequenceId = hton64(extract(data, 2)); else - return std::make_pair(0, 0); + return resp; size_t pos = 2 + sequenceLength; flag = (uint8_t)data[pos]; @@ -262,43 +249,47 @@ std::pair MercurySession::decodeResponse( uint16_t parts = ntohs(extract(data, pos)); pos += 2; auto partial = partials.begin(); - while (partial != partials.end() && partial->first != sequenceId) + while (partial != partials.end() && partial->sequenceId != sequenceId) partial++; // if(partial.first == sequenceId) if (partial == partials.end()) { CSPOT_LOG(debug, "Creating new Mercury Response, seq: %lli, flags: %i, parts: %i", sequenceId, flag, parts); - this->partials.push_back(std::make_pair(sequenceId, Response())); + this->partials.push_back(Response()); partial = partials.end() - 1; - partial->second.parts = {}; - partial->second.fail = false; + partial->parts = {}; + partial->sequenceId = sequenceId; } else CSPOT_LOG(debug, "Adding to Mercury Response, seq: %lli, flags: %i, parts: %i", sequenceId, flag, parts); uint8_t index = 0; while (parts) { - if (data.size() <= pos || partial->second.fail) + if (data.size() <= pos) break; auto partSize = ntohs(extract(data, pos)); pos += 2; - if (partial->second.mercuryHeader.uri == NULL) { - partial->second.fail = false; + if (partial->mercuryHeader.uri == NULL) { auto headerBytes = std::vector(data.begin() + pos, data.begin() + pos + partSize); - pbDecode(partial->second.mercuryHeader, Header_fields, headerBytes); + pbDecode(partial->mercuryHeader, Header_fields, headerBytes); } else { - if (index >= partial->second.parts.size()) - partial->second.parts.push_back(std::vector{}); - partial->second.parts[index].insert(partial->second.parts[index].end(), - data.begin() + pos, - data.begin() + pos + partSize); + if (index >= partial->parts.size()) + partial->parts.push_back(std::vector{}); + partial->parts[index].insert(partial->parts[index].end(), + data.begin() + pos, + data.begin() + pos + partSize); index++; } pos += partSize; parts--; } - return std::make_pair(flag, sequenceId); + if (flag == static_cast(ResponseFlag::FINAL)) { + resp = *partial; + partials.erase(partial); + resp.fail = false; + } + return resp; } void MercurySession::addSubscriptionListener(const std::string& uri, diff --git a/targets/cli/CliPlayer.cpp b/targets/cli/CliPlayer.cpp index a3a56e32..38bd39e4 100644 --- a/targets/cli/CliPlayer.cpp +++ b/targets/cli/CliPlayer.cpp @@ -140,10 +140,10 @@ void CliPlayer::runTask() { } else { if (lastHash != chunk->trackHash) { if (lastHash) { - this->handler->trackPlayer->eofCallback(true); - tracks.pop_front(); tracks.at(0)->trackMetrics->endTrack(); this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + tracks.pop_front(); + this->handler->trackPlayer->eofCallback(true); } lastHash = chunk->trackHash; tracks.at(0)->trackMetrics->startTrackPlaying( diff --git a/targets/esp32/main/EspPlayer.cpp b/targets/esp32/main/EspPlayer.cpp index f1c57ded..7f957e88 100644 --- a/targets/esp32/main/EspPlayer.cpp +++ b/targets/esp32/main/EspPlayer.cpp @@ -147,10 +147,10 @@ void EspPlayer::runTask() { } else { if (lastHash != current_hash) { if (lastHash) { - this->handler->trackPlayer->eofCallback(true); - tracks.pop_front(); tracks.at(0)->trackMetrics->endTrack(); this->handler->ctx->playbackMetrics->sendEvent(tracks[0]); + tracks.pop_front(); + this->handler->trackPlayer->eofCallback(true); } lastHash = current_hash; tracks.at(0)->trackMetrics->startTrackPlaying( diff --git a/targets/esp32/main/main.cpp b/targets/esp32/main/main.cpp index e1ab2983..8f37e3aa 100644 --- a/targets/esp32/main/main.cpp +++ b/targets/esp32/main/main.cpp @@ -140,7 +140,7 @@ class CSpotTask : public bell::Task { #endif public: - CSpotTask() : bell::Task("cspot", 8 * 1024, 0, 0) { + CSpotTask() : bell::Task("cspot", 32 * 1024, 0, 0) { startTask(); } void runTask() {