diff --git a/python/mujoco/experimental/netimgui/.clang-format b/python/mujoco/experimental/netimgui/.clang-format new file mode 100644 index 00000000..5846b1ec --- /dev/null +++ b/python/mujoco/experimental/netimgui/.clang-format @@ -0,0 +1,3 @@ +# Disable clang-format for third-party code to keep diffs minimal during Copybara updates. +DisableFormat: true +SortIncludes: Never diff --git a/python/mujoco/experimental/netimgui/CMakeLists.txt b/python/mujoco/experimental/netimgui/CMakeLists.txt new file mode 100644 index 00000000..b5295215 --- /dev/null +++ b/python/mujoco/experimental/netimgui/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright 2026 DeepMind Technologies Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# NetImgui client library (vendored, MIT licensed — see LICENSE). +# +# This CMakeLists is included from two different build contexts: +# 1. The main MuJoCo tree under Emscripten (for the web viewer WASM client), +# where the `dear_imgui` target exists. +# 2. The Python bindings build (for the headless_ui pybind module), where Dear +# ImGui is an imported archive named `mujoco::dep::dear_imgui`. + +if(TARGET netimgui) + return() +endif() + +# Resolve the Dear ImGui target for the current build context. Check the +# imported archive first: in the Python bindings build a pybind module named +# `dear_imgui` is also defined (the Python ImGui bindings), which must not be +# confused with the C++ library. +if(TARGET mujoco::dep::dear_imgui) + set(NETIMGUI_IMGUI_TARGET mujoco::dep::dear_imgui) +elseif(TARGET dear_imgui) + set(NETIMGUI_IMGUI_TARGET dear_imgui) +else() + message(WARNING "No Dear ImGui target found. netimgui will not be built.") + return() +endif() + +add_library(netimgui STATIC + Code/Client/Private/NetImgui_Api.cpp + Code/Client/Private/NetImgui_Client.cpp + Code/Client/Private/NetImgui_CmdPackets_DrawFrame.cpp +) + +if(EMSCRIPTEN) + # WebSocket-based networking for the browser (WASM) build. + target_sources(netimgui PRIVATE google/NetImgui_NetworkWASM.cpp) + # emscripten_websocket_* requires the JS websocket library. + target_link_options(netimgui PUBLIC -lwebsocket.js) +elseif(WIN32) + # Winsock2 networking for Windows. + target_sources(netimgui PRIVATE Code/Client/Private/NetImgui_NetworkWin32.cpp) + # The source self-links ws2_32 via `#pragma comment(lib, ...)` under MSVC; + # link it explicitly so non-MSVC toolchains (e.g. clang-cl) resolve it too. + target_link_libraries(netimgui PUBLIC ws2_32) +elseif(UNIX) + # BSD-socket networking for Linux and macOS (both are UNIX). + target_sources(netimgui PRIVATE Code/Client/Private/NetImgui_NetworkPosix.cpp) +else() + message(WARNING "NetImgui networking is not available on this platform. " + "netimgui will not be built.") + return() +endif() + +target_include_directories(netimgui + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} # google/logging.h + ${CMAKE_CURRENT_SOURCE_DIR}/Code/Client # NetImgui_Api.h + ${CMAKE_CURRENT_SOURCE_DIR}/Code/Client/Private # NetImgui_CmdPackets.h etc. +) + +target_link_libraries(netimgui PUBLIC ${NETIMGUI_IMGUI_TARGET}) + +set_target_properties(netimgui PROPERTIES POSITION_INDEPENDENT_CODE ON) diff --git a/python/mujoco/experimental/netimgui/Code/Client/NetImgui_Api.h b/python/mujoco/experimental/netimgui/Code/Client/NetImgui_Api.h new file mode 100644 index 00000000..838c3b43 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/NetImgui_Api.h @@ -0,0 +1,353 @@ +#pragma once + +//================================================================================================= +//! @Name : NetImgui +//================================================================================================= +//! @author : Sammy Fatnassi +//! @date : 2026/01/04 +//! @version : v1.13.0 +//! @Details : For integration info : +//! https://github.com/sammyfreg/netImgui/wiki +//================================================================================================= +#define NETIMGUI_VERSION "1.13.0" // Release of v 1.13 +#define NETIMGUI_VERSION_NUM 11300 + +//------------------------------------------------------------------------------------------------- +// Deactivate a few warnings to allow Imgui header include +// without generating warnings in maximum level '-Wall' +//------------------------------------------------------------------------------------------------- +#if defined(__clang__) +#pragma clang diagnostic push +// ImGui.h warnings(s) +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#pragma clang diagnostic ignored \ + "-Wreserved-identifier" // Enum values using '__' or member starting with + // '_' in imgui.h +// NetImgui_Api.h Warning(s) +#pragma clang diagnostic ignored \ + "-Wzero-as-null-pointer-constant" // Not using nullptr in case this file is + // used in pre C++11 +#elif defined(_MSC_VER) +#pragma warning(push) +// ImGui.h warnings(s) +#pragma warning( \ + disable : 4514) // 'xxx': unreferenced inline function has been removed +#pragma warning(disable : 4710) // 'xxx': function not inlined +#pragma warning( \ + disable \ + : 4820) // 'xxx': 'yyy' bytes padding added after data member 'zzz' +#pragma warning(disable : 5045) // Compiler will insert Spectre mitigation for + // memory load if /Qspectre switch specified +#endif + +//================================================================================================= +// Include the user config file. It should contain the include for : +// 'imgui.h' : always +// 'imgui_internal.h' when 'NETIMGUI_INTERNAL_INCLUDE' is defined +//================================================================================================= +#ifdef NETIMGUI_IMPLEMENTATION +#define NETIMGUI_INTERNAL_INCLUDE +#include "NetImgui_Config.h" +#undef NETIMGUI_INTERNAL_INCLUDE +#else +#include "NetImgui_Config.h" +#endif + +//------------------------------------------------------------------------------------------------- +// If 'NETIMGUI_ENABLED' hasn't been defined yet (in project settings or +// NetImgui_Config.h') we define this library as 'Disabled' +//------------------------------------------------------------------------------------------------- +#ifndef NETIMGUI_ENABLED +#define NETIMGUI_ENABLED 0 +#endif + +//------------------------------------------------------------------------------------------------- +// NetImgui needs to detect Dear ImGui to be active, otherwise we disable it +// When including this header, make sure imgui.h is included first +// (either always included in NetImgui_config.h or have it included after +// Imgui.h in your cpp) +//------------------------------------------------------------------------------------------------- +#if !defined(IMGUI_VERSION) +#undef NETIMGUI_ENABLED +#define NETIMGUI_ENABLED 0 +#endif + +//------------------------------------------------------------------------------------------------- +// Control support for native Dear ImGui texture backend support +// At the moment, meant to always be active on recent Dear Imgui version (1.92+) +//------------------------------------------------------------------------------------------------- +#ifndef NETIMGUI_IMGUI_TEXTURES_ENABLED +#ifdef IMGUI_HAS_TEXTURES +#define NETIMGUI_IMGUI_TEXTURES_ENABLED 1 +#else +#define NETIMGUI_IMGUI_TEXTURES_ENABLED 0 +#endif +#endif + +#if NETIMGUI_ENABLED + +#include + +//================================================================================================= +// Default Build settings defines values +// Assign default values when not set in user NetImgui_Config.h +//================================================================================================= +//------------------------------------------------------------------------------------------------- +// Prepended to functions signature, for dll export/import +//------------------------------------------------------------------------------------------------- +#ifndef NETIMGUI_API +#define NETIMGUI_API \ + IMGUI_API // Use same value as defined by Dear ImGui by default +#endif + +//------------------------------------------------------------------------------------------------- +// Enable TCP socket 'reuse port' option when opening it as a 'listener'. +// Note: Can help when unable to open a socket because it wasn't properly +// released after a crash. +//------------------------------------------------------------------------------------------------- +#ifndef NETIMGUI_FORCE_TCP_LISTEN_BINDING +#define NETIMGUI_FORCE_TCP_LISTEN_BINDING \ + 0 // Doesn't seem to be needed on Window/Linux +#endif + +//------------------------------------------------------------------------------------------------- +// Enable Dear ImGui Callbacks support for BeginFrame/Render automatic +// interception. Note: Avoid having to replace ImGui::BeginFrame/ImGui::Render +// with in library user code, by +// 'NetImgui::NewFrame/NetImgui::EndFrame'. But prevent +//benefit of skipping frame draw when unneeded, that 'NetImgui::NewFrame' can +//provide. For more info, consult 'SampleNewFrame.cpp'. Needs Dear ImGui 1.81+ +//------------------------------------------------------------------------------------------------- +#ifndef NETIMGUI_IMGUI_CALLBACK_ENABLED +#define NETIMGUI_IMGUI_CALLBACK_ENABLED \ + (IMGUI_VERSION_NUM >= 18100) // Not supported pre Dear ImGui 1.81 +#endif + +namespace NetImgui { + +//================================================================================================= +// List of texture format supported +//================================================================================================= +enum eTexFormat { + // Match Dear Imgui 1.92 'ImTextureFormat' + kTexFmtRGBA8, + kTexFmtA8, + + // Support of 'user defined' texture format. + // Implementation must be added on both client and Server code. + // Search for TEXTURE_CUSTOM_SAMPLE for example implementation. + kTexFmtCustom, + + // + kTexFmt_Count, + kTexFmt_Invalid = kTexFmt_Count +}; + +//================================================================================================= +// Data Compression wanted status +//================================================================================================= +enum eCompressionMode { + kForceDisable, // Disable data compression for communications + kForceEnable, // Enable data compression for communications + kUseServerSetting // Use Server setting for compression (default) +}; + +//------------------------------------------------------------------------------------------------- +// Function typedefs +//------------------------------------------------------------------------------------------------- +typedef void (*ThreadFunctPtr)(void threadedFunction(void* pClientInfo), + void* pClientInfo); +typedef void (*FontCreateFuncPtr)(float PreviousDPIScale, float NewDPIScale); + +//================================================================================================= +// Initialize the Network Library +//================================================================================================= +NETIMGUI_API bool Startup(void); + +//================================================================================================= +// Free Resources +// Wait until all communication threads have terminated before returning +//================================================================================================= +NETIMGUI_API void Shutdown(); + +//================================================================================================= +// Establish a connection between the NetImgui server application and this +// client. +// +// Can connect with NetImgui Server application by either reaching it directly +// using 'ConnectToApp' or waiting for Server to reach us after Client called +// 'ConnectFromApp'. +// +// Note: Start a new communication thread using std::Thread by default, +// but can receive custom +// thread start function instead (Look at ClientExample +//'CustomCommunicationThread'). +//------------------------------------------------------------------------------------------------- +// clientName : Client name displayed in the Server's clients +// list serverHost : NetImgui Server Application address +// (Ex1: 127.0.0.2, Ex2: localhost) serverPort : PortID of the +// NetImgui Server application to connect to clientPort : PortID +// this Client should wait for connection from Server application threadFunction +// : User provided function to launch new networking thread. +// Use +//'DefaultStartCommunicationThread' by default (uses 'std::thread'). +// fontCreateFunction : User provided function to call when the Server expect +// an update of +// the font atlas, because of a +//monitor DPI change. When left to nullptr, uses 'ImGuiIO.FontGlobalScale' +//instead to increase text size, with blurier results. NOTE: Not used by Dear +//ImGui 1.92+, unneeded with font update support. +//================================================================================================= +NETIMGUI_API bool ConnectToApp(const char* clientName, const char* serverHost, + uint32_t serverPort = kDefaultServerPort, + ThreadFunctPtr threadFunction = 0, + FontCreateFuncPtr FontCreateFunction = 0); +NETIMGUI_API bool ConnectFromApp(const char* clientName, + uint32_t clientPort = kDefaultClientPort, + ThreadFunctPtr threadFunction = 0, + FontCreateFuncPtr fontCreateFunction = 0); + +//================================================================================================= +// Request a disconnect from the NetImguiServer application +//================================================================================================= +NETIMGUI_API void Disconnect(void); + +//================================================================================================= +// True if connected to the NetImguiServer application +//================================================================================================= +NETIMGUI_API bool IsConnected(void); + +//================================================================================================= +// True if connection request is waiting to be completed. For example, while +// waiting for Server to reach ud after having called 'ConnectFromApp()' +//================================================================================================= +NETIMGUI_API bool IsConnectionPending(void); + +//================================================================================================= +// True when Dear ImGui is currently expecting draw commands +// This means that we are between NewFrame() and EndFrame() +//================================================================================================= +NETIMGUI_API bool IsDrawing(void); + +//================================================================================================= +// True when we are currently drawing on the NetImguiServer application +// Means that we are between NewFrame() and EndFrame() of drawing for remote +// application +//================================================================================================= +NETIMGUI_API bool IsDrawingRemote(void); + +//================================================================================================= +// Send an updated texture used by imgui, to the NetImguiServer application +// Note: To remove a texture, set pData to nullptr +// Note: User needs to provide a valid 'dataSize' when using format +// 'kTexFmtCustom', +// can be ignored otherwise +// Note: Can now rely on native Dear ImGui managed texture support to let the +// system handle their +// creation/update/destruction automatically, without needing to +//call this function (since Dear ImGui 1.92+. See 'SampleTextures'). +//================================================================================================= +NETIMGUI_API void SendDataTexture(ImTextureID textureId, void* pData, + uint16_t width, uint16_t height, + eTexFormat format, uint32_t dataSize = 0); +#if NETIMGUI_IMGUI_TEXTURES_ENABLED +NETIMGUI_API void SendDataTexture(const ImTextureRef& textureRef, void* pData, + uint16_t width, uint16_t height, + eTexFormat format, uint32_t dataSize = 0); +#endif + +//================================================================================================= +// Start a new Imgui Frame and wait for Draws commands, using ImContext that was +// active on connect. Returns true if we are awaiting a new ImGui frame. +// +// All ImGui drawing should be skipped when return is false. +// +// Note: This code can be used instead, to know if you should be drawing or not +// : +// 'if( !NetImgui::IsDrawing() )' +// +// Note: If your code cannot handle skipping a ImGui frame, leave +// 'bSupportFrameSkip=false', +// and this function will always call 'ImGui::NewFrame()' +//internally and return true +// +// Note: With Dear ImGui 1.81+, you can keep using the +// ImGui::BeginFrame()/Imgui::Render() +// without having to use NetImgui::NewFrame()/NetImgui::EndFrame() +// (unless wanting to support frame skip) +//================================================================================================= +NETIMGUI_API bool NewFrame(bool bSupportFrameSkip = false); + +//================================================================================================= +// Process all receives draws, send them to remote connection and restore the +// ImGui Context +//================================================================================================= +NETIMGUI_API void EndFrame(void); + +//================================================================================================= +// Return the context associated to this remote connection. Null when not +// connected. +//================================================================================================= +NETIMGUI_API ImGuiContext* GetContext(); + +//================================================================================================= +// Set the remote client background color and texture +// Note: If no TextureID is specified, will use the default server texture +//================================================================================================= +NETIMGUI_API void SetBackground(const ImVec4& bgColor); +NETIMGUI_API void SetBackground(const ImVec4& bgColor, + const ImVec4& textureTint); +NETIMGUI_API void SetBackground(const ImVec4& bgColor, + const ImVec4& textureTint, + ImTextureID bgTextureID); +#if NETIMGUI_IMGUI_TEXTURES_ENABLED +NETIMGUI_API void SetBackground(const ImVec4& bgColor, + const ImVec4& textureTint, + const ImTextureRef& bgTextureRef); +#endif + +//================================================================================================= +// Control the data compression for communications between Client/Server +//================================================================================================= +NETIMGUI_API void SetCompressionMode(eCompressionMode eMode); +NETIMGUI_API eCompressionMode GetCompressionMode(); + +//================================================================================================= +// Helper functions +//================================================================================================= +NETIMGUI_API uint8_t GetTexture_BitsPerPixel(eTexFormat eFormat); +NETIMGUI_API uint32_t GetTexture_BytePerLine(eTexFormat eFormat, + uint32_t pixelWidth); +NETIMGUI_API uint32_t GetTexture_BytePerImage(eTexFormat eFormat, + uint32_t pixelWidth, + uint32_t pixelHeight); +} // namespace NetImgui + +//================================================================================================= +// Optional single include compiling option +// Note: User wanting to avoid adding the few NetImgui sources files to their +// project, +// can instead define 'NETIMGUI_IMPLEMENTATION' *once* before +//including 'NetImgui_Api.h' to pull all the needed cpp files alongside for +//compilation +//================================================================================================= +#if defined(NETIMGUI_IMPLEMENTATION) +#include "Private/NetImgui_Api.cpp" +#include "Private/NetImgui_Client.cpp" +#include "Private/NetImgui_CmdPackets_DrawFrame.cpp" +#include "Private/NetImgui_NetworkPosix.cpp" +#include "Private/NetImgui_NetworkUE4.cpp" +#include "Private/NetImgui_NetworkWin32.cpp" +#endif + +#endif // NETIMGUI_ENABLED + +//------------------------------------------------------------------------------------------------- +// Re-Enable the Deactivated warnings +//------------------------------------------------------------------------------------------------- +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/python/mujoco/experimental/netimgui/Code/Client/NetImgui_Config.h b/python/mujoco/experimental/netimgui/Code/Client/NetImgui_Config.h new file mode 100644 index 00000000..c5621528 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/NetImgui_Config.h @@ -0,0 +1,71 @@ +#pragma once + +//================================================================================================= +// Enable code compilation for this library +// Note: Useful to disable 'netImgui' on unsupported builds while keeping +// functions declared +//================================================================================================= +#ifndef NETIMGUI_ENABLED +#define NETIMGUI_ENABLED 1 +#endif + +#if NETIMGUI_ENABLED + +#include + +#ifdef NETIMGUI_INTERNAL_INCLUDE +#include // Only needed when compiling NetImgui, not when using the NetImgui Api + +#include "Private/NetImgui_WarningDisableImgui.h" // Disable some extra warning generated by imgui_internal in '-Wall' +#include "Private/NetImgui_WarningReenable.h" +#endif + +#endif // NETIMGUI_ENABLED + +//================================================================================================= +// Default Ports used to reach the Server or the Client (listen port for +// incoming connection) +//================================================================================================= +namespace NetImgui { +enum Constants { + kDefaultServerPort = 8888, //!< Default port Server waits for a connection + kDefaultClientPort = 8889 //!< Default port Client waits for a connection +}; +} + +//================================================================================================= +// Enable default Win32/Posix networking code +// Note: By default, netImgui uses Winsock on Windows and Posix sockets +// on other platforms +// +// The use your own code, turn off both +//NETIMGUI_WINSOCKET_ENABLED, NETIMGUI_POSIX_SOCKETS_ENABLED and provide your +//own implementation of the functions declared in 'NetImgui_Network.h'. +// +// As an example, 'SampleCompression' disable default com +//implementation and use its own +//================================================================================================= +#if !defined(NETIMGUI_WINSOCKET_ENABLED) && !defined(__UNREAL__) +#ifdef _WIN32 +#define NETIMGUI_WINSOCKET_ENABLED \ + 1 // Project needs 'ws2_32.lib' added to input libraries +#else +#define NETIMGUI_WINSOCKET_ENABLED 0 +#endif +#endif + +#if !defined(NETIMGUI_POSIX_SOCKETS_ENABLED) && !defined(__UNREAL__) +#define NETIMGUI_POSIX_SOCKETS_ENABLED !(NETIMGUI_WINSOCKET_ENABLED) +#endif + +//================================================================================================= +// Various build settings define +// Note: for more information, please look in 'NetImgui_Api.h' for description +// and default values +//================================================================================================= +// #define NETIMGUI_IMGUI_CALLBACK_ENABLED (IMGUI_VERSION_NUM >= +// 18100) // Not supported pre Dear ImGui 1.81 #define +// NETIMGUI_FORCE_TCP_LISTEN_BINDING 0 +// // Doesn't seem to be needed on Window/Linux #define NETIMGUI_API +// IMGUI_API // Use same value as +// defined by Dear ImGui by default diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Api.cpp b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Api.cpp new file mode 100644 index 00000000..aeb8f310 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Api.cpp @@ -0,0 +1,948 @@ +// Google modifications: +// - Adding missing headers. +// - Added logging for network events. +#include "NetImgui_Shared.h" +#include "NetImgui_WarningDisable.h" + +#if NETIMGUI_ENABLED +#include +#include +#include +#include + +#include +#include + +#include "NetImgui_Client.h" +#include "NetImgui_CmdPackets.h" +#include "NetImgui_Network.h" +#include "google/logging.h" + +using namespace NetImgui::Internal; + +namespace NetImgui { + +static Client::ClientInfo* gpClientInfo = nullptr; + +bool ProcessInputData(Client::ClientInfo& client); + +//================================================================================================= +void DefaultStartCommunicationThread(void ComFunctPtr(void*), void* pClient) +//================================================================================================= +{ +// Visual Studio 2017 generate this warning on std::thread, avoid the warning +// preventing build +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#pragma warning(push) +#pragma warning(disable \ + : 4625) // 'std::_LaunchPad<_Target>' : copy constructor was + // implicitly defined as deleted +#pragma warning(disable : 4626) // 'std::_LaunchPad<_Target>' : assignment + // operator was implicitly defined as deleted +#endif + + std::thread(ComFunctPtr, pClient).detach(); + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#pragma warning(pop) +#endif +} + +//================================================================================================= +bool ConnectToApp(const char* clientName, const char* ServerHost, + uint32_t serverPort, ThreadFunctPtr threadFunction, + FontCreateFuncPtr FontCreateFunction) +//================================================================================================= +{ + if (!gpClientInfo) return false; + + Client::ClientInfo& client = *gpClientInfo; + Disconnect(); + + while (client.IsActive()) std::this_thread::yield(); + + client.ContextRestore(); // Restore context setting override, after a + // disconnect + client.ContextRemoveHooks(); // Remove hooks callback only when completely + // disconnected + + StringCopy( + client.mName, + (clientName == nullptr || clientName[0] == 0 ? "Unnamed" : clientName)); + client.mpSocketPending = Network::Connect(ServerHost, serverPort); +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + IM_UNUSED(FontCreateFunction); +#else + client.mFontCreationFunction = FontCreateFunction; +#endif + if (client.mpSocketPending.load() != nullptr) { + client.ContextInitialize(); + threadFunction = threadFunction == nullptr ? DefaultStartCommunicationThread + : threadFunction; + threadFunction(Client::CommunicationsConnect, &client); + } + + return client.IsActive(); +} + +//================================================================================================= +bool ConnectFromApp(const char* clientName, uint32_t serverPort, + ThreadFunctPtr threadFunction, + FontCreateFuncPtr FontCreateFunction) +//================================================================================================= +{ + if (!gpClientInfo) return false; + + Client::ClientInfo& client = *gpClientInfo; + Disconnect(); + + while (client.IsActive()) std::this_thread::yield(); + + client.ContextRestore(); // Restore context setting override, after a + // disconnect + client.ContextRemoveHooks(); // Remove hooks callback only when completly + // disconnected + + StringCopy( + client.mName, + (clientName == nullptr || clientName[0] == 0 ? "Unnamed" : clientName)); + client.mpSocketPending = Network::ListenStart(serverPort); +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + IM_UNUSED(FontCreateFunction); +#else + client.mFontCreationFunction = FontCreateFunction; +#endif + client.mThreadFunction = (threadFunction == nullptr) + ? DefaultStartCommunicationThread + : threadFunction; + if (client.mpSocketPending.load() != nullptr) { + client.ContextInitialize(); + client.mSocketListenPort = serverPort; + client.mThreadFunction(Client::CommunicationsHost, &client); + } + + return client.IsActive(); +} + +//================================================================================================= +void Disconnect(void) +//================================================================================================= +{ + if (!gpClientInfo) return; + + // Attempt fake connection on local socket waiting for a Server connection, + // so the blocking operation can terminate and release the communication + // thread + Client::ClientInfo& client = *gpClientInfo; + client.mbDisconnectPending = true; + client.mbDisconnectListen = true; + if (client.mpSocketListen.load() != nullptr && + client.mSocketListenPort != 0) { + Network::SocketInfo* pFakeSocket = + Network::Connect("127.0.0.1", client.mSocketListenPort); + client.mSocketListenPort = 0; + client.mbDisconnectPending = true; + + if (pFakeSocket) { + Network::Disconnect(pFakeSocket); + } + } + + // Wait for connection attempt to complete and fail + while (client.mbComInitActive || client.mbClientThreadActive); + + // If fake connection to exit Listening failed, force disconnect socket + // directly even though it might potentially cause a race condition + Network::SocketInfo* pListenSocket = client.mpSocketListen.exchange(nullptr); + if (pListenSocket) { + Network::Disconnect(pListenSocket); + } + + Network::SocketInfo* pPendingSocket = + client.mpSocketPending.exchange(nullptr); + if (pPendingSocket) { + Network::Disconnect(pPendingSocket); + } +} + +//================================================================================================= +bool IsConnected(void) +//================================================================================================= +{ + if (!gpClientInfo) return false; + + Client::ClientInfo& client = *gpClientInfo; + + // If disconnected in middle of a remote frame drawing, + // want to behave like it is still connected to finish frame properly + return client.IsConnected() || IsDrawingRemote(); +} + +//================================================================================================= +bool IsConnectionPending(void) +//================================================================================================= +{ + if (!gpClientInfo) return false; + + Client::ClientInfo& client = *gpClientInfo; + return client.IsConnectPending(); +} + +//================================================================================================= +bool IsDrawing(void) +//================================================================================================= +{ + if (!gpClientInfo) return false; + + Client::ClientInfo& client = *gpClientInfo; + return client.mbIsDrawing; +} + +//================================================================================================= +bool IsDrawingRemote(void) +//================================================================================================= +{ + if (!gpClientInfo) return false; + + Client::ClientInfo& client = *gpClientInfo; + return IsDrawing() && client.mbIsRemoteDrawing; +} + +//================================================================================================= +bool NewFrame(bool bSupportFrameSkip) +//================================================================================================= +{ + if (!gpClientInfo || gpClientInfo->mbIsDrawing) return false; + + Client::ClientInfo& client = *gpClientInfo; + ScopedBool scopedInside(client.mbInsideNewEnd, true); + + // ImGui Newframe handled by remote connection settings + if (NetImgui::IsConnected()) { + ImGui::SetCurrentContext(client.mpContext); + + // Save current context settings and override settings to fit our netImgui + // usage + if (!client.IsContextOverriden()) { + client.ContextOverride(); + } + + auto elapsedCheck = + std::chrono::steady_clock::now() - client.mLastOutgoingDrawCheckTime; + auto elapsedDraw = + std::chrono::steady_clock::now() - client.mLastOutgoingDrawTime; + auto elapsedCheckMs = + static_cast( + std::chrono::duration_cast(elapsedCheck) + .count()) / + 1000.f; + auto elapsedDrawMs = + static_cast( + std::chrono::duration_cast(elapsedDraw) + .count()) / + 1000.f; + client.mLastOutgoingDrawCheckTime = std::chrono::steady_clock::now(); + + // Update input and see if remote netImgui expect a new frame + client.mbValidDrawFrame = false; + + // Take into account delay until next method call, for more precise fps + bool shouldDraw = + client.mDesiredFps > 0.f && + (elapsedDrawMs + elapsedCheckMs / 2.f) > (1000.f / client.mDesiredFps); + + VLOG(2, + "NewFrame: elapsedDrawMs=%.2f, elapsedCheckMs=%.2f, shouldDraw=%s, " + "mDesiredFps=%.1f (target=%.1f)", + elapsedDrawMs, elapsedCheckMs, shouldDraw ? "Y" : "N", + client.mDesiredFps, 1000.f / client.mDesiredFps); + + if (shouldDraw) { + VLOG(2, "NewFrame: shouldDraw=Y, triggering draw!"); + + client.mLastOutgoingDrawTime = std::chrono::steady_clock::now(); + client.mbValidDrawFrame = true; + client.mSavedDisplaySize = ImGui::GetIO().DisplaySize; + +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + client.mFontSavedScaling = ImGui::GetStyle().FontScaleDpi; + ImGui::GetStyle().FontScaleDpi = client.mFontServerScale; +#else + // We are about to start drawing for remote context, check for font data + // update + const ImFontAtlas* pFonts = ImGui::GetIO().Fonts; + if (pFonts->TexPixelsAlpha8 && + (pFonts->TexPixelsAlpha8 != client.mpFontTextureData || + client.mFontTextureID != ConvertToClientTexID(pFonts->TexID))) { + uint8_t* pPixelData(nullptr); + int width(0), height(0); + ImGui::GetIO().Fonts->GetTexDataAsAlpha8(&pPixelData, &width, &height); + SendDataTexture(pFonts->TexID, pPixelData, static_cast(width), + static_cast(height), eTexFormat::kTexFmtA8); + } + // No font texture has been sent to the netImgui server, you can either + // 1. Leave font data available in ImGui (not call ImGui::ClearTexData) + // for netImgui to auto send it + // 2. Manually call 'NetImgui::SendDataTexture' with font texture data + assert(client.mbFontUploaded); +#endif + } + + ProcessInputData(client); + + // Update current active content with our time + ImGui::GetIO().DeltaTime = + std::max(1.f / 1000.f, elapsedCheckMs / 1000.f); + + // NetImgui isn't waiting for a new frame, try to skip drawing when caller + // supports it + if (!client.mbValidDrawFrame && bSupportFrameSkip) { + return false; + } + } + // Regular Imgui NewFrame + else { + // Restore context setting override, after a disconnect + client.ContextRestore(); + + // Remove hooks callback only when completly disconnected + if (!client.IsConnectPending()) { + client.ContextRemoveHooks(); + } + } + + // A new frame is expected, update the current time of the drawing context, + // and let Imgui know to prepare a new drawing frame + client.mbIsRemoteDrawing = NetImgui::IsConnected(); + client.mbIsDrawing = true; + + // Reset Dear ImGui managed Textures status if not handled by backend, to not + // re-process the same elements (active on 1.92+) + client.TextureTrackingClear(); + + // This function can be called from a 'NewFrame' ImGui hook, we should not + // start a new frame again + if (!client.mbInsideHook) { + ImGui::NewFrame(); + } + + return true; +} + +//================================================================================================= +void EndFrame(void) +//================================================================================================= +{ + if (!gpClientInfo) return; + + Client::ClientInfo& client = *gpClientInfo; + ScopedBool scopedInside(client.mbInsideNewEnd, true); + + if (client.mbIsDrawing) { + // Must be fetched before 'Render' + ImGuiMouseCursor Cursor = ImGui::GetMouseCursor(); + + // This function can be called from a 'EndFrame' ImGui hook, in which case + // no need to call this again + if (!client.mbInsideHook) { + ImGui::Render(); + } + + // Detect all DearImgui ImGui managed Textures waiting for updates before + // backend process them (active on 1.92+) + client.TextureTrackingUpdate(); + + // Prepare the Dear Imgui DrawData for later transmission to Server + ImDrawData* imDrawData = ImGui::GetDrawData(); + client.ProcessDrawData(imDrawData, Cursor); + + // Detect change to background settings by user, and forward them to server + if (client.mBGSetting != client.mBGSettingSent) { + CmdBackground* pCmdBackground = netImguiNew(); + *pCmdBackground = client.mBGSetting; + client.mBGSettingSent = client.mBGSetting; + client.mPendingBackgroundOut.Assign(pCmdBackground); + } + + if (client.mbIsRemoteDrawing) { +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + // Clear the ImGui Draw Data while leaving the texture updates intact + // This allows the backend to process the texture updates/status normally + // (usually done in Render backend implementation) while not displaying + // anything. + if (imDrawData) { + imDrawData->CmdLists.resize(0); + imDrawData->CmdListsCount = 0; + imDrawData->TotalIdxCount = 0; + imDrawData->TotalVtxCount = 0; + } + ImGui::GetStyle().FontScaleDpi = client.mFontSavedScaling; +#endif + // Restore display size, so we never lose original setting + // that may get updated after initial connection + ImGui::GetIO().DisplaySize = client.mSavedDisplaySize; + } + } + + VLOG(2, "EndFrame: mbIsDrawing was %s, mbIsRemoteDrawing was %s", + client.mbIsDrawing ? "Y" : "N", client.mbIsRemoteDrawing ? "Y" : "N"); + + client.mbIsRemoteDrawing = false; + client.mbIsDrawing = false; + client.mbValidDrawFrame = false; +} + +//================================================================================================= +ImGuiContext* GetContext() +//================================================================================================= +{ + if (!gpClientInfo) return nullptr; + + Client::ClientInfo& client = *gpClientInfo; + return client.mpContext; +} + +//================================================================================================= +void SendDataTexture(ImTextureID textureId, void* pData, uint16_t width, + uint16_t height, eTexFormat format, uint32_t dataSize) +//================================================================================================= +{ + if (!gpClientInfo) return; + Client::ClientInfo& client = *gpClientInfo; + ClientTextureID clientTexID = ConvertToClientTexID(textureId); + + // Add/Update a texture + if (pData != nullptr) { + CmdTexture* pCmdTexture = + client.TextureCmdAllocate(clientTexID, width, height, format, dataSize); + if (pCmdTexture) { + memcpy(pCmdTexture->mpTextureData.Get(), pData, dataSize); + pCmdTexture->mpTextureData.ToOffset(); + client.TextureTrackingAdd(*pCmdTexture); + + // Detects when user is sending the font texture +#if !NETIMGUI_IMGUI_TEXTURES_ENABLED + ScopedImguiContext scopedCtx( + client.mpContext ? client.mpContext : ImGui::GetCurrentContext()); + if (ImGui::GetIO().Fonts && ImGui::GetIO().Fonts->TexID == textureId) { + client.mbFontUploaded |= true; + client.mpFontTextureData = ImGui::GetIO().Fonts->TexPixelsAlpha8; + client.mFontTextureID = clientTexID; + } +#endif + } + } + // Texture to remove + else { + client.TextureTrackingRem(clientTexID); + } +} + +#if NETIMGUI_IMGUI_TEXTURES_ENABLED +//================================================================================================= +void SendDataTexture(const ImTextureRef& textureRef, void* pData, + uint16_t width, uint16_t height, eTexFormat format, + uint32_t dataSize) +//================================================================================================= +{ + if (!gpClientInfo) return; + Client::ClientInfo& client = *gpClientInfo; + ClientTextureID clientTexID = ConvertToClientTexID(textureRef); + + // Add/Update a texture + if (pData != nullptr) { + CmdTexture* pCmdTexture = + client.TextureCmdAllocate(clientTexID, width, height, format, dataSize); + if (pCmdTexture) { + memcpy(pCmdTexture->mpTextureData.Get(), pData, dataSize); + pCmdTexture->mpTextureData.ToOffset(); + client.TextureTrackingAdd(*pCmdTexture); + } + } + // Texture to remove + else { + client.TextureTrackingRem(clientTexID); + } +} +#endif // NETIMGUI_IMGUI_TEXTURES_ENABLED + +//================================================================================================= +void SetBackground(const ImVec4& bgColor) +//================================================================================================= +{ + if (!gpClientInfo) return; + + Client::ClientInfo& client = *gpClientInfo; + client.mBGSetting = NetImgui::Internal::CmdBackground(); + client.mBGSetting.mClearColor[0] = bgColor.x; + client.mBGSetting.mClearColor[1] = bgColor.y; + client.mBGSetting.mClearColor[2] = bgColor.z; + client.mBGSetting.mClearColor[3] = bgColor.w; +} + +//================================================================================================= +void SetBackground(const ImVec4& bgColor, const ImVec4& textureTint) +//================================================================================================= +{ + if (!gpClientInfo) return; + + Client::ClientInfo& client = *gpClientInfo; + client.mBGSetting.mClearColor[0] = bgColor.x; + client.mBGSetting.mClearColor[1] = bgColor.y; + client.mBGSetting.mClearColor[2] = bgColor.z; + client.mBGSetting.mClearColor[3] = bgColor.w; + client.mBGSetting.mTextureTint[0] = textureTint.x; + client.mBGSetting.mTextureTint[1] = textureTint.y; + client.mBGSetting.mTextureTint[2] = textureTint.z; + client.mBGSetting.mTextureTint[3] = textureTint.w; + client.mBGSetting.mTextureId = + NetImgui::Internal::CmdBackground::kDefaultTexture; +} + +//================================================================================================= +void SetBackground(const ImVec4& bgColor, const ImVec4& textureTint, + ImTextureID bgTextureID) +//================================================================================================= +{ + if (!gpClientInfo) return; + + Client::ClientInfo& client = *gpClientInfo; + client.mBGSetting.mClearColor[0] = bgColor.x; + client.mBGSetting.mClearColor[1] = bgColor.y; + client.mBGSetting.mClearColor[2] = bgColor.z; + client.mBGSetting.mClearColor[3] = bgColor.w; + client.mBGSetting.mTextureTint[0] = textureTint.x; + client.mBGSetting.mTextureTint[1] = textureTint.y; + client.mBGSetting.mTextureTint[2] = textureTint.z; + client.mBGSetting.mTextureTint[3] = textureTint.w; + + uint64_t texId64(0); + reinterpret_cast(&texId64)[0] = bgTextureID; + client.mBGSetting.mTextureId = texId64; +} + +#if NETIMGUI_IMGUI_TEXTURES_ENABLED +//================================================================================================= +void SetBackground(const ImVec4& bgColor, const ImVec4& textureTint, + const ImTextureRef& bgTextureRef) +//================================================================================================= +{ + SetBackground(bgColor, textureTint, ConvertToClientTexID(bgTextureRef)); +} +#endif + +//================================================================================================= +void SetCompressionMode(eCompressionMode eMode) +//================================================================================================= +{ + if (!gpClientInfo) return; + + Client::ClientInfo& client = *gpClientInfo; + client.mClientCompressionMode = static_cast(eMode); +} +//================================================================================================= +eCompressionMode GetCompressionMode() +//================================================================================================= +{ + if (!gpClientInfo) return eCompressionMode::kUseServerSetting; + + Client::ClientInfo& client = *gpClientInfo; + return static_cast(client.mClientCompressionMode); +} + +//================================================================================================= +bool Startup(void) +//================================================================================================= +{ + if (!gpClientInfo) { + gpClientInfo = netImguiNew(); + } + + return Network::Startup(); +} + +//================================================================================================= +void Shutdown() +//================================================================================================= +{ + if (!gpClientInfo) return; + + Disconnect(); + while (gpClientInfo->IsActive()) std::this_thread::yield(); + Network::Shutdown(); + + netImguiDeleteSafe(gpClientInfo); +} + +//================================================================================================= +ImGuiContext* CloneContext(ImGuiContext* pSourceContext) +//================================================================================================= +{ + // Create a context duplicate + ScopedImguiContext scopedSourceCtx(pSourceContext); + ImGuiContext* pContextClone = ImGui::CreateContext(ImGui::GetIO().Fonts); + ImGuiIO& sourceIO = ImGui::GetIO(); + ImGuiStyle& sourceStyle = ImGui::GetStyle(); + { + ScopedImguiContext scopedCloneCtx(pContextClone); + ImGuiIO& newIO = ImGui::GetIO(); + ImGuiStyle& newStyle = ImGui::GetStyle(); + + // Import the style/options settings of current context, into this one + memcpy(&newStyle, &sourceStyle, sizeof(newStyle)); + memcpy(&newIO, &sourceIO, sizeof(newIO)); + // memcpy(newIO.KeyMap, sourceIO.KeyMap, sizeof(newIO.KeyMap)); + newIO.InputQueueCharacters.Data = nullptr; + newIO.InputQueueCharacters.Size = 0; + newIO.InputQueueCharacters.Capacity = 0; + } + return pContextClone; +} + +//================================================================================================= +uint8_t GetTexture_BitsPerPixel(eTexFormat eFormat) +//================================================================================================= +{ + switch (eFormat) { + case eTexFormat::kTexFmtA8: + return 8 * 1; + case eTexFormat::kTexFmtRGBA8: + return 8 * 4; + case eTexFormat::kTexFmtCustom: + return 0; + case eTexFormat::kTexFmt_Invalid: + return 0; + } + return 0; +} + +//================================================================================================= +uint32_t GetTexture_BytePerLine(eTexFormat eFormat, uint32_t pixelWidth) +//================================================================================================= +{ + uint32_t bitsPerPixel = + static_cast(GetTexture_BitsPerPixel(eFormat)); + return pixelWidth * bitsPerPixel / 8; + // Note: If adding support to BC compression format, have to take into account + // 4x4 size alignment +} + +//================================================================================================= +uint32_t GetTexture_BytePerImage(eTexFormat eFormat, uint32_t pixelWidth, + uint32_t pixelHeight) +//================================================================================================= +{ + return GetTexture_BytePerLine(eFormat, pixelWidth) * pixelHeight; + // Note: If adding support to BC compression format, have to take into account + // 4x4 size alignement +} + +static inline void AddKeyEvent(const Client::ClientInfo& client, + const CmdInput* pCmdInput, + CmdInput::NetImguiKeys netimguiKey, + ImGuiKey imguiKey) { + uint32_t valIndex = netimguiKey / 64; + uint64_t valMask = 0x0000000000000001ull << (netimguiKey % 64); +#if IMGUI_VERSION_NUM < 18700 + IM_UNUSED(client); + ImGui::GetIO().KeysDown[imguiKey] = + (pCmdInput->mInputDownMask[valIndex] & valMask) != 0; +#else + bool bChanged = (pCmdInput->mInputDownMask[valIndex] ^ + client.mPreviousInputState.mInputDownMask[valIndex]) & + valMask; + if (bChanged) { + ImGui::GetIO().AddKeyEvent(imguiKey, + pCmdInput->mInputDownMask[valIndex] & valMask); + } +#endif +} + +static inline void AddKeyAnalogEvent(const Client::ClientInfo& client, + const CmdInput* pCmdInput, + CmdInput::NetImguiKeys netimguiKey, + ImGuiKey imguiKey) { + uint32_t valIndex = netimguiKey / 64; + uint64_t valMask = 0x0000000000000001ull << (netimguiKey % 64); + assert(CmdInput::kAnalog_First <= static_cast(netimguiKey) && + static_cast(netimguiKey) <= CmdInput::kAnalog_Last); +#if IMGUI_VERSION_NUM < 18700 + IM_UNUSED(client); + IM_UNUSED(pCmdInput); + IM_UNUSED(netimguiKey); + IM_UNUSED(imguiKey); +#else + int indexAnalog = netimguiKey - CmdInput::kAnalog_First; + indexAnalog = indexAnalog >= static_cast(CmdInput::kAnalog_Count) + ? CmdInput::kAnalog_Count - 1 + : indexAnalog; + float analogValue = pCmdInput->mInputAnalog[indexAnalog]; + bool bChanged = (pCmdInput->mInputDownMask[valIndex] ^ + client.mPreviousInputState.mInputDownMask[valIndex]) & + valMask; + bChanged |= abs(client.mPreviousInputState.mInputAnalog[indexAnalog] - + analogValue) > 0.001f; + if (bChanged) { + ImGui::GetIO().AddKeyAnalogEvent( + imguiKey, pCmdInput->mInputDownMask[valIndex] & valMask, analogValue); + } +#endif +} + +//================================================================================================= +bool ProcessInputData(Client::ClientInfo& client) +//================================================================================================= +{ + // Update the current clipboard data received from Server + CmdClipboard* pCmdClipboardNew = client.mPendingClipboardIn.Release(); + if (pCmdClipboardNew) { + netImguiDeleteSafe(client.mpCmdClipboard); + client.mpCmdClipboard = pCmdClipboardNew; + } + + // Update the keyboard/mouse/gamepad inputs + CmdInput* pCmdInputNew = client.mPendingInputIn.Release(); + bool hasNewInput = pCmdInputNew != nullptr; + CmdInput* pCmdInput = hasNewInput ? pCmdInputNew : client.mpCmdInputPending; + ImGuiIO& io = ImGui::GetIO(); + + if (pCmdInput) { + const float wheelY = pCmdInput->mMouseWheelVert - + client.mPreviousInputState.mMouseWheelVertPrev; + const float wheelX = pCmdInput->mMouseWheelHoriz - + client.mPreviousInputState.mMouseWheelHorizPrev; + io.DisplaySize = + ImVec2(pCmdInput->mScreenSize[0], pCmdInput->mScreenSize[1]); +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + client.mFontServerScale = pCmdInput->mFontDPIScaling; +#else + // User assigned a function callback handling FontScaling, + // use it to request a Font update on DPI scaling change on the server + if (gpClientInfo->mFontCreationFunction != nullptr) { + io.FontGlobalScale = 1.f; + if (abs(gpClientInfo->mFontServerScale - pCmdInput->mFontDPIScaling) > + 0.01f) { + gpClientInfo->mFontCreationFunction(gpClientInfo->mFontSavedScaling, + pCmdInput->mFontDPIScaling); + client.mFontServerScale = pCmdInput->mFontDPIScaling; + } + } + // Client doesn't support regenerating the font at new DPI + // Use FontGlobalScale to affect rendering size, resulting in blurrier + // result + else { + io.FontGlobalScale = pCmdInput->mFontDPIScaling; + } +#endif + +#if IMGUI_VERSION_NUM < 18700 + io.MousePos = ImVec2(pCmdInput->mMousePos[0], pCmdInput->mMousePos[1]); + io.MouseWheel = wheelY; + io.MouseWheelH = wheelX; + for (uint32_t i(0); + i < CmdInput::NetImguiMouseButton::ImGuiMouseButton_COUNT; ++i) { + io.MouseDown[i] = + (pCmdInput->mMouseDownMask & (0x0000000000000001ull << i)) != 0; + } + +#define AddInputDown(KEYNAME) \ + AddKeyEvent(client, pCmdInput, CmdInput::KEYNAME, ImGuiKey_::KEYNAME); + AddInputDown(ImGuiKey_Tab) AddInputDown(ImGuiKey_LeftArrow) AddInputDown( + ImGuiKey_RightArrow) AddInputDown(ImGuiKey_UpArrow) + AddInputDown(ImGuiKey_DownArrow) AddInputDown(ImGuiKey_PageUp) + AddInputDown(ImGuiKey_PageDown) AddInputDown(ImGuiKey_Home) + AddInputDown(ImGuiKey_End) AddInputDown(ImGuiKey_Insert) + AddInputDown(ImGuiKey_Delete) AddInputDown( + ImGuiKey_Backspace) AddInputDown(ImGuiKey_Space) + AddInputDown(ImGuiKey_Enter) + AddInputDown(ImGuiKey_Escape) AddInputDown( + ImGuiKey_A) // for text edit CTRL+A: select all + AddInputDown(ImGuiKey_C) // for text edit CTRL+C: copy + AddInputDown(ImGuiKey_V) // for text edit CTRL+V: paste + AddInputDown(ImGuiKey_X) // for text edit CTRL+X: cut + AddInputDown(ImGuiKey_Y) // for text edit CTRL+Y: redo + AddInputDown(ImGuiKey_Z) // for text edit CTRL+Z: undo + + io.KeyShift = pCmdInput->IsKeyDown( + CmdInput::NetImguiKeys::ImGuiKey_ReservedForModShift); + io.KeyCtrl = pCmdInput->IsKeyDown( + CmdInput::NetImguiKeys::ImGuiKey_ReservedForModCtrl); + io.KeyAlt = pCmdInput->IsKeyDown( + CmdInput::NetImguiKeys::ImGuiKey_ReservedForModAlt); + io.KeySuper = pCmdInput->IsKeyDown( + CmdInput::NetImguiKeys::ImGuiKey_ReservedForModSuper); +#else +#if IMGUI_VERSION_NUM < 18837 +#define ImGuiKey ImGuiKey_ +#endif +// At the moment All Dear Imgui version share the same ImGuiKey_ enum (with a +// 512 value offset), but could change in the future, so convert from our own +// enum version, to Dear ImGui. +#define AddInputDown(KEYNAME) \ + AddKeyEvent(client, pCmdInput, CmdInput::KEYNAME, ImGuiKey::KEYNAME); +#define AddAnalogInputDown(KEYNAME) \ + AddKeyAnalogEvent(client, pCmdInput, CmdInput::KEYNAME, ImGuiKey::KEYNAME); + AddInputDown(ImGuiKey_Tab) AddInputDown(ImGuiKey_LeftArrow) AddInputDown( + ImGuiKey_RightArrow) AddInputDown(ImGuiKey_UpArrow) AddInputDown(ImGuiKey_DownArrow) + AddInputDown(ImGuiKey_PageUp) AddInputDown(ImGuiKey_PageDown) AddInputDown( + ImGuiKey_Home) AddInputDown(ImGuiKey_End) AddInputDown(ImGuiKey_Insert) + AddInputDown(ImGuiKey_Delete) AddInputDown(ImGuiKey_Backspace) AddInputDown( + ImGuiKey_Space) AddInputDown(ImGuiKey_Enter) AddInputDown(ImGuiKey_Escape) + + AddInputDown(ImGuiKey_LeftCtrl) AddInputDown(ImGuiKey_LeftShift) AddInputDown( + ImGuiKey_LeftAlt) AddInputDown(ImGuiKey_LeftSuper) AddInputDown(ImGuiKey_RightCtrl) + AddInputDown(ImGuiKey_RightShift) AddInputDown(ImGuiKey_RightAlt) AddInputDown( + ImGuiKey_RightSuper) AddInputDown(ImGuiKey_Menu) AddInputDown(ImGuiKey_0) + AddInputDown(ImGuiKey_1) AddInputDown(ImGuiKey_2) AddInputDown(ImGuiKey_3) AddInputDown( + ImGuiKey_4) AddInputDown(ImGuiKey_5) AddInputDown(ImGuiKey_6) + AddInputDown(ImGuiKey_7) AddInputDown(ImGuiKey_8) AddInputDown( + ImGuiKey_9) AddInputDown(ImGuiKey_A) AddInputDown(ImGuiKey_B) + AddInputDown(ImGuiKey_C) AddInputDown(ImGuiKey_D) AddInputDown( + ImGuiKey_E) AddInputDown(ImGuiKey_F) AddInputDown(ImGuiKey_G) + AddInputDown(ImGuiKey_H) AddInputDown(ImGuiKey_I) AddInputDown( + ImGuiKey_J) AddInputDown(ImGuiKey_K) AddInputDown(ImGuiKey_L) + AddInputDown(ImGuiKey_M) AddInputDown(ImGuiKey_N) AddInputDown( + ImGuiKey_O) AddInputDown(ImGuiKey_P) AddInputDown(ImGuiKey_Q) + AddInputDown(ImGuiKey_R) AddInputDown(ImGuiKey_S) AddInputDown( + ImGuiKey_T) AddInputDown(ImGuiKey_U) AddInputDown(ImGuiKey_V) + AddInputDown(ImGuiKey_W) AddInputDown(ImGuiKey_X) AddInputDown( + ImGuiKey_Y) AddInputDown(ImGuiKey_Z) + AddInputDown(ImGuiKey_F1) AddInputDown( + ImGuiKey_F2) AddInputDown(ImGuiKey_F3) + AddInputDown(ImGuiKey_F4) AddInputDown( + ImGuiKey_F5) AddInputDown(ImGuiKey_F6) + AddInputDown(ImGuiKey_F7) AddInputDown( + ImGuiKey_F8) AddInputDown(ImGuiKey_F9) + AddInputDown(ImGuiKey_F10) AddInputDown( + ImGuiKey_F11) AddInputDown(ImGuiKey_F12) + + AddInputDown(ImGuiKey_Apostrophe) AddInputDown( + ImGuiKey_Comma) AddInputDown(ImGuiKey_Minus) + AddInputDown(ImGuiKey_Period) AddInputDown( + ImGuiKey_Slash) AddInputDown(ImGuiKey_Semicolon) + AddInputDown( + ImGuiKey_Equal) + AddInputDown( + ImGuiKey_LeftBracket) + AddInputDown( + ImGuiKey_Backslash) + AddInputDown(ImGuiKey_RightBracket) AddInputDown(ImGuiKey_GraveAccent) AddInputDown(ImGuiKey_CapsLock) AddInputDown(ImGuiKey_ScrollLock) AddInputDown(ImGuiKey_NumLock) AddInputDown(ImGuiKey_PrintScreen) AddInputDown(ImGuiKey_Pause) AddInputDown(ImGuiKey_Keypad0) AddInputDown(ImGuiKey_Keypad1) AddInputDown(ImGuiKey_Keypad2) AddInputDown(ImGuiKey_Keypad3) AddInputDown(ImGuiKey_Keypad4) AddInputDown(ImGuiKey_Keypad5) AddInputDown(ImGuiKey_Keypad6) AddInputDown(ImGuiKey_Keypad7) + AddInputDown(ImGuiKey_Keypad8) AddInputDown(ImGuiKey_Keypad9) AddInputDown(ImGuiKey_KeypadDecimal) AddInputDown(ImGuiKey_KeypadDivide) AddInputDown(ImGuiKey_KeypadMultiply) AddInputDown(ImGuiKey_KeypadSubtract) AddInputDown(ImGuiKey_KeypadAdd) AddInputDown(ImGuiKey_KeypadEnter) + AddInputDown( + ImGuiKey_KeypadEqual) + +#if IMGUI_VERSION_NUM >= 19000 + AddInputDown( + ImGuiKey_F13) + AddInputDown( + ImGuiKey_F14) + AddInputDown( + ImGuiKey_F15) AddInputDown(ImGuiKey_F16) AddInputDown(ImGuiKey_F17) AddInputDown(ImGuiKey_F18) AddInputDown(ImGuiKey_F19) AddInputDown(ImGuiKey_F20) AddInputDown(ImGuiKey_F21) AddInputDown(ImGuiKey_F22) AddInputDown(ImGuiKey_F23) AddInputDown(ImGuiKey_F24) + AddInputDown( + ImGuiKey_AppBack) + AddInputDown( + ImGuiKey_AppForward) +#endif + // Gamepad + AddInputDown(ImGuiKey_GamepadStart) AddInputDown( + ImGuiKey_GamepadBack) AddInputDown(ImGuiKey_GamepadFaceUp) + AddInputDown(ImGuiKey_GamepadFaceDown) AddInputDown( + ImGuiKey_GamepadFaceLeft) AddInputDown(ImGuiKey_GamepadFaceRight) + AddInputDown(ImGuiKey_GamepadDpadUp) AddInputDown( + ImGuiKey_GamepadDpadDown) AddInputDown(ImGuiKey_GamepadDpadLeft) + AddInputDown(ImGuiKey_GamepadDpadRight) AddInputDown( + ImGuiKey_GamepadL1) AddInputDown(ImGuiKey_GamepadR1) + AddInputDown(ImGuiKey_GamepadL2) AddInputDown( + ImGuiKey_GamepadR2) AddInputDown(ImGuiKey_GamepadL3) + AddInputDown(ImGuiKey_GamepadR3) AddAnalogInputDown( + ImGuiKey_GamepadLStickUp) + AddAnalogInputDown(ImGuiKey_GamepadLStickDown) AddAnalogInputDown( + ImGuiKey_GamepadLStickLeft) + AddAnalogInputDown( + ImGuiKey_GamepadLStickRight) + AddAnalogInputDown( + ImGuiKey_GamepadRStickUp) + AddAnalogInputDown( + ImGuiKey_GamepadRStickDown) + AddAnalogInputDown( + ImGuiKey_GamepadRStickLeft) + AddAnalogInputDown( + ImGuiKey_GamepadRStickRight) + +#undef AddInputDown +#undef AddAnalogInputDown +#if IMGUI_VERSION_NUM < 18837 +#undef ImGuiKey +#endif + +#if IMGUI_VERSION_NUM < 18837 +#define ImGuiMod_Ctrl ImGuiKey_ModCtrl +#define ImGuiMod_Shift ImGuiKey_ModShift +#define ImGuiMod_Alt ImGuiKey_ModAlt +#define ImGuiMod_Super ImGuiKey_ModSuper +#endif + io.AddKeyEvent( + ImGuiMod_Ctrl, + pCmdInput->IsKeyDown( + CmdInput::NetImguiKeys:: + ImGuiKey_ReservedForModCtrl)); + io.AddKeyEvent(ImGuiMod_Shift, + pCmdInput->IsKeyDown( + CmdInput::NetImguiKeys::ImGuiKey_ReservedForModShift)); + io.AddKeyEvent(ImGuiMod_Alt, + pCmdInput->IsKeyDown( + CmdInput::NetImguiKeys::ImGuiKey_ReservedForModAlt)); + io.AddKeyEvent(ImGuiMod_Super, + pCmdInput->IsKeyDown( + CmdInput::NetImguiKeys::ImGuiKey_ReservedForModSuper)); + + // Mouse + io.AddMouseWheelEvent(wheelX, wheelY); + io.AddMousePosEvent(pCmdInput->mMousePos[0], pCmdInput->mMousePos[1]); + for (int i(0); i < CmdInput::NetImguiMouseButton::ImGuiMouseButton_COUNT; + ++i) { + uint64_t valMask = 0x0000000000000001ull << i; + if ((pCmdInput->mMouseDownMask ^ + client.mPreviousInputState.mMouseDownMask) & + valMask) { + io.AddMouseButtonEvent(i, pCmdInput->mMouseDownMask & valMask); + } + } +#endif + uint16_t character; + io.InputQueueCharacters.resize(0); + while (client.mPendingKeyIn.ReadData(&character)) { + ImWchar ConvertedKey = static_cast(character); + io.AddInputCharacter(ConvertedKey); + } + + static_assert(sizeof(client.mPreviousInputState.mInputDownMask) == + sizeof(pCmdInput->mInputDownMask), + "Array size should match"); + static_assert(sizeof(client.mPreviousInputState.mInputAnalog) == + sizeof(pCmdInput->mInputAnalog), + "Array size should match"); + memcpy(client.mPreviousInputState.mInputDownMask, pCmdInput->mInputDownMask, + sizeof(client.mPreviousInputState.mInputDownMask)); + memcpy(client.mPreviousInputState.mInputAnalog, pCmdInput->mInputAnalog, + sizeof(client.mPreviousInputState.mInputAnalog)); + client.mPreviousInputState.mMouseDownMask = pCmdInput->mMouseDownMask; + client.mPreviousInputState.mMouseWheelVertPrev = pCmdInput->mMouseWheelVert; + client.mPreviousInputState.mMouseWheelHorizPrev = + pCmdInput->mMouseWheelHoriz; + client.mServerCompressionEnabled = pCmdInput->mCompressionUse; + client.mServerCompressionSkip |= pCmdInput->mCompressionSkip; + } + + if (hasNewInput) { + netImguiDeleteSafe(client.mpCmdInputPending); + client.mpCmdInputPending = pCmdInputNew; + } + return hasNewInput; +} + +} // namespace NetImgui + +#endif // NETIMGUI_ENABLED + +#include "NetImgui_WarningReenable.h" diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.cpp b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.cpp new file mode 100644 index 00000000..e4628558 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.cpp @@ -0,0 +1,1046 @@ +// Google modifications: +// - Replaced yield() with sleep_for(1ms) in handshake wait loop to reduce +// CPU usage, and added a 5-second timeout to prevent infinite hangs when +// the server is unreachable. +// - Added cmdTexture.mpNext = nullptr in TexturePendingServerAdd to +// terminate the linked list when appending a new texture command. +// - Added logging for network events. +#include "NetImgui_Shared.h" +#include "google/logging.h" + +#if NETIMGUI_ENABLED +#include +#include +#include +#include + +#include +#include + +#include "NetImgui_Client.h" +#include "NetImgui_CmdPackets.h" +#include "NetImgui_Network.h" +#include "NetImgui_WarningDisable.h" + +namespace NetImgui { +namespace Internal { +namespace Client { + +//================================================================================================= +// SAVED IMGUI CONTEXT +// Because we overwrite some Imgui context IO values, we save them before makign +// any change and restore them after detecting a disconnection +//================================================================================================= +void SavedImguiContext::Save(ImGuiContext* copyFrom) { + ScopedImguiContext scopedContext(copyFrom); + ImGuiIO& sourceIO = ImGui::GetIO(); + mSavedContext = true; + mConfigFlags = sourceIO.ConfigFlags; + mBackendFlags = sourceIO.BackendFlags; + mBackendPlatformName = sourceIO.BackendPlatformName; + mBackendRendererName = sourceIO.BackendRendererName; + mDrawMouse = sourceIO.MouseDrawCursor; +#if !NETIMGUI_IMGUI_TEXTURES_ENABLED + mFontGeneratedSize = + sourceIO.Fonts->Fonts.Size > 0 + ? sourceIO.Fonts->Fonts[0]->FontSize + : 13.f; // Save size to restore the font to original size + mFontGlobalScale = sourceIO.FontGlobalScale; +#endif + +#if IMGUI_VERSION_NUM < 18700 + memcpy(mKeyMap, sourceIO.KeyMap, sizeof(mKeyMap)); +#endif +#if IMGUI_VERSION_NUM < 19110 + mGetClipboardTextFn = sourceIO.GetClipboardTextFn; + mSetClipboardTextFn = sourceIO.SetClipboardTextFn; + mClipboardUserData = sourceIO.ClipboardUserData; +#else + ImGuiPlatformIO& plaformIO = ImGui::GetPlatformIO(); + mGetClipboardTextFn = plaformIO.Platform_GetClipboardTextFn; + mSetClipboardTextFn = plaformIO.Platform_SetClipboardTextFn; + mClipboardUserData = plaformIO.Platform_ClipboardUserData; +#endif +} + +void SavedImguiContext::Restore(ImGuiContext* copyTo) { + ScopedImguiContext scopedContext(copyTo); + ImGuiIO& destIO = ImGui::GetIO(); + mSavedContext = false; + destIO.ConfigFlags = mConfigFlags; + destIO.BackendFlags = mBackendFlags; + destIO.BackendPlatformName = mBackendPlatformName; + destIO.BackendRendererName = mBackendRendererName; + destIO.MouseDrawCursor = mDrawMouse; +#if !NETIMGUI_IMGUI_TEXTURES_ENABLED + destIO.FontGlobalScale = mFontGlobalScale; +#endif +#if IMGUI_VERSION_NUM < 18700 + memcpy(destIO.KeyMap, mKeyMap, sizeof(destIO.KeyMap)); +#endif +#if IMGUI_VERSION_NUM < 19110 + destIO.GetClipboardTextFn = mGetClipboardTextFn; + destIO.SetClipboardTextFn = mSetClipboardTextFn; + destIO.ClipboardUserData = mClipboardUserData; +#else + ImGuiPlatformIO& plaformIO = ImGui::GetPlatformIO(); + plaformIO.Platform_GetClipboardTextFn = mGetClipboardTextFn; + plaformIO.Platform_SetClipboardTextFn = mSetClipboardTextFn; + plaformIO.Platform_ClipboardUserData = mClipboardUserData; +#endif +} + +//================================================================================================= +// GET CLIPBOARD +// Content received from the Server +//================================================================================================= +#if IMGUI_VERSION_NUM < 19110 +static const char* GetClipboardTextFn_NetImguiImpl(void* user_data_ctx) { + const ClientInfo* pClient = + reinterpret_cast(user_data_ctx); + return pClient && pClient->mpCmdClipboard + ? pClient->mpCmdClipboard->mContentUTF8.Get() + : nullptr; +} +#else +static const char* GetClipboardTextFn_NetImguiImpl(ImGuiContext* ctx) { + ScopedImguiContext scopedContext(ctx); + const ClientInfo* pClient = reinterpret_cast( + ImGui::GetPlatformIO().Platform_ClipboardUserData); + return pClient && pClient->mpCmdClipboard + ? pClient->mpCmdClipboard->mContentUTF8.Get() + : nullptr; +} +#endif + +//================================================================================================= +// SET CLIPBOARD +//================================================================================================= +#if IMGUI_VERSION_NUM < 19110 +static void SetClipboardTextFn_NetImguiImpl(void* user_data_ctx, + const char* text) { + if (user_data_ctx) { + ClientInfo* pClient = reinterpret_cast(user_data_ctx); + CmdClipboard* pClipboardOut = CmdClipboard::Create(text); + pClient->mPendingClipboardOut.Assign(pClipboardOut); + } +} +#else +static void SetClipboardTextFn_NetImguiImpl(ImGuiContext* ctx, + const char* text) { + ScopedImguiContext scopedContext(ctx); + ClientInfo* pClient = reinterpret_cast( + ImGui::GetPlatformIO().Platform_ClipboardUserData); + CmdClipboard* pClipboardOut = CmdClipboard::Create(text); + pClient->mPendingClipboardOut.Assign(pClipboardOut); +} +#endif + +//================================================================================================= +// INCOM: INPUT +// Receive new keyboard/mouse/screen resolution input to pass on to dearImgui +//================================================================================================= +void Communications_Incoming_Input(ClientInfo& client) { + auto pCmdInput = static_cast(client.mPendingRcv.pCommand); + client.mPendingRcv.bAutoFree = false; // Taking ownership of the data + client.mDesiredFps = + pCmdInput->mDesiredFps > 0.f ? pCmdInput->mDesiredFps : 0.f; + size_t keyCount(pCmdInput->mKeyCharCount); + client.mPendingKeyIn.AddData(pCmdInput->mKeyChars, keyCount); + + VLOG(2, "CmdInput: mDesiredFps=%.1f, screen=%dx%d, mouse=%d,%d", + pCmdInput->mDesiredFps, pCmdInput->mScreenSize[0], + pCmdInput->mScreenSize[1], pCmdInput->mMousePos[0], + pCmdInput->mMousePos[1]); + + client.mPendingInputIn.Assign(pCmdInput); +} + +//================================================================================================= +// INCOM: CLIPBOARD +// Receive server new clipboard content, updating internal cache +//================================================================================================= +void Communications_Incoming_Clipboard(ClientInfo& client) { + auto pCmdClipboard = static_cast(client.mPendingRcv.pCommand); + client.mPendingRcv.bAutoFree = false; // Taking ownership of the data + pCmdClipboard->ToPointers(); + client.mPendingClipboardIn.Assign(pCmdClipboard); +} + +//================================================================================================= +// OUTCOM: TEXTURE +// Transmit the next pending texture command +//================================================================================================= +void Communications_Outgoing_Textures(ClientInfo& client) { + if (client.mPendingTextures) { + std::lock_guard guard(client.mPendingTexturesLock); + if (client.mPendingTextures) { + // Get oldest texture command to sent to server + CmdTexture* pPendingTexture = client.mPendingTextures; + client.mPendingTextures = client.mPendingTextures->mpNext; + pPendingTexture->mpNext = nullptr; + client.mPendingSend.pCommand = pPendingTexture; + client.mPendingSend.bAutoFree = + false; // free handled by main update thread + } + } +} + +//================================================================================================= +// OUTCOM: BACKGROUND +// Transmit the current client background settings +//================================================================================================= +void Communications_Outgoing_Background(ClientInfo& client) { + CmdBackground* pPendingBackground = client.mPendingBackgroundOut.Release(); + if (pPendingBackground) { + client.mPendingSend.pCommand = pPendingBackground; + client.mPendingSend.bAutoFree = false; + } +} + +//================================================================================================= +// OUTCOM: FRAME +// Transmit a new dearImgui frame to render +//================================================================================================= +void Communications_Outgoing_Frame(ClientInfo& client) { + CmdDrawFrame* pPendingDraw = client.mPendingFrameOut.Release(); + if (pPendingDraw) { + pPendingDraw->mFrameIndex = client.mFrameIndex++; + //--------------------------------------------------------------------- + // Apply delta compression to DrawCommand, when requested + if (pPendingDraw->mCompressed) { + // Create a new Compressed DrawFrame Command + if (client.mpCmdDrawLast && !client.mServerCompressionSkip) { + client.mpCmdDrawLast->ToPointers(); + CmdDrawFrame* pDrawCompressed = + CompressCmdDrawFrame(client.mpCmdDrawLast, pPendingDraw); + netImguiDeleteSafe(client.mpCmdDrawLast); + client.mpCmdDrawLast = pPendingDraw; // Keep original new command for + // next frame delta compression + pPendingDraw = + pDrawCompressed; // Request compressed copy to be sent to server + } + // Save DrawCmd for next frame delta compression + else { + pPendingDraw->mCompressed = false; + client.mpCmdDrawLast = pPendingDraw; + } + } + client.mServerCompressionSkip = false; + + //--------------------------------------------------------------------- + // Ready to send command to server + pPendingDraw->ToOffsets(); + client.mPendingSend.pCommand = pPendingDraw; + client.mPendingSend.bAutoFree = client.mpCmdDrawLast != pPendingDraw; + } +} + +//================================================================================================= +// OUTCOM: Clipboard +// Send client 'Copy' clipboard content to Server +//================================================================================================= +void Communications_Outgoing_Clipboard(ClientInfo& client) { + CmdClipboard* pPendingClipboard = client.mPendingClipboardOut.Release(); + if (pPendingClipboard) { + pPendingClipboard->ToOffsets(); + client.mPendingSend.pCommand = pPendingClipboard; + client.mPendingSend.bAutoFree = true; + } +} + +//================================================================================================= +// INCOMING COMMUNICATIONS +//================================================================================================= +void Communications_Incoming(ClientInfo& client) { + if (Network::DataReceivePending(client.mpSocketComs)) { + //----------------------------------------------------------------------------------------- + // 1. Ready to receive new command, starts the process by reading Header + //----------------------------------------------------------------------------------------- + if (client.mPendingRcv.IsReady()) { + client.mCmdPendingRead = CmdPendingRead(); + client.mPendingRcv.pCommand = &client.mCmdPendingRead; + client.mPendingRcv.bAutoFree = false; + } + + //----------------------------------------------------------------------------------------- + // 2. Read incoming command from server + //----------------------------------------------------------------------------------------- + if (client.mPendingRcv.IsPending()) { + Network::DataReceive(client.mpSocketComs, client.mPendingRcv); + + // Detected a new command bigger than header, allocate memory for it + if (client.mPendingRcv.pCommand->mSize > sizeof(CmdPendingRead) && + client.mPendingRcv.pCommand == &client.mCmdPendingRead) { + CmdPendingRead* pCmdHeader = reinterpret_cast( + netImguiSizedNew(client.mPendingRcv.pCommand->mSize)); + *pCmdHeader = client.mCmdPendingRead; + client.mPendingRcv.pCommand = pCmdHeader; + client.mPendingRcv.bAutoFree = true; + } + } + + //----------------------------------------------------------------------------------------- + // 3. Command fully received from Server, process it + //----------------------------------------------------------------------------------------- + if (client.mPendingRcv.IsDone()) { + if (!client.mPendingRcv.IsError()) { + switch (client.mPendingRcv.pCommand->mType) { + case CmdHeader::eCommands::Input: + Communications_Incoming_Input(client); + break; + case CmdHeader::eCommands::Clipboard: + Communications_Incoming_Clipboard(client); + break; + // Commands not received in main loop, by Client + case CmdHeader::eCommands::Version: + case CmdHeader::eCommands::Texture: + case CmdHeader::eCommands::DrawFrame: + case CmdHeader::eCommands::Background: + case CmdHeader::eCommands::Count: + break; + } + } + + // Cleanup after read completion + if (client.mPendingRcv.IsError()) { + // Routine on any disconnect (server restart, browser handover), so + // logged as Info rather than Error. + VLOG(1, + "Communications_Incoming: receive error, triggering disconnect"); + client.mbDisconnectPending = true; + } + if (client.mPendingRcv.bAutoFree) { + netImguiDeleteSafe(client.mPendingRcv.pCommand); + } + client.mPendingRcv = PendingCom(); + } + } + // Prevent high CPU usage when waiting for new data + else { + // std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::microseconds(250)); + } +} + +//================================================================================================= +// OUTGOING COMMUNICATIONS +//================================================================================================= +void Communications_Outgoing(ClientInfo& client) { + //--------------------------------------------------------------------------------------------- + // Try finishing sending a pending command to Server + //--------------------------------------------------------------------------------------------- + if (client.mPendingSend.IsPending()) { + Network::DataSend(client.mpSocketComs, client.mPendingSend); + + // Free allocated memory for command + if (client.mPendingSend.IsDone()) { + VLOG(2, "Outgoing: send DONE type=%d, size=%u, error=%s", + static_cast(client.mPendingSend.pCommand->mType), + client.mPendingSend.pCommand->mSize, + client.mPendingSend.IsError() ? "Y" : "N"); + client.mPendingSend.pCommand->mSent = true; + if (client.mPendingSend.IsError()) { + client.mbDisconnectPending = true; + } + if (client.mPendingSend.bAutoFree) { + netImguiDeleteSafe(client.mPendingSend.pCommand); + } + client.mPendingSend = PendingCom(); + } + } + //--------------------------------------------------------------------------------------------- + // Initiate sending next command to Server, when none are in flight + // Note: The cmd order is important, textures must always be sent before + // DrawFrame + // @sammyfreg todo Could add a frame number awareness to avoid sending only + // textures with no stop + //--------------------------------------------------------------------------------------------- + constexpr CmdHeader::eCommands kCommandsOrder[] = { + CmdHeader::eCommands::Texture, CmdHeader::eCommands::Background, + CmdHeader::eCommands::Clipboard, CmdHeader::eCommands::DrawFrame}; + constexpr uint32_t kCommandCounts = IM_ARRAYSIZE(kCommandsOrder); + + uint32_t Index(0); + while (client.mPendingSend.IsReady() && Index < kCommandCounts) { + CmdHeader::eCommands NextCmd = kCommandsOrder[Index++]; + switch (NextCmd) { + case CmdHeader::eCommands::Texture: + Communications_Outgoing_Textures(client); + break; + case CmdHeader::eCommands::Background: + Communications_Outgoing_Background(client); + break; + case CmdHeader::eCommands::Clipboard: + Communications_Outgoing_Clipboard(client); + break; + case CmdHeader::eCommands::DrawFrame: + Communications_Outgoing_Frame(client); + break; + // Commands not sent in main loop, by Client + case CmdHeader::eCommands::Input: + case CmdHeader::eCommands::Version: + case CmdHeader::eCommands::Count: + break; + } + } + + // Log new send if one was started + VLOG(2, "Outgoing: ready=%s, pending=%s, frameOut=%s", + client.mPendingSend.IsReady() ? "Y" : "N", + client.mPendingSend.IsPending() ? "Y" : "N", + client.mPendingFrameOut.IsNull() ? "empty" : "HAS_DATA"); + if (client.mPendingSend.IsPending()) { + VLOG(2, "Outgoing: started type=%d, size=%u", + static_cast(client.mPendingSend.pCommand->mType), + client.mPendingSend.pCommand->mSize); + } +} + +//================================================================================================= +// COMMUNICATIONS INITIALIZE +// Initialize a new connection to a RemoteImgui server +//================================================================================================= +bool Communications_Initialize(ClientInfo& client) { + CmdVersion cmdVersionSend, cmdVersionRcv; + PendingCom PendingRcv, PendingSend; + + client.mbComInitActive = true; + + //--------------------------------------------------------------------- + // Handshake confirming connection validity + //--------------------------------------------------------------------- + PendingRcv.pCommand = reinterpret_cast(&cmdVersionRcv); + while (!PendingRcv.IsDone() && + cmdVersionRcv.mType == CmdHeader::eCommands::Version) { + auto start_time = std::chrono::steady_clock::now(); + while (!client.mbDisconnectPending && + !Network::DataReceivePending(client.mpSocketPending)) { + std::this_thread::sleep_for(std::chrono::milliseconds( + 1)); // Idle until we receive the remote data + if (std::chrono::steady_clock::now() - start_time > + std::chrono::seconds(5)) { + LOG(Error, "Communications_Initialize: Timeout waiting for data"); + client.mbDisconnectPending = true; + break; + } + } + if (client.mbDisconnectPending) break; + Network::DataReceive(client.mpSocketPending, PendingRcv); + } + + bool bForceConnect = + client.mServerForceConnectEnabled && + (cmdVersionRcv.mFlags & + static_cast(CmdVersion::eFlags::ConnectForce)) != 0; + bool bCanConnect = !PendingRcv.IsError() && + cmdVersionRcv.mType == cmdVersionSend.mType && + cmdVersionRcv.mVersion == cmdVersionSend.mVersion && + cmdVersionRcv.mWCharSize == cmdVersionSend.mWCharSize && + (!client.IsConnected() || bForceConnect); + + StringCopy(cmdVersionSend.mClientName, client.mName); + cmdVersionSend.mFlags = + client.IsConnected() && !bCanConnect + ? static_cast(CmdVersion::eFlags::IsConnected) + : 0; + cmdVersionSend.mFlags |= + client.IsConnected() && !client.mServerForceConnectEnabled + ? static_cast(CmdVersion::eFlags::IsUnavailable) + : 0; + + PendingSend.pCommand = reinterpret_cast(&cmdVersionSend); + while (!PendingSend.IsDone()) { + Network::DataSend(client.mpSocketPending, PendingSend); + } + + //--------------------------------------------------------------------- + // Connection established, init client + //--------------------------------------------------------------------- + if (bCanConnect && !PendingSend.IsError() && + (!client.IsConnected() || bForceConnect)) { + Network::SocketInfo* pNewComSocket = + client.mpSocketPending.exchange(nullptr); + + // If we detect an active connection with Server and 'ForceConnect was + // requested, close it first + if (client.IsConnected()) { + client.mbDisconnectPending = true; + while (client.IsConnected()); + } + + client.mpSocketComs = pNewComSocket; // Take ownerhip of socket + client.mBGSettingSent.mTextureId = + client.mBGSetting.mTextureId - + 1u; // Force sending the Background settings (by making different than + // current settings) + client.mFrameIndex = 0; + client.mClientTextureIDNext = 0; + client.mServerForceConnectEnabled = + (cmdVersionRcv.mFlags & + static_cast(CmdVersion::eFlags::ConnectExclusive)) == 0; + client.mPendingRcv = PendingCom(); + client.mPendingSend = PendingCom(); + } + + // Disconnect pending socket if init failed + Network::SocketInfo* SocketPending = client.mpSocketPending.exchange(nullptr); + bool bValidConnection = SocketPending == nullptr; + if (SocketPending) { + NetImgui::Internal::Network::Disconnect(SocketPending); + } + + client.mbComInitActive = false; + return bValidConnection; +} + +//================================================================================================= +// COMMUNICATIONS MAIN LOOP +//================================================================================================= +void Communications_Loop(void* pClientVoid) { + IM_ASSERT(pClientVoid != nullptr); + ClientInfo* pClient = reinterpret_cast(pClientVoid); + pClient->mbDisconnectPending = false; + pClient->mbClientThreadActive = true; + + VLOG(1, "Communications_Loop: entering loop"); + while (!pClient->mbDisconnectPending) { + Communications_Outgoing(*pClient); + Communications_Incoming(*pClient); + VLOG(2, "Communications_Loop spin, disconnectPending=%s", + pClient->mbDisconnectPending ? "Y" : "N"); + } + VLOG(1, "Communications_Loop: exiting loop"); + + Network::SocketInfo* pSocket = pClient->mpSocketComs.exchange(nullptr); + if (pSocket) { + NetImgui::Internal::Network::Disconnect(pSocket); + } + + pClient->mbClientThreadActive = false; +} + +//================================================================================================= +// COMMUNICATIONS CONNECT THREAD : Reach out and connect to a NetImGuiServer +//================================================================================================= +void CommunicationsConnect(void* pClientVoid) { + IM_ASSERT(pClientVoid != nullptr); + ClientInfo* pClient = reinterpret_cast(pClientVoid); + if (Communications_Initialize(*pClient)) { + Communications_Loop(pClientVoid); + } +} + +//================================================================================================= +// COMMUNICATIONS HOST THREAD : Waiting NetImGuiServer reaching out to us. +// Launch a new com +//loop when connection is established +//================================================================================================= +void CommunicationsHost(void* pClientVoid) { + ClientInfo* pClient = reinterpret_cast(pClientVoid); + pClient->mbListenThreadActive = true; + pClient->mbDisconnectListen = false; + pClient->mpSocketListen = pClient->mpSocketPending.exchange(nullptr); + + while (pClient->mpSocketListen.load() != nullptr && + !pClient->mbDisconnectListen) { + pClient->mpSocketPending = Network::ListenConnect(pClient->mpSocketListen); + if (pClient->mpSocketPending.load() != nullptr && + Communications_Initialize(*pClient)) { + pClient->mThreadFunction(Client::Communications_Loop, pClient); + } + std::this_thread::sleep_for(std::chrono::milliseconds( + 16)); // Prevents this thread from taking entire core, waiting on + // server connection requests + } + + Network::SocketInfo* pSocket = pClient->mpSocketListen.exchange(nullptr); + NetImgui::Internal::Network::Disconnect(pSocket); + pClient->mbListenThreadActive = false; +} + +//================================================================================================= +// Support of the Dear ImGui hooks +// (automatic call to NetImgui::BeginFrame()/EndFrame() on +// ImGui::BeginFrame()/Imgui::Render() +//================================================================================================= +#if NETIMGUI_IMGUI_CALLBACK_ENABLED +void HookBeginFrame(ImGuiContext*, ImGuiContextHook* hook) { + Client::ClientInfo& client = + *reinterpret_cast(hook->UserData); + if (!client.mbInsideNewEnd) { + ScopedBool scopedInside(client.mbInsideHook, true); + NetImgui::NewFrame(false); + } +} + +void HookEndFrame(ImGuiContext*, ImGuiContextHook* hook) { + Client::ClientInfo& client = + *reinterpret_cast(hook->UserData); + if (!client.mbInsideNewEnd) { + ScopedBool scopedInside(client.mbInsideHook, true); + NetImgui::EndFrame(); + } +} + +#endif // NETIMGUI_IMGUI_CALLBACK_ENABLED + +//================================================================================================= +// CLIENT INFO Constructor +//================================================================================================= +ClientInfo::ClientInfo() + : mpSocketPending(nullptr), + mpSocketComs(nullptr), + mpSocketListen(nullptr), + mbClientThreadActive(false), + mbListenThreadActive(false), + mbComInitActive(false) {} + +//================================================================================================= +// CLIENT INFO Constructor +//================================================================================================= +ClientInfo::~ClientInfo() { + ContextRemoveHooks(); + + // Free all tracked textures + for (auto cmdTexture : mTrackedTextures) { + netImguiDelete(cmdTexture); + } + mTrackedTextures.clear(); + + netImguiDeleteSafe(mpCmdInputPending); + netImguiDeleteSafe(mpCmdDrawLast); + netImguiDeleteSafe(mpCmdClipboard); +} + +//================================================================================================= +// Initialize the associated ImguiContext +//================================================================================================= +void ClientInfo::ContextInitialize() { + mpContext = ImGui::GetCurrentContext(); +#if NETIMGUI_IMGUI_CALLBACK_ENABLED + ImGuiContextHook hookNewframe, hookEndframe; + ContextRemoveHooks(); + hookNewframe.HookId = 0; + hookNewframe.Type = ImGuiContextHookType_NewFramePre; + hookNewframe.Callback = HookBeginFrame; + hookNewframe.UserData = this; + mhImguiHookNewframe = ImGui::AddContextHook(mpContext, &hookNewframe); + hookEndframe.HookId = 0; + hookEndframe.Type = ImGuiContextHookType_RenderPost; + hookEndframe.Callback = HookEndFrame; + hookEndframe.UserData = this; + mhImguiHookEndframe = ImGui::AddContextHook(mpContext, &hookEndframe); +#endif +#if !NETIMGUI_IMGUI_TEXTURES_ENABLED + mbFontUploaded = false; +#endif +} + +//================================================================================================= +// Take over a Dear ImGui context for use with NetImgui +//================================================================================================= +void ClientInfo::ContextOverride() { + ScopedImguiContext scopedSourceCtx(mpContext); + + // Keep a copy of original settings of this context + mSavedContextValues.Save(mpContext); + mLastOutgoingDrawCheckTime = std::chrono::steady_clock::now(); + + // Override some settings + // Note: Make sure every setting overwritten here, are handled in + // 'SavedImguiContext::Save(...)' + { + ImGuiIO& newIO = ImGui::GetIO(); + newIO.MouseDrawCursor = false; + newIO.BackendPlatformName = "NetImgui"; + newIO.BackendRendererName = "DirectX11"; +#if IMGUI_VERSION_NUM < 18700 + for (uint32_t i(0); i < ImGuiKey_COUNT; ++i) { + newIO.KeyMap[i] = i; + } +#endif +#if IMGUI_VERSION_NUM < 19110 + newIO.GetClipboardTextFn = GetClipboardTextFn_NetImguiImpl; + newIO.SetClipboardTextFn = SetClipboardTextFn_NetImguiImpl; + newIO.ClipboardUserData = this; +#else + ImGuiPlatformIO& platformIO = ImGui::GetPlatformIO(); + platformIO.Platform_GetClipboardTextFn = GetClipboardTextFn_NetImguiImpl; + platformIO.Platform_SetClipboardTextFn = SetClipboardTextFn_NetImguiImpl; + platformIO.Platform_ClipboardUserData = this; +#endif +#if defined(IMGUI_HAS_VIEWPORT) + newIO.ConfigFlags &= + ~(ImGuiConfigFlags_ViewportsEnable); // Viewport unsupported at the + // moment +#endif + + // Resend every tracked textures + for (auto textureCmd : mTrackedTextures) { + if (textureCmd->mStatus == CmdTexture::eType::Create) { + TexturePendingServerAdd(*textureCmd); + } + } + +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + mFontSavedScaling = ImGui::GetStyle().FontScaleDpi; + newIO.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; + TextureTrackingUpdate( + true); // Force resend all Dear Imgui managed textures +#else + if (mFontCreationFunction != nullptr) { + newIO.FontGlobalScale = 1; + mFontServerScale = -1; + } +#endif + } +} + +//================================================================================================= +// Restore a Dear ImGui context to initial state before we modified it +//================================================================================================= +void ClientInfo::ContextRestore() { + // Note: only happens if context overriden is same as current one, to prevent + // trying to restore to a deleted context + if (IsContextOverriden() && ImGui::GetCurrentContext() == mpContext) { +#ifdef IMGUI_HAS_VIEWPORT + ImGui::UpdatePlatformWindows(); // Prevents issue with mismatched frame + // tracking, when restoring enabled + // viewport feature +#endif +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + // Remove all auto managed texture from our tracking, + // leaving only the manually managed textures. + // Auto-Managed will automatically get re-added on reconnect. + ImVector& Textures = ImGui::GetPlatformIO().Textures; + ImTextureRef ClientTextureRef; + for (auto TexData : Textures) { + ImTextureStatus TexStatus = + TexData != nullptr ? TexData->Status : ImTextureStatus_Destroyed; + if (TexStatus != ImTextureStatus_Destroyed && + TexStatus != ImTextureStatus_WantDestroy) { + ClientTextureRef._TexData = TexData; + TextureTrackingRem(ClientTextureRef.GetTexID()); + } + } + ImGui::GetStyle().FontScaleDpi = mFontSavedScaling; +#else + if (mFontCreationFunction && ImGui::GetIO().Fonts && + ImGui::GetIO().Fonts->Fonts.size() > 0) { + float noScaleSize = + ImGui::GetIO().Fonts->Fonts[0]->FontSize / mFontServerScale; + float originalScale = + mSavedContextValues.mFontGeneratedSize / noScaleSize; + mFontCreationFunction(mFontSavedScaling, originalScale); + } +#endif + mSavedContextValues.Restore(mpContext); + } +} + +//================================================================================================= +// Remove callback hooks, once we detect a disconnection +//================================================================================================= +void ClientInfo::ContextRemoveHooks() { +#if NETIMGUI_IMGUI_CALLBACK_ENABLED + if (mpContext && mhImguiHookNewframe != 0) { + ImGui::RemoveContextHook(mpContext, mhImguiHookNewframe); + ImGui::RemoveContextHook(mpContext, mhImguiHookEndframe); + mhImguiHookNewframe = mhImguiHookNewframe = 0; + } +#endif +} + +//================================================================================================= +// If backend doesn't support Dear ImGui managed texture (used by font) as +// indicated with 'ImGuiBackendFlags_RendererHasTextures', we still want to +// handle it with our RemoteServer so we take it upon ourselves to clear the +// list of texture updates. Otherwise, we'd be constantly re applying the same +// updates +//================================================================================================= +void ClientInfo::TextureTrackingClear() { +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + if (IsConnected() && (mSavedContextValues.mBackendFlags & + ImGuiBackendFlags_RendererHasTextures) == 0) { + // This is basically a stripped version of 'ImGui_ImplDX11_UpdateTexture' + // where we only care about the TexID and status values + ImVector& Textures = ImGui::GetPlatformIO().Textures; + for (auto TexData : Textures) { + if (TexData->Status == ImTextureStatus_WantCreate) { + IM_ASSERT(TexData->TexID == ImTextureID_Invalid && + TexData->BackendUserData == nullptr); + static ImTextureID sUniqueID(1); + TexData->SetTexID(static_cast(sUniqueID++)); + TexData->SetStatus(ImTextureStatus_OK); + } else if (TexData->Status == ImTextureStatus_WantUpdates) { + TexData->SetStatus(ImTextureStatus_OK); + } else if (TexData->Status == ImTextureStatus_WantDestroy && + TexData->UnusedFrames > 0) { + TexData->SetTexID(ImTextureID_Invalid); + TexData->SetStatus(ImTextureStatus_Destroyed); + } + } + } + + // Remove all Dear ImGui Managed textures on disconnect, + // they will be resent on reconnect + if (!IsConnected() && mDearImguiTextureCount > 0) { + for (auto pCmdTexture : mTrackedTextures) { + if (pCmdTexture->mIsDearImGuiManaged) { + mbTrackedTexturesPending |= + TextureTrackingRem(pCmdTexture->mTextureClientID); + } + } + } +#endif +} + +//================================================================================================= +// Process backend texture updates and forward it to NetImguiServer +// Note: This is mostly used by the Font Atlas Texture added in Dear ImGui 1.92+ +//================================================================================================= +void ClientInfo::TextureTrackingUpdate(bool bResendAll) { +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + if (IsConnected()) { + ImVector& Textures = ImGui::GetPlatformIO().Textures; + ImTextureRef ClientTextureRef; + + //------------------------------------------------------------------------ + // Find and send all Dear ImGui managed textures creation/update to + // remote NetImgui Server + //------------------------------------------------------------------------ + for (auto TexData : Textures) { + ClientTextureRef._TexData = TexData; + ImTextureStatus TexStatus = + TexData != nullptr ? TexData->Status : ImTextureStatus_OK; + eTexFormat TexFormat = + NetImgui::Internal::ConvertTextureFormat(TexData->Format); + uint32_t dataSize = 0; + uint16_t w = static_cast(TexData->Width); + uint16_t h = static_cast(TexData->Height); + + if ((TexStatus == ImTextureStatus_WantCreate) || + (bResendAll && TexStatus != ImTextureStatus_Destroyed && + TexStatus != ImTextureStatus_WantDestroy)) { + // @sammyfreg todo UserID and mClientTextureIDNext used for dear + // imgui managed's textures + // could potentially collide when + //generating ClientTextureID. Needs something more robust. + TexData->UniqueID = ++mClientTextureIDNext; + CmdTexture* pCmdTexture = TextureCmdAllocate( + ConvertToClientTexID(ClientTextureRef), w, h, TexFormat, dataSize); + if (pCmdTexture) { + memcpy(pCmdTexture->mpTextureData.Get(), TexData->GetPixels(), + dataSize); + pCmdTexture->mUpdatable = true; + pCmdTexture->mpTextureData.ToOffset(); + pCmdTexture->mIsDearImGuiManaged = true; + TextureTrackingAdd( + *pCmdTexture); // Add texture to our list and request it to be + // sent over to Server + mbTrackedTexturesPending = true; + } + } else if (TexStatus == ImTextureStatus_WantUpdates) { + uint16_t dstW = static_cast(TexData->UpdateRect.w); + uint16_t dstH = static_cast(TexData->UpdateRect.h); + CmdTexture* pCmdTexture = + TextureCmdAllocate(ConvertToClientTexID(ClientTextureRef), dstW, + dstH, TexFormat, dataSize); + if (pCmdTexture) { + size_t SrcLineBytes = static_cast(TexData->GetPitch()); + size_t DstLineBytes = static_cast(TexData->BytesPerPixel * + TexData->UpdateRect.w); + size_t OffsetBytes = static_cast( + TexData->GetPitch() * TexData->UpdateRect.y + + TexData->BytesPerPixel * TexData->UpdateRect.x); + const uint8_t* pDataSrc = + reinterpret_cast(TexData->GetPixels()); + uint8_t* pDataDst = pCmdTexture->mpTextureData.Get(); + for (uint64_t y(0); y < TexData->UpdateRect.h; ++y) { + memcpy(&pDataDst[y * DstLineBytes], + &pDataSrc[OffsetBytes + (y * SrcLineBytes)], DstLineBytes); + } + pCmdTexture->mStatus = CmdTexture::eType::Update; + pCmdTexture->mOffsetX = TexData->UpdateRect.x; + pCmdTexture->mOffsetY = TexData->UpdateRect.y; + pCmdTexture->mUpdatable = true; + pCmdTexture->mIsDearImGuiManaged = true; + pCmdTexture->mpTextureData.ToOffset(); + TexturePendingServerAdd( + *pCmdTexture); // Request texture to be sent over to Server + mbTrackedTexturesPending = true; + } + } + } + + //------------------------------------------------------------------------ + // Detects Textures changes that have not been tracked + // (caused by internal font atlas changes) + // This is not ideal with large texture count but should be ok for most + // cases. Using a unordered_map for 'mTrackedTextures' could help for + // high count, but adds a std dependency + //------------------------------------------------------------------------ + if (mDearImguiTextureCount != Textures.Size) { + for (auto pCmdTexture : mTrackedTextures) { + if (pCmdTexture->mIsDearImGuiManaged) { + bool bFound(false); + for (int i(0); !bFound && i < Textures.Size; ++i) { + ClientTextureRef._TexData = Textures[i]; + bFound = pCmdTexture->mTextureClientID == + ConvertToClientTexID(ClientTextureRef); + } + if (!bFound) { + mbTrackedTexturesPending |= + TextureTrackingRem(pCmdTexture->mTextureClientID); + } + } + } + } + } +#endif + + //---------------------------------------- + if (mbTrackedTexturesPending) { + int TrackedCount(mTrackedTextures.Size); + mbTrackedTexturesPending = false; + for (int i(0); i < TrackedCount; ++i) { + mbTrackedTexturesPending |= + !mTrackedTextures[i]->mSent && + mTrackedTextures[i]->mStatus != CmdTexture::eType::Create; + // As soon as we detect a command to be un-needed, release it + if (mTrackedTextures[i]->mSent && + mTrackedTextures[i]->mStatus != CmdTexture::eType::Create) { + netImguiDelete(mTrackedTextures[i]); + mTrackedTextures[i] = + mTrackedTextures[--TrackedCount]; // Erase swap with last element + --i; // re-process same index after its entry was swapped with last + // valid element + } + } + mTrackedTextures.resize(TrackedCount); + } +} + +CmdTexture* ClientInfo::TextureCmdAllocate(ClientTextureID clientTexID, + uint16_t width, uint16_t height, + eTexFormat format, + uint32_t& dataSizeInOut) { + if (format != eTexFormat::kTexFmtCustom) { + dataSizeInOut = GetTexture_BytePerImage(format, width, height); + } + + uint32_t SizeNeeded = dataSizeInOut + sizeof(CmdTexture); + CmdTexture* pCmdTexture = netImguiSizedNew(SizeNeeded); + if (pCmdTexture) { + pCmdTexture->mpTextureData.SetPtr( + reinterpret_cast(&pCmdTexture[1])); + pCmdTexture->mStatus = CmdTexture::eType::Create; + pCmdTexture->mSize = SizeNeeded; + pCmdTexture->mWidth = width; + pCmdTexture->mHeight = height; + pCmdTexture->mTextureClientID = clientTexID; + pCmdTexture->mFormat = static_cast(format); + pCmdTexture->mUpdatable = false; + } + return pCmdTexture; +} + +// Start tracking this client texture +bool ClientInfo::TextureTrackingAdd(CmdTexture& cmdTexture) { + if (cmdTexture.mStatus != CmdTexture::eType::Create) { + return false; + } + + TextureTrackingRem(cmdTexture.mTextureClientID); + mTrackedTextures.push_back( + &cmdTexture); // Add the new entry needing to be tracked + TexturePendingServerAdd( + cmdTexture); // Request texture to be sent over to Server + mDearImguiTextureCount += cmdTexture.mIsDearImGuiManaged ? 1 : 0; + return true; +} + +bool ClientInfo::TextureTrackingRem(ClientTextureID clientTextureID) { + // If texture has been sent to server, re-purpose existing command + // as a 'destroy' and re-send it to server + for (int i(0); i < mTrackedTextures.Size; ++i) { + CmdTexture* pCmdTexture = mTrackedTextures[i]; + if (pCmdTexture && pCmdTexture->mTextureClientID == clientTextureID && + pCmdTexture->mStatus == CmdTexture::eType::Create) { + pCmdTexture->mSent = false; + pCmdTexture->mStatus = + CmdTexture::eType::Destroy; // Re-purpose create cmd to destroy the + // texture + TexturePendingServerAdd(*pCmdTexture); + + // Remove item from our list + mDearImguiTextureCount -= pCmdTexture->mIsDearImGuiManaged ? 1 : 0; + mTrackedTextures[i] = mTrackedTextures.back(); + mTrackedTextures.pop_back(); + return true; + } + } + return false; +} + +void ClientInfo::TexturePendingServerAdd(CmdTexture& cmdTexture) { + std::lock_guard guard(mPendingTexturesLock); + if (IsConnected()) { + // Find last added entry + CmdTexture** ppNextTexture = &mPendingTextures; + CmdTexture* pendingTexture = mPendingTextures; + while (pendingTexture != nullptr) { + // Remove all unprocessed texture commands with same id + // (only need the latest action for create/destroy, but can have multiple + // update queued) + if (cmdTexture.mStatus != CmdTexture::eType::Update && + cmdTexture.mSent == false && + cmdTexture.mTextureClientID == pendingTexture->mTextureClientID) { + // Mark as sent and un-needed (which gets it removed from tracking array + // and deleted later) + pendingTexture->mSent = true; + pendingTexture->mStatus = CmdTexture::eType::Destroy; + *ppNextTexture = pendingTexture->mpNext; + } + ppNextTexture = &pendingTexture->mpNext; + pendingTexture = pendingTexture->mpNext; + } + + // Add as last element and ready to be sent + cmdTexture.mSent = false; + cmdTexture.mpNext = nullptr; + *ppNextTexture = &cmdTexture; + } +} + +//================================================================================================= +// Create a new Draw Command from Dear Imgui draw data. +// 1. New ImGui frame has been completed, create a new draw command from draw +// data (Main Thread) +// 2. We see a pending Draw Command, take ownership of it and send it to Server +// (Com thread) +//================================================================================================= +void ClientInfo::ProcessDrawData(const ImDrawData* pDearImguiData, + ImGuiMouseCursor mouseCursor) { + if (!mbValidDrawFrame) return; + + VLOG(2, "ProcessDrawData: %s (mbValidDrawFrame=%s, mDesiredFps=%.1f)", + mbValidDrawFrame ? "SENDING" : "SKIPPED", + mbValidDrawFrame ? "true" : "false", mDesiredFps); + + CmdDrawFrame* pDrawFrameNew = + ConvertToCmdDrawFrame(pDearImguiData, mouseCursor); + pDrawFrameNew->mCompressed = + mClientCompressionMode == eCompressionMode::kForceEnable || + (mClientCompressionMode == eCompressionMode::kUseServerSetting && + mServerCompressionEnabled); + mPendingFrameOut.Assign(pDrawFrameNew); +} + +} // namespace Client +} // namespace Internal +} // namespace NetImgui + +#include "NetImgui_WarningReenable.h" +#endif // #if NETIMGUI_ENABLED diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.h new file mode 100644 index 00000000..83ad7c50 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.h @@ -0,0 +1,236 @@ +#pragma once + +#include + +#include "NetImgui_CmdPackets.h" +#include "NetImgui_Shared.h" + +//============================================================================= +// Forward Declares +//============================================================================= +namespace NetImgui { +namespace Internal { +namespace Network { +struct SocketInfo; +} +} // namespace Internal +} // namespace NetImgui + +namespace NetImgui { +namespace Internal { +namespace Client { + +//============================================================================= +// Keeps a list of ImGui context values NetImgui overrides (to restore) +//============================================================================= +struct SavedImguiContext { + void Save(ImGuiContext* copyFrom); + void Restore(ImGuiContext* copyTo); + const char* mBackendPlatformName = nullptr; + const char* mBackendRendererName = nullptr; + void* mImeWindowHandle = nullptr; + ImGuiBackendFlags mBackendFlags = 0; + ImGuiConfigFlags mConfigFlags = 0; + bool mDrawMouse = false; + bool mSavedContext = false; + char mPadding1[2] = {}; + void* mClipboardUserData = nullptr; +#if IMGUI_VERSION_NUM < 19110 + const char* (*mGetClipboardTextFn)(void*) = nullptr; + void (*mSetClipboardTextFn)(void*, const char*) = nullptr; +#else + const char* (*mGetClipboardTextFn)(ImGuiContext*) = nullptr; + void (*mSetClipboardTextFn)(ImGuiContext*, const char*) = nullptr; +#endif +#if IMGUI_VERSION_NUM < 18700 + int mKeyMap[ImGuiKey_COUNT] = {}; + char mPadding2[8 - (sizeof(mKeyMap) % 8)] = {}; +#endif +#if !NETIMGUI_IMGUI_TEXTURES_ENABLED + float mFontGlobalScale = 1.f; + float mFontGeneratedSize = 0.f; +#endif +}; + +//============================================================================= +// Keep all Client infos needed for communication with server +//============================================================================= +struct ClientInfo { + using BufferKeys = Ringbuffer; + using TimePoint = std::chrono::time_point; + + struct InputState { + uint64_t mInputDownMask[(CmdInput::ImGuiKey_COUNT + 63) / 64] = {}; + float mInputAnalog[CmdInput::kAnalog_Count] = {}; + uint64_t mMouseDownMask = 0; + float mMouseWheelVertPrev = 0.f; + float mMouseWheelHorizPrev = 0.f; + }; + ClientInfo(); + ~ClientInfo(); + void ContextInitialize(); + void ContextOverride(); + void ContextRestore(); + void ContextRemoveHooks(); + inline bool IsContextOverriden() const; + inline bool IsConnected() const; + inline bool IsConnectPending() const; + inline bool IsActive() const; + + bool TextureTrackingAdd(CmdTexture& cmdTexture); + bool TextureTrackingRem(ClientTextureID cmdTexture); + void TextureTrackingClear(); + void TextureTrackingUpdate( + bool bResendAll = false); // Process Backend ImGui textures + CmdTexture* TextureCmdAllocate(ClientTextureID clientTexID, uint16_t width, + uint16_t height, eTexFormat format, + uint32_t& dataSizeInOut); + + void TexturePendingServerAdd( + CmdTexture& cmdTexture); // Add CmdTexture to list of command waiting for + // send off to Server + + void ProcessDrawData(const ImDrawData* pDearImguiData, + ImGuiMouseCursor mouseCursor); + + std::atomic + mpSocketPending; // Hold socket info until communication is established + std::atomic + mpSocketComs; // Socket used for communications with server + std::atomic + mpSocketListen; // Socket used to wait for communication request from + // server + std::atomic_bool mbDisconnectPending; // Terminate Client/Server coms + std::atomic_bool + mbDisconnectListen; // Terminate waiting connection from Server + uint32_t mSocketListenPort = 0; // Socket Port number used to wait for + // communication request from server + char mName[64] = {}; + uint64_t mFrameIndex = + 0; // Incremented every time we send a DrawFrame Command + std::mutex mPendingTexturesLock; // Lock to prevent thread contention on the + // list of texure cmd waiting to be sent to + // the NetImgui Server + CmdTexture* mPendingTextures = + nullptr; // List of texture commands waiting to be send to Sever (single + // linked list with oldest item at the head) + ImVector + mTrackedTextures; // List of texture commands to create textures used by + // this client (note for large texture count, should be + // replace with a unordered_map for fast operations) + ExchangePtr mPendingFrameOut; + ExchangePtr mPendingBackgroundOut; + ExchangePtr mPendingInputIn; + ExchangePtr + mPendingClipboardIn; // Clipboard content received from Server and + // waiting to be taken by client + ExchangePtr + mPendingClipboardOut; // Clipboard content copied on Client and waiting + // to be sent to Server + ImGuiContext* mpContext = + nullptr; // Context that the remote drawing should use (the one active + // when connection request happened) + PendingCom mPendingRcv; // Data being currently received from Server + PendingCom mPendingSend; // Data being currently sent to Server + CmdPendingRead mCmdPendingRead; // Used to get info on the next incoming + // command from Server + CmdInput* mpCmdInputPending = nullptr; // Last Input Command from server, + // waiting to be processed by client + CmdClipboard* mpCmdClipboard = nullptr; // Last received clipboad command + CmdDrawFrame* mpCmdDrawLast = + nullptr; // Last sent Draw Command. Used by data compression, to generate + // delta between previous and current frame + CmdBackground + mBGSetting; // Current value assigned to background appearance by user + CmdBackground mBGSettingSent; // Last sent value to remote server + BufferKeys + mPendingKeyIn; // Keys pressed received. Results of 2 CmdInputs are + // concatenated if received before being processed + TimePoint mLastOutgoingDrawCheckTime; // When we last checked if we have a + // pending draw command to send + TimePoint mLastOutgoingDrawTime; // When we last sent an updated draw command + // to the server + ImVec2 mSavedDisplaySize = { + 0, 0}; // Save original display size on 'NewFrame' and restore it on + // 'EndFrame' (making sure size is still valid after a disconnect) + SavedImguiContext mSavedContextValues; // Oiginal ImGui context values that + // will be restored on disconnect + std::atomic_bool mbClientThreadActive; // True when connected and + // communicating with Server + std::atomic_bool mbListenThreadActive; // True when listening from connection + // request from Server + std::atomic_bool + mbComInitActive; // True when attempting to initialize a new connection + bool mbTrackedTexturesPending = + false; // True if there are some pending tracked textures waiting to be + // removed + bool mbIsDrawing = + false; // We are inside a 'NetImgui::NewFrame' / 'NetImgui::EndFrame' + // (even if not for a remote draw) + bool mbIsRemoteDrawing = + false; // True if the rendering it meant for the remote netImgui server + bool mbRestorePending = + false; // Original context has had some settings overridden, original + // values stored in mRestoreXXX + bool mbInsideHook = false; // Currently inside ImGui hook callback + bool mbInsideNewEnd = + false; // Currently inside NetImgui::NewFrame() or NetImgui::EndFrame() + // (prevents recusrive hook call) + bool mbValidDrawFrame = false; // If we should forward the drawdata to the + // server at the end of ImGui::Render() + uint8_t mClientCompressionMode = eCompressionMode::kUseServerSetting; + bool mServerCompressionEnabled = + false; // If Server would like compression to be enabled + // (mClientCompressionMode value can override this value) + bool mServerCompressionSkip = + false; // Force ignore compression setting for 1 frame + bool mServerForceConnectEnabled = + true; // If another NetImguiServer can take connection away from the one + // currently active + ThreadFunctPtr mThreadFunction = + nullptr; // Function to use when laucnhing new threads + float mFontSavedScaling = 0.f; // Original Font scaling before our override + // between NewFrame / EndFrame + float mFontServerScale = + 1.f; // Desired Font DPI Scaling by the NetImgui Server + float mDesiredFps = 30.f; // How often we should update the remote drawing. + // Received from server + InputState mPreviousInputState; // Keeping track of last keyboard/mouse state + ImGuiID mhImguiHookNewframe = 0; + ImGuiID mhImguiHookEndframe = 0; + int mClientTextureIDNext = + 0; // Next available ID to assign to new Dear ImGui managed textures + int mDearImguiTextureCount = + 0; // Keep track of number of Dear ImGui managed texture added (to detect + // when DearImgui released some) +#if !NETIMGUI_IMGUI_TEXTURES_ENABLED + const void* mpFontTextureData = + nullptr; // Last font texture data send to server (used to detect if font + // was changed) + uint64_t mFontTextureID = + 0; // Used to detect textureID change [Before ImGui 1.92, old Font Atlas] + FontCreateFuncPtr mFontCreationFunction = + nullptr; // Method to call to generate the remote ImGui font. By default, + // re-use the local font, but this doesn't handle native DPI + // scaling on remote server. //NOTE: Unused by Dear imGui 1.92+ + bool mbFontUploaded = false; // Auto detect if font was sent to server +#endif + + // Prevent warnings about implicitly created copy + protected: + ClientInfo(const ClientInfo&) = delete; + ClientInfo(const ClientInfo&&) = delete; + void operator=(const ClientInfo&) = delete; +}; + +//============================================================================= +// Main communication loop threads that are run in separate threads +//============================================================================= +void CommunicationsConnect(void* pClientVoid); +void CommunicationsHost(void* pClientVoid); + +} // namespace Client +} // namespace Internal +} // namespace NetImgui + +#include "NetImgui_Client.inl" diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.inl b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.inl new file mode 100644 index 00000000..e6ee7da5 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Client.inl @@ -0,0 +1,26 @@ + +#include "NetImgui_Network.h" + +namespace NetImgui { namespace Internal { namespace Client { + +bool ClientInfo::IsConnected()const +{ + return mpSocketComs.load() != nullptr; +} + +bool ClientInfo::IsConnectPending()const +{ + return mbComInitActive || mpSocketPending.load() != nullptr || mpSocketListen.load() != nullptr; +} + +bool ClientInfo::IsActive()const +{ + return mbClientThreadActive || mbListenThreadActive; +} + +bool ClientInfo::IsContextOverriden()const +{ + return mSavedContextValues.mSavedContext; +} + +}}} // namespace NetImgui::Internal::Client diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets.h new file mode 100644 index 00000000..7cdbca57 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets.h @@ -0,0 +1,426 @@ +#pragma once + +#include "NetImgui_CmdPackets_DrawFrame.h" +#include "NetImgui_Shared.h" + +namespace NetImgui { +namespace Internal { + +// Note: If updating any of these commands data structure, increase +// 'CmdVersion::eVersion' +struct alignas(8) CmdHeader { + enum class eCommands : uint8_t { + Version, + Texture, + Input, + DrawFrame, + Background, + Clipboard, + Count + }; + CmdHeader(eCommands CmdType, uint16_t Size) : mSize(Size), mType(CmdType) {} + uint32_t mSize = 0; + eCommands mType = eCommands::Count; + uint8_t mSent = + false; // True when command finished being sent to client or server + uint8_t mPadding[2] = {}; +}; + +// Used as step 1 of 2 of reading incoming transmission between Client/Server, +// to get header whose size we know +struct alignas(8) CmdPendingRead : public CmdHeader { + CmdPendingRead() : CmdHeader(eCommands::Count, sizeof(CmdPendingRead)) {} +}; + +struct alignas(8) CmdVersion : public CmdHeader { + enum class eVersion : uint32_t { + Initial = 1, + NewTextureFormat = 2, + ImguiVersionInfo = + 3, // Added Dear Imgui/ NetImgui version info to 'CmdVersion' + ServerRefactor = 4, // Change to 'CmdInput' and 'CmdVersion' store size of + // 'ImWchar' to make sure they are compatible + BackgroundCmd = 5, // Added new command to control background appearance + ClientName = + 6, // Increase maximum allowed client name that a program can set + DataCompression = 7, // Adding support for data compression between + // client/server. Simple low cost delta compressor + // (only send difference from previous frame) + DataCompression2 = 8, // Improvement to data compression (save corner + // position and use SoA for vertices data) + VertexUVRange = 9, // Changed vertices UV value range to [0,1] for + // increased precision on large font texture + Imgui_1_87 = 10, // Added Dear ImGui Input refactor + OffetPointer = + 11, // Updated the handling of OffsetPoint. Moved flag bit from last + // bit to first bit. Addresses and data are always at least 4 bytes + // aligned, so should never conflict with potential address space + CustomTexture = 12, // Added a 'custom' texture format to let user + // potentially handle their how format + DPIScale = 13, // Server now handle monitor DPI + Clipboard = 14, // Added clipboard support between server/client + ForceReconnect = + 15, // Server can now take over the connection from another server + UpdatedComs = 16, // Faster protocol by removing blocking coms + RemDisconnect = 17, // Removed Disconnect command + ManagedTextures = 18, // Adding support for Dear Imgui Managed Textures + // (introduced in 1.92)) + // Insert new version here + + //-------------------------------- + _count, + _current = _count - 1 + }; + enum class eFlags : uint8_t { + IsUnavailable = 0x01, // Client telling Server it cannot be used + IsConnected = + 0x02, // Client telling Server there's already a valid connection (can + // potentially be taken over if !IsUnavailable) + ConnectForce = 0x04, // Server telling Client it want to take over + // connection if there's already one + ConnectExclusive = 0x08, // Server telling Client that once connected, + // others servers should be denied access + }; + CmdVersion() : CmdHeader(CmdHeader::eCommands::Version, sizeof(CmdVersion)) {} + char mClientName[64] = {}; + char mImguiVerName[16] = {IMGUI_VERSION}; + char mNetImguiVerName[16] = {NETIMGUI_VERSION}; + eVersion mVersion = eVersion::_current; + uint32_t mImguiVerID = IMGUI_VERSION_NUM; + uint32_t mNetImguiVerID = NETIMGUI_VERSION_NUM; + uint8_t mWCharSize = static_cast(sizeof(ImWchar)); + uint8_t mFlags = 0; + uint8_t PADDING[2] = {}; +}; + +struct alignas(8) CmdInput : public CmdHeader { + // Identify a mouse button. + // Those values are guaranteed to be stable and we frequently use 0/1 + // directly. Named enums provided for convenience. + enum NetImguiMouseButton { + ImGuiMouseButton_Left = 0, + ImGuiMouseButton_Right = 1, + ImGuiMouseButton_Middle = 2, + ImGuiMouseButton_Extra1 = 3, // Additional entry + ImGuiMouseButton_Extra2 = 4, // Additional entry + ImGuiMouseButton_COUNT = 5 + }; + + // Copy of Dear ImGui key enum + // We keep our own internal version, to make sure Client key is the same as + // Server Key (since they can have different Imgui version) + enum NetImguiKeys { + // Keyboard + ImGuiKey_Tab, + ImGuiKey_LeftArrow, + ImGuiKey_RightArrow, + ImGuiKey_UpArrow, + ImGuiKey_DownArrow, + ImGuiKey_PageUp, + ImGuiKey_PageDown, + ImGuiKey_Home, + ImGuiKey_End, + ImGuiKey_Insert, + ImGuiKey_Delete, + ImGuiKey_Backspace, + ImGuiKey_Space, + ImGuiKey_Enter, + ImGuiKey_Escape, + ImGuiKey_LeftCtrl, + ImGuiKey_LeftShift, + ImGuiKey_LeftAlt, + ImGuiKey_LeftSuper, + ImGuiKey_RightCtrl, + ImGuiKey_RightShift, + ImGuiKey_RightAlt, + ImGuiKey_RightSuper, + ImGuiKey_Menu, + ImGuiKey_0, + ImGuiKey_1, + ImGuiKey_2, + ImGuiKey_3, + ImGuiKey_4, + ImGuiKey_5, + ImGuiKey_6, + ImGuiKey_7, + ImGuiKey_8, + ImGuiKey_9, + ImGuiKey_A, + ImGuiKey_B, + ImGuiKey_C, + ImGuiKey_D, + ImGuiKey_E, + ImGuiKey_F, + ImGuiKey_G, + ImGuiKey_H, + ImGuiKey_I, + ImGuiKey_J, + ImGuiKey_K, + ImGuiKey_L, + ImGuiKey_M, + ImGuiKey_N, + ImGuiKey_O, + ImGuiKey_P, + ImGuiKey_Q, + ImGuiKey_R, + ImGuiKey_S, + ImGuiKey_T, + ImGuiKey_U, + ImGuiKey_V, + ImGuiKey_W, + ImGuiKey_X, + ImGuiKey_Y, + ImGuiKey_Z, + ImGuiKey_F1, + ImGuiKey_F2, + ImGuiKey_F3, + ImGuiKey_F4, + ImGuiKey_F5, + ImGuiKey_F6, + ImGuiKey_F7, + ImGuiKey_F8, + ImGuiKey_F9, + ImGuiKey_F10, + ImGuiKey_F11, + ImGuiKey_F12, + ImGuiKey_F13, + ImGuiKey_F14, + ImGuiKey_F15, + ImGuiKey_F16, + ImGuiKey_F17, + ImGuiKey_F18, + ImGuiKey_F19, + ImGuiKey_F20, + ImGuiKey_F21, + ImGuiKey_F22, + ImGuiKey_F23, + ImGuiKey_F24, + ImGuiKey_Apostrophe, // ' + ImGuiKey_Comma, // , + ImGuiKey_Minus, // - + ImGuiKey_Period, // . + ImGuiKey_Slash, // / + ImGuiKey_Semicolon, // ; + ImGuiKey_Equal, // = + ImGuiKey_LeftBracket, // [ + ImGuiKey_Backslash, // \ (this text inhibit multiline comment caused by + // backslash) + ImGuiKey_RightBracket, // ] + ImGuiKey_GraveAccent, // ` + ImGuiKey_CapsLock, + ImGuiKey_ScrollLock, + ImGuiKey_NumLock, + ImGuiKey_PrintScreen, + ImGuiKey_Pause, + ImGuiKey_Keypad0, + ImGuiKey_Keypad1, + ImGuiKey_Keypad2, + ImGuiKey_Keypad3, + ImGuiKey_Keypad4, + ImGuiKey_Keypad5, + ImGuiKey_Keypad6, + ImGuiKey_Keypad7, + ImGuiKey_Keypad8, + ImGuiKey_Keypad9, + ImGuiKey_KeypadDecimal, + ImGuiKey_KeypadDivide, + ImGuiKey_KeypadMultiply, + ImGuiKey_KeypadSubtract, + ImGuiKey_KeypadAdd, + ImGuiKey_KeypadEnter, + ImGuiKey_KeypadEqual, + ImGuiKey_AppBack, // Available on some keyboard/mouses. Often referred as + // "Browser Back" + ImGuiKey_AppForward, + ImGuiKey_Oem102, // Non-US backslash. + + // // XBOX | SWITCH | PLAYSTA. | -> + // ACTION + ImGuiKey_GamepadStart, // Menu | + | Options | + ImGuiKey_GamepadBack, // View | - | Share | + ImGuiKey_GamepadFaceLeft, // X | Y | Square | Tap: Toggle + // Menu. Hold: Windowing mode (Focus/Move/Resize + // windows) + ImGuiKey_GamepadFaceRight, // B | A | Circle | Cancel / + // Close / Exit + ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Text Input / + // On-screen Keyboard + ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / + // Open / Toggle / Tweak + ImGuiKey_GamepadDpadLeft, // D-pad Left | " | " | Move / + // Tweak / Resize Window (in Windowing mode) + ImGuiKey_GamepadDpadRight, // D-pad Right | " | " | Move / + // Tweak / Resize Window (in Windowing mode) + ImGuiKey_GamepadDpadUp, // D-pad Up | " | " | Move / Tweak + // / Resize Window (in Windowing mode) + ImGuiKey_GamepadDpadDown, // D-pad Down | " | " | Move / + // Tweak / Resize Window (in Windowing mode) + ImGuiKey_GamepadL1, // L Bumper | L | L1 | Tweak Slower / + // Focus Previous (in Windowing mode) + ImGuiKey_GamepadR1, // R Bumper | R | R1 | Tweak Faster / + // Focus Next (in Windowing mode) + ImGuiKey_GamepadL2, // L Trigger | ZL | L2 | [Analog] + ImGuiKey_GamepadR2, // R Trigger | ZR | R2 | [Analog] + ImGuiKey_GamepadL3, // L Stick | L3 | L3 | + ImGuiKey_GamepadR3, // R Stick | R3 | R3 | + ImGuiKey_GamepadLStickLeft, // | | | [Analog] + // Move Window (in Windowing mode) + ImGuiKey_GamepadLStickRight, // | | | [Analog] + // Move Window (in Windowing mode) + ImGuiKey_GamepadLStickUp, // | | | [Analog] + // Move Window (in Windowing mode) + ImGuiKey_GamepadLStickDown, // | | | [Analog] + // Move Window (in Windowing mode) + ImGuiKey_GamepadRStickLeft, // | | | [Analog] + ImGuiKey_GamepadRStickRight, // | | | [Analog] + ImGuiKey_GamepadRStickUp, // | | | [Analog] + ImGuiKey_GamepadRStickDown, // | | | [Analog] + + // Mouse Buttons (auto-submitted from AddMouseButtonEvent() calls) + // - This is mirroring the data also written to io.MouseDown[], + // io.MouseWheel, in a format allowing them to be accessed via standard key + // API. + ImGuiKey_MouseLeft, + ImGuiKey_MouseRight, + ImGuiKey_MouseMiddle, + ImGuiKey_MouseX1, + ImGuiKey_MouseX2, + ImGuiKey_MouseWheelX, + ImGuiKey_MouseWheelY, + + // Keyboard Modifiers (explicitly submitted by backend via AddKeyEvent() + // calls) + // - This is mirroring the data also written to io.KeyCtrl, io.KeyShift, + // io.KeyAlt, io.KeySuper, in a format allowing + // them to be accessed via standard key API, allowing calls such as + // IsKeyPressed(), IsKeyReleased(), querying duration etc. + // - Code polling every keys (e.g. an interface to detect a key press for + // input mapping) might want to ignore those + // and prefer using the real keys (e.g. ImGuiKey_LeftCtrl, + // ImGuiKey_RightCtrl instead of ImGuiKey_ModCtrl). + // - In theory the value of keyboard modifiers should be roughly equivalent + // to a logical or of the equivalent left/right keys. + // In practice: it's complicated; mods are often provided from different + // sources. Keyboard layout, IME, sticky keys and backends tend to + // interfere and break that equivalence. The safer decision is to relay + // that ambiguity down to the end-user... + ImGuiKey_ReservedForModCtrl, + ImGuiKey_ReservedForModShift, + ImGuiKey_ReservedForModAlt, + ImGuiKey_ReservedForModSuper, + + // End of list + ImGuiKey_COUNT, // No valid ImGuiKey is ever greater than this value + }; + + static constexpr uint32_t kAnalog_First = ImGuiKey_GamepadLStickLeft; + static constexpr uint32_t kAnalog_Last = ImGuiKey_GamepadRStickDown; + static constexpr uint32_t kAnalog_Count = kAnalog_Last - kAnalog_First + 1; + + CmdInput() : CmdHeader(CmdHeader::eCommands::Input, sizeof(CmdInput)) {} + uint16_t mScreenSize[2] = {}; + int16_t mMousePos[2] = {}; + float mMouseWheelVert = 0.f; + float mMouseWheelHoriz = 0.f; + uint16_t mKeyChars[256] = {}; // Input characters + uint16_t mKeyCharCount = 0; // Number of valid input characters + bool mCompressionUse = + false; // Server would like client to compress the communication data + bool mCompressionSkip = + false; // Server forcing next client's frame data to be uncompressed + float mFontDPIScaling = + 1.f; // Font scaling request by Server accounting for monitor DPI + float mDesiredFps = 30.f; // Requested redraw speed + uint64_t mMouseDownMask = 0; + uint64_t mInputDownMask[(ImGuiKey_COUNT + 63) / 64] = {}; + float mInputAnalog[kAnalog_Count] = {}; + inline bool IsKeyDown(NetImguiKeys netimguiKey) const; +}; + +struct alignas(8) CmdTexture : public CmdHeader { + enum class eType : uint8_t { Create, Update, Destroy }; + CmdTexture() : CmdHeader(CmdHeader::eCommands::Texture, sizeof(CmdTexture)) {} + ClientTextureID mTextureClientID = 0; + eType mStatus = eType::Create; + uint8_t mFormat = eTexFormat::kTexFmt_Invalid; // eTexFormat + uint8_t mUpdatable = false; // Set to true on Create, for updatable textures + uint8_t mIsDearImGuiManaged = + false; // True if this is not an user created/managed texture + uint16_t mWidth = + 0; // Either the texture width on create, or the update area width + uint16_t mHeight = + 0; // Either the texture height on create, or the update area height + uint16_t mOffsetX = 0; // Used by partial update + uint16_t mOffsetY = 0; // Used by partial update + uint8_t PADDING[4] = {}; + alignas(8) CmdTexture* mpNext = + nullptr; // Used for single linked list of pending textures (alignas + // needed to keep class size the same between win32/x64) + OffsetPointer mpTextureData; +}; + +struct alignas(8) CmdDrawFrame : public CmdHeader { + CmdDrawFrame() + : CmdHeader(CmdHeader::eCommands::DrawFrame, sizeof(CmdDrawFrame)) {} + uint64_t mFrameIndex = 0; + uint32_t mMouseCursor = 0; // ImGuiMouseCursor value + float mDisplayArea[4] = {}; + uint32_t mIndiceByteSize = 0; + uint32_t mDrawGroupCount = 0; + uint32_t mTotalVerticeCount = 0; + uint32_t mTotalIndiceCount = 0; + uint32_t mTotalDrawCount = 0; + uint32_t mUncompressedSize = 0; + uint8_t mCompressed = false; + uint8_t PADDING[3] = {}; + OffsetPointer mpDrawGroups; + inline void ToPointers(); + inline void ToOffsets(); +}; + +struct alignas(8) CmdBackground : public CmdHeader { + CmdBackground() + : CmdHeader(CmdHeader::eCommands::Background, sizeof(CmdBackground)) {} + static constexpr uint64_t kDefaultTexture = ~0u; + float mClearColor[4] = {0.2f, 0.2f, 0.2f, 1.f}; // Background color + float mTextureTint[4] = {1.f, 1.f, 1.f, + 0.5f}; // Tint/alpha applied to texture + uint64_t mTextureId = kDefaultTexture; // Texture rendered in background, use + // server texture by default + inline bool operator==(const CmdBackground& cmp) const; + inline bool operator!=(const CmdBackground& cmp) const; +}; + +struct alignas(8) CmdClipboard : public CmdHeader { + CmdClipboard() + : CmdHeader(CmdHeader::eCommands::Clipboard, sizeof(CmdClipboard)) {} + size_t mByteSize = 0; + OffsetPointer mContentUTF8; + inline void ToPointers(); + inline void ToOffsets(); + inline static CmdClipboard* Create(const char* clipboard); +}; + +//============================================================================= +// Keeping track of partial incoming/outgoing transmissions +//============================================================================= +struct PendingCom { + size_t SizeCurrent = 0; // Amount of data sent or received so far + bool bAutoFree = false; // Need to free data buffer at the end of processing + bool bError = false; // If an error occurs during coms + CmdHeader* pCommand = + nullptr; // Where to store incoming data or read to send data + inline bool IsError() const { return bError; } + inline bool IsDone() const { + return IsError() || (pCommand && pCommand->mSize == SizeCurrent); + } + inline bool IsReady() const { return !IsError() && pCommand == nullptr; } + inline bool IsPending() const { + return !IsError() && !IsDone() && !IsReady(); + } +}; + +} // namespace Internal +} // namespace NetImgui + +#include "NetImgui_CmdPackets.inl" diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets.inl b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets.inl new file mode 100644 index 00000000..e03b6222 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets.inl @@ -0,0 +1,101 @@ +#include "NetImgui_CmdPackets.h" + +namespace NetImgui { namespace Internal +{ + +void CmdDrawFrame::ToPointers() +{ + if( !mpDrawGroups.IsPointer() ) + { + mpDrawGroups.ToPointer(); + for (uint32_t i(0); i < mDrawGroupCount; ++i) { + mpDrawGroups[i].ToPointers(); + } + } +} + +void CmdDrawFrame::ToOffsets() +{ + if( !mpDrawGroups.IsOffset() ) + { + for (uint32_t i(0); i < mDrawGroupCount; ++i) { + mpDrawGroups[i].ToOffsets(); + } + mpDrawGroups.ToOffset(); + } +} + +void ImguiDrawGroup::ToPointers() +{ + if( !mpIndices.IsPointer() ) //Safer to test the first element after CmdHeader + { + mpIndices.ToPointer(); + mpVertices.ToPointer(); + mpDraws.ToPointer(); + } +} + +void ImguiDrawGroup::ToOffsets() +{ + if( !mpIndices.IsOffset() ) //Safer to test the first element after CmdHeader + { + mpIndices.ToOffset(); + mpVertices.ToOffset(); + mpDraws.ToOffset(); + } +} + +bool CmdInput::IsKeyDown( CmdInput::NetImguiKeys netimguiKey) const +{ + uint32_t valIndex = netimguiKey/64; + uint64_t valMask = 0x0000000000000001ull << (netimguiKey%64); + return mInputDownMask[valIndex] & valMask; +} + +bool CmdBackground::operator==(const CmdBackground& cmp)const +{ + bool sameValue(true); + for(size_t i(0); i(this)[i] == reinterpret_cast(&cmp)[i]; + } + return sameValue; +} + +bool CmdBackground::operator!=(const CmdBackground& cmp)const +{ + return (*this == cmp) == false; +} + + +void CmdClipboard::ToPointers() +{ + if( !mContentUTF8.IsPointer() ){ + mContentUTF8.ToPointer(); + } +} + +void CmdClipboard::ToOffsets() +{ + if( !mContentUTF8.IsOffset() ){ + mContentUTF8.ToOffset(); + } +} + +CmdClipboard* CmdClipboard::Create(const char* clipboard) +{ + if( clipboard ) + { + size_t clipboardByteSize(0); + while(clipboard[clipboardByteSize++] != 0); + size_t totalDataCount = sizeof(CmdClipboard) + DivUp(clipboardByteSize, ComDataSize); + auto pNewClipboard = NetImgui::Internal::netImguiSizedNew(totalDataCount*ComDataSize); + pNewClipboard->mSize = static_cast(totalDataCount*ComDataSize); + pNewClipboard->mByteSize = clipboardByteSize; + pNewClipboard->mContentUTF8.SetPtr(reinterpret_cast(&pNewClipboard[1])); + memcpy(pNewClipboard->mContentUTF8.Get(), clipboard, clipboardByteSize); + return pNewClipboard; + } + return nullptr; +} + +}} // namespace NetImgui::Internal diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets_DrawFrame.cpp b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets_DrawFrame.cpp new file mode 100644 index 00000000..0ce41750 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets_DrawFrame.cpp @@ -0,0 +1,477 @@ +#include "NetImgui_Shared.h" + +#if NETIMGUI_ENABLED +#include "NetImgui_CmdPackets.h" +#include "NetImgui_WarningDisable.h" + +namespace NetImgui { +namespace Internal { + +template +inline void SetAndIncreaseDataPointer(OffsetPointer& dataPointer, + uint32_t dataSize, + ComDataType*& pDataOutput) { + dataPointer.SetComDataPtr(pDataOutput); + const size_t dataCount = DivUp(dataSize, ComDataSize); + pDataOutput[dataCount - 1] = 0; + pDataOutput += dataCount; +} + +//============================================================================= +// Safely convert a pointer to a int value, even if int storage size > pointer +//============================================================================= +template +TInt PointerCast(TPointer* pointer) { + union CastHelperUnion { + TInt ValueInt; + TPointer* ValuePointer; + }; + CastHelperUnion helperObject = {}; + helperObject.ValuePointer = pointer; + return helperObject.ValueInt; +} + +//================================================================================================= +// +//================================================================================================= +inline void ImGui_ExtractIndices(const ImDrawList& cmdList, + ImguiDrawGroup& drawGroupOut, + ComDataType*& pDataOutput) { + bool is16Bit = + sizeof(ImDrawIdx) == 2 || + cmdList.VtxBuffer.size() <= + 0xFFFF; // When Dear Imgui is compiled with ImDrawIdx = uint16, we + // know for certain that there won't be any drawcall with + // index > 65k, even if Vertex buffer is bigger than 65k. + drawGroupOut.mBytePerIndex = is16Bit ? 2 : 4; + drawGroupOut.mIndiceCount = static_cast(cmdList.IdxBuffer.size()); + uint32_t sizeNeeded = drawGroupOut.mIndiceCount * drawGroupOut.mBytePerIndex; + SetAndIncreaseDataPointer(drawGroupOut.mpIndices, sizeNeeded, pDataOutput); + + // No conversion needed, straight copy + if (drawGroupOut.mBytePerIndex == sizeof(ImDrawIdx)) { + memcpy(drawGroupOut.mpIndices.Get(), &cmdList.IdxBuffer.front(), + sizeNeeded); + } + // From 32bits to 16bits + else if (is16Bit) { + for (int i(0); i < static_cast(drawGroupOut.mIndiceCount); ++i) + reinterpret_cast(drawGroupOut.mpIndices.Get())[i] = + static_cast(cmdList.IdxBuffer[i]); + } + // From 16bits to 32bits + else { + for (int i(0); i < static_cast(drawGroupOut.mIndiceCount); ++i) + reinterpret_cast(drawGroupOut.mpIndices.Get())[i] = + static_cast(cmdList.IdxBuffer[i]); + } +} + +//================================================================================================= +// +//================================================================================================= +inline void ImGui_ExtractVertices(const ImDrawList& cmdList, + ImguiDrawGroup& drawGroupOut, + ComDataType*& pDataOutput) { + drawGroupOut.mVerticeCount = static_cast(cmdList.VtxBuffer.size()); + drawGroupOut.mReferenceCoord[0] = + drawGroupOut.mVerticeCount > 0 ? cmdList.VtxBuffer[0].pos.x : 0.f; + drawGroupOut.mReferenceCoord[1] = + drawGroupOut.mVerticeCount > 0 ? cmdList.VtxBuffer[0].pos.y : 0.f; + SetAndIncreaseDataPointer(drawGroupOut.mpVertices, + drawGroupOut.mVerticeCount * sizeof(ImguiVert), + pDataOutput); + ImguiVert* pVertices = drawGroupOut.mpVertices.Get(); + for (int i(0); i < static_cast(drawGroupOut.mVerticeCount); ++i) { + const auto& Vtx = cmdList.VtxBuffer[i]; + pVertices[i].mColor = Vtx.col; + pVertices[i].mUV[0] = static_cast( + (Vtx.uv.x - static_cast(ImguiVert::kUvRange_Min) + + 0.5f / 65535.f) * + 0xFFFF / (ImguiVert::kUvRange_Max - ImguiVert::kUvRange_Min)); + pVertices[i].mUV[1] = static_cast( + (Vtx.uv.y - static_cast(ImguiVert::kUvRange_Min) + + 0.5f / 65535.f) * + 0xFFFF / (ImguiVert::kUvRange_Max - ImguiVert::kUvRange_Min)); + pVertices[i].mPos[0] = static_cast( + (Vtx.pos.x - drawGroupOut.mReferenceCoord[0] - + static_cast(ImguiVert::kPosRange_Min)) * + 0xFFFF / (ImguiVert::kPosRange_Max - ImguiVert::kPosRange_Min)); + pVertices[i].mPos[1] = static_cast( + (Vtx.pos.y - drawGroupOut.mReferenceCoord[1] - + static_cast(ImguiVert::kPosRange_Min)) * + 0xFFFF / (ImguiVert::kPosRange_Max - ImguiVert::kPosRange_Min)); + } +} + +//================================================================================================= +// +//================================================================================================= +inline void ImGui_ExtractDraws(const ImDrawList& cmdList, + ImguiDrawGroup& drawGroupOut, + ComDataType*& pDataOutput) { + int maxDrawCount = static_cast(cmdList.CmdBuffer.size()); + uint32_t drawCount = 0; + ImguiDraw* pOutDraws = reinterpret_cast(pDataOutput); + for (int cmd_i = 0; cmd_i < maxDrawCount; ++cmd_i) { + const ImDrawCmd* pCmd = &cmdList.CmdBuffer[cmd_i]; + if (pCmd->UserCallback == nullptr) { +#if IMGUI_VERSION_NUM >= 17100 + pOutDraws[drawCount].mVtxOffset = pCmd->VtxOffset; + pOutDraws[drawCount].mIdxOffset = pCmd->IdxOffset; +#else + pOutDraws[drawCount].mVtxOffset = 0; + pOutDraws[drawCount].mIdxOffset = 0; +#endif + +#if NETIMGUI_IMGUI_TEXTURES_ENABLED + ClientTextureID texClientID = ConvertToClientTexID(pCmd->TexRef); +#else + ClientTextureID texClientID = ConvertToClientTexID(pCmd->TextureId); +#endif + pOutDraws[drawCount].mClientTexId = texClientID; + pOutDraws[drawCount].mIdxCount = pCmd->ElemCount; + pOutDraws[drawCount].mClipRect[0] = pCmd->ClipRect.x; + pOutDraws[drawCount].mClipRect[1] = pCmd->ClipRect.y; + pOutDraws[drawCount].mClipRect[2] = pCmd->ClipRect.z; + pOutDraws[drawCount].mClipRect[3] = pCmd->ClipRect.w; + ++drawCount; + } + } + drawGroupOut.mDrawCount = drawCount; + static_assert(sizeof(ImguiDraw) % ComDataSize == 0, + "Need to support zero-ing the pending bytes, when not a size " + "multiple of DataComType"); + drawGroupOut.mpDraws.SetComDataPtr(pDataOutput); + pDataOutput += drawGroupOut.mDrawCount * sizeof(ImguiDraw) / ComDataSize; +} + +//================================================================================================= +// Delta comress data. +// Take 2 data stream and output a stream with only the data difference from +// each other +//================================================================================================= +void CompressData(const ComDataType* pDataPrev, size_t dataSizePrev, + const ComDataType* pDataNew, size_t dataSizeNew, + ComDataType*& pCommandMemoryInOut) { + static_assert(sizeof(uint32_t) * 2 <= ComDataSize, + "Need to adjust compression algorithm pointer calculation"); + const size_t elemCountPrev = + static_cast(DivUp(dataSizePrev, sizeof(uint64_t))); + const size_t elemCountNew = + static_cast(DivUp(dataSizeNew, sizeof(uint64_t))); + const size_t elemCount = + elemCountPrev < elemCountNew ? elemCountPrev : elemCountNew; + size_t n = 0; + + if (pDataPrev) { + while (n < elemCount) { + uint32_t* pBlockInfo = reinterpret_cast( + pCommandMemoryInOut++); // Add a new block info to output + + // Find number of elements with same value as last frame + size_t startN = n; + while (n < elemCount && pDataPrev[n] == pDataNew[n]) ++n; + pBlockInfo[0] = static_cast(n - startN); + + // Find number of elements with different value as last frame, and save + // new value + while (n < elemCount && pDataPrev[n] != pDataNew[n]) { + *pCommandMemoryInOut = pDataNew[n++]; + ++pCommandMemoryInOut; + } + pBlockInfo[1] = + static_cast(pCommandMemoryInOut - + reinterpret_cast(pBlockInfo)) - + 1; + } + } + + // New frame has more element than previous frame, add the remaining entries + if (elemCount < elemCountNew) { + uint32_t* pBlockInfo = reinterpret_cast( + pCommandMemoryInOut++); // Add a new block info to output + while (n < elemCountNew) { + *pCommandMemoryInOut = pDataNew[n++]; + ++pCommandMemoryInOut; + } + pBlockInfo[0] = 0; + pBlockInfo[1] = + static_cast(pCommandMemoryInOut - + reinterpret_cast(pBlockInfo)) - + 1; + } +} + +//================================================================================================= +// Unpack a delta data compressed stream +//================================================================================================= +void DecompressData(const ComDataType* pDataPrev, size_t dataSizePrev, + const ComDataType* pDataPack, size_t dataUnpackSize, + ComDataType*& pCommandMemoryInOut) { + const size_t elemCountPrev = DivUp(dataSizePrev, ComDataSize); + const size_t elemCountUnpack = DivUp(dataUnpackSize, ComDataSize); + const size_t elemCountCopy = + elemCountPrev < elemCountUnpack ? elemCountPrev : elemCountUnpack; + uint64_t* pCommandMemoryEnd = &pCommandMemoryInOut[elemCountUnpack]; + if (pDataPrev) { + memcpy(pCommandMemoryInOut, pDataPrev, elemCountCopy * ComDataSize); + } + while (pCommandMemoryInOut < pCommandMemoryEnd) { + const uint32_t* pBlockInfo = reinterpret_cast( + pDataPack++); // Add a new block info to output + pCommandMemoryInOut += pBlockInfo[0]; + memcpy(pCommandMemoryInOut, pDataPack, pBlockInfo[1] * sizeof(uint64_t)); + pCommandMemoryInOut += pBlockInfo[1]; + pDataPack += pBlockInfo[1]; + } +} + +//================================================================================================= +// Take a regular NetImgui DrawFrame command and create a new compressed command +// It uses a basic delta compression method that works really well with Imgui +// data +// - Most of the drawing data do not change between 2 frames +// - Even if 1 window content changes, the others windows probably won't be +// changing at all +// - This means that for each window, we can only send the data that changed +// - This requires little cpu usage and generate good results +// - In 'SampleBasic' with 3 windows open (Main Window, ImGui Demo, ImGui +// Metric) at 30fps +// - Compression Off: 1650KB/sec of transfert +// - Compression On : 12KB/sec of transfert (130x less data) +//================================================================================================= +CmdDrawFrame* CompressCmdDrawFrame(const CmdDrawFrame* pDrawFramePrev, + const CmdDrawFrame* pDrawFrameNew) { + //----------------------------------------------------------------------------------------- + // Allocate memory for the new compressed command + //----------------------------------------------------------------------------------------- + // Allocate memory for worst case scenario (no compression possible) + // New DrawFrame size + 2 'compression block info' per data stream + size_t neededDataCount = + DivUp(pDrawFrameNew->mSize, ComDataSize) + + 6 * static_cast(pDrawFrameNew->mDrawGroupCount); + CmdDrawFrame* pDrawFramePacked = + netImguiSizedNew(neededDataCount * ComDataSize); + *pDrawFramePacked = *pDrawFrameNew; + pDrawFramePacked->mCompressed = true; + + ComDataType* pDataOutput = + reinterpret_cast(&pDrawFramePacked[1]); + SetAndIncreaseDataPointer( + pDrawFramePacked->mpDrawGroups, + pDrawFramePacked->mDrawGroupCount * sizeof(ImguiDrawGroup), pDataOutput); + + //----------------------------------------------------------------------------------------- + // Copy draw data (vertices, indices, drawcall info, ...) + //----------------------------------------------------------------------------------------- + const uint32_t groupCountPrev = pDrawFramePrev->mDrawGroupCount; + for (uint32_t n = 0; n < pDrawFramePacked->mDrawGroupCount; n++) { + // Look for the same drawgroup in previous frame + // Can usually avoid a search by checking same index in previous frame + // (drawgroup ordering shouldn't change often) + const ImguiDrawGroup& drawGroupNew = pDrawFrameNew->mpDrawGroups[n]; + ImguiDrawGroup& drawGroup = pDrawFramePacked->mpDrawGroups[n]; + drawGroup = drawGroupNew; + drawGroup.mDrawGroupIdxPrev = + (n < groupCountPrev && + drawGroup.mGroupID == pDrawFramePrev->mpDrawGroups[n].mGroupID) + ? n + : ImguiDrawGroup::kInvalidDrawGroup; + for (uint32_t j(0); + j < groupCountPrev && + drawGroup.mDrawGroupIdxPrev == ImguiDrawGroup::kInvalidDrawGroup; + ++j) { + drawGroup.mDrawGroupIdxPrev = + (drawGroup.mGroupID == pDrawFramePrev->mpDrawGroups[j].mGroupID) + ? j + : ImguiDrawGroup::kInvalidDrawGroup; + } + + // Delta compress the 3 data streams + const uint64_t *pVerticePrev(nullptr), *pIndicePrev(nullptr), + *pDrawsPrev(nullptr); + size_t verticeSizePrev(0), indiceSizePrev(0), drawSizePrev(0); + if (drawGroup.mDrawGroupIdxPrev < pDrawFramePrev->mDrawGroupCount) { + const ImguiDrawGroup& drawGroupPrev = + pDrawFramePrev->mpDrawGroups[drawGroup.mDrawGroupIdxPrev]; + pVerticePrev = + reinterpret_cast(drawGroupPrev.mpVertices.Get()); + pIndicePrev = + reinterpret_cast(drawGroupPrev.mpIndices.Get()); + pDrawsPrev = + reinterpret_cast(drawGroupPrev.mpDraws.Get()); + verticeSizePrev = drawGroupPrev.mVerticeCount * sizeof(ImguiVert); + indiceSizePrev = drawGroupPrev.mIndiceCount * + static_cast(drawGroupPrev.mBytePerIndex); + drawSizePrev = drawGroupPrev.mDrawCount * sizeof(ImguiDraw); + } + + drawGroup.mpIndices.SetComDataPtr(pDataOutput); + CompressData(pIndicePrev, indiceSizePrev, + drawGroupNew.mpIndices.GetComData(), + drawGroupNew.mIndiceCount * + static_cast(drawGroupNew.mBytePerIndex), + pDataOutput); + + drawGroup.mpVertices.SetComDataPtr(pDataOutput); + CompressData(pVerticePrev, verticeSizePrev, + drawGroupNew.mpVertices.GetComData(), + drawGroupNew.mVerticeCount * sizeof(ImguiVert), pDataOutput); + + drawGroup.mpDraws.SetComDataPtr(pDataOutput); + CompressData(pDrawsPrev, drawSizePrev, drawGroupNew.mpDraws.GetComData(), + drawGroupNew.mDrawCount * sizeof(ImguiDraw), pDataOutput); + } + + // Adjust data transfert amount to memory that has been actually needed + pDrawFramePacked->mSize = + static_cast( + (pDataOutput - reinterpret_cast(pDrawFramePacked))) * + static_cast(sizeof(uint64_t)); + return pDrawFramePacked; +} + +//================================================================================================= +// +//================================================================================================= +CmdDrawFrame* DecompressCmdDrawFrame(const CmdDrawFrame* pDrawFramePrev, + const CmdDrawFrame* pDrawFramePacked) { + //----------------------------------------------------------------------------------------- + // Allocate memory for the new uncompressed compressed command + //----------------------------------------------------------------------------------------- + CmdDrawFrame* pDrawFrameNew = + netImguiSizedNew(pDrawFramePacked->mUncompressedSize); + *pDrawFrameNew = *pDrawFramePacked; + pDrawFrameNew->mCompressed = false; + ComDataType* pDataOutput = reinterpret_cast(&pDrawFrameNew[1]); + SetAndIncreaseDataPointer( + pDrawFrameNew->mpDrawGroups, + pDrawFrameNew->mDrawGroupCount * sizeof(ImguiDrawGroup), pDataOutput); + + for (uint32_t n = 0; n < pDrawFrameNew->mDrawGroupCount; n++) { + const ImguiDrawGroup& drawGroupPack = pDrawFramePacked->mpDrawGroups[n]; + ImguiDrawGroup& drawGroup = pDrawFrameNew->mpDrawGroups[n]; + drawGroup = drawGroupPack; + + // Uncompress the 3 data streams + const ComDataType* pVerticePrev = nullptr; + const ComDataType* pIndicePrev = nullptr; + const ComDataType* pDrawsPrev = nullptr; + size_t verticeSizePrev(0), indiceSizePrev(0), drawSizePrev(0); + if (drawGroup.mDrawGroupIdxPrev < pDrawFramePrev->mDrawGroupCount) { + const ImguiDrawGroup& drawGroupPrev = + pDrawFramePrev->mpDrawGroups[drawGroup.mDrawGroupIdxPrev]; + pVerticePrev = + reinterpret_cast(drawGroupPrev.mpVertices.Get()); + pIndicePrev = + reinterpret_cast(drawGroupPrev.mpIndices.Get()); + pDrawsPrev = + reinterpret_cast(drawGroupPrev.mpDraws.Get()); + verticeSizePrev = drawGroupPrev.mVerticeCount * sizeof(ImguiVert); + indiceSizePrev = drawGroupPrev.mIndiceCount * + static_cast(drawGroupPrev.mBytePerIndex); + drawSizePrev = drawGroupPrev.mDrawCount * sizeof(ImguiDraw); + } + + drawGroup.mpIndices.SetComDataPtr(pDataOutput); + DecompressData(pIndicePrev, indiceSizePrev, + drawGroupPack.mpIndices.GetComData(), + drawGroupPack.mIndiceCount * + static_cast(drawGroupPack.mBytePerIndex), + pDataOutput); + + drawGroup.mpVertices.SetComDataPtr(pDataOutput); + DecompressData( + pVerticePrev, verticeSizePrev, drawGroupPack.mpVertices.GetComData(), + drawGroupPack.mVerticeCount * sizeof(ImguiVert), pDataOutput); + + drawGroup.mpDraws.SetComDataPtr(pDataOutput); + DecompressData(pDrawsPrev, drawSizePrev, drawGroupPack.mpDraws.GetComData(), + drawGroupPack.mDrawCount * sizeof(ImguiDraw), pDataOutput); + } + return pDrawFrameNew; +} + +//================================================================================================= +// Take a regular Dear Imgui Draw Data, and convert it to a NetImgui DrawFrame +// Command It involves saving each window draw group vertex/indices/draw buffers +// and packing their data a little bit, to reduce the bandwidth usage +//================================================================================================= +CmdDrawFrame* ConvertToCmdDrawFrame(const ImDrawData* pDearImguiData, + ImGuiMouseCursor mouseCursor) { + //----------------------------------------------------------------------------------------- + // Find memory needed for entire DrawFrame Command + //----------------------------------------------------------------------------------------- + static_assert(sizeof(CmdDrawFrame) % ComDataSize == 0, + "Make sure Command Data is aligned to com data type size"); + size_t neededDataCount = DivUp(sizeof(CmdDrawFrame), ComDataSize); + neededDataCount += DivUp(static_cast(pDearImguiData->CmdListsCount) * + sizeof(ImguiDrawGroup), + ComDataSize); + for (int n = 0; n < pDearImguiData->CmdListsCount; n++) { + const ImDrawList* pCmdList = pDearImguiData->CmdLists[n]; + bool is16Bit = pCmdList->VtxBuffer.size() <= 0xFFFF; + neededDataCount += DivUp( + static_cast(pCmdList->VtxBuffer.size()) * sizeof(ImguiVert), + ComDataSize); + neededDataCount += DivUp( + static_cast(pCmdList->IdxBuffer.size()) * (is16Bit ? 2 : 4), + ComDataSize); + neededDataCount += DivUp( + static_cast(pCmdList->CmdBuffer.size()) * sizeof(ImguiDraw), + ComDataSize); + } + + //----------------------------------------------------------------------------------------- + // Allocate Data and initialize general frame information + //----------------------------------------------------------------------------------------- + CmdDrawFrame* pDrawFrame = + netImguiSizedNew(neededDataCount * ComDataSize); + ComDataType* pDataOutput = reinterpret_cast(&pDrawFrame[1]); + pDrawFrame->mMouseCursor = static_cast(mouseCursor); + pDrawFrame->mDisplayArea[0] = pDearImguiData->DisplayPos.x; + pDrawFrame->mDisplayArea[1] = pDearImguiData->DisplayPos.y; + pDrawFrame->mDisplayArea[2] = + pDearImguiData->DisplayPos.x + pDearImguiData->DisplaySize.x; + pDrawFrame->mDisplayArea[3] = + pDearImguiData->DisplayPos.y + pDearImguiData->DisplaySize.y; + pDrawFrame->mDrawGroupCount = + static_cast(pDearImguiData->CmdListsCount); + SetAndIncreaseDataPointer(pDrawFrame->mpDrawGroups, + static_cast(pDrawFrame->mDrawGroupCount * + sizeof(ImguiDrawGroup)), + pDataOutput); + + //----------------------------------------------------------------------------------------- + // Copy draw data (vertices, indices, drawcall info, ...) + //----------------------------------------------------------------------------------------- + for (size_t n = 0; n < pDrawFrame->mDrawGroupCount; n++) { + ImguiDrawGroup& drawGroup = pDrawFrame->mpDrawGroups[n]; + const ImDrawList* pCmdList = pDearImguiData->CmdLists[static_cast(n)]; + drawGroup = ImguiDrawGroup(); + drawGroup.mGroupID = PointerCast( + pCmdList->_OwnerName); // Use the name string pointer as a unique ID + // (seems to remain the same between frame) + ImGui_ExtractIndices(*pCmdList, drawGroup, pDataOutput); + ImGui_ExtractVertices(*pCmdList, drawGroup, pDataOutput); + ImGui_ExtractDraws(*pCmdList, drawGroup, pDataOutput); + pDrawFrame->mTotalVerticeCount += drawGroup.mVerticeCount; + pDrawFrame->mTotalIndiceCount += drawGroup.mIndiceCount; + pDrawFrame->mTotalDrawCount += drawGroup.mDrawCount; + } + + pDrawFrame->mSize = + static_cast(pDataOutput - + reinterpret_cast(pDrawFrame)) * + ComDataSize; + pDrawFrame->mUncompressedSize = + pDrawFrame->mSize; // No compression with this item, so same value + return pDrawFrame; +} + +} // namespace Internal +} // namespace NetImgui + +#include "NetImgui_WarningReenable.h" +#endif // #if NETIMGUI_ENABLED diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets_DrawFrame.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets_DrawFrame.h new file mode 100644 index 00000000..15ae1bdc --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_CmdPackets_DrawFrame.h @@ -0,0 +1,63 @@ +#pragma once + +#include "NetImgui_Shared.h" + +namespace NetImgui { +namespace Internal { + +struct ImguiVert { + // Note: If updating this, increase 'CmdVersion::eVersion' + enum Constants { + kUvRange_Min = 0, + kUvRange_Max = 1, + kPosRange_Min = -8192, + kPosRange_Max = 8192 + }; + uint16_t mPos[2]; + uint16_t mUV[2]; + uint32_t mColor; +}; + +struct ImguiDraw { + ClientTextureID + mClientTexId; // TextureID used by client to identify the texture + uint32_t mIdxCount; // Drawcall number of indices (3 indices per triangles) + uint32_t mVtxOffset; // Drawcall start position in vertices buffer + // (considered index 0) + uint32_t mIdxOffset; // Drawcall start position in indices buffer + float mClipRect[4]; + uint8_t PADDING[4] = {}; +}; + +// Each DearImgui window has its own vertex/index buffers with multiple +// drawcalls +struct alignas(8) ImguiDrawGroup { + static constexpr uint32_t kInvalidDrawGroup = 0xFFFFFFFF; + uint64_t mGroupID = 0; // Unique ID to recognize DrawGroup between 2 frames + uint32_t mVerticeCount = 0; + uint32_t mIndiceCount = 0; + uint32_t mDrawCount = 0; + uint32_t mDrawGroupIdxPrev = + kInvalidDrawGroup; // Group index in previous DrawFrame + // (kInvalidDrawGroup when not using delta + // compression) + uint8_t mBytePerIndex = 2; // 2, 4 bytes + uint8_t PADDING[7] = {}; + float mReferenceCoord[2] = {}; // Reference position for the encoded vertices + // offsets (1st vertice top/left position) + OffsetPointer mpIndices; + OffsetPointer mpVertices; + OffsetPointer mpDraws; + inline void ToPointers(); + inline void ToOffsets(); +}; + +struct CmdDrawFrame* ConvertToCmdDrawFrame(const ImDrawData* pDearImguiData, + ImGuiMouseCursor cursor); +struct CmdDrawFrame* CompressCmdDrawFrame(const CmdDrawFrame* pDrawFramePrev, + const CmdDrawFrame* pDrawFrameNew); +struct CmdDrawFrame* DecompressCmdDrawFrame( + const CmdDrawFrame* pDrawFramePrev, const CmdDrawFrame* pDrawFramePacked); + +} // namespace Internal +} // namespace NetImgui diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Network.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Network.h new file mode 100644 index 00000000..c50f9b01 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Network.h @@ -0,0 +1,44 @@ +// Google modifications: +// - Added #include for uint32_t (not implicitly available in Google) +#pragma once + +#include +namespace NetImgui { +namespace Internal { +struct PendingCom; +} +} // namespace NetImgui + +namespace NetImgui { +namespace Internal { +namespace Network { + +struct SocketInfo; + +bool Startup(void); +void Shutdown(void); + +SocketInfo* Connect( + const char* ServerHost, + uint32_t ServerPort); // Communication Socket expected to be blocking +SocketInfo* ListenConnect( + SocketInfo* ListenSocket); // Communication Socket expected to be blocking +SocketInfo* ListenStart( + uint32_t ListenPort); // Listening Socket expected to be non blocking +void Disconnect(SocketInfo* pClientSocket); + +bool DataReceivePending( + SocketInfo* pClientSocket); // True if some new data if waiting to be + // processed from remote connection +void DataReceive( + SocketInfo* pClientSocket, + PendingCom& PendingComRcv); // Try reading X amount of bytes from remote + // connection, but can fall short. +void DataSend( + SocketInfo* pClientSocket, + PendingCom& PendingComSend); // Try sending X amount of bytes to remote + // connection, but can fall short. + +} // namespace Network +} // namespace Internal +} // namespace NetImgui diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_NetworkPosix.cpp b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_NetworkPosix.cpp new file mode 100644 index 00000000..e3d3b24d --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_NetworkPosix.cpp @@ -0,0 +1,391 @@ +// Google modifications: +// - Replaced select() with poll() to avoid FD_SETSIZE (1024) limit and +// a SIGSEGV caused by Linux select() writing to a const timeval placed +// in read-only memory by the compiler. +// - Added logging for network events. +#include "NetImgui_Shared.h" +#include "google/logging.h" + +#if defined(_MSC_VER) +#pragma warning(disable : 4221) +#endif + +#if NETIMGUI_ENABLED && NETIMGUI_POSIX_SOCKETS_ENABLED +#include +#include +#include // Required for TCP_NODELAY +#include // Preferred over select() (no FD_SETSIZE limit) +#include +#include +#include + +#include // Required for std::string / std::to_string with GCC +#include +#include + +#include + +#include "NetImgui_CmdPackets.h" + +// NOTE: Removed static_assert(0) as requested changes are implemented below + +namespace NetImgui { +namespace Internal { +namespace Network { + +//================================================================================================= +// Wrapper around native socket object and init some socket options +//================================================================================================= +struct SocketInfo { + SocketInfo(int socket) : mSocket(socket) { + if (mSocket != -1) { + // Set Non-Blocking + int flags = fcntl(mSocket, F_GETFL, 0); + fcntl(mSocket, F_SETFL, flags | O_NONBLOCK); + + // Set TCP No Delay + int flag = 1; + setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int)); + + // Optional: Set Send Buffer Size (Mirroring Win32's attempt) + // int kComsSendBuffer = 2 * mSendSizeMax; + // setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, (char*)&kComsSendBuffer, + // sizeof(kComsSendBuffer)); + } + } + + int mSocket = -1; + int mSendSizeMax = 1024 * 1024; // Limit tx data to avoid socket error on + // large amount (texture) [cite: 258] +}; + +bool Startup() { + // No specific startup needed for POSIX sockets like WSAStartup in Winsock + return true; +} + +void Shutdown() { + // No specific cleanup needed for POSIX sockets like WSACleanup in Winsock +} + +//================================================================================================= +// Try establishing a connection to a remote client at given address +// (Non-Blocking) +//================================================================================================= +SocketInfo* Connect(const char* ServerHost, uint32_t ServerPort) { + int ClientSocket = -1; + addrinfo hints, *pResults = nullptr, *pResultCur = nullptr; + SocketInfo* pSocketInfo = nullptr; + char zPortName[32]; + sprintf(zPortName, "%u", ServerPort); + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6 + hints.ai_socktype = SOCK_STREAM; + + if (getaddrinfo(ServerHost, zPortName, &hints, &pResults) != 0) { + return nullptr; // Failed to resolve host + } + + for (pResultCur = pResults; pResultCur != nullptr && pSocketInfo == nullptr; + pResultCur = pResultCur->ai_next) { + ClientSocket = socket(pResultCur->ai_family, pResultCur->ai_socktype, + pResultCur->ai_protocol); + if (ClientSocket == -1) { + continue; // Failed to create socket for this address + } + + // Set non-blocking *before* connect for non-blocking connect + int flags = fcntl(ClientSocket, F_GETFL, 0); + fcntl(ClientSocket, F_SETFL, flags | O_NONBLOCK); + + int Result = + connect(ClientSocket, pResultCur->ai_addr, pResultCur->ai_addrlen); + bool Connected = (Result == 0); + + if (Result == -1 && errno == EINPROGRESS) { + // Connection attempt is in progress, use poll to wait + struct pollfd pfd = {ClientSocket, POLLOUT, 0}; + Result = poll(&pfd, 1, 1000); // 1 second timeout + + if (Result > 0) { + // Select indicated socket is writable, check for connection errors + int optVal; + socklen_t optLen = sizeof(optVal); + if (getsockopt(ClientSocket, SOL_SOCKET, SO_ERROR, &optVal, &optLen) == + 0 && + optVal == 0) { + Connected = true; + } else { + // Connection failed + Connected = false; + } + } else { + // Select timed out or error + Connected = false; + } + } else if (Result == -1) { + // Immediate connection error + Connected = false; + } + + if (Connected) { + pSocketInfo = netImguiNew(ClientSocket); + // Socket is already non-blocking from the SocketInfo constructor + } else if (ClientSocket != -1) { + close(ClientSocket); // Close socket if connection failed + ClientSocket = -1; + } + } + + freeaddrinfo(pResults); + + if (!pSocketInfo && ClientSocket != -1) { + close(ClientSocket); // Clean up socket if loop finished without success + } + + return pSocketInfo; +} + +//================================================================================================= +// Start waiting for connection request on this socket +//================================================================================================= +SocketInfo* ListenStart(uint32_t ListenPort) { + addrinfo hints, *addrInfo; + int ListenSocket = -1; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_INET; // Typically listen on IPv4 for simplicity, or + // AF_UNSPEC for both + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; // Use my IP + + std::string portStr = std::to_string(ListenPort); + if (getaddrinfo(nullptr, portStr.c_str(), &hints, &addrInfo) != 0) { + return nullptr; + } + + ListenSocket = + socket(addrInfo->ai_family, addrInfo->ai_socktype, addrInfo->ai_protocol); + if (ListenSocket != -1) { +#if NETIMGUI_FORCE_TCP_LISTEN_BINDING + int flag = 1; + setsockopt(ListenSocket, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); +#ifdef SO_REUSEPORT // SO_REUSEPORT might not be available on all POSIX systems + setsockopt(ListenSocket, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag)); +#endif +#endif + + if (bind(ListenSocket, addrInfo->ai_addr, addrInfo->ai_addrlen) != -1 && + listen(ListenSocket, SOMAXCONN) != -1) // Use SOMAXCONN for backlog + { + // Keep listening socket blocking for accept() simplicity, + // the *accepted* socket will be non-blocking via SocketInfo ctor + int flags = fcntl(ListenSocket, F_GETFL, 0); + fcntl(ListenSocket, F_SETFL, flags & (~O_NONBLOCK)); // Ensure blocking + + freeaddrinfo(addrInfo); + // Note: We create SocketInfo wrapper here just for consistency, + // but it doesn't set options on the *listening* socket. + return netImguiNew(ListenSocket); + } + close(ListenSocket); + } + + freeaddrinfo(addrInfo); + return nullptr; +} + +//================================================================================================= +// Accept a new connection (blocking call on ListenSocket) +//================================================================================================= +SocketInfo* ListenConnect(SocketInfo* pListenSocket) { + if (pListenSocket && pListenSocket->mSocket != -1) { + sockaddr_storage ClientAddress; + socklen_t Size = sizeof(ClientAddress); + // ListenSocket should be blocking (set in ListenStart) + int ServerSocket = + accept(pListenSocket->mSocket, (sockaddr*)&ClientAddress, &Size); + if (ServerSocket != -1) { + VLOG(1, "TCP connection accepted (fd=%d)", ServerSocket); + // Create SocketInfo wrapper, which sets the new socket to non-blocking + return netImguiNew(ServerSocket); + } + } + return nullptr; +} + +//================================================================================================= +// Close a connection and free allocated object +//================================================================================================= +void Disconnect(SocketInfo* pClientSocket) { + if (pClientSocket && pClientSocket->mSocket != -1) { + // Set SO_LINGER option to force close and discard pending data + // to ensure the socket is closed immediately and exits the CLOSE_WAIT state + // more reliably + struct linger sl; + sl.l_onoff = 1; // Enable linger + sl.l_linger = 0; // Set timeout to 0 seconds (force RST) + setsockopt(pClientSocket->mSocket, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl)); + + shutdown(pClientSocket->mSocket, SHUT_RDWR); + close(pClientSocket->mSocket); + pClientSocket->mSocket = -1; // Mark as closed + } + netImguiDelete(pClientSocket); +} + +//================================================================================================= +// Return true if data has been received, or there's a connection error +//================================================================================================= +bool DataReceivePending(SocketInfo* pClientSocket) { + if (!pClientSocket || pClientSocket->mSocket == -1) { + return true; // Error condition + } + + // Use poll() instead of select() to avoid FD_SETSIZE limitation. + struct pollfd pfd = {pClientSocket->mSocket, POLLIN, 0}; + int result = poll(&pfd, 1, 0); // 0ms timeout = non-blocking check + + // poll() syscall error (e.g. EINTR) — treat as "no data" and retry next + // frame rather than speculatively calling recv() on unknown socket state. + if (result < 0) { + return false; + } + + // No events on the socket. + if (result == 0) { + return false; + } + + // result > 0: the socket has events. + if (pfd.revents & POLLERR) { + // Report as data-pending so the caller's recv() surfaces the error + // through its own error-handling path. Info, not Error: this is routine + // when the peer tears the connection down (e.g. viewer shutdown). + VLOG(1, "DataReceivePending: POLLERR revents=%d", pfd.revents); + return true; + } + + if (pfd.revents & POLLHUP) { + // Peer hung up. The persistent TCP proxy keeps connections alive across + // browser refreshes, so a transient POLLHUP does not mean the session is + // over — ignore it. + VLOG(1, "DataReceivePending: POLLHUP revents=%d", pfd.revents); + } + + // Only signal data-pending when the kernel has bytes ready to read. + return (pfd.revents & POLLIN) != 0; +} + +//================================================================================================= +// Receive as much as possible into PendingCom buffer (Non-Blocking) +//================================================================================================= +void DataReceive(SocketInfo* pClientSocket, + NetImgui::Internal::PendingCom& PendingComRcv) { + // Invalid command or socket state + if (!pClientSocket || pClientSocket->mSocket == -1 || + !PendingComRcv.pCommand) { + PendingComRcv.bError = true; + return; + } + + size_t BytesToRead = + PendingComRcv.pCommand->mSize - PendingComRcv.SizeCurrent; + if (BytesToRead == 0) { + return; // Already fully received + } + + // Receive data from remote connection (non-blocking) + ssize_t resultRcv = + recv(pClientSocket->mSocket, + &reinterpret_cast( + PendingComRcv.pCommand)[PendingComRcv.SizeCurrent], + BytesToRead, + 0); // No flags, non-blocking behavior comes from socket setting + + if (resultRcv > 0) { + // Successfully received some data + PendingComRcv.SizeCurrent += static_cast(resultRcv); + PendingComRcv.bError = false; // Reset error flag on successful read + } else if (resultRcv == 0) { + // Connection closed gracefully by peer + PendingComRcv.bError = true; + VLOG(1, "DataReceive: Connection closed gracefully"); + } else { // resultRcv < 0 + // Error occurred + if (errno == EWOULDBLOCK || errno == EAGAIN) { + // Not an error, just no data available right now on non-blocking socket + PendingComRcv.bError = false; + } else { + // Actual socket error + PendingComRcv.bError = true; + } + } +} + +//================================================================================================= +// Send as much as possible from PendingCom buffer (Non-Blocking) +//================================================================================================= +void DataSend(SocketInfo* pClientSocket, + NetImgui::Internal::PendingCom& PendingComSend) { + // Invalid command or socket state + if (!pClientSocket || pClientSocket->mSocket == -1 || + !PendingComSend.pCommand) { + PendingComSend.bError = true; + return; + } + + size_t BytesRemaining = + PendingComSend.pCommand->mSize - PendingComSend.SizeCurrent; + if (BytesRemaining == 0) { + return; // Already fully sent + } + + // Limit send size per call [cite: 281] + size_t BytesToSend = + BytesRemaining > static_cast(pClientSocket->mSendSizeMax) + ? static_cast(pClientSocket->mSendSizeMax) + : BytesRemaining; + + // Send data to remote connection (non-blocking) + ssize_t resultSent = + send(pClientSocket->mSocket, + &reinterpret_cast( + PendingComSend.pCommand)[PendingComSend.SizeCurrent], + BytesToSend, + MSG_NOSIGNAL); // Use MSG_NOSIGNAL to prevent SIGPIPE on Linux if + // connection is broken + + if (resultSent > 0) { + // Successfully sent some data + PendingComSend.SizeCurrent += static_cast(resultSent); + PendingComSend.bError = false; // Reset error flag on successful send + } else if (resultSent == 0) { + // This shouldn't typically happen with TCP unless BytesToSend was 0 + PendingComSend.bError = false; // Treat as non-error for now + } else { // resultSent < 0 + // Error occurred + if (errno == EWOULDBLOCK || errno == EAGAIN) { + // Not an error, socket buffer is full, try again later + PendingComSend.bError = false; + } else { + // Actual socket error (e.g., EPIPE if connection broken and MSG_NOSIGNAL + // not used/supported) + PendingComSend.bError = true; + } + } +} + +} // namespace Network +} // namespace Internal +} // namespace NetImgui +#else + +// Prevents Linker warning LNK4221 in Visual Studio (This object file does not +// define any previously undefined public symbols, so it will not be used by any +// link operation that consumes this library) +extern int sSuppresstLNK4221_NetImgui_NetworkPosix; +int sSuppresstLNK4221_NetImgui_NetworkPosix(0); + +#endif // #if NETIMGUI_ENABLED && NETIMGUI_POSIX_SOCKETS_ENABLED diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_NetworkWin32.cpp b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_NetworkWin32.cpp new file mode 100644 index 00000000..27fbdc4f --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_NetworkWin32.cpp @@ -0,0 +1,258 @@ +#include "NetImgui_Shared.h" + +#if NETIMGUI_ENABLED && NETIMGUI_WINSOCKET_ENABLED +#include +#include + +#include "NetImgui_WarningDisableStd.h" + +#if defined(_MSC_VER) +#pragma comment(lib, "ws2_32") +#endif + +#include "NetImgui_CmdPackets.h" + +namespace NetImgui { +namespace Internal { +namespace Network { +//================================================================================================= +// Wrapper around native socket object and init some socket options +//================================================================================================= +struct SocketInfo { + SocketInfo(SOCKET socket) : mSocket(socket) { + u_long kNonBlocking = true; + ioctlsocket(mSocket, static_cast(FIONBIO), &kNonBlocking); + + constexpr DWORD kComsNoDelay = 1; + setsockopt(mSocket, SOL_SOCKET, TCP_NODELAY, + reinterpret_cast(&kComsNoDelay), + sizeof(kComsNoDelay)); + + const int kComsSendBuffer = 2 * mSendSizeMax; + setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, + reinterpret_cast(&kComsSendBuffer), + sizeof(kComsSendBuffer)); + + // constexpr int kComsRcvBuffer = 1014*1024; + // setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast(&kComsRcvBuffer), sizeof(kComsRcvBuffer)); + } + + SOCKET mSocket; + int mSendSizeMax = + 1024 * + 1024; // Limit tx data to avoid socket error on large amount (texture) +}; + +bool Startup() { + WSADATA wsa; + if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) return false; + + return true; +} + +void Shutdown() { WSACleanup(); } + +//================================================================================================= +// Try establishing a connection to a remote client at given address +//================================================================================================= +SocketInfo* Connect(const char* ServerHost, uint32_t ServerPort) { + const timeval kConnectTimeout = { + 1, 0}; // Waiting 1 seconds before failing connection attempt + u_long kNonBlocking = true; + + SOCKET ClientSocket = socket(AF_INET, SOCK_STREAM, 0); + if (ClientSocket == INVALID_SOCKET) return nullptr; + + char zPortName[32] = {}; + addrinfo* pResults = nullptr; + SocketInfo* pSocketInfo = nullptr; + NetImgui::Internal::StringFormat(zPortName, "%i", ServerPort); + getaddrinfo(ServerHost, zPortName, nullptr, &pResults); + addrinfo* pResultCur = pResults; + fd_set SocketSet; + + ioctlsocket(ClientSocket, static_cast(FIONBIO), &kNonBlocking); + while (pResultCur && !pSocketInfo) { + int Result = connect(ClientSocket, pResultCur->ai_addr, + static_cast(pResultCur->ai_addrlen)); + bool Connected = Result != SOCKET_ERROR; + + // Not connected yet, wait some time before bailing out + if (Result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) { + FD_ZERO(&SocketSet); + FD_SET(ClientSocket, &SocketSet); + Result = select(0, nullptr, &SocketSet, nullptr, &kConnectTimeout); + Connected = + Result == 1; // when 1 socket ready for write, otherwise it's -1 or 0 + } + + if (Connected) { + pSocketInfo = netImguiNew(ClientSocket); + } + + pResultCur = pResultCur->ai_next; + } + freeaddrinfo(pResults); + if (!pSocketInfo) { + closesocket(ClientSocket); + } + return pSocketInfo; +} + +//================================================================================================= +// Start waiting for connection request on this socket +//================================================================================================= +SocketInfo* ListenStart(uint32_t ListenPort) { + SOCKET ListenSocket = INVALID_SOCKET; + if ((ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != + INVALID_SOCKET) { + sockaddr_in server; + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(static_cast(ListenPort)); + +#if NETIMGUI_FORCE_TCP_LISTEN_BINDING + constexpr BOOL ReUseAdrValue(true); + setsockopt(ListenSocket, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast(&ReUseAdrValue), + sizeof(ReUseAdrValue)); +#endif + if (bind(ListenSocket, reinterpret_cast(&server), + sizeof(server)) != SOCKET_ERROR && + listen(ListenSocket, 0) != SOCKET_ERROR) { + u_long kIsNonBlocking = false; + ioctlsocket(ListenSocket, static_cast(FIONBIO), &kIsNonBlocking); + return netImguiNew(ListenSocket); + } + closesocket(ListenSocket); + } + return nullptr; +} + +//================================================================================================= +// Establish a new connection to a remote request +//================================================================================================= +SocketInfo* ListenConnect(SocketInfo* ListenSocket) { + if (ListenSocket) { + sockaddr ClientAddress; + int Size(sizeof(ClientAddress)); + SOCKET ClientSocket = accept(ListenSocket->mSocket, &ClientAddress, &Size); + if (ClientSocket != INVALID_SOCKET) { + return netImguiNew(ClientSocket); + } + } + return nullptr; +} + +//================================================================================================= +// Close a connection and free allocated object +//================================================================================================= +void Disconnect(SocketInfo* pClientSocket) { + if (pClientSocket) { + shutdown(pClientSocket->mSocket, SD_BOTH); + closesocket(pClientSocket->mSocket); + netImguiDelete(pClientSocket); + } +} + +//================================================================================================= +// Return true if data has been received, or there's a connection error +//================================================================================================= +bool DataReceivePending(SocketInfo* pClientSocket) { + const timeval kConnectTimeout = {0, 0}; // No wait time + if (pClientSocket) { + fd_set fdSetRead; + fd_set fdSetErr; + FD_ZERO(&fdSetRead); + FD_ZERO(&fdSetErr); + FD_SET(pClientSocket->mSocket, &fdSetRead); + FD_SET(pClientSocket->mSocket, &fdSetErr); + + // Note: return true if data ready or connection error (to exit parent loop + // waiting on data) + int result = select(0, &fdSetRead, nullptr, &fdSetErr, &kConnectTimeout); + return result != 0; + } + return true; +} + +//================================================================================================= +// Receive as much as possible a command and keep track of transfer status +//================================================================================================= +void DataReceive(SocketInfo* pClientSocket, + NetImgui::Internal::PendingCom& PendingComRcv) { + // Invalid command + if (!pClientSocket || !PendingComRcv.pCommand || !pClientSocket->mSocket) { + PendingComRcv.bError = true; + return; + } + + // Receive data from remote connection + int resultRcv = recv(pClientSocket->mSocket, + &reinterpret_cast( + PendingComRcv.pCommand)[PendingComRcv.SizeCurrent], + static_cast(PendingComRcv.pCommand->mSize - + PendingComRcv.SizeCurrent), + 0); + + // Note: 'DataReceive' is called after pending data has been confirm. + // 0 received data means connection lost + if (resultRcv != SOCKET_ERROR) { + PendingComRcv.SizeCurrent += static_cast(resultRcv); + PendingComRcv.bError |= + resultRcv <= 0; // Error if no data read since DataReceivePending() + // said there was some available + } + // Connection error, abort transmission + else if (WSAGetLastError() != WSAEWOULDBLOCK) { + PendingComRcv.bError = true; + } +} + +//================================================================================================= +// Receive as much as possible a command and keep track of transfer status +//================================================================================================= +void DataSend(SocketInfo* pClientSocket, + NetImgui::Internal::PendingCom& PendingComSend) { + // Invalid command + if (!pClientSocket || !PendingComSend.pCommand || !pClientSocket->mSocket) { + PendingComSend.bError = true; + return; + } + + // Send data to remote connection + int sizeToSend = static_cast(PendingComSend.pCommand->mSize - + PendingComSend.SizeCurrent); + sizeToSend = sizeToSend > pClientSocket->mSendSizeMax + ? pClientSocket->mSendSizeMax + : sizeToSend; + int resultSent = + send(pClientSocket->mSocket, + &reinterpret_cast( + PendingComSend.pCommand)[PendingComSend.SizeCurrent], + sizeToSend, 0); + + if (resultSent != SOCKET_ERROR) { + PendingComSend.SizeCurrent += static_cast(resultSent); + } + // Connection error, abort transmission + else if (WSAGetLastError() != WSAEWOULDBLOCK) { + PendingComSend.bError = true; + } +} + +} // namespace Network +} // namespace Internal +} // namespace NetImgui + +#include "NetImgui_WarningReenable.h" +#else + +// Prevents Linker warning LNK4221 in Visual Studio (This object file does not +// define any previously undefined public symbols, so it will not be used by any +// link operation that consumes this library) +extern int sSuppresstLNK4221_NetImgui_NetworkWin23; +int sSuppresstLNK4221_NetImgui_NetworkWin23(0); + +#endif // #if NETIMGUI_ENABLED && NETIMGUI_WINSOCKET_ENABLED diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Shared.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Shared.h new file mode 100644 index 00000000..aa197efe --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Shared.h @@ -0,0 +1,205 @@ +#pragma once + +//================================================================================================= +// Include NetImgui_Api.h with almost no warning suppression. +// this is to make sure library user does not need to suppress any +#if defined(_MSC_VER) +#pragma warning(disable \ + : 4464) // warning C4464: relative include path contains '..' +#endif + +#ifndef NETIMGUI_INTERNAL_INCLUDE +#define NETIMGUI_INTERNAL_INCLUDE 1 +#include "NetImgui_Api.h" +#undef NETIMGUI_INTERNAL_INCLUDE +#else +#include "NetImgui_Api.h" +#endif + +#if NETIMGUI_ENABLED + +//================================================================================================= +// Include a few standard c++ header, with additional warning suppression +#include +#include +#include +#include + +#include "NetImgui_WarningDisableStd.h" +#include "NetImgui_WarningReenable.h" +//================================================================================================= + +//================================================================================================= +#include "NetImgui_WarningDisable.h" +namespace NetImgui { +namespace Internal { + +using ComDataType = uint64_t; +constexpr size_t ComDataSize = sizeof(ComDataType); +using ClientTextureID = uint64_t; + +//============================================================================= +// All allocations made by netImgui goes through here. +// Relies in ImGui allocator +//============================================================================= +template +TType* netImguiNew(Args... args); +template +TType* netImguiSizedNew(size_t placementSize); +template +void netImguiDelete(TType* pData); +template +void netImguiDeleteSafe(TType*& pData); + +class ScopedImguiContext { + public: + ScopedImguiContext(ImGuiContext* pNewContext) + : mpSavedContext(ImGui::GetCurrentContext()) { + ImGui::SetCurrentContext(pNewContext); + } + ~ScopedImguiContext() { ImGui::SetCurrentContext(mpSavedContext); } + + protected: + ImGuiContext* mpSavedContext; +}; + +template +class ScopedValue { + public: + ScopedValue(TType& ValueRef, TType Value) + : mValueRef(ValueRef), mValueRestore(ValueRef) { + mValueRef = Value; + } + ~ScopedValue() { mValueRef = mValueRestore; } + + protected: + TType& mValueRef; + TType mValueRestore; + uint8_t mPadding[sizeof(void*) - (sizeof(TType) % 8)] = {}; + + // Prevents warning about implicitly delete functions + ScopedValue(const ScopedValue&) = delete; + ScopedValue(const ScopedValue&&) = delete; + void operator=(const ScopedValue&) = delete; +}; + +using ScopedBool = ScopedValue; + +//============================================================================= +// Class to safely exchange a pointer between two threads +//============================================================================= +template +class ExchangePtr { + public: + ExchangePtr() : mpData(nullptr) {} + ~ExchangePtr(); + inline TType* Release(); + inline void Assign(TType*& pNewData); + inline void Free(); + inline bool IsNull() const { return mpData.load() == nullptr; } + + private: + std::atomic mpData; + + // Prevents warning about implicitly delete functions + private: + ExchangePtr(const ExchangePtr&) = delete; + ExchangePtr(const ExchangePtr&&) = delete; + void operator=(const ExchangePtr&) = delete; +}; + +//============================================================================= +// Make data serialization easier +//============================================================================= +template +struct OffsetPointer { + inline OffsetPointer(); + inline explicit OffsetPointer(TType* pPointer); + inline explicit OffsetPointer(uint64_t offset); + + inline bool IsPointer() const; + inline bool IsOffset() const; + + inline TType* ToPointer(); + inline uint64_t ToOffset(); + inline TType* operator->(); + inline const TType* operator->() const; + inline TType& operator[](size_t index); + inline const TType& operator[](size_t index) const; + + inline TType* Get(); + inline const TType* Get() const; + inline const ComDataType* GetComData() const; + inline uint64_t GetOff() const; + inline void SetPtr(TType* pPointer); + inline void SetComDataPtr(ComDataType* pPointer); + inline void SetOff(uint64_t offset); + + private: + union { + uint64_t mOffset; + TType* mPointer; + }; +}; + +//============================================================================= +//============================================================================= +template +class Ringbuffer { + public: + Ringbuffer() : mPosCur(0), mPosLast(0) {} + void AddData(const TType* pData, size_t& count); + bool ReadData(TType* pData); + + private: + TType mBuffer[TCount] = {0}; + std::atomic_uint64_t mPosCur; + std::atomic_uint64_t mPosLast; + + // Prevents warning about implicitly delete functions + private: + Ringbuffer(const Ringbuffer&) = delete; + Ringbuffer(const Ringbuffer&&) = delete; + void operator=(const Ringbuffer&) = delete; +}; + +template +constexpr std::size_t ArrayCount(T const (&)[N]) noexcept { + return N; +} + +//============================================================================= +//============================================================================= +template +inline void StringCopy(char (&output)[charCount], const char* pSrc, + size_t srcCharCount = 0xFFFFFFFE); + +template +int StringFormat(char (&output)[charCount], char const* const format, ...); + +//============================================================================= +// Get the (value / Denominator) rounded up to the next int value big enough +//============================================================================= +template +IntType DivUp(IntType Value, IntType Denominator); + +//============================================================================= +// Get the rounded up value +//============================================================================= +template +IntType RoundUp(IntType Value, IntType Round); + +#if NETIMGUI_IMGUI_TEXTURES_ENABLED +inline NetImgui::eTexFormat ConvertTextureFormat(ImTextureFormat ImFormat); +inline ClientTextureID ConvertToClientTexID(const ImTextureRef& textureRef); +#endif +inline ClientTextureID ConvertToClientTexID(ImTextureID textureID); +inline ImTextureID ConvertFromClientTexID(ClientTextureID textureID); + +} // namespace Internal +} // namespace NetImgui + +#include "NetImgui_Shared.inl" +#include "NetImgui_WarningReenable.h" + +#endif // NETIMGUI_ENABLED diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Shared.inl b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Shared.inl new file mode 100644 index 00000000..15d65edb --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_Shared.inl @@ -0,0 +1,341 @@ +#pragma once + +#include +#include + +namespace NetImgui { namespace Internal +{ + +template +TType* netImguiNew(Args... args) +{ + return new( ImGui::MemAlloc(sizeof(TType)) ) TType(args...); +} + +template +TType* netImguiSizedNew(size_t placementSize) +{ + return new( ImGui::MemAlloc(placementSize > sizeof(TType) ? placementSize : sizeof(TType)) ) TType(); +} + +template +void netImguiDelete(TType* pData) +{ + if( pData ) + { + pData->~TType(); + ImGui::MemFree(pData); + } +} + +template +void netImguiDeleteSafe(TType*& pData) +{ + netImguiDelete(pData); + pData = nullptr; +} + +//============================================================================= +// Acquire ownership of the resource +//============================================================================= +template +TType* ExchangePtr::Release() +{ + return mpData.exchange(nullptr); +} + +//----------------------------------------------------------------------------- +// Take ownership of the provided data. +// If there's a previous unclaimed pointer to some data, release it +//----------------------------------------------------------------------------- +template +void ExchangePtr::Assign(TType*& pNewData) +{ + netImguiDelete( mpData.exchange(pNewData) ); + pNewData = nullptr; +} + +template +void ExchangePtr::Free() +{ + TType* pNull(nullptr); + Assign(pNull); +} + +template +ExchangePtr::~ExchangePtr() +{ + Free(); +} + +//============================================================================= +// +//============================================================================= +template +OffsetPointer::OffsetPointer() +: mOffset(0) +{ + SetOff(0); +} + +template +OffsetPointer::OffsetPointer(TType* pPointer) +{ + SetPtr(pPointer); +} + +template +OffsetPointer::OffsetPointer(uint64_t offset) +{ + SetOff(offset); +} + +template +void OffsetPointer::SetPtr(TType* pPointer) +{ + mOffset = 0; // Remove 'offset flag' that can be left active on non 64bits pointer + mPointer = pPointer; +} + +template +void OffsetPointer::SetComDataPtr(ComDataType* pPointer) +{ + SetPtr(reinterpret_cast(pPointer)); +} + +template +void OffsetPointer::SetOff(uint64_t offset) +{ + mOffset = offset | 0x0000000000000001u; +} + +template +uint64_t OffsetPointer::GetOff()const +{ + return mOffset & ~0x0000000000000001u; +} + +template +bool OffsetPointer::IsOffset()const +{ + return (mOffset & 0x0000000000000001u) != 0; +} + +template +bool OffsetPointer::IsPointer()const +{ + return !IsOffset(); +} + +template +TType* OffsetPointer::ToPointer() +{ + assert(IsOffset()); + SetPtr( reinterpret_cast( reinterpret_cast(&mPointer) + GetOff() ) ); + return mPointer; +} + +template +uint64_t OffsetPointer::ToOffset() +{ + assert(IsPointer()); + SetOff( reinterpret_cast(mPointer) - reinterpret_cast(&mPointer) ); + return mOffset; +} + +template +TType* OffsetPointer::operator->() +{ + assert(IsPointer()); + return mPointer; +} + +template +const TType* OffsetPointer::operator->()const +{ + assert(IsPointer()); + return mPointer; +} + +template +TType* OffsetPointer::Get() +{ + assert(IsPointer()); + return mPointer; +} + +template +const TType* OffsetPointer::Get()const +{ + assert(IsPointer()); + return mPointer; +} + +template +const ComDataType* OffsetPointer::GetComData()const +{ + return reinterpret_cast(Get()); +} + +template +TType& OffsetPointer::operator[](size_t index) +{ + assert(IsPointer()); + return mPointer[index]; +} + +template +const TType& OffsetPointer::operator[](size_t index)const +{ + assert(IsPointer()); + return mPointer[index]; +} + +//============================================================================= +template +void Ringbuffer::AddData(const TType* pData, size_t& count) +//============================================================================= +{ + size_t i(0); + while (i < count && (mPosLast - mPosCur < TCount)) { + mBuffer[mPosLast % TCount] = pData[i]; + mPosLast++; + i++; + } + count = i; +} + +//============================================================================= +template +bool Ringbuffer::ReadData(TType* pData) +//============================================================================= +{ + if (mPosCur < mPosLast) + { + *pData = mBuffer[mPosCur % TCount]; + mPosCur++; + return true; + } + return false; +} + + +//============================================================================= +// The _s string functions are a mess. There's really no way to do this right +// in a cross-platform way. Best solution I've found is to set just use +// strncpy, infer the buffer length, and null terminate. Still need to suppress +// the warning on Windows. +// See https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/ +// and many other discussions online on the topic. +//============================================================================= +template +void StringCopy(char (&output)[charCount], const char* pSrc, size_t srcCharCount) +{ +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) + #pragma warning (push) + #pragma warning (disable: 4996) // warning C4996: 'strncpy': This function or variable may be unsafe. +#endif + + size_t charToCopyCount = charCount < srcCharCount + 1 ? charCount : srcCharCount + 1; + strncpy(output, pSrc, charToCopyCount - 1); + output[charCount - 1] = 0; + +#if defined(_MSC_VER) && defined(__clang__) + #pragma clang diagnostic pop +#elif defined(_MSC_VER) + #pragma warning (pop) +#endif +} + +template +int StringFormat(char(&output)[charCount], char const* const format, ...) +{ +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wformat-nonliteral" +#endif + + va_list args; + va_start(args, format); + int w = vsnprintf(output, charCount, format, args); + va_end(args); + output[charCount - 1] = 0; + return w; + +#if defined(__clang__) + #pragma clang diagnostic pop +#endif +} + +//============================================================================= +//============================================================================= +template +IntType DivUp(IntType Value, IntType Denominator) +{ + return (Value + Denominator - 1) / Denominator; +} + +template +IntType RoundUp(IntType Value, IntType Round) +{ + return DivUp(Value, Round) * Round; +} + +union TextureCastHelperUnion +{ + const void* TexData; + ImTextureID TexID; + ClientTextureID TexClientID; +}; + +#if NETIMGUI_IMGUI_TEXTURES_ENABLED +NetImgui::eTexFormat ConvertTextureFormat(ImTextureFormat ImFormat) +{ + switch(ImFormat) + { + case ImTextureFormat_RGBA32: return eTexFormat::kTexFmtRGBA8; + case ImTextureFormat_Alpha8: return eTexFormat::kTexFmtA8; + } + return eTexFormat::kTexFmtRGBA8; +} + +ClientTextureID ConvertToClientTexID(const ImTextureRef& textureRef) +{ + static_assert(sizeof(uint64_t) >= sizeof(ImTextureID), "ImTextureID is bigger than 64bits, CmdTexture::mTextureId needs to be updated to support it"); + TextureCastHelperUnion textureUnion; + textureUnion.TexClientID = 0; + if( textureRef._TexData ){ + //Note: Cannot rely on textureRef.GetTexID() because it uses a pointer to + // a texture object that might not have been created by the backend yet. + // Instead, use a stable value that remain valid for texture lifetime, + // to id it with the NetImgui Server + textureUnion.TexClientID = static_cast(textureRef._TexData->UniqueID); + } + else{ + textureUnion.TexID = textureRef._TexID; + } + return textureUnion.TexClientID; +} +#endif + +ClientTextureID ConvertToClientTexID(ImTextureID textureID) +{ + static_assert(sizeof(uint64_t) >= sizeof(ImTextureID), "ImTextureID is bigger than 64bits, CmdTexture::mTextureId needs to be updated to support it"); + TextureCastHelperUnion textureUnion; + textureUnion.TexClientID = 0; + textureUnion.TexID = textureID; + return textureUnion.TexClientID; + +} + +ImTextureID ConvertFromClientTexID(ClientTextureID clientTexID) +{ + TextureCastHelperUnion textureUnion; + textureUnion.TexClientID = clientTexID; + return textureUnion.TexID; +} + +}} //namespace NetImgui::Internal diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisable.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisable.h new file mode 100644 index 00000000..d185eb80 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisable.h @@ -0,0 +1,52 @@ +#pragma once +// +// Deactivate a few warnings to allow internal netImgui code to compile +// with 'Warning as error' and '-Wall' compile actions enabled +// + +//================================================================================================= +// Clang +//================================================================================================= +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wold-style-cast" // For ImTextureID_Invalid +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#pragma clang diagnostic ignored "-Wswitch-default" +#pragma clang diagnostic ignored \ + "-Wnontrivial-memcall" // For ImGui::IO memcpy warning + +//================================================================================================= +// Visual Studio warnings +//================================================================================================= +#elif defined(_MSC_VER) +#pragma warning(disable : 5032) // detected #pragma warning(push) with no + // corresponding #pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4365) // conversion from 'long' to 'unsigned int', + // signed/unsigned mismatch for +#pragma warning(disable : 4464) // relative include path contains '..' +#pragma warning(disable \ + : 4514) // unreferenced inline function has been removed +#pragma warning( \ + disable \ + : 4577) // 'noexcept' used with no exception handling mode specified; + // termination on exception is not guaranteed. Specify +#pragma warning(disable : 4710) // 'xxx': function not inlined +#pragma warning( \ + disable : 4711) // function 'xxx' selected for automatic inline expansion +#pragma warning( \ + disable \ + : 4826) // Conversion from 'TType *' to 'uint64_t' is sign-extended. This + // may cause unexpected runtime behavior. +#pragma warning(disable \ + : 5031) // #pragma warning(pop): likely mismatch, popping + // warning state pushed in different file +#pragma warning(disable : 5045) // Compiler will insert Spectre mitigation for + // memory load if / Qspectre switch specified +#pragma warning(disable : 5264) // 'xxx': 'const' variable is not used + +#endif diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisableImgui.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisableImgui.h new file mode 100644 index 00000000..bb803219 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisableImgui.h @@ -0,0 +1,48 @@ +#pragma once +// +// Deactivate a few warnings to allow Imgui header includes, +// without generating warnings in '-Wall' compile actions enabled +// + +//================================================================================================= +// Clang +//================================================================================================= +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#pragma clang diagnostic ignored \ + "-Wnonportable-include-path" // Sharpmake convert include path to + // lowercase, avoid warning +#pragma clang diagnostic ignored \ + "-Wreserved-identifier" // Enum values using '__' or member starting with + // '_' in imgui.h + +//================================================================================================= +// Visual Studio warnings +//================================================================================================= +#elif defined(_MSC_VER) +#pragma warning(push) +#pragma warning( \ + disable : 4514) // 'xxx': unreferenced inline function has been removed +#pragma warning(disable : 4365) // '=': conversion from 'ImGuiTabItemFlags' to + // 'ImGuiID', signed/unsigned mismatch +#pragma warning(disable : 4710) // 'xxx': function not inlined +#pragma warning( \ + disable \ + : 4820) // 'xxx': 'yyy' bytes padding added after data member 'zzz' +#pragma warning(disable \ + : 5031) // #pragma warning(pop): likely mismatch, popping + // warning state pushed in different file +#pragma warning(disable : 5045) // Compiler will insert Spectre mitigation for + // memory load if /Qspectre switch specified +#if _MSC_VER >= 1920 +#pragma warning(disable : 5219) // implicit conversion from 'int' to 'float', + // possible loss of data +#endif +#pragma warning( \ + disable \ + : 26495) // Code Analysis warning : Variable + // 'ImGuiStorage::ImGuiStoragePair::::val_p' is + // uninitialized. Always initialize a member variable (type.6). +#endif diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisableStd.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisableStd.h new file mode 100644 index 00000000..1ae15f10 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningDisableStd.h @@ -0,0 +1,32 @@ +#pragma once +// +// Deactivate a few more warnings to allow standard header includes, +// without generating warnings in '-Wall' compile actions enabled +// + +#include "NetImgui_WarningDisable.h" + +//================================================================================================= +// Clang +//================================================================================================= +#if defined(__clang__) + +//================================================================================================= +// Visual Studio warnings +//================================================================================================= +#elif defined(_MSC_VER) +#pragma warning(disable \ + : 4061) // enumerator xxx in switch of enum yyy is not + // explicitly handled by a case label (d3d11.h) +#pragma warning(disable \ + : 4548) // expression before comma has no effect; expected + // expression with side - effect (malloc.h VS2017) +#pragma warning(disable \ + : 4668) // xxx is not defined as a preprocessor macro, + // replacing with '0' for '#if/#elif' (winsock2.h) +#pragma warning(disable : 4574) // xxx is defined to be '0': did you mean to + // use yyy (winsock2.h VS2017) +#pragma warning( \ + disable : 4820) // xxx : yyy bytes padding added after data member zzz + +#endif diff --git a/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningReenable.h b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningReenable.h new file mode 100644 index 00000000..ff200586 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Client/Private/NetImgui_WarningReenable.h @@ -0,0 +1,15 @@ + +#pragma once + +//================================================================================================= +// Clang +//================================================================================================= +#if defined(__clang__) +#pragma clang diagnostic pop + +//================================================================================================= +// Visual Studio warnings +//================================================================================================= +#elif defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/python/mujoco/experimental/netimgui/Code/Sample/Common/Sample.cpp b/python/mujoco/experimental/netimgui/Code/Sample/Common/Sample.cpp new file mode 100644 index 00000000..f59fb71b --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Sample/Common/Sample.cpp @@ -0,0 +1,195 @@ +//================================================================================================= +// SAMPLE +//------------------------------------------------------------------------------------------------- +// Common code shared by all samples +//================================================================================================= + +#include "Sample.h" + +#include +#include + +#include "../../ServerApp/Source/Fonts/Roboto_Medium.cpp" + +namespace Sample { +//================================================================================================= +// Constructor +//------------------------------------------------------------------------------------------------- +// +//================================================================================================= +Base::Base(const char* sampleName) : mSampleName(sampleName) { +#if NETIMGUI_ENABLED + mConnect_PortClient = NetImgui::kDefaultClientPort; + mConnect_PortServer = NetImgui::kDefaultServerPort; +#endif +} + +//================================================================================================= +// Startup +//------------------------------------------------------------------------------------------------- +// +//================================================================================================= +bool Base::Startup() { +#if NETIMGUI_ENABLED + if (!NetImgui::Startup()) return false; +#endif + AddFont(); + return true; +} + +//================================================================================================= +// Shutdown +//------------------------------------------------------------------------------------------------- +// +//================================================================================================= +void Base::Shutdown() { +#if NETIMGUI_ENABLED + NetImgui::Shutdown(); +#endif +} + +//================================================================================================= +// AddFont +//------------------------------------------------------------------------------------------------- +// Add and configure the fonts wanted in the demo. +// Method can be overriden to use different font, byt default to Roboto 18pts +// +// Note: Since Dear ImGui 1.92+, we do not need to manage font +// scaling/dpi at all, +// It is automatically done, and NetImgui Server also +//assign desired DPI behind the scene. +//================================================================================================= +void Base::AddFont() { + constexpr float kFontPixelSize = 16.f; + ImFontConfig FontConfig = {}; +// Using Roboto Font for prettier results +#if 1 + // Note: Using memcpy to avoid warnings related to OS string copy variations, + // and cannot rely on 'NetImgui::Internal::StringCopy' that can + //handle this problem because 'SampleDisabled' couln't compile properly + const char FontName[] = "Roboto Medium"; + memcpy(FontConfig.Name, FontName, sizeof(FontName)); + ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF( + Roboto_Medium_compressed_data, Roboto_Medium_compressed_size, + kFontPixelSize, &FontConfig); + +// But can as easily rely on the default font +#else + FontConfig.SizePixels = kFontPixelSize; + FontAtlas->AddFontDefault(&FontConfig); +#endif +} + +//================================================================================================= +// Draw_Connect +//------------------------------------------------------------------------------------------------- +// Function called by all samples, to display the Connection Options, and some +// other default MainMenu entries. +//================================================================================================= +void Base::Draw_Connect() { +#if NETIMGUI_ENABLED + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(3, 6)); + if (ImGui::BeginMainMenuBar()) { + ImGui::AlignTextToFramePadding(); + ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "%s", mSampleName); + ImGui::SameLine(0, 32); + + //----------------------------------------------------------------------------------------- + if (NetImgui::IsConnected()) + //----------------------------------------------------------------------------------------- + { + ImGui::TextUnformatted("Status: Connected"); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(3, 3)); + ImGui::SetCursorPosY(3); + if (ImGui::Button(" Disconnect ")) { + NetImgui::Disconnect(); + } + ImGui::PopStyleVar(); + } + + //----------------------------------------------------------------------------------------- + else if (NetImgui::IsConnectionPending()) + //----------------------------------------------------------------------------------------- + { + ImGui::TextUnformatted("Status: Waiting Server"); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(3, 3)); + ImGui::SetCursorPosY(3); + if (ImGui::Button(" Cancel ")) { + NetImgui::Disconnect(); + } + ImGui::PopStyleVar(); + } + + //----------------------------------------------------------------------------------------- + else // No connection + //----------------------------------------------------------------------------------------- + { + //------------------------------------------------------------------------------------- + if (ImGui::BeginMenu("[ Connect To ]")) + //------------------------------------------------------------------------------------- + { + ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Server Settings"); + ImGui::InputText("Hostname", mConnect_HostnameServer, + sizeof(mConnect_HostnameServer)); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip( + "Address of PC running the netImgui server application. Can be " + "an IP like 127.0.0.1"); + ImGui::InputInt("Port", &mConnect_PortServer); + ImGui::NewLine(); + ImGui::Separator(); + if (ImGui::Button("Connect", + ImVec2(ImGui::GetContentRegionAvail().x, 0))) { + NetImgui::ConnectToApp(mSampleName, mConnect_HostnameServer, + mConnect_PortServer, mCallback_ThreadLaunch); + } + ImGui::EndMenu(); + } + + if (ImGui::IsItemHovered()) + ImGui::SetTooltip( + "Attempt a connection to a remote netImgui server at the provided " + "address."); + + //------------------------------------------------------------------------------------- + if (ImGui::BeginMenu("[ Wait For ]")) + //------------------------------------------------------------------------------------- + { + ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Client Settings"); + ImGui::InputInt("Port", &mConnect_PortClient); + ImGui::NewLine(); + ImGui::Separator(); + if (ImGui::Button("Listen", + ImVec2(ImGui::GetContentRegionAvail().x, 0))) { + NetImgui::ConnectFromApp(mSampleName, mConnect_PortClient, + mCallback_ThreadLaunch); + } + ImGui::EndMenu(); + } + if (ImGui::IsItemHovered()) + ImGui::SetTooltip( + "Start listening for a connection request by a remote netImgui " + "server, on the provided Port."); + } + + ImGui::SameLine(0, 40); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.8, 0.8, 0.8, 0.9)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(3, 3)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, + mbShowDemoWindow ? 1.f : 0.f); + ImGui::SetCursorPosY(3); + if (ImGui::Button(" Show ImGui Demo ")) { + mbShowDemoWindow = !mbShowDemoWindow; + } + ImGui::PopStyleColor(); + ImGui::PopStyleVar(2); + ImGui::EndMainMenuBar(); + } + ImGui::PopStyleVar(); +#endif // #if NETIMGUI_ENABLED + if (mbShowDemoWindow) { + ImGui::ShowDemoWindow(&mbShowDemoWindow); + } +} + +}; // namespace Sample \ No newline at end of file diff --git a/python/mujoco/experimental/netimgui/Code/Sample/Common/Sample.h b/python/mujoco/experimental/netimgui/Code/Sample/Common/Sample.h new file mode 100644 index 00000000..17120486 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Sample/Common/Sample.h @@ -0,0 +1,55 @@ +#pragma once + +#include + +// Reusing internal NetImgui functions for TextureID conversion and String copy. +// Normally, you wouldn't include this file +#include + +// Forward declares when NetImgui is not enabled +// When NetImgui is disabled, it doesn't include these needed headers +#if !NETIMGUI_ENABLED +#include "imgui.h" +#endif + +namespace Sample { + +class Base { + public: + Base(const char* sampleName); //!< Constructor receiving pointer to constant + //!< string that must remains valid + virtual bool Startup(); //!< Called once when starting + virtual void Shutdown(); //!< Called once when exiting + virtual void Draw() = 0; //!< Each sample should have their Dear ImGui + //!< drawing routines in this overloaded method + virtual void AddFont(); //!< Called on startup to add the wanted font + + protected: + void Draw_Connect(); //!< Display UI for initiating a connection to the + //!< remote NetImgui server application + const char* mSampleName = + nullptr; //!< Name displayed in the Main Menu bar (must receive string + //!< pointer in constructor that remains valid) + bool mbShowDemoWindow = + !NETIMGUI_ENABLED; //!< If we should show the Dear ImGui demo window + +#if NETIMGUI_ENABLED + NetImgui::ThreadFunctPtr mCallback_ThreadLaunch = + nullptr; //!< [Optional] Thread launcher callback assigned on NetImgui + //!< connection. Used to start a new thread for coms with + //!< NetImgui server + char mConnect_HostnameServer[128] = { + "localhost"}; //!< IP/Hostname used to send a connection request when + //!< when trying to reach the server + int mConnect_PortServer = 0; //!< Port used to send a connection request when + //!< when trying to reach the server + int mConnect_PortClient = + 0; //!< Port opened when waiting for a server connection request +#endif +}; +}; // namespace Sample + +Sample::Base& GetSample(); // Each Sample must implement this function and + // return a valid sample object + +#include diff --git a/python/mujoco/experimental/netimgui/Code/Sample/Common/main.cpp b/python/mujoco/experimental/netimgui/Code/Sample/Common/main.cpp new file mode 100644 index 00000000..2612c78f --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Sample/Common/main.cpp @@ -0,0 +1,423 @@ +// Dear ImGui: standalone example application for DirectX 11 + +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ +// folder). +// - Introduction, links and more at the top of imgui.cpp +//================================================================================================= +// @SAMPLE_EDIT +#include +#include + +#include "Sample.h" +//================================================================================================= + +#include +#include + +#include "imgui.h" +#include "imgui_impl_dx11.h" +#include "imgui_impl_win32.h" + +// Data +ID3D11Device* g_pd3dDevice = nullptr; // @SAMPLE_EDIT (removed static) +static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr; +static IDXGISwapChain* g_pSwapChain = nullptr; +static bool g_SwapChainOccluded = false; +static UINT g_ResizeWidth = 0, g_ResizeHeight = 0; +static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr; + +// Forward declarations of helper functions +bool CreateDeviceD3D(HWND hWnd); +void CleanupDeviceD3D(); +void CreateRenderTarget(); +void CleanupRenderTarget(); +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +// Main code +int main(int, char**) { + // Make process DPI aware and obtain main monitor scale + ImGui_ImplWin32_EnableDpiAwareness(); + float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor( + ::MonitorFromPoint(POINT{0, 0}, MONITOR_DEFAULTTOPRIMARY)); + + // Create application window + WNDCLASSEXW wc = {sizeof(wc), + CS_CLASSDC, + WndProc, + 0L, + 0L, + GetModuleHandle(nullptr), + nullptr, + nullptr, + nullptr, + nullptr, + L"ImGui Example", + nullptr}; + ::RegisterClassExW(&wc); + HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui DirectX11 Example", + WS_OVERLAPPEDWINDOW, 100, 100, + (int)(1280 * main_scale), (int)(800 * main_scale), + nullptr, nullptr, wc.hInstance, nullptr); + + // Initialize Direct3D + if (!CreateDeviceD3D(hwnd)) { + CleanupDeviceD3D(); + ::UnregisterClassW(wc.lpszClassName, wc.hInstance); + return 1; + } + + // Show the window + ::ShowWindow(hwnd, SW_SHOWDEFAULT); + ::UpdateWindow(hwnd); + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + (void)io; + io.ConfigFlags |= + ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= + ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable + // Multi-Viewport / Platform Windows // @SAMPLE_EDIT disabled temporarily + // io.ConfigViewportsNoAutoMerge = true; + // io.ConfigViewportsNoTaskBarIcon = true; + // io.ConfigViewportsNoDefaultParent = true; + // io.ConfigDockingAlwaysTabBar = true; + // io.ConfigDockingTransparentPayload = true; + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + // ImGui::StyleColorsLight(); + + // Setup scaling + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes( + main_scale); // Bake a fixed style scale. (until we have a solution for + // dynamic style scaling, changing this requires resetting + // Style + calling this again) + style.FontScaleDpi = + main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true + // makes this unnecessary. We leave both here for + // documentation purpose) + io.ConfigDpiScaleFonts = + true; // [Experimental] Automatically overwrite style.FontScaleDpi in + // Begin() when Monitor DPI changes. This will scale fonts but + // _NOT_ scale sizes/padding for now. + io.ConfigDpiScaleViewports = + true; // [Experimental] Scale Dear ImGui and Platform Windows when + // Monitor DPI changes. + + // When viewports are enabled we tweak WindowRounding/WindowBg so platform + // windows can look identical to regular ones. + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + + // Setup Platform/Renderer backends + ImGui_ImplWin32_Init(hwnd); + ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can + // also load multiple fonts and use ImGui::PushFont()/PopFont() to select + // them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you + // need to select the font among multiple. + // - If the file cannot be loaded, the function will return a nullptr. Please + // handle those errors in your application (e.g. use an assertion, or display + // an error and quit). + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype + // for higher quality font rendering. + // - Read 'docs/FONTS.md' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string + // literal you need to write a double backslash \\ ! + // style.FontSizeBase = 20.0f; + // io.Fonts->AddFontDefault(); + // io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf"); + // io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf"); + // io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf"); + // io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf"); + // ImFont* font = + // io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf"); + // IM_ASSERT(font != nullptr); + + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; + Sample::Base& sample = GetSample(); // @SAMPLE_EDIT + done = !sample.Startup(); // @SAMPLE_EDIT + while (!done) { + // Poll and handle messages (inputs, window resize, etc.) + // See the WndProc() function below for our to dispatch events to the Win32 + // backend. + MSG msg; + while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + if (msg.message == WM_QUIT) done = true; + } + if (done) break; + + // Handle window being minimized or screen locked + if (g_SwapChainOccluded && + g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED) { + ::Sleep(10); + continue; + } + g_SwapChainOccluded = false; + + // Handle window resize (we don't resize directly in the WM_SIZE handler) + if (g_ResizeWidth != 0 && g_ResizeHeight != 0) { + CleanupRenderTarget(); + g_pSwapChain->ResizeBuffers(0, g_ResizeWidth, g_ResizeHeight, + DXGI_FORMAT_UNKNOWN, 0); + g_ResizeWidth = g_ResizeHeight = 0; + CreateRenderTarget(); + } + + // Start the Dear ImGui frame + ImGui_ImplDX11_NewFrame(); + ImGui_ImplWin32_NewFrame(); + +#if 0 // @SAMPLE_EDIT + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; + g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr); + g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + + // Update and Render additional Platform Windows + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } +#endif // @SAMPLE_EDIT + + //========================================================================================= + // @SAMPLE_EDIT EDIT TO ORIGINAL IMGUI main.cpp + + IM_UNUSED(show_demo_window); + IM_UNUSED(show_another_window); + + // Avoids high CPU/GPU usage by releasing this thread until enough time has + // passed + static auto sLastTime = std::chrono::steady_clock::now(); + std::chrono::duration elapsedSec = + std::chrono::steady_clock::now() - sLastTime; + if (elapsedSec.count() < 1.f / 120.f) { + std::this_thread::sleep_for(std::chrono::microseconds(250)); + continue; + } + + // Draw the Local Imgui UI and remote imgui UI + sLastTime = std::chrono::steady_clock::now(); + const float clear_color_with_alpha[4] = { + clear_color.x * clear_color.w, clear_color.y * clear_color.w, + clear_color.z * clear_color.w, clear_color.w}; + g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); + g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, + clear_color_with_alpha); + sample.Draw(); + if (ImGui::GetDrawData()) { + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + } + // Update and render additional Platform Windows + static int sLastFrame = -1; + int newFrame = ImGui::GetFrameCount(); + + if (sLastFrame != newFrame && + io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + sLastFrame = newFrame; + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + //========================================================================================= + + // Present + // HRESULT hr = g_pSwapChain->Present(1, 0); // Present with vsync + HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync + g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED); + } + + // Cleanup + ImGui_ImplDX11_Shutdown(); + ImGui_ImplWin32_Shutdown(); + sample.Shutdown(); // @SAMPLE_EDIT + ImGui::DestroyContext(); + + CleanupDeviceD3D(); + ::DestroyWindow(hwnd); + ::UnregisterClassW(wc.lpszClassName, wc.hInstance); + + return 0; +} + +// Helper functions +bool CreateDeviceD3D(HWND hWnd) { + // Setup swap chain + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 2; + sd.BufferDesc.Width = 0; + sd.BufferDesc.Height = 0; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = TRUE; + sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + UINT createDeviceFlags = 0; + // createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; + D3D_FEATURE_LEVEL featureLevel; + const D3D_FEATURE_LEVEL featureLevelArray[2] = { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_0, + }; + HRESULT res = D3D11CreateDeviceAndSwapChain( + nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, + featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, + &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); + if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software + // driver if hardware is not available. + res = D3D11CreateDeviceAndSwapChain( + nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, + featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, + &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); + if (res != S_OK) return false; + + CreateRenderTarget(); + return true; +} + +void CleanupDeviceD3D() { + CleanupRenderTarget(); + if (g_pSwapChain) { + g_pSwapChain->Release(); + g_pSwapChain = nullptr; + } + if (g_pd3dDeviceContext) { + g_pd3dDeviceContext->Release(); + g_pd3dDeviceContext = nullptr; + } + if (g_pd3dDevice) { + g_pd3dDevice->Release(); + g_pd3dDevice = nullptr; + } +} + +void CreateRenderTarget() { + ID3D11Texture2D* pBackBuffer; + g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); + g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, + &g_mainRenderTargetView); + pBackBuffer->Release(); +} + +void CleanupRenderTarget() { + if (g_mainRenderTargetView) { + g_mainRenderTargetView->Release(); + g_mainRenderTargetView = nullptr; + } +} + +// Forward declare message handler from imgui_impl_win32.cpp +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, + UINT msg, + WPARAM wParam, + LPARAM lParam); + +// Win32 message handler +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if +// dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your +// main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to +// your main application, or clear/overwrite your copy of the keyboard data. +// Generally you may always pass all inputs to dear imgui, and hide them from +// your application based on those two flags. +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) return true; + + switch (msg) { + case WM_SIZE: + if (wParam == SIZE_MINIMIZED) return 0; + g_ResizeWidth = (UINT)LOWORD(lParam); // Queue resize + g_ResizeHeight = (UINT)HIWORD(lParam); + return 0; + case WM_SYSCOMMAND: + if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu + return 0; + break; + case WM_DESTROY: + ::PostQuitMessage(0); + return 0; + } + return ::DefWindowProcW(hWnd, msg, wParam, lParam); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int nShowCmd) { + IM_UNUSED(hInstance); + IM_UNUSED(hPrevInstance); + IM_UNUSED(lpCmdLine); + IM_UNUSED(nShowCmd); + return main(0, nullptr); +} +//================================================================================================= diff --git a/python/mujoco/experimental/netimgui/Code/Sample/SampleNoBackend/SampleNoBackend.cpp b/python/mujoco/experimental/netimgui/Code/Sample/SampleNoBackend/SampleNoBackend.cpp new file mode 100644 index 00000000..41226a5a --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/Sample/SampleNoBackend/SampleNoBackend.cpp @@ -0,0 +1,198 @@ +// Adapted for Google: removed NETIMGUI_IMPLEMENTATION (sources compiled +// separately), updated include paths for third_party layout. + +//================================================================================================= +// SAMPLE NO BACKEND +//------------------------------------------------------------------------------------------------- +// Demonstration of using Dear ImGui without any Backend support. +// This way, user can use DearImgui without any code needed for drawing / input +// management, since it is all handled by the NetImgui remote server instead. +// Useful when this code is running on hardward without any display and/or +// convenient input. +// +// Because we are not using any Backend code, this Sample is a little bit +// different from the others. All of its code is included in this file (except +// for Dear ImGui sources) and does not rely on some shared sample source file. +// +// This sample compile both 'Dear Imgui' and 'NetImgui' sources directly +// (not using their project version in the solution) +// +// NOTE: This sample is also use in backward compatibility test with +// older Dear ImGui versions, +// making it easier to compile Dear Imgui without any OS +//specific code (Backends) +// +// NOTE: This is also an excellent example of own little is needed to add +// NetImgui support +// to a project. It doesn't handle Font DPI regeneration, +//keeping things simple. +//================================================================================================= + +#include + +#include +#include + +#include "NetImgui_Api.h" +#include "Source/Fonts/Roboto_Medium.cpp" + +namespace SampleNoBackend { + +enum eSampleState : uint8_t { + Start, + Disconnected, + Connected, +}; + +//================================================================================================= +// Initialize the Dear Imgui Context and the NetImgui library +//================================================================================================= +bool Client_Startup() { + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + io.BackendFlags |= + ImGuiBackendFlags_HasGamepad; // Enable NetImgui Gamepad support + io.DisplaySize = ImVec2(8, 8); + + ImFontConfig FontConfig = {}; + const char FontName[] = "Roboto Medium"; + memcpy(FontConfig.Name, FontName, sizeof(FontName)); + io.Fonts->AddFontFromMemoryCompressedTTF(Roboto_Medium_compressed_data, + Roboto_Medium_compressed_size, 16.f, + &FontConfig); +#if !NETIMGUI_IMGUI_TEXTURES_ENABLED + io.Fonts->Build(); + io.Fonts->SetTexID(0); +#endif + + ImGui::StyleColorsDark(); + + if (!NetImgui::Startup()) return false; + + return true; +} + +//================================================================================================= +// Release resources +//================================================================================================= +void Client_Shutdown() { + NetImgui::Shutdown(); + ImGui::DestroyContext(ImGui::GetCurrentContext()); +} + +//================================================================================================= +// Manage connection to NetImguiServer +//================================================================================================= +void Client_Connect(eSampleState& sampleState) { + constexpr char zClientName[] = "SampleNoBackend (ImGui " IMGUI_VERSION ")"; + if (sampleState == eSampleState::Start) { + printf("- Connecting to NetImguiServer to (127.0.0.1:%i)... ", + NetImgui::kDefaultServerPort); + NetImgui::ConnectToApp(zClientName, "localhost"); + while (NetImgui::IsConnectionPending()); + bool bSuccess = NetImgui::IsConnected(); + sampleState = + bSuccess ? eSampleState::Connected : eSampleState::Disconnected; + printf(bSuccess ? "Success\n" : "Failed\n"); + if (!bSuccess) { + printf("- Waiting for a connection from NetImguiServer on port %i... ", + NetImgui::kDefaultClientPort); + NetImgui::ConnectFromApp(zClientName); + } + } else if (sampleState == eSampleState::Disconnected && + NetImgui::IsConnected()) { + sampleState = eSampleState::Connected; + printf("CONNECTED\n"); + } else if (sampleState == eSampleState::Connected && + !NetImgui::IsConnected()) { + sampleState = eSampleState::Disconnected; + printf("DISCONNECTED\n"); + printf("- Waiting for a connection from NetImguiServer on port %i... ", + NetImgui::kDefaultClientPort); + NetImgui::ConnectFromApp(zClientName); + } +} + +//================================================================================================= +// Render all of our Dear ImGui Content (when appropriate) +//================================================================================================= +void Client_Draw(bool& bQuit) { + if (NetImgui::IsConnected() && NetImgui::NewFrame(true)) { + ImGui::ShowDemoWindow(); + + ImGui::SetNextWindowPos(ImVec2(32, 48), ImGuiCond_Once); + ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_Once); + if (ImGui::Begin("Sample No Backend", nullptr)) { + ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Client:"); + ImGui::TextUnformatted(" DearImgui Version: " IMGUI_VERSION); + ImGui::TextUnformatted(" NetImgui Version: " NETIMGUI_VERSION); + ImGui::TextUnformatted(""); + ImGui::SameLine(); + bQuit = ImGui::Button(" Quit "); + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Terminate this sample."); + ImGui::NewLine(); + ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Description:"); + ImGui::TextWrapped( + "This sample demonstate the ability to use Dear ImGui without any " + "Backend. " + "Rely instead on NetImgui to remotely handle drawing and inputs. " + "This avoids the need for rendering/input/window management code on " + "the client itself."); + } + ImGui::End(); + + NetImgui::EndFrame(); + } +} + +} // namespace SampleNoBackend + +int main(int, char**) { + printf( + "========================================================================" + "========\n"); + printf(" NetImgui Sample: No Backend\n"); + printf( + "========================================================================" + "========\n"); + printf( + " Demonstrate 'Dear ImGui' + 'NetImgui' for a UI displayed on a remote " + "server.\n"); + printf(" Dear ImGui : " IMGUI_VERSION "\n"); + printf(" NetImgui : " NETIMGUI_VERSION "\n"); + printf(" ['Ctrl + C' to quit]\n"); + printf( + "------------------------------------------------------------------------" + "--------\n"); + if (!SampleNoBackend::Client_Startup()) { + printf("Failed initializing NetImgui."); + SampleNoBackend::Client_Shutdown(); + return -1; + } + + // Main loop + bool bQuit = false; + SampleNoBackend::eSampleState sampleState = + SampleNoBackend::eSampleState::Start; + while (!bQuit) { + // Avoids high CPU/GPU usage by releasing this thread until enough time has + // passed + static auto sLastTime = std::chrono::steady_clock::now(); + std::chrono::duration elapsedSec = + std::chrono::steady_clock::now() - sLastTime; + if (elapsedSec.count() < 1.f / 120.f) { + std::this_thread::sleep_for(std::chrono::microseconds(250)); + continue; + } + sLastTime = std::chrono::steady_clock::now(); + + // Sample Update + SampleNoBackend::Client_Connect(sampleState); + SampleNoBackend::Client_Draw(bQuit); + } + + // Cleanup + SampleNoBackend::Client_Shutdown(); + return 0; +} diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/Fonts/Roboto_Medium.cpp b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/Fonts/Roboto_Medium.cpp new file mode 100644 index 00000000..8423be9f --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/Fonts/Roboto_Medium.cpp @@ -0,0 +1,4828 @@ +// File: 'Roboto-Medium.ttf' (162588 bytes) +// Exported using binary_to_compressed_c.cpp +const unsigned int Roboto_Medium_compressed_size = 115741; +const unsigned int Roboto_Medium_compressed_data[115744 / 4] = { + 0x0000bc57, 0x00000000, 0x1c7b0200, 0x00000400, 0x00010025, 0x82110000, + 0x042e0804, 0x50471000, 0xaa7d534f, 0x02008c71, 0x0000a808, 0x53470c59, + 0x9c4c4255, 0x0200e028, 0x0000b461, 0x534f6819, 0x0ba1322f, 0x0000b6b1, + 0x35829801, 0x6d63603c, 0x26407061, 0x00007248, 0x00006c1a, 0x7663c812, + 0x97042074, 0x00004a2b, 0x1f82bc2f, 0x7066562c, 0xf97b6d67, 0x0000ab61, + 0x3382342d, 0x6167bc28, 0x08007073, 0x5f821300, 0x1f829c20, 0x670c2808, + 0xae66796c, 0x00e9629e, 0x00dc3900, 0x68cccb01, 0x3d786d64, 0x00203c3f, + 0x00801500, 0x68ec0400, 0xf8646165, 0x8208ab7b, 0x821c203b, 0x6836212f, + 0x0a231082, 0x829b0aef, 0x8254200f, 0x6824280f, 0x2478746d, 0x82f544f3, + 0x00f83b0f, 0x6c881300, 0xdd61636f, 0x00ad66de, 0x00143000, 0x6dc60900, + 0x07707861, 0x1f830212, 0x2f827820, 0x616e202b, 0x633d656d, 0x02004c6f, + 0x29df8205, 0x6f70d402, 0x6dff7473, 0x8f826400, 0x1f837c20, 0x6572702b, + 0xf8b11b70, 0x2e000036, 0x220f82f0, 0x820100cc, 0x00022c05, 0xa4401100, + 0x3c0f5f6d, 0x821b00f5, 0x0000268a, 0x11f0c400, 0x2c06822e, 0x4edbd000, + 0xfd24fa94, 0x085c09d5, 0x230f8273, 0x00020009, 0x01260085, 0x6c070000, + 0x83820cfe, 0x24fa6b26, 0x5c0941fe, 0x1b854984, 0x04210584, 0x821183e2, + 0x008f2605, 0x004e0016, 0x211f8605, 0x4282000e, 0x00160223, 0x240f8206, + 0x01950403, 0x241982f4, 0x059a0500, 0x20e18233, 0x2607851f, 0x6600d103, + 0x88000002, 0x00002d6a, 0xff0a00e0, 0x7f210050, 0x21000000, 0x00380382, + 0x474f4f47, 0x00004000, 0x0006fdff, 0x660000fe, 0x00029a07, 0x9f010020, + 0x04231b83, 0x82b0053a, 0x0020240c, 0x828c0302, 0x821283f7, 0x82012003, + 0x27038326, 0x8f002502, 0x65009802, 0x60219782, 0x081f8204, 0x00e0052b, + 0x001d0563, 0x005a0156, 0x00ca0252, 0x00d20280, 0x00890328, 0x0075041b, + 0x00c20144, 0x00a0021c, 0x003c0247, 0x002a0387, 0x202f8202, 0x20038269, + 0x200382a8, 0x20038251, 0x2003824f, 0x20038234, 0x20038281, 0x20038275, + 0x20038245, 0x08038268, 0x1f025d2e, 0xe7018200, 0x11042e00, 0x7a043f00, + 0x2a049100, 0xe4038000, 0x28073c00, 0x53055b00, 0x0c051200, 0x39059400, + 0x3a056600, 0x86049400, 0x65200382, 0x72300f82, 0xaf056a00, 0x42029400, + 0x7104a300, 0x0b052d00, 0x54241782, 0x01079400, 0xae201b82, 0x86200382, + 0x1d202f82, 0x60220784, 0x1b82fe04, 0x4a00d424, 0x2782db04, 0x7d00373e, + 0x12002d05, 0x30000a07, 0x29001005, 0x0700e004, 0x5000d104, 0x84003102, + 0x14005803, 0x0c3a0782, 0x35006b03, 0x03009c03, 0x31009402, 0x5a005404, + 0x7c008104, 0x4f003004, 0x03828404, 0x53004b2a, 0x2d00d602, 0x52008904, + 0x792a7782, 0x7d000b02, 0xb5ff0102, 0x07822d04, 0x8c000b24, 0x2b82f606, + 0x79007324, 0x2b828e04, 0x8b243783, 0xd0024f00, 0x213a1382, 0xa9024b00, + 0x72040800, 0xf5037700, 0xf2051600, 0x06042100, 0xe5031f00, 0x07820c00, + 0xaf025228, 0x02023800, 0x0782ae00, 0x51051b34, 0x1e027500, 0x7d048600, + 0xb5046400, 0x9d055e00, 0xa7825d00, 0xfc01193c, 0xf8048800, 0x85035a00, + 0x44065d00, 0x91035700, 0xe2038d00, 0x6d045700, 0x0f847f00, 0x8700db2e, + 0x7f000a03, 0x5f004a04, 0x3c00f602, 0x37340382, 0x70009b02, 0x9200bb04, + 0x4500ed03, 0x8e004202, 0x6d001002, 0x80221782, 0x8782a703, 0x00e23408, + 0x00d0055d, 0x002b0659, 0x00570650, 0x00e40367, 0xff850742, 0x004404f6, + 0x0084054d, 0x00ca0469, 0x00e70494, 0x00c10688, 0x00a70448, 0x00910467, + 0x82880443, 0x00973ad7, 0x00b00582, 0x001a021f, 0x0098048f, 0x0064048e, + 0x004f0222, 0x00930521, 0x081f8290, 0xb4077e36, 0x3a076400, 0x0c025b00, + 0x88058b00, 0xd0025100, 0x8a05e4ff, 0x9e045800, 0xa4054f00, 0xf2047d00, + 0x26027700, 0x3c04b5ff, 0xe6035900, 0xb0039400, 0xdc037200, 0x7c20bb82, + 0x0b3ef782, 0xb2028100, 0x4d027800, 0xd8032900, 0x1f037a00, 0x6c024900, + 0x00008200, 0x00008efc, 0x07825efd, 0x07827320, 0x07823e20, 0x07820c20, + 0x5d021c24, 0x4782c600, 0xdb836720, 0x00750437, 0x00bf059b, 0x007a0519, + 0x0038055b, 0x00900420, 0x00b1056c, 0x3607829b, 0x00ef0547, 0x00aa054a, + 0x005b0544, 0x0084046b, 0x00c60456, 0x820e0496, 0x00882a23, 0x00600454, + 0x001a0460, 0x33bb8361, 0x7300a104, 0xa900aa02, 0x16006a04, 0x64001304, + 0x2d00f304, 0x80261782, 0x52003704, 0x03829004, 0x3f002d22, 0x80222f82, + 0x4b82d005, 0x00c92608, 0x0094064f, 0x00b30466, 0xff7b0476, 0x007106e1, + 0x00fe0533, 0x00590522, 0x00880868, 0x008f082d, 0x005b069b, 0x2a778231, + 0x00080592, 0x00060690, 0x82a20724, 0xd6280857, 0xa8054900, 0xa9059400, + 0x0a052d00, 0x5f063900, 0xf9054f00, 0x89059200, 0x9b078e00, 0xf9079800, + 0x1a069800, 0xf9061800, 0x3408cf82, 0x05900007, 0x076b0050, 0x04a00054, + 0x042000f7, 0x045b007d, 0x038f008f, 0x0485005a, 0x062700f6, 0x041e0076, + 0x044d0016, 0x04860098, 0x048f006e, 0x0621009a, 0x20078203, 0x820f8297, + 0xf5032513, 0xd3052300, 0xd320e382, 0x66300f82, 0x8e065f00, 0xec068600, + 0x17057e00, 0x6f061f00, 0x68202782, 0x3c380382, 0x84065100, 0x70049100, + 0x71042700, 0x3c04dbff, 0xd1065400, 0xe4061e00, 0x89223382, 0x5b83eeff, + 0x0049072d, 0x004f0688, 0xff670470, 0x822807e0, 0x00013e9f, 0x000c0586, + 0x0060041c, 0x0042070a, 0x003606ac, 0x00ed069d, 0x00e60580, 0x00320982, + 0x2ec382a3, 0x0020048f, 0x00f00328, 0x007a0533, 0x8288045f, 0x001a26e3, + 0x000e0410, 0x210f8720, 0x53824507, 0x74004422, 0x052f5b87, 0x0466001a, + 0x045c004a, 0x006d00ff, 0x4166fc00, 0x7b2806eb, 0xa5fd0000, 0x24fa0000, + 0x4d200382, 0x05337f83, 0x04940013, 0x047c0086, 0x038f006a, 0x047e00a1, + 0x829b00b7, 0x7e24086b, 0x90002c05, 0x8e00ab04, 0x34009506, 0x3d00a405, + 0x9400d007, 0x7e00aa05, 0x9b004708, 0x7e00f506, 0x67002a06, 0x613e5b82, + 0x2d003107, 0x26007005, 0x80007405, 0x74007304, 0x85008705, 0x16002406, + 0xcbffc304, 0x43822105, 0x8e007824, 0x5382af05, 0x7e00882a, 0x51008805, + 0x5b00a604, 0x5d260382, 0x3400c704, 0x3b825303, 0x52000738, 0x6800f106, + 0x5e00dd06, 0x3c005306, 0x2f002805, 0x48007b04, 0xcb823e04, 0x00be2408, + 0x009d0642, 0x00fd0740, 0x009e0694, 0x00040577, 0x002c045d, 0x00aa0555, + 0x001d0521, 0x00550544, 0x822c0381, 0x00142787, 0x00290800, 0x07860400, + 0x00b90229, 0x000a0200, 0x825c0100, 0x007f2413, 0x82300200, 0x00a2240b, + 0x82d10000, 0x23028203, 0x4700a102, 0x05250383, 0x069d0029, 0x08438230, + 0x04009d74, 0x6300c001, 0x3300bc01, 0x3200ce01, 0x4a00a801, 0x6c001403, + 0x40001b03, 0x32000803, 0x40005d04, 0x5c009904, 0x8800cb02, 0x8a00fa03, + 0x8a00a605, 0x47006c01, 0x4a00a707, 0x6c007202, 0x54006902, 0x2d009c03, + 0x3500f602, 0x69005c03, 0x5f00b504, 0x21007006, 0x9800b806, 0x94009308, + 0x35008807, 0x7c008c06, 0x5e008c04, 0x2100f505, 0x28003404, 0xc382a204, + 0x005e3408, 0x007d054f, 0x00e40528, 0x00e20370, 0x002e084c, 0x00090590, + 0x0014056d, 0x00350696, 0x00dd0659, 0x00d10654, 0x00a2065b, 0x00910458, + 0x00960562, 0x82d904a6, 0x8328088b, 0xb2049e00, 0x45083b00, 0x2d025e00, + 0x8e04afff, 0x7a046500, 0x11049100, 0x2a043c00, 0x0c048000, 0x5b022400, + 0x9802a100, 0xf130d382, 0x1b054500, 0xa8042d00, 0xbc041800, 0x23072d00, + 0x05280385, 0x062d0011, 0x004b00b7, 0x083b0082, 0x08590030, 0x045c0035, + 0x043a0033, 0x024f0093, 0x01b0ff10, 0x035c00b3, 0x877500a1, 0x0b042303, + 0x03857500, 0x824cff21, 0x837a2007, 0x05022f17, 0x9e049400, 0x60040900, + 0x80047600, 0x83824f00, 0xe0037626, 0xc5037600, 0xa6300f82, 0xde045400, + 0xfc017600, 0xd5038500, 0x5b042400, 0xb9241782, 0x06067600, 0xdd201b82, + 0xc0200382, 0x6d202f82, 0x4c220784, 0x07825c04, 0x3e003424, 0x27823b04, + 0x67008432, 0x09007b04, 0x28000706, 0x15005e04, 0x05003c04, 0x4124d382, + 0x4b00f602, 0x80200382, 0x22088b45, 0x823500f6, 0x824f200b, 0x824d2003, + 0x86362003, 0x0346281f, 0x029000b9, 0x829600b2, 0x040a324b, 0x055600bb, + 0x059b0044, 0x049b0028, 0x05810030, 0x23078239, 0x0481002d, 0x66266b83, + 0x4d043800, 0x2f820e00, 0x6f837620, 0x8f830420, 0x03257782, 0x04420098, + 0x308f82d8, 0x05440019, 0x0550009d, 0x04500054, 0x055f00e4, 0x829b8291, + 0x540729e3, 0x57072400, 0x97057600, 0xd7200f82, 0x71202782, 0x59280b82, + 0x3a062700, 0x46041a00, 0xe4203b82, 0x5c201382, 0xcb200382, 0x46241f82, + 0x5d051f00, 0x8c280b82, 0x84064100, 0x0a077600, 0x5a242b82, 0x20060a00, + 0x67201382, 0x80240382, 0x92063c00, 0x88240782, 0x22044300, 0x92201782, + 0x9d204382, 0x1a202382, 0x6e300382, 0xf0052400, 0x5a044f00, 0xc4040500, + 0x95061500, 0x47824f82, 0x828c0421, 0x00fe241b, 0x82d2040a, 0x836f831b, + 0x25cb82b7, 0x4600f703, 0x4b823608, 0x2800eb28, 0x7c008804, 0xb7823d04, + 0x4f00982c, 0x5b00a403, 0x4c00a104, 0x13829404, 0x33829f20, 0x53004b2c, + 0x51008904, 0x6b007a05, 0x0382a205, 0x9b008624, 0x0782e005, 0x6b00e22c, + 0x97001b04, 0x6e008204, 0x4782b903, 0x0f005726, 0x3500be04, 0x41065741, + 0x0428146b, 0x0466006b, 0x0643002e, 0x042b6782, 0x047300b4, 0x026200eb, + 0x84b5ff26, 0x001b2703, 0xff1b028f, 0x078202fb, 0x0060042f, 0x00fe0176, + 0x00a00200, 0xff580547, 0x2f0383f7, 0xd4ff8f04, 0x2d00db04, 0xe8ffa902, + 0x12005305, 0x39200398, 0x86236382, 0x8a049400, 0x42022703, 0x4202c8ff, + 0x0782a300, 0x0382cb20, 0xae05bf28, 0x86059400, 0x03906600, 0x7d003723, + 0x27038a05, 0x0700e004, 0x5a005404, 0x30200398, 0x23061f41, 0x0453004b, + 0x02250386, 0x02b4ff1a, 0x22cb821a, 0x82b7ff1a, 0x04ab210b, 0x20078f48, + 0x8b2b828e, 0x00722303, 0x038a0477, 0x00e50323, 0x8303830c, 0x906f83d7, + 0x82d78307, 0x9705206f, 0x823a2007, 0x821a20d3, 0x83f78363, 0x27079e8b, + 0x6a007205, 0x52008904, 0xaf2a0798, 0x71049400, 0x42027900, 0xc782b3ff, + 0x07829f20, 0x0782b920, 0x0782a520, 0x0782df20, 0x4202cb34, 0x0b021700, + 0x42020000, 0xb3069d00, 0x0c04a300, 0x2f827d00, 0x26022d26, 0x0b05b5ff, + 0x2d203b82, 0x54220f82, 0x23829400, 0xcf828a20, 0x55200783, 0xa1220784, + 0x07848c00, 0x8c00e724, 0x2782ae05, 0x79007322, 0x042b078f, 0x05a5ff73, + 0x04660086, 0x8f4f008e, 0xfe042107, 0xd0225382, 0x07867c00, 0x07864f20, + 0xd4043828, 0x21044a00, 0x07a04b00, 0x2d00db26, 0x0800a902, 0x86054b42, + 0x00d12407, 0x82370508, 0x007222af, 0x2f07a777, 0x30000a07, 0x2100f205, + 0x0700e004, 0x0c00e503, 0x04270783, 0x045000d1, 0x8f520006, 0x85073307, + 0xc106f6ff, 0x84054800, 0x88046900, 0x7a044f00, 0x0384a6ff, 0x24003b26, + 0x09009e04, 0x80250398, 0xe0034f00, 0x05234500, 0x01270786, 0x01a6fffc, + 0x828300fc, 0x82a92007, 0x049d2103, 0x20071b45, 0x8b5782c0, 0x00842303, + 0x038b0467, 0x05003c22, 0x5b82678c, 0x038b0420, 0x6a007a22, 0x0f836b8f, + 0x00a60423, 0x22038c54, 0x827600de, 0x82912077, 0x82972003, 0x82bd2003, + 0x8215208b, 0x457c2003, 0x03210bb3, 0x05bb45b9, 0x9f840783, 0xa78fa383, + 0xf7445c20, 0x23078306, 0x043e0034, 0x3b23038b, 0x87042400, 0x86c78f03, + 0x0706240f, 0x83042800, 0x06ef45d3, 0x002a0423, 0x3f038341, 0x12005305, + 0x4affea04, 0x53ff1306, 0x56ffa602, 0xa7ff9a05, 0xe1fe4405, 0xb2ff6f05, + 0x87ffaa02, 0x05211f83, 0x061f440c, 0x5000d122, 0x2107c74c, 0xbf4c0b05, + 0xdb042f11, 0xe0042d00, 0x10050700, 0x42022900, 0x0b83bfff, 0x0084042f, + 0x00600456, 0x00880460, 0x00aa027e, 0x340b82a9, 0x00980480, 0x008e048e, + 0x00bb044f, 0x00f50392, 0x00060416, 0x206b821f, 0x831b84cc, 0x00602417, + 0x44940680, 0x75260697, 0xd4049b00, 0x8f444a00, 0x04bf2806, 0x052d0071, + 0x839b0028, 0x0a05237f, 0x9f883900, 0x86242783, 0xa8059400, 0xaf209786, + 0x2006b344, 0x202b82b1, 0x200b821d, 0x824f8239, 0x279b839f, 0x5a005404, + 0x53004b04, 0x86208782, 0x334d8784, 0x4c032006, 0x1f2005df, 0x03371b83, + 0x0485005a, 0x024b0021, 0x027d000b, 0x02abff1a, 0x04b5ff01, 0x838f006e, + 0x07cb4223, 0xdb42078f, 0x5a013b07, 0x98025200, 0x4a046500, 0x26028f00, + 0xbc01b1ff, 0x01073300, 0xf6069400, 0xaf837c00, 0xab867f84, 0x05258787, + 0x054400aa, 0x07774ac9, 0x08f1ff27, 0x094f0073, 0x26b3826b, 0x044900d6, + 0x444d0016, 0x638307c7, 0x000e042f, 0x00420220, 0x00a207a3, 0x00760616, + 0x440b831e, 0x43430fff, 0x44042007, 0x052706d7, 0x04510088, 0x8359003c, + 0x20378703, 0x275b8704, 0x049400a8, 0x05860098, 0x4b440787, 0x070b4b07, + 0x50220787, 0x3f826b00, 0x0a055128, 0xe5033900, 0x07900c00, 0x8e008938, + 0x5f006604, 0x9b00f906, 0x8f006f06, 0x29001005, 0x1f000604, 0xd7828404, + 0x2d00a926, 0x21009a04, 0x0f8aa78f, 0x54041024, 0x1f9a9aff, 0xe7451220, + 0x00532114, 0xef87178c, 0xff250799, 0xff4b04d5, 0x271f978e, 0xa3004202, + 0x8f001a02, 0x94240782, 0x78000b02, 0x8a0f4f45, 0x0427240f, 0x98a3ff8e, + 0x07434e1f, 0x4745079f, 0x06734e0f, 0x97077b4e, 0x0b474507, 0x4f450320, + 0x23078406, 0x044f00a2, 0x05370382, 0x049b0028, 0x058f006e, 0x049400af, + 0x04860097, 0x032d00db, 0x412300f5, 0x05200793, 0x8706ab41, 0x75042707, + 0x5a039b00, 0x1b428500, 0x07634c07, 0x00710427, 0xff070579, 0x2f0383d0, + 0xf0ff7504, 0xe2ff5a03, 0xe3ff3c05, 0xaeff4404, 0x86082f42, 0x01072563, + 0x03069400, 0xeb417382, 0x07ab4206, 0x042b7387, 0x04600060, 0x06020065, + 0x51810030, 0xa0261067, 0xb4045d00, 0x5f477d00, 0x07eb4608, 0x3005df41, + 0x0086040d, 0x004b0448, 0xfe420201, 0xfe1a02f6, 0x067741e2, 0xfe041636, + 0xd0023200, 0x37056eff, 0x72047100, 0xdf040f00, 0x0c05acfe, 0x8124f382, + 0x3a057c00, 0x84220782, 0x07884f00, 0x4706a347, 0x7747076f, 0x4378200e, + 0x7b8708a3, 0x47851d20, 0x20063347, 0x082b4772, 0x27061347, 0x12002d05, + 0x1600f503, 0xe3460787, 0x06d74608, 0xfecc053f, 0x009e041c, 0xff1c0409, + 0xff1a052a, 0xff380237, 0xffca0439, 0xfe780493, 0xffee04e8, 0x201b84a4, + 0x05af4660, 0x002a0423, 0x07cf4b41, 0x4b5b0421, 0xc34b06c7, 0x003b2e07, + 0x003c0424, 0x005e0405, 0xfffc0115, 0x210b839d, 0x3346e003, 0x34042705, + 0xfc013e00, 0x17838500, 0x23075346, 0x1f004604, 0xb9205b88, 0xe4205f86, + 0xde235386, 0x83047600, 0x82d82057, 0x826d2007, 0x00802303, 0x5f83044f, + 0x37825b82, 0x83834220, 0x13830420, 0x05246f82, 0x040a00fe, 0x17823782, + 0x9d051f24, 0xbb445000, 0x0421080b, 0x0253004b, 0x0078001a, 0x00010000, + 0x09e40400, 0x0000040b, 0x03020202, 0x06070506, 0x04030302, 0x20048405, + 0x21008705, 0x09820202, 0x06080422, 0x05270082, 0x03060605, 0x84050605, + 0x8306200c, 0x8208200d, 0x04022505, 0x03040402, 0x05822e84, 0x05020224, + 0x0c830802, 0x0305032c, 0x05070405, 0x02030504, 0x43820603, 0x0205062a, + 0x04070406, 0x04070504, 0x03201a82, 0x18821c82, 0x07040426, 0x08040707, + 0x06205382, 0x28833484, 0x09238882, 0x82060208, 0x82062006, 0x8204200e, + 0x21908300, 0xb0820304, 0x03200282, 0x06225682, 0x31820606, 0x05820720, + 0x05207584, 0x0f821282, 0x4d820b83, 0x07050526, 0x0a0a0607, 0x07221d82, + 0x29820509, 0x09220d82, 0xb2820709, 0xab820820, 0x07060422, 0x05202684, + 0x05209a83, 0x07221582, 0x02820505, 0x08080526, 0x07080505, 0xdc820282, + 0x07080727, 0x0405090a, 0x85528206, 0x8209820d, 0x21028278, 0x37820605, + 0x052af682, 0x06090607, 0x06070809, 0x1b820608, 0x28840720, 0x33821a82, + 0x14820820, 0x09050525, 0x82070907, 0x06063418, 0x05090504, 0x02020309, + 0x01020205, 0x06030300, 0x82020407, 0x04032200, 0x24b28203, 0x09020604, + 0x240a8203, 0x08070504, 0x237b820a, 0x06050507, 0x09202082, 0x08200482, + 0x4f830e82, 0x05020922, 0x03220083, 0x0d820203, 0x06080827, 0x09090008, + 0x224b8205, 0x83040404, 0x84042017, 0x210b831e, 0xcf840402, 0xd0852d84, + 0x00880320, 0x06206c83, 0x31848d82, 0x3a820482, 0x00820620, 0x4f820520, + 0x06050525, 0x82060507, 0x41062013, 0x1082090a, 0x05211482, 0x22468507, + 0x84090405, 0x830520d8, 0x24358200, 0x05050707, 0x85bc8204, 0x2023835d, + 0x83d08206, 0x820320e0, 0x82052063, 0x82248204, 0x82b68502, 0x860e85f1, + 0x0a534211, 0x0d883282, 0x6b410420, 0x05714106, 0x06200582, 0x5a411a88, + 0x22138206, 0x86020305, 0x05082301, 0x21820205, 0x02050224, 0x71820305, + 0x04842284, 0x06050623, 0x89018303, 0x8720833d, 0x215d8522, 0xbf830708, + 0x08212184, 0x22678a08, 0x82040505, 0x8acb8300, 0x820a873d, 0x04042119, + 0xec840c84, 0x2b840420, 0x12822792, 0x16840720, 0x07060625, 0x82060603, + 0x0506218b, 0x08209383, 0x0621ff84, 0x841b8303, 0x82042004, 0x05052898, + 0x05050507, 0x82050303, 0x8306201c, 0x06554327, 0x04219486, 0x82a88205, + 0x0405236e, 0x01830708, 0x02040526, 0x02020503, 0x8205b541, 0x06072855, + 0x050b0a05, 0x82050605, 0x82092043, 0x2109826d, 0x0f840808, 0x83070921, + 0x084c4106, 0x04060522, 0x05220184, 0x2c820708, 0x5b41168a, 0x061e420a, + 0x0323d28c, 0x99020302, 0x4119822d, 0x042009da, 0x0420aa82, 0x37437485, + 0x04052407, 0x82070709, 0x87062012, 0x847d8410, 0x052241ae, 0x84083443, + 0x8e032065, 0x8405209a, 0x216482e8, 0xdf820503, 0x0820bf83, 0x20059142, + 0x43108206, 0x02210585, 0x28488505, 0x04040502, 0x04020205, 0x21008205, + 0xdf430404, 0x24c88605, 0x06050607, 0x240b8206, 0x00000002, 0x24038603, + 0x0003001c, 0x830b8201, 0x000a2807, 0x00880600, 0x826c0604, 0x00ea260f, + 0x00060080, 0x0809826a, 0x0d0002e7, 0xa0007e00, 0xad00ac00, 0xc600bf00, + 0xe600cf00, 0xfe00ef00, 0x11010f01, 0x27012501, 0x53013001, 0x67015f01, + 0x7f017e01, 0x92018f01, 0xb001a101, 0xff01f001, 0x37021b02, 0xbc025902, + 0xc902c702, 0xf302dd02, 0x03030103, 0x0f030903, 0x8a032303, 0x92038c03, + 0xb003a103, 0xc903b903, 0xd203ce03, 0x2504d603, 0x45042f04, 0x62044f04, + 0x79046f04, 0xce048604, 0xe104d704, 0x0105f504, 0x13051005, 0x3f1e011e, + 0xf11e851e, 0xf91ef31e, 0x0b204d1f, 0x15201120, 0x22201e20, 0x30202720, + 0x3a203320, 0x44203c20, 0x7f207420, 0xaa20a420, 0xb120ac20, 0xbd20ba20, + 0x13210521, 0x22211621, 0x2e212621, 0x02225e21, 0x0f220622, 0x1a221222, + 0x2b221e22, 0x60224822, 0xca256522, 0xc3f602ee, 0xfffe04fb, 0xfffffdff, + 0x83008300, 0x822020eb, 0x82a120eb, 0x00ae3ceb, 0x00c700c0, 0x00e700d0, + 0x01ff00f0, 0x01120110, 0x01280126, 0x01540131, 0x86680160, 0x01a022eb, + 0x22eb82af, 0x861802fa, 0x82c620eb, 0x82d820eb, 0x880020eb, 0x828420eb, + 0x038e2ceb, 0x03a30393, 0x03ba03b1, 0x82d103ca, 0x002808eb, 0x30042604, + 0x50044604, 0x70046304, 0x88047a04, 0xd804cf04, 0xf604e204, 0x11050205, + 0x3e1e001e, 0xa01e801e, 0xf41ef21e, 0x002aeb82, 0x13201020, 0x20201720, + 0xeb822520, 0x39203222, 0xa324eb88, 0xab20a620, 0xb922eb82, 0xeb8cbc20, + 0xeb865b20, 0xeb8a1120, 0xeb826420, 0xeb820120, 0xeb820120, 0xeb82fc20, + 0x00000132, 0xe4fff6ff, 0xc2ffa401, 0xc1ff9801, 0x8b010000, 0x86200382, + 0x82200382, 0x80200382, 0x7e200382, 0x76200382, 0x782d0382, 0x06ff15ff, + 0xf7fe04ff, 0xba01eafe, 0x37008200, 0x43fe64fe, 0xd7fdef00, 0xc8fdd6fd, + 0xa7fdb3fd, 0xa1fda6fd, 0x89fd9cfd, 0xca225182, 0x2082c9ff, 0x09fd0022, + 0xaa280b82, 0xfafcfdfc, 0xb9fc0000, 0xb1200382, 0xa6200382, 0xa0240382, + 0xf4fe0000, 0xf1200382, 0x2e080b82, 0xe5000049, 0xe56ee5ae, 0xe44ee51f, + 0xe54ce5b3, 0xe15be15c, 0xe1000057, 0xe153e154, 0xe349e151, 0xe341e175, + 0xe138e16d, 0x00ffe009, 0x82dae000, 0xd5340803, 0xcde0cee0, 0x79e086e0, + 0x6ce077e0, 0x61e093df, 0x92df35e0, 0x86dfabde, 0x7edf85df, 0x6fdf7bdf, + 0x3cdf53df, 0xd5db39df, 0xdf0a9f13, 0xab02a306, 0x0100af01, 0x038c8f83, + 0x00214982, 0x20d782e4, 0x2003820e, 0x20038a28, 0x24258c6a, 0x016a0100, + 0x89118d74, 0x6201210d, 0x21820b83, 0x00008624, 0x0b839e01, 0xb6200782, + 0xfe240382, 0x26020000, 0x48200382, 0x58200382, 0xe2200382, 0xf2240382, + 0x06030000, 0x058b2385, 0x8bf80221, 0x240b870d, 0x0000e802, 0x87038202, + 0x0a07ab0f, 0x024b02b6, 0x024d024c, 0x024f024e, 0x02810050, 0x025b0247, + 0x025d025c, 0x025f025e, 0x00820060, 0x02610283, 0x02630262, 0x00650264, + 0x02850084, 0x02670266, 0x02690268, 0x006b026a, 0x02870086, 0x02770276, + 0x02790278, 0x007b027a, 0x02890088, 0x027d027c, 0x027f027e, 0x028a0080, + 0x00460446, 0x0048028b, 0x02af028c, 0x02b102b0, 0x02b302b2, 0x028d00b4, + 0x02b602b5, 0x02b802b7, 0x02ba02b9, 0x00bc02bb, 0x028f008e, 0x02be02bd, + 0x02c002bf, 0x02c202c1, 0x009000c3, 0x02c40291, 0x02c602c5, 0x02c802c7, + 0x009200c9, 0x02d80293, 0x02dc02d9, 0x02de02dd, 0x024902df, 0x0251024a, + 0x02f7026c, 0x02f902f8, 0x02d602fa, 0x02da02d7, 0x00ad00db, 0x005203ae, + 0x035303af, 0x00550354, 0x03b100b0, 0x035d035c, 0x03b2005e, 0x0060035f, + 0x036103b3, 0x03b40062, 0x03b50063, 0x03b60064, 0x00660365, 0x006703b7, + 0x03b900b8, 0x03690368, 0x036b036a, 0x036d036c, 0x006f036e, 0x037103c3, + 0x03c40072, 0x00c50070, 0x00c700c6, 0x00c900c8, 0x03cb00ca, 0x00cc0073, + 0x03b003cd, 0x03d10079, 0x03d2007a, 0x037c037b, 0x007e037d, 0x00d400d3, + 0x038003d5, 0x008103b1, 0x008203d6, 0x038303d7, 0x03d80084, 0x00d90085, + 0x03db00da, 0x007f0386, 0x038703dc, 0x03890388, 0x038b038a, 0x008d038c, + 0x03de00dd, 0x008f038e, 0x00ea00e9, 0x03ec00eb, 0x00ed0090, 0x03ef00ee, + 0x00f00091, 0x00f200f1, 0x009203f3, 0x039303f4, 0x03f50094, 0x03f60095, + 0x03b20396, 0x03010197, 0x03020198, 0x039a0399, 0x019c039b, 0x01040103, + 0x039d0305, 0x019e03b3, 0x01070106, 0x035c0408, 0x01b503b4, 0x01170116, + 0x03190118, 0x03b703b6, 0x01b803b9, 0x04280127, 0x04620461, 0x0129015b, + 0x012b012a, 0x042d012c, 0x015e045d, 0x042f012e, 0x03570456, 0x04bb03ba, + 0x01490448, 0x04310130, 0x0160045f, 0x04330132, 0x014b044a, 0x01350134, + 0x01370136, 0x03390138, 0x04bd03bc, 0x034d044c, 0x04bf03be, 0x046a0469, + 0x014f044e, 0x043b013a, 0x01510450, 0x013d013c, 0x015a043e, 0x0440013f, + 0x03590458, 0x03c103c0, 0x014101c2, 0x04670442, 0x01430168, 0x04630444, + 0x04520464, 0x04650453, 0x03450166, 0x03cc03cd, 0x03cf03ce, 0x03d103d0, + 0x014601d2, 0x04540447, 0x03e70355, 0x014801e8, 0x03e90349, 0x046b04ea, + 0x034a016c, 0x036d04eb, 0x01ed03ec, 0x046a0169, 0x016e046f, 0x0147047f, + 0x000c0085, 0x0c210082, 0x82048240, 0x04012102, 0x02870482, 0x08820120, + 0x83075e5f, 0x000d2407, 0x820d0000, 0x82032003, 0x82202003, 0x827e2003, + 0x82042003, 0x85a02003, 0x44022103, 0xa1200782, 0xac200382, 0x63200382, + 0xad200382, 0x02210385, 0x20078245, 0x200382ae, 0x200382bf, 0x2003826f, + 0x240382c0, 0x020000c5, 0x2007824b, 0x200386c6, 0x20078281, 0x200382c7, + 0x201782cf, 0x20078252, 0x210385d0, 0x07824702, 0x0382d120, 0x1782d620, + 0x07825b20, 0x0382d720, 0x0382d820, 0x03828220, 0x0382d920, 0x1782dd20, + 0x07826120, 0x0382de20, 0x0382df20, 0x03828420, 0x0382e020, 0x1782e520, + 0x07826620, 0x0386e620, 0x07828620, 0x0382e720, 0x1782ef20, 0x07826d20, + 0x0386f020, 0x07828720, 0x0382f120, 0x1782f620, 0x07827620, 0x0382f720, + 0x0382f820, 0x03828820, 0x0382f920, 0x1782fd20, 0x07827c20, 0x0386fe20, + 0x07828a20, 0x0000ff24, 0x17820f01, 0x0121b382, 0x820b8210, 0x46022103, + 0x11200782, 0x04200385, 0x12200b83, 0x25200b82, 0x92202382, 0x26200782, + 0x00210385, 0x2007828b, 0x21038527, 0xf7444802, 0x82302006, 0x82a62023, + 0x8531200b, 0x8c002103, 0x32200782, 0x37200382, 0xaf201782, 0x38200782, + 0x00210385, 0x2007828d, 0x20038239, 0x20178240, 0x200782b5, 0x20038241, + 0x208b8242, 0x2007828e, 0x20038243, 0x20178249, 0x200782bd, 0x2003824a, + 0x2017824b, 0x20078290, 0x2003824c, 0x20178251, 0x200782c4, 0x20038252, + 0x20178253, 0x20078292, 0x20038254, 0x2017825f, 0x200782ca, 0x20038260, + 0x200b8261, 0x200782d8, 0x20038262, 0x200b8265, 0x200782dc, 0x20038266, + 0x200b8267, 0x20078249, 0x20038268, 0x200b827e, 0x200782e0, 0x2103857f, + 0x07829400, 0x03858f20, 0x82950021, 0x82578307, 0x96002103, 0xa0200b82, + 0xa1200382, 0x97206b82, 0xc3830782, 0x0b82b020, 0x0b829920, 0x0385f020, + 0x82aa0321, 0x85fa2007, 0x51022103, 0xfb200782, 0x02210385, 0x2007826c, + 0x200382fc, 0x206b82ff, 0x200382f7, 0x20038218, 0x20038219, 0x200382d6, + 0x2003821a, 0x2003821b, 0x200382da, 0x21038537, 0x07829b00, 0x03855920, + 0x829c0021, 0x85bc2007, 0xab032103, 0xc6200782, 0xc7200382, 0x9d207782, + 0xc9200782, 0x00210385, 0x21e7859f, 0xaf42dd02, 0x82f32006, 0x2403820f, + 0x0000a600, 0x21128203, 0x04820103, 0x0b82a720, 0x03850320, 0x82a90021, + 0x85092007, 0x82002003, 0x0f0321b3, 0x03820b82, 0x82ab0021, 0x85232007, + 0xac002103, 0x84200782, 0x85200382, 0x2105eb42, 0x0b828603, 0x52200383, + 0x87200782, 0x00210385, 0x200782af, 0x20038288, 0x2003828a, 0x20038253, + 0x2003868c, 0x20078256, 0x2003828e, 0x20038292, 0x20038257, 0x20038293, + 0x20478294, 0x200782b0, 0x20038295, 0x20038297, 0x2003825c, 0x21038598, + 0x0782b200, 0x03829920, 0x03829a20, 0x03825f20, 0x03859b20, 0x82b30021, + 0x21ff8207, 0x07829d03, 0x03826120, 0x03859e20, 0x82b40021, 0x869f2007, + 0x82632003, 0x85a02007, 0xb5002103, 0xa1200782, 0x64200386, 0xa3200782, + 0x00210385, 0x200782b6, 0x200382a4, 0x200382a5, 0x20038265, 0x210385a6, + 0x0782b700, 0x0386a720, 0x07826720, 0x0382a820, 0xa782a920, 0x0782b820, + 0x0382aa20, 0x0382b020, 0x03826820, 0x0382b120, 0x1782b920, 0x0782ba20, + 0x6f200387, 0xbb200b82, 0x00210385, 0x200782c3, 0x200382bc, 0x200382bd, + 0x20038271, 0x210385be, 0x0782c400, 0x0386bf20, 0x07827020, 0x0382c020, + 0x2344c620, 0xc7032105, 0x03830b82, 0x07827320, 0x0382c820, 0x1782c920, + 0x0782cc20, 0x0382ca20, 0x0382ce20, 0x03827420, 0x0382d120, 0x1782d220, + 0xd6200f83, 0x03820b82, 0x00d00024, 0x12820400, 0x03200383, 0x04219f82, + 0x820f8201, 0x79032103, 0x02200782, 0x00200385, 0x04213782, 0x820b8203, + 0x7a032103, 0x2c820782, 0x03820420, 0x82d20021, 0x8205200b, 0x82082003, + 0x827b204b, 0x82092007, 0x000b2403, 0x82d30000, 0x850c2007, 0x80032103, + 0x0d200782, 0x03200385, 0x0421f782, 0x820b820e, 0x81032103, 0x0f200782, + 0x00200385, 0x042d8782, 0x04000010, 0x03000010, 0x04000082, 0x21038511, + 0x0782d700, 0x00001224, 0x17821304, 0x07828320, 0x03851420, 0x82d80021, + 0x85152007, 0x85032103, 0x16200782, 0x18200382, 0x2105e744, 0x0b821904, + 0x03210382, 0x20078286, 0x2103851a, 0x07827f03, 0x03851b20, 0x82dc0021, + 0x821c2007, 0x42222003, 0x04210573, 0x200b8223, 0x203b8224, 0x200782dd, + 0x21038525, 0x07828e03, 0x03822620, 0x17822f20, 0x0782df20, 0x03853020, + 0x828f0321, 0x82312007, 0x82342003, 0x82e92017, 0x85352007, 0x90032103, + 0x36200782, 0x38200382, 0xed201782, 0x39200782, 0x03210385, 0x20078291, + 0x2003823a, 0x0543453d, 0x823e0421, 0x2103820b, 0x07829203, 0x03853f20, + 0x82f40021, 0x82402007, 0x82412003, 0x8293208f, 0x85422007, 0xf5002103, + 0x43200782, 0x03210385, 0x20078295, 0x21038544, 0x0782f600, 0x03854520, + 0x82960321, 0x82462007, 0x824f2003, 0x82f7205f, 0x85502007, 0xb2032103, + 0x51200782, 0x03210385, 0x20078297, 0x21038552, 0x07820101, 0x03855320, + 0x82980321, 0x85542007, 0x02012103, 0x55200782, 0x58200382, 0x99208382, + 0x59200782, 0x5b240382, 0x03010000, 0x5c200782, 0x03210385, 0x2007829d, + 0x2103855d, 0x0782b303, 0x03855e20, 0x829e0321, 0x825f2007, 0x82612003, + 0x8206202f, 0x86622007, 0x825c2003, 0x82632007, 0x006f2403, 0x82090100, + 0x82702007, 0x82712003, 0x82b4205f, 0x82722007, 0x82752003, 0x82162017, + 0x82762007, 0x82772003, 0x82b62017, 0x85782007, 0xb9032103, 0x79200782, + 0x03210385, 0x200782b8, 0x2003827a, 0x202f8286, 0x2007821a, 0x20038288, + 0x200b8289, 0x20078227, 0x2003828a, 0x217b858b, 0x07828c04, 0xb7820383, + 0x828d0421, 0x8291200b, 0x82292023, 0x82922007, 0x85932003, 0x940421b7, + 0x95200782, 0x2e201782, 0x96200782, 0x97200382, 0x56200382, 0x98200382, + 0xf7820382, 0x82ba0321, 0x829a2007, 0x829b2003, 0x82482003, 0x829c2003, + 0x21f78203, 0x07823001, 0x03829e20, 0xeb869f20, 0x0782a020, 0x4782a120, + 0x07823220, 0x0382a220, 0x0382a320, 0x03824a20, 0x0382a420, 0x1782a920, + 0x07823420, 0x0382aa20, 0xc743ab20, 0xac042105, 0xad200b82, 0x4c200382, + 0xae200382, 0xaf200382, 0xbe201782, 0xb0200782, 0xb1200382, 0x69200382, + 0xb2200382, 0xb3200382, 0x4e200382, 0xb4200382, 0xb5200382, 0x3a204782, + 0xb6200782, 0xb7200382, 0x2105d741, 0x0782b804, 0x1782ba20, 0x07823c20, + 0x0386bb20, 0x07825a20, 0x0382bc20, 0x1782bd20, 0x07823f20, 0x0382be20, + 0xcb41bf20, 0xc0042105, 0xc2200782, 0xc0206b82, 0xc3200782, 0xc4200382, + 0x21050f47, 0x0b82c504, 0x0382c620, 0x03826720, 0x0382c720, 0x1782c820, + 0x07824320, 0x0382c920, 0xb741ca20, 0x82cb2006, 0x42cc2007, 0x04210537, + 0x200782cd, 0x200382ce, 0x20038265, 0x200382cf, 0x835382d7, 0x82d8204f, + 0x2103820b, 0x07824501, 0x0385d920, 0x82cd0321, 0x85da2007, 0xcc032103, + 0xdb200782, 0xdf200382, 0xce202f82, 0xe0200782, 0xe1200382, 0x46206b82, + 0xe2200782, 0xf5200382, 0xd3201782, 0xf6200782, 0xf7200382, 0x21058b42, + 0x0782f804, 0x1782f920, 0x0782e720, 0x0382fa20, 0x2f82fb20, 0x07824820, + 0x0382fc20, 0x1782fd20, 0x0782e920, 0x0382fe20, 0x0382ff20, 0x00006b24, + 0x03850005, 0x824a0121, 0x85012007, 0xeb032103, 0x02200782, 0x10200382, + 0x2105e347, 0x0b821105, 0x04210382, 0x2007826d, 0x20038212, 0x24478213, + 0x1e0000ec, 0x82038200, 0xae032133, 0x3e200782, 0x3f200382, 0xac201782, + 0x80200782, 0x85200382, 0x21050f46, 0x0b82a01e, 0x0b82f120, 0x0782ee20, + 0x0382f220, 0x0b82f320, 0x0782a520, 0x0382f420, 0x0000f928, 0x00004004, + 0x03854d1f, 0x00a90424, 0x53822000, 0x820b2021, 0x825b2077, 0x8210200b, + 0x48112003, 0x2021051f, 0x200b8213, 0x200b8214, 0x20078269, 0x21038515, + 0x07826f04, 0x03821720, 0x01218882, 0x8207826b, 0x2220213c, 0x73202382, + 0x25200b82, 0x27200382, 0x76200b82, 0x30200782, 0x01210385, 0x20078279, + 0x20038232, 0x05634633, 0x82392021, 0x823a200b, 0x827a2023, 0x853c2007, + 0x83032003, 0x82442083, 0x2103820b, 0x07827c01, 0x03857420, 0x827d0121, + 0x857f2007, 0x7e012103, 0xa3200782, 0x04210385, 0x2007826e, 0x200385a4, + 0x201f8301, 0x200b82a6, 0x245382aa, 0x20000080, 0x210385ab, 0x07824704, + 0x0385ac20, 0x82850121, 0x85b12007, 0x86012103, 0xb9200782, 0xba200382, + 0x87202f82, 0xbc200782, 0xbd200382, 0x89240b82, 0x05210000, 0x01210385, + 0x8207828b, 0x822120fb, 0x8c012103, 0x16200b82, 0x01210385, 0x8207828d, + 0x822120eb, 0x8e012103, 0x26200b82, 0x00200385, 0x21214f82, 0x820b822e, + 0x8f012103, 0x5b200782, 0x5e200382, 0x90245382, 0x02220000, 0x01210385, + 0x20078294, 0x20038506, 0x218b8200, 0x0b820f22, 0x01210382, 0x20078295, + 0x24038211, 0x01000012, 0x20078296, 0x2103851a, 0x07829801, 0x03851e20, + 0x82990121, 0x852b2007, 0x9a012103, 0x48200782, 0x01210385, 0x2007829b, + 0x21038560, 0x07829c01, 0x03826420, 0x47826520, 0x00009d24, 0x0385ca25, + 0x009f0125, 0x8201ee00, 0x25878203, 0x0000a001, 0x0385c3f6, 0x00a20124, + 0x1782fb00, 0x0004fb29, 0x00a40100, 0x85fffe00, 0xaa012503, 0xfcff0000, + 0xfd200382, 0x4b081782, 0x2c00b0ab, 0x5009b04b, 0x0101b158, 0x01b8598e, + 0x84b085ff, 0x0309b11d, 0xb02d5e5f, 0x20202c01, 0xb0446945, 0xb02d6001, + 0x01b02c02, 0xb02d212a, 0x46202c03, 0x462503b0, 0x59235852, 0x8a208a20, + 0x208a6449, 0x61682046, 0x2504b064, 0x18820784, 0x598a6529, 0x00b0202f, + 0x82695853, 0x58542605, 0x5940b021, 0x260a881b, 0x3a595965, 0x8304b02d, + 0x82318246, 0x598a212d, 0x6a204082, 0x07824086, 0x29081284, 0xb02dfd2f, + 0x204b2c05, 0x502603b0, 0xb0585158, 0xb01b4480, 0x1b594440, 0x45202121, + 0x5850c0b0, 0x1b44c0b0, 0x2d595921, 0xa38806b0, 0x7d22ab82, 0xad851869, + 0xb02c0727, 0xb02d2a06, 0x29418508, 0x40b05853, 0x5900b01b, 0x4f838a8a, + 0x23585329, 0x8a80b021, 0x828a1b8a, 0x845f82c1, 0x8dc0200f, 0x01b8220f, + 0x20108f00, 0x27108b40, 0x452503b0, 0x508001b8, 0x06824a82, 0x1b212322, + 0x23231083, 0x82212321, 0x445929a1, 0x2c09b02d, 0x4558534b, 0x2120a282, + 0x0a2aa282, 0x4529b02c, 0x2c0bb02d, 0x06822ab0, 0xb12c0c3f, 0x20880127, + 0xb958538a, 0x00040040, 0x0008b863, 0xb9585488, 0xe8032900, 0xb01b5970, + 0x24ac8223, 0x10b88820, 0x83138800, 0x2c0d34e5, 0xb88840b0, 0x585a0020, + 0x44002ab1, 0x2a00b91b, 0x8244e803, 0x2b0c2e5a, 0x002b00b0, 0x020d01b2, + 0x0eb2012b, 0x31058201, 0x303a0eb7, 0x00101b25, 0xb7002b08, 0x242e3801, + 0x0a82111a, 0x4e02b726, 0x15233240, 0x03250983, 0x212e3b48, 0x20098314, + 0x25138804, 0x1f283005, 0x13830e16, 0x51630625, 0x831b2d3f, 0x40072209, + 0x253b8634, 0x3a4a5b08, 0x13831929, 0x64830925, 0x83233a4e, 0x770a2509, + 0x21364c62, 0x0b230983, 0x855c7791, 0x760c2513, 0x1d364b60, 0x0d251383, + 0x141c242c, 0x2409820c, 0x0d0fb200, 0x31a28207, 0x697d4520, 0xb0b24418, + 0xb2730113, 0x74011350, 0x048380b2, 0x01137026, 0x1f0fb275, 0x6f2b1382, + 0x0075011f, 0x00cc002a, 0x829e0091, 0xec460803, 0xb2007200, 0x56007d00, + 0x4e005f00, 0x04016000, 0x0000c400, 0x60fe1400, 0x9b021400, 0x39ff1000, + 0x97fe0d00, 0x21031200, 0x3a040b00, 0x8d041400, 0xb0051000, 0x18061400, + 0xc0061500, 0x5b021000, 0x04071200, 0x33820500, 0x60210285, 0x0a018700, + 0xc4009aaa, 0xbf014001, 0xf4025802, 0x3a030e03, 0x9c036903, 0xe303c103, + 0x2004f903, 0x8b043704, 0x0a05b904, 0xc1057d05, 0x8f062706, 0x3a07bc06, + 0xb007a407, 0xdb07bc07, 0x21080208, 0x33098708, 0xdd097309, 0x790a300a, + 0xef0ab90a, 0x8b0b4e0b, 0xd90ba60b, 0x440c200c, 0xd90c9d0c, 0x7e0d330d, + 0x370ede0d, 0xcf0ea50e, 0x3e0f0d0f, 0xd80f8d0f, 0x41100910, 0x7c106510, + 0xc810a110, 0x0411e310, 0xe3118311, 0x94123712, 0x51130813, 0x0b14cb13, + 0x90144514, 0xf214d714, 0xa6155d15, 0x5816f415, 0xf516b816, 0xae176317, + 0x2418f417, 0xbb187218, 0x3419fc18, 0x8e197719, 0x131acf19, 0xb21a501a, + 0x761b151b, 0xf81bd91b, 0xc41c931c, 0xe31d651d, 0x0c1eef1d, 0xd21ebc1e, + 0x541f111f, 0x1920a71f, 0x8a203920, 0xd620b620, 0x39210b21, 0x8f218321, + 0xc321a921, 0x4622dd21, 0xe822aa22, 0xb4236323, 0xde242024, 0xab255625, + 0x7c261d26, 0xf526da26, 0x8a274127, 0x1e28c727, 0xfd287928, 0xc9299929, + 0x922a2c2a, 0x632bff2a, 0x112cb72b, 0xa52c422c, 0x042ddc2c, 0x3b2d0c2d, + 0x962d5e2d, 0x052ec22d, 0x7e2e3a2e, 0xbe2e9e2e, 0xf52ec72e, 0x432f272f, + 0xa12f5c2f, 0xcf2fa92f, 0x7530fc2f, 0xe330a330, 0x4d311131, 0x1c32c231, + 0xf8328532, 0x9b336833, 0x8d340f34, 0x3035e734, 0xd035a335, 0x98362836, + 0x4237e936, 0xf5379f37, 0x78383938, 0x3639e438, 0x0e3a9639, 0xd33a5e3a, + 0xa33b343b, 0x8c3c183c, 0x193ddd3c, 0xcd3d713d, 0xb83e393e, 0x3a3ff13e, + 0xec3f803f, 0x63402240, 0xe940a040, 0xa6414241, 0x6842f241, 0x4143e742, + 0x1344a943, 0x8e443944, 0x7945fb44, 0x0346b245, 0x94464a46, 0x1847ea46, + 0xce474447, 0x46480448, 0xc7488348, 0x7d491b49, 0x384ac749, 0x094bb04a, + 0xef4b814b, 0xd34c634c, 0x734d374d, 0x314ed24d, 0x1d4f984e, 0xeb4f9e4f, + 0xa5503950, 0x84511251, 0x7e52f551, 0xa4530653, 0xa5543754, 0x53550f55, + 0x04569955, 0x2b576b56, 0x5c58e357, 0x3059db58, 0xb8598359, 0x075ad459, + 0x335a1d5a, 0x725b045b, 0x315cda5b, 0xcc5ca05c, 0x4a5df55c, 0xeb5d955d, + 0x8d5e3d5e, 0x415fe25e, 0xed5f8f5f, 0xd2604360, 0xa2615c61, 0x3762e561, + 0xc9628662, 0xb7633863, 0x6c641764, 0x2565ca64, 0xee658c65, 0x57664866, + 0xb6666766, 0xa5671e67, 0x80681768, 0x4a69e668, 0x1f6ab569, 0xf06a836a, + 0x9d6b4b6b, 0x406cef6b, 0xe16cb66c, 0xb8090198, 0x6cf16ce9, 0x6d056dfb, + 0x6d436d20, 0x6d856d65, 0x6db06da4, 0x6eee6dbc, 0x6e8d6e2c, 0x6ebd6eb1, + 0x6fe66ecd, 0x6fd06fb4, 0x70ff6fec, 0x705a7013, 0x727e71dc, 0x7216720a, + 0x734b73e6, 0x747e74c9, 0x755e75e4, 0x762476b6, 0x772277c1, 0x781678b8, + 0x78927878, 0x78c678ac, 0x794b79e0, 0x79a97971, 0x7af379bf, 0x7bc77a85, + 0x7b857b46, 0x7ba37b94, 0x7cef7bdc, 0x7c317c18, 0x7ca07c3d, 0x7e8e7df5, + 0x7f8f7e18, 0x80487f48, 0x816181f8, 0x820b828e, 0x8252823c, 0x831b83c1, + 0x84d98368, 0x8475842f, 0x850a85bc, 0x856b852d, 0x864486ef, 0x87cc868c, + 0x87608702, 0x88d587ba, 0x88438800, 0x88b98867, 0x894689f2, 0x8aea898f, + 0x8aab8a42, 0x8b0e8bd5, 0x8b898b3f, 0x8c038cd2, 0x8c838c3b, 0x8dfe8cac, + 0x8eb38d71, 0x8e6e8e12, 0x8f1f8f9b, 0x8f958f7f, 0x909690e8, 0x916291ff, + 0x92f191ab, 0x92749233, 0x935393ea, 0x94f393c9, 0x949b9428, 0x951895ce, + 0x958d954a, 0x964c96fb, 0x970c97af, 0x98f89785, 0x99d89888, 0x996c9917, + 0x9a3d9ac2, 0x9bf79abb, 0x9b989b4f, 0x9c149cdb, 0x9c8d9c55, 0x9d219dcb, + 0x9d799d2d, 0x9e7e9eef, 0x9f139fd1, 0xa0f99f94, 0xa1c1a05f, 0xa15ca150, + 0xa2f9a1ad, 0xa288a247, 0xa35ca3f7, 0xa430a4ba, 0xa547a5c2, 0xa653a6de, + 0xa705a7b2, 0xa76da765, 0xa81ea8b9, 0xa9f2a881, 0xaac0a96d, 0xaa6daa22, + 0xab2aabc9, 0xababab54, 0xac2eacd7, 0xac8aac76, 0xacb0ac9e, 0xacd6acc4, + 0xad01aded, 0xae85ad5f, 0xae66ae02, 0xaec0aeb8, 0xaed0aec8, 0xafe3aedb, + 0x0d018249, 0xc1af515d, 0x92b031b0, 0x37b1d4b0, 0x65b14eb1, 0x8eb17cb1, + 0xb9b1a6b1, 0xd1b1c5b1, 0xffb1e8b1, 0x2eb216b2, 0x5cb245b2, 0x8bb273b2, + 0xb4b29db2, 0xe2b2cbb2, 0x11b3f9b2, 0x3ab328b3, 0x69b351b3, 0x97b380b3, + 0xbfb3a9b3, 0xecb3d5b3, 0x10b404b4, 0x33b41cb4, 0x5bb445b4, 0x88b472b4, + 0xb5b49eb4, 0xdeb4cdb4, 0x07b5f5b4, 0x2eb51db5, 0x5db546b5, 0x85b56fb5, + 0xaeb59cb5, 0xdcb5c5b5, 0x04b6edb5, 0x85b61bb6, 0x39b727b7, 0x62b74bb7, + 0x8fb778b7, 0xb8b7a6b7, 0xdbb7c9b7, 0x02b8ebb7, 0x2ab813b8, 0x57b840b8, + 0xdbb86eb8, 0x89b972b9, 0xb1b99ab9, 0xdeb9c7b9, 0x0bbaf4b9, 0x2eba22ba, + 0x57ba40ba, 0x80ba69ba, 0xa9ba92ba, 0xd7bac0ba, 0xf9baeeba, 0x1bbb04bb, + 0x33bb27bb, 0x61bb4abb, 0x79bb6dbb, 0xa7bb90bb, 0xbfbbb3bb, 0xe9bbd4bb, + 0x01bcf5bb, 0x2abc18bc, 0x42bc36bc, 0x6abc59bc, 0x96bc7fbc, 0xbebca7bc, + 0xedbcd5bc, 0x17bd05bd, 0x35bd29bd, 0x53bd41bd, 0x76bd64bd, 0x9fbd88bd, + 0xc1bdb5bd, 0xd9bdcdbd, 0xf7bde5bd, 0x14be08be, 0x2cbe20be, 0x4fbe38be, + 0x72be5bbe, 0x9abe88be, 0xc7beb0be, 0xf1bedebe, 0x1cbf04bf, 0x8dbf2fbf, + 0x06c0efbf, 0x34c01dc0, 0x62c04ac0, 0x90c079c0, 0xbec0a7c0, 0xe1c0d0c0, + 0x0ac1f8c0, 0x38c121c1, 0x98c168c1, 0xbfc1a8c1, 0xecc1d6c1, 0x15c2fdc1, + 0x39c22dc2, 0x5cc245c2, 0x89c273c2, 0xb7c2a0c2, 0xe4c2cdc2, 0x0ec3fcc2, + 0x37c325c3, 0x5ec34dc3, 0x8dc376c3, 0xbac3a4c3, 0xe9c3d2c3, 0x16c4ffc3, + 0x8fc47dc4, 0xbcc4a5c4, 0xdec4cdc4, 0x0ac5f4c4, 0x8ec521c5, 0xbac5a4c5, + 0xe8c5d1c5, 0x0ac6f4c5, 0x33c61cc6, 0x55c64ac6, 0x82c66bc6, 0xa4c68ec6, + 0xc5c6b0c6, 0xe8c6d1c6, 0x0bc7f4c6, 0x33c71cc7, 0x58c746c7, 0x75c764c7, + 0x9dc787c7, 0xbac7a9c7, 0xdcc7c6c7, 0xfec7e8c7, 0x26c80fc8, 0x4cc839c8, + 0xc4c8adc8, 0xf1c8dac8, 0x1fc908c9, 0x40c935c9, 0x58c94cc9, 0x70c964c9, + 0x88c97cc9, 0xabc9a3c9, 0xbbc9b3c9, 0xcbc9c3c9, 0xdbc9d3c9, 0xebc9e3c9, + 0xfbc9f3c9, 0x0bca03ca, 0x2bca13ca, 0x55ca43ca, 0x79ca67ca, 0xa4ca8aca, + 0xb4caacca, 0xc4cabcca, 0xe4caccca, 0x0dcbfbca, 0x31cb1fcb, 0x60cb49cb, + 0xd6cbcecb, 0xf6cbeecb, 0x15ccfecb, 0x34cc2ccc, 0x44cc3ccc, 0x63cc4ccc, + 0x73cc6bcc, 0x83cc7bcc, 0x93cc8bcc, 0xa3cc9bcc, 0xb3ccabcc, 0xd2cccacc, + 0x2ecddacc, 0x3ecd36cd, 0x6ccd55cd, 0x7ccd74cd, 0x9ccd94cd, 0xc9cdb3cd, + 0xf7cde0cd, 0x25ce0ece, 0x4bce38ce, 0x73ce62ce, 0xa6ce87ce, 0xc4ceb2ce, + 0xe3ceccce, 0x01cff5ce, 0x24cf0dcf, 0x52cf3bcf, 0x71cf69cf, 0x91cf79cf, + 0xb5cfa9cf, 0xcdcfc1cf, 0xe5cfd9cf, 0xf9cff1cf, 0x09d001d0, 0x37d020d0, + 0x56d03fd0, 0x85d06dd0, 0xa4d09cd0, 0xc3d0acd0, 0xf1d0d9d0, 0x10d1f9d0, + 0x40d128d1, 0x6fd158d1, 0x9cd186d1, 0xccd1b4d1, 0xfcd1e4d1, 0x0cd204d2, + 0x3bd224d2, 0x6ad253d2, 0x8dd27cd2, 0xbcd2a5d2, 0xecd2d4d2, 0x1bd304d3, + 0x53d337d3, 0x6bd35fd3, 0x7fd373d3, 0x97d38bd3, 0xb5d3a3d3, 0xe0d3c7d3, + 0x0bd4f2d3, 0x30d41dd4, 0x55d442d4, 0x77d467d4, 0x99d486d4, 0xbed4abd4, + 0xe3d4d0d4, 0x08d5f5d4, 0x2ad51ad5, 0x46d53ad5, 0x64d552d5, 0x88d576d5, + 0xb2d599d5, 0xddd5c4d5, 0x02d6efd5, 0x27d614d6, 0x49d639d6, 0x6ad658d6, + 0x88d67cd6, 0xa0d694d6, 0xbed6acd6, 0xe3d6d0d6, 0x08d7f5d6, 0x2dd71ad7, + 0x52d73fd7, 0x74d764d7, 0x8fd783d7, 0xadd7a1d7, 0xcbd7bfd7, 0xe9d7ddd7, + 0x06d8fad7, 0x1ed812d8, 0x3cd82ad8, 0x60d84ed8, 0x84d872d8, 0xa8d896d8, + 0xccd8bad8, 0xe9d8ddd8, 0x01d9f5d8, 0x1fd90dd9, 0x43d931d9, 0xced954d9, + 0xf4d9e8d9, 0x0cda00da, 0x24da18da, 0x3cda30da, 0x54da48da, 0x6cda60da, + 0x84da78da, 0x9cda90da, 0xb4daa8da, 0xc8dac0da, 0x92db2ddb, 0x0fdcd0db, + 0xccdc6ddc, 0x02dde7dc, 0x1add0edd, 0x32dd26dd, 0x4add3edd, 0xe4dd95dd, + 0x96de3ede, 0xaade9ede, 0xbcdeb4de, 0xccdec4de, 0xdcded4de, 0xf6dee4de, + 0x1fdf08df, 0x4edf36df, 0x7edf66df, 0xaedf96df, 0xdedfc6df, 0x0ee0f6df, + 0x3ee026e0, 0x62e056e0, 0x7ae06ee0, 0x92e086e0, 0xaae09ee0, 0xc2e0b6e0, + 0xe6e0d4e0, 0xfee0f2e0, 0x16e10ae1, 0x2ee122e1, 0x46e13ae1, 0x6ae158e1, + 0x82e176e1, 0x9ae18ee1, 0xb2e1a6e1, 0xd5e1c4e1, 0xede1e1e1, 0x05e2f9e1, + 0x1de211e2, 0x35e229e2, 0x4de241e2, 0x65e259e2, 0x7de271e2, 0x8de285e2, + 0x9de295e2, 0xade2a5e2, 0xbde2b5e2, 0xcde2c5e2, 0xdde2d5e2, 0xfde2e5e2, + 0x2be314e3, 0x45e33de3, 0x65e34de3, 0x7fe36de3, 0x9de395e3, 0xade3a5e3, + 0xcce3b5e3, 0xdce3d4e3, 0xece3e4e3, 0xfce3f4e3, 0x0ce404e4, 0x0ae599e4, + 0x73e56be5, 0x91e57fe5, 0xaae5a2e5, 0xc2e5b6e5, 0xdae5cee5, 0x0000e6e5, + 0x64000500, 0x28030000, 0x0300b005, 0x09000600, 0x0f000c00, 0x0cb26f00, + 0x12111110, 0x100cb039, 0x83d000b0, 0x84062005, 0x84092005, 0xd00d2f05, + 0x4500b000, 0x2f02b058, 0x1f02b11b, 0x0c84593e, 0x0c820020, 0x3e0f0027, + 0x0204b259, 0x21398200, 0x068505b2, 0x06850720, 0x06840820, 0xdc0ab024, + 0x09840cb2, 0x840db221, 0xb04a0806, 0x0eb01002, 0x213130dc, 0x03211121, + 0x11010111, 0x01210301, 0x03210135, 0x023cfd28, 0xeefe36c4, 0x0c01bafe, + 0xfe0302e4, 0xfd0201fe, 0xfab005fd, 0xfd0705a4, 0xfb77027d, 0xfd780211, + 0x885e025e, 0x02005e02, 0xf2ff8f00, 0xbf84a301, 0x3b000d26, 0x0f0e06b2, + 0xb0247f82, 0x01b01006, 0x0c20a793, 0x0c20a782, 0x0629a783, 0x582b0a0d, + 0xf41bd821, 0x08288259, 0x2f01b02d, 0x23013130, 0x34012103, 0x15163236, + 0x26220614, 0x17d17e01, 0xf9fe0001, 0x484a804a, 0xad014884, 0xc3fa0304, + 0x394b4b39, 0x824a4a37, 0x03652c73, 0x064002f4, 0x00040000, 0x41250009, + 0x0320050e, 0x03385982, 0xb0593e21, 0x02b0d002, 0xd007b02f, 0xb02f07b0, + 0x08b01003, 0x2f08b0d0, 0x03245d82, 0x05331123, 0x01260483, 0xae8b2313, + 0x04822d01, 0xfe770526, 0x890c027d, 0x53820483, 0x4e826020, 0xc782bc20, + 0x1f001b24, 0x53858d00, 0x6241ad84, 0x82102007, 0x87102060, 0x8202200c, + 0x8202200c, 0x00b025c7, 0x1ab05845, 0x1a200c82, 0xb2230c82, 0x83020c1d, + 0x2f1d24fc, 0x880300b2, 0xd00426de, 0xb0101db0, 0x26058406, 0x0bb0d00b, + 0x8908b22f, 0x100b231c, 0x13820eb0, 0x12b01028, 0x1008b0d0, 0x258414b0, + 0xb0d01626, 0x18b01000, 0x1e211184, 0x26bb82d0, 0x13230323, 0x84213523, + 0x03332303, 0x03821333, 0x03231523, 0x82038233, 0x23133205, 0x4ce0cf02, + 0x01e74ca8, 0x01f33a05, 0x4ea74e11, 0x380382e1, 0xdd3aeed0, 0x76a74cfb, + 0x01e03ae0, 0x0166fe9a, 0x39019e9a, 0xfea0019f, 0x3b038360, 0x9ec7fe9f, + 0x380266fe, 0x01003901, 0x2dff6400, 0x9b062604, 0x7d002c00, 0x2e2d2ab2, + 0xfc92c082, 0xe2820920, 0xfc870920, 0x0c822320, 0xfc872320, 0x0c822020, + 0x0c822020, 0x0c19b223, 0x253b8220, 0xb21019b0, 0xfc870102, 0x090fb223, + 0x05c84223, 0x8913b221, 0x23272214, 0x23148309, 0x2ab21023, 0xe5821488, + 0x26348b08, 0x35262726, 0x35373634, 0x16161533, 0x26342315, 0x15062223, + 0x1e041614, 0x06141502, 0x35231507, 0x33352626, 0x32331614, 0x6c330336, + 0xcae946fc, 0xbeaea0ad, 0x606171f2, 0x00016b6c, 0xcf366492, 0xd5c69fb9, + 0x72747ff3, 0x557c0177, 0x7d26596f, 0x14d6a6f5, 0xf519dcda, 0x68917ec4, + 0x5e695761, 0x5a866750, 0xc313d2a9, 0xc6f016c2, 0x006e8a7e, 0x63000500, + 0x8905ecff, 0x0d00c505, 0x27001a00, 0x39003500, 0x05b28900, 0x9f833b3a, + 0xb0100525, 0x82b0d013, 0x841b2005, 0x84282005, 0xd0362e05, 0x2f36b000, + 0xb02f38b0, 0xb0584500, 0x20fc8203, 0x07164103, 0x0c822520, 0x3e0f252f, + 0x1003b059, 0xb0d00ab0, 0x11b22f0a, 0x08054202, 0xb2100323, 0x2c0d8918, + 0x1eb01025, 0x2f1eb0d0, 0xb21025b0, 0x2316892b, 0x32b2101e, 0x30280d88, + 0x36341331, 0x15163233, 0x2324fc82, 0x17352622, 0x3527f984, 0x22263435, + 0x88011506, 0x8b20201a, 0x82232019, 0x057b081a, 0x63170127, 0xa98c8aaa, + 0xaf878aa9, 0x3e3f4daa, 0x4b7e4d4c, 0x87ae1202, 0xfea7ad88, 0x4faaabe8, + 0x4e49403e, 0xfe4d3e3d, 0xc7027d02, 0x8498047d, 0x4889a9a9, 0x8ca5a883, + 0x55554506, 0x56454949, 0xd0fc4757, 0x8da6a686, 0xa7a98247, 0x57440589, + 0x464b4b53, 0xf44a5454, 0x48720448, 0x56000300, 0x1105ecff, 0x1c00c405, + 0x31002500, 0x2eb29800, 0x12113332, 0x102eb039, 0x83d010b0, 0x431e2005, + 0x324206f7, 0x2f1b240c, 0x421bb11b, 0x18200732, 0x18200c82, 0xb2230c82, + 0x82091b20, 0x28b2233a, 0x06831b09, 0x28200322, 0x10220683, 0x06832028, + 0x1b851320, 0x18131122, 0x19220d83, 0x06831318, 0x19111622, 0xb0240682, + 0x1db2101b, 0x23083942, 0x111d1fb2, 0x09231483, 0x882fb210, 0x31302814, + 0x37363413, 0x41352626, 0x8e080527, 0x07070614, 0x33353601, 0x21170710, + 0x24200627, 0x01373205, 0x14150607, 0x17140316, 0x35363737, 0x22232634, + 0xa26e5606, 0xb0d04355, 0x695ccb9f, 0x3d190163, 0xfed67ed3, 0xfe9c52e6, + 0x01fdfe50, 0xfe6b7be2, 0x82781fc2, 0x1f6f6719, 0x4742563e, 0x65890154, + 0x966b74a9, 0xbbc7ab46, 0x4c995b8a, 0x78b4fe48, 0xacf3fe93, 0xe57561fd, + 0x77015223, 0x65755b16, 0x54aa037e, 0x37194c7f, 0x60513956, 0x00010000, + 0x01fc0352, 0x0000060b, 0x44160004, 0x230813b1, 0x03013130, 0x01331123, + 0xb99f1a0b, 0x79fe8305, 0x01000402, 0x31fe8000, 0x5f06a202, 0x10001000, + 0x121107b2, 0x0026e682, 0xb02f04b0, 0xdf832f0d, 0x12123708, 0x02061737, + 0x12100703, 0x02260717, 0xf07c8002, 0xaf8d3086, 0x9aab0108, 0x7bf18630, + 0x01e75002, 0x4247019f, 0x49fe6b8e, 0xfe56e5fe, 0x7c25fed1, 0x49014287, + 0x57829d01, 0x57822820, 0x57825120, 0x57831220, 0x87141321, 0x820e2057, + 0x013f0857, 0x07020214, 0x11123627, 0x27021035, 0x12163727, 0x51021712, + 0x3087f87a, 0x8e98af96, 0xf080301f, 0x40020880, 0xfe63fede, 0x748741ad, + 0x3201dd01, 0x01160117, 0x881c8ac9, 0xfec4fe3e, 0x8200d079, 0x021b2a5d, + 0x0574034d, 0x000e00b0, 0x31e98520, 0xb11b2f04, 0x593e1f04, 0x19d000b0, + 0x182f00b0, 0x078209b0, 0x182f0922, 0x3508f382, 0x03053725, 0x17250333, + 0x03071305, 0x4c012703, 0x0137cffe, 0x0fb30f2e, 0xfe362901, 0xb491c8ca, + 0xcc0392b2, 0x0175a958, 0x73a2fe58, 0xf6fe58ac, 0xfe20016a, 0x658366e9, + 0x9200442e, 0xb6042a04, 0x1a000b00, 0x2f09b000, 0xb0245b82, 0x06b21009, + 0x22080242, 0x82d003b0, 0x2120085f, 0x23112115, 0x21352111, 0xae023311, + 0x84fe7c01, 0x0182feec, 0x2103ec7e, 0x014ffede, 0x9501deb1, 0x1c37af82, + 0x5d01b8fe, 0x0900eb00, 0x09b21800, 0x12110b0a, 0x0ab00039, 0x4605b22f, + 0x303e08a2, 0x36271331, 0x33353736, 0x9f060607, 0x012b3a83, 0x690101db, + 0x5b4eb8fe, 0xafbd4687, 0x8d83d56a, 0x09024730, 0xcd025402, 0x11000300, + 0x2f02b000, 0x878801b2, 0x352a8483, 0xfd540221, 0x020d02f3, 0x6f82c409, + 0xf5ff872e, 0x0001a201, 0x22000a00, 0x0c0b00b2, 0x29087145, 0xb11b2f06, + 0x593e0f06, 0x798a00b2, 0x16320122, 0x33050044, 0x14013634, 0x444a4a44, + 0x014a4c41, 0x393a4d00, 0x4d744a4b, 0x02267983, 0xfe0283ff, 0x7982b005, + 0xb0001323, 0x05974400, 0x1b480220, 0x30220806, 0x01231731, 0x02bfc133, + 0x067dbf3d, 0x0200002d, 0xecff6900, 0xc4052204, 0x1b000d00, 0x03b24600, + 0x7d821d1c, 0x1003b024, 0xb54311b0, 0x820a2006, 0x1f0a2139, 0x20065548, + 0x200c8203, 0x24908203, 0xb2100ab0, 0x82d08811, 0x18b2212e, 0x52080d88, + 0x10013130, 0x02222302, 0x12103503, 0x13123233, 0x23263427, 0x11070622, + 0x32331614, 0x22043736, 0xefecf0eb, 0xeff1eb03, 0x70f303eb, 0x0370777a, + 0x70757a72, 0xfe650203, 0x01c1fec6, 0xfc310137, 0x3a013a01, 0xcffecefe, + 0xb5bfcd14, 0xccb6fec0, 0x83c5b9c8, 0x00a82ad5, 0x05ff0200, 0x000600b5, + 0x05434239, 0x8b820520, 0xee480520, 0x05002111, 0x0423c083, 0x8803b22f, + 0x02b22291, 0x35148303, 0x23213130, 0x25350511, 0xf2ff0233, 0x38029bfe, + 0x7a91041f, 0x5b83d1cd, 0x0000512e, 0xc4054004, 0x4e001900, 0x1b1a11b2, + 0x20087f41, 0x20628211, 0x22629011, 0x82001103, 0x11b02421, 0x8909b210, + 0x85162062, 0x10002114, 0x240c0941, 0x01352121, 0x064d4436, 0x23154108, + 0x33363634, 0x14151632, 0x21010706, 0x2dfc4004, 0x5969e501, 0x82766375, + 0x93e179f3, 0x8c7bf5d4, 0xa4029cfe, 0x751102a7, 0x80684f9d, 0xd5857d90, + 0x6dbcd576, 0x83fe98ef, 0x4f000100, 0x1504ecff, 0x2926a182, 0x07b26e00, + 0xa1882b2a, 0xa1820f20, 0xa1870f20, 0x22075345, 0x830f01b2, 0x01b02ec3, + 0x011fb22f, 0x9fb27101, 0xb25d0101, 0x2409823f, 0xb2100fb0, 0x09b64107, + 0xb2100123, 0x230d8828, 0x012815b2, 0x20064a45, 0x23148822, 0x33013130, + 0x1620bf93, 0x0423c582, 0x47242223, 0x5408067d, 0x23263435, 0x94860123, + 0x706d8370, 0x77f37e62, 0xf9da84d5, 0x7d78637d, 0xd2dbf3fe, 0x81f3f4fe, + 0x8882716d, 0x47038f86, 0x686c7201, 0x705b7173, 0xc3db67b8, 0x292cad62, + 0xe8c47ab0, 0x7860bae0, 0x7c737278, 0x00020000, 0x04000034, 0x00b00558, + 0x000e000a, 0x05e54149, 0x200c3446, 0x27ed8204, 0x593e0f04, 0x040901b2, + 0xe082ab83, 0x2c095a48, 0xb0d006b0, 0x0bb01001, 0x0608b2d0, 0x211d820b, + 0x24840db2, 0x3408c283, 0x23112315, 0x01272111, 0x11210133, 0xb5a30307, + 0x8bfdf3b5, 0xfb740207, 0x7d0190fd, 0xc3070212, 0x4401bcfe, 0xfcd80394, + 0x20600257, 0x00010000, 0x04ecff81, 0x2687823a, 0xb26a001d, 0x411f1e1a, + 0x0120086d, 0x01207f82, 0x20076d41, 0x200c820d, 0x828c820d, 0x0b6b4274, + 0x0d010722, 0xb0242f82, 0x1ab22f07, 0x23084641, 0x1a0705b2, 0x0d231483, + 0x8914b210, 0x14112114, 0xb2231483, 0x82141a1d, 0x3130371b, 0x15211313, + 0x33360321, 0x14151232, 0x24222300, 0x16163327, 0x3c423233, 0x073a0806, + 0x0e034fae, 0x6528bcfd, 0xffe7d07f, 0xfec8df00, 0x0eeb0bf9, 0x7d70647c, + 0x5c42798a, 0x02d20236, 0xa4fed2de, 0xe1f6fe3a, 0xe3f9fede, 0xa0716aba, + 0x239b858a, 0x02000033, 0xcb827500, 0xb705372c, 0x1f001400, 0x15b26200, + 0x6c822120, 0x1015b023, 0x07354cb0, 0xc6820020, 0xd3900020, 0x44100021, + 0xb2220ab0, 0xd3870007, 0x83070521, 0x15b22109, 0xb024c588, 0x1bb2100d, + 0x30270d88, 0x23150131, 0x88070606, 0x005c08c5, 0x00103511, 0x06220321, + 0x16141507, 0x26103632, 0xcc1e6103, 0xb67517f4, 0xfbfedfc1, 0xf1fedad4, + 0x5e017501, 0x1f8550ec, 0x807ed888, 0x03c9b705, 0xfe7bc8da, 0xfeded7f0, + 0x014201ed, 0x7f015305, 0x49fdb201, 0xa24a4b5a, 0x0801a2bf, 0x010000a6, + 0x00004500, 0xb0053604, 0x32000600, 0x20120744, 0x26cd8201, 0x593e0f01, + 0x411005b0, 0x00200b94, 0x3d060044, 0x01230101, 0x04213521, 0xffbafd36, + 0x0ffd4502, 0x2905f103, 0xed04d7fa, 0x030000c3, 0x09456800, 0x00172a06, + 0x002b0021, 0x2c09b274, 0x0546482d, 0xd01ab027, 0xb01009b0, 0x06114524, + 0x63821520, 0x31411520, 0x82092007, 0x8209200c, 0x29b22370, 0x2d831509, + 0xb22f2926, 0x7101291f, 0x220bfc41, 0x82291a03, 0x0fb22319, 0x4e851a29, + 0x411fb221, 0xb024082f, 0x25b21015, 0x30250d88, 0x06140131, 0x085b4307, + 0x290aaf48, 0x22263403, 0x16141506, 0x09893632, 0x02045508, 0x7b725f6e, + 0xd9d8fcfe, 0x707cfbfe, 0xccf06d5e, 0x81d3f0cd, 0xdc7d7fd4, 0xba6e1f7b, + 0x6dba6d6c, 0xa76b3004, 0x74b83530, 0xbfe2e1c0, 0x3032ba75, 0xdaba6ba7, + 0x6caffcda, 0x6b6d8485, 0xfd027c80, 0x65757b5f, 0x00767664, 0x5d000200, + 0x1204faff, 0x1500c405, 0x6424fb82, 0x232209b2, 0xb021aa85, 0x13bb4916, + 0xf3821120, 0xf3831120, 0x09111622, 0x7c242782, 0x182f16b0, 0x210be34b, + 0x16830200, 0x1011b024, 0xdb8812b2, 0x4909b021, 0xe9820ba2, 0x22230639, + 0x36343502, 0x00323336, 0x00101511, 0x33352305, 0x32033636, 0x86353736, + 0x035508eb, 0xc0a37a1e, 0x8dd674e4, 0xfe0201dc, 0x1d9ffe9c, 0xdce6d723, + 0x84238049, 0x027e7dd2, 0x0d018161, 0x82ea90db, 0xedfeb8fe, 0xfe76fe44, + 0x03c90362, 0x540f01c9, 0xc4a15f4a, 0xa88984ad, 0x00ffff00, 0x01f5ff82, + 0x0051049d, 0xfb120026, 0x00070000, 0x03fbff12, 0x24178251, 0x01b8fe2e, + 0x20178288, 0x32118227, 0x005103e6, 0x12100006, 0x00010000, 0x03a4003f, + 0x824e0484, 0xb217240f, 0x43080700, 0x052008f5, 0x0523ee82, 0x82593e1b, + 0x052308b4, 0x01350115, 0x02360115, 0x03bbfc4e, 0xe0770245, 0xc17501f3, + 0x00f37401, 0x01910002, 0x03ef0364, 0x820300d6, 0x00252c69, 0xb02f07b0, + 0x03b0d003, 0x4100b22f, 0x07230902, 0x4804b210, 0x11290e05, 0x03213521, + 0x03a2fcef, 0x2503835e, 0xfdca0c03, 0x8b83c98e, 0xa5008024, 0x8b92e003, + 0x8b820220, 0x8b850220, 0x89832520, 0xea023532, 0x600396fd, 0x7c02a0fc, + 0x8cfeefe3, 0xef8cfec1, 0x3c308b82, 0x9803f4ff, 0x1800c405, 0x5e002300, + 0x252409b2, 0x2006cd41, 0x06cd411c, 0x200cb94e, 0x25528222, 0x593e0f22, + 0x64481cb2, 0x00b02908, 0x2f00b0d0, 0x100004b2, 0x10203883, 0x220ce846, + 0x8200100c, 0x15b22114, 0x30251b84, 0x36340131, 0x072f4b36, 0x46231521, + 0x072406e0, 0x03070607, 0x0807684b, 0x01262236, 0x1ac3425e, 0x565a5d28, + 0xed02f369, 0x98e1c9c3, 0xf402427b, 0x4a403f4a, 0x01478448, 0xbd9e85ac, + 0x5e473d28, 0xb1536163, 0xa3b7ccce, 0x904b799e, 0x493bc9fe, 0x3007d94f, + 0x063bfe5b, 0x009005d9, 0x00420036, 0x433bb27c, 0x247d8244, 0xb0103bb0, + 0x23cb8223, 0x33b02f2a, 0x4c0a774d, 0x0820074e, 0x0820d182, 0xb2230c82, + 0x82083305, 0x0fb2212d, 0xb0270684, 0x08b02f0f, 0x4d3ab210, 0xb027084f, + 0x33b0d015, 0x891bb210, 0x102a2310, 0x0d8923b2, 0xb2100f23, 0x820d8840, + 0x062108e9, 0x27222302, 0x22230606, 0x12363726, 0x16323336, 0x33060317, + 0x12373632, 0x04222100, 0x12060702, 0x200d8304, 0x2d218317, 0x13262724, + 0x33241212, 0x01120432, 0x16831606, 0x26139d08, 0x06062223, 0xbede0ccd, + 0x87333db5, 0x1297924a, 0x6ec37f10, 0x34578154, 0x83668513, 0xc1fe1106, + 0xfec4c0fe, 0x0c09b2d1, 0xcf1f018b, 0x2640b754, 0xfe69cf3d, 0x5e5b94fe, + 0x01de0c0b, 0x01f9f681, 0x03fcb267, 0x36514a0d, 0x322d1e60, 0x028c6f2f, + 0xdffefa06, 0xf04c4c9a, 0x0601a3c9, 0xfd422a8f, 0xaedbc6cd, 0x88017101, + 0xed8dfec4, 0xb6a3fef1, 0x28892228, 0xd3ccd731, 0x12012601, 0xdbf2b501, + 0x8cfe65fe, 0x535f8d88, 0xd113ed01, 0x12000200, 0x42050000, 0x0700b005, + 0x46000a00, 0x520f954b, 0x5141074d, 0x08884a07, 0x02040927, 0xb0391211, + 0x0bd74209, 0x840ab221, 0x31302914, 0x21032101, 0x21013301, 0x26080782, + 0xccfdc303, 0x02f9fe76, 0x2702e326, 0x9cfdf8fe, 0x01d3a601, 0x05adfe53, + 0x0250fab0, 0x005c021f, 0x00940003, 0x82a30400, 0x000e287f, 0x001f0016, + 0x4602b26d, 0x02250599, 0xd011b010, 0x200582b0, 0x06ab421e, 0x520c7347, + 0x172208d5, 0x87830100, 0xb22f1728, 0x7101171f, 0x56430fb2, 0x08b22308, + 0x1983170f, 0xb2100023, 0x0ce94810, 0x0d881e20, 0x33313027, 0x04322111, + 0x086b4515, 0x0e820120, 0x34353624, 0x6e472527, 0x23450806, 0xf7f30194, + 0x686c0201, 0xf9fe8176, 0x01eafef5, 0xe8867719, 0x76f8d2fe, 0xf6827b85, + 0xc4c6b005, 0x202ca064, 0xdccd7cb1, 0x39fe9102, 0x05e36976, 0x6c626bba, + 0x00010060, 0x04ecff66, 0x00c405eb, 0xb240001d, 0x0a374803, 0x4b0c3652, + 0x0c210843, 0x0a035110, 0x1003b022, 0x350a3346, 0x06013130, 0x24222300, + 0x34352702, 0x32332412, 0x26231700, 0x45472326, 0x08a48205, 0xeb043756, + 0xf9d4fe16, 0x90f7feae, 0x11019203, 0x2601f1b3, 0x9312fc18, 0x02b1a58e, + 0x9695a3a9, 0xe9da0114, 0x01a5fbfe, 0xce88c930, 0xfeaa3a01, 0x8b9deffa, + 0xec81e9f1, 0x009c86f8, 0x94000200, 0xd2040000, 0x0b00b005, 0x46001500, + 0x171602b2, 0xb0391211, 0x15b01002, 0x241b7141, 0xb21001b0, 0x0842410c, + 0x1000b024, 0x50410db2, 0x1512280f, 0x04021415, 0x83110323, 0x352b08a1, + 0x94232634, 0x01c1ae01, 0xfea5a42b, 0xa5a6c5cf, 0xce02d5c7, 0xacb005c4, + 0x49ccc4fe, 0xaac6fecf, 0xe6fbe404, 0xed51e9f9, 0x840100fa, 0x844c2091, + 0x424e2091, 0x06240589, 0x06b11b2f, 0x49076247, 0x0b2208f5, 0xaa830406, + 0x54450b20, 0x5204200c, 0xb0240b5e, 0x08b21006, 0x230c6245, 0x21152111, + 0x03370385, 0x02aafde7, 0x0348fcbb, 0x024cfdb1, 0xfe8a0256, 0xb005ca40, + 0x866efecc, 0x8231207f, 0x0009227f, 0x1a094340, 0xfc42b220, 0x04b02113, + 0x250b624e, 0x21013130, 0x6f862311, 0xb6fddb2d, 0xfd9d03fd, 0x024a0260, + 0x8397fd69, 0x824f206b, 0xff6a2e6b, 0x05f004ec, 0x001e00c4, 0x1f0bb255, + 0x08654620, 0xf2820b20, 0xf2870b20, 0x20082342, 0x19674d0b, 0x0b1eb223, + 0x223d8203, 0x492f1eb0, 0x25220c80, 0x38420406, 0x10510805, 0x04322100, + 0x21022317, 0x15070622, 0x32331214, 0x35211137, 0x4ff00421, 0xb7b2e8fe, + 0x0399e6fe, 0x1b013c01, 0x1d1e01f3, 0xf9fe2af8, 0xc703b1aa, 0xfe52c2b1, + 0xbd2802d4, 0x01a66a67, 0x0172ce35, 0xf073014a, 0xf50701e2, 0xfeec70ed, + 0x1d0158fb, 0x052941c0, 0x05180527, 0x000b00b0, 0x12a9414c, 0x430c2b4e, + 0xb02407ab, 0xb0584500, 0x2208c341, 0x44000609, 0xb94b0640, 0x31302909, + 0x21112321, 0x33112311, 0x33340582, 0xfdfc1805, 0x02fdfd75, 0x8702fc8b, + 0xb00579fd, 0x5e02a2fd, 0xa3247982, 0x9f010000, 0x03227982, 0xee561d00, + 0x244a841a, 0xfc9f0133, 0x822a82fc, 0xff2d2435, 0x82e403ec, 0x000f260a, + 0x1005b22f, 0x086d4111, 0x270cf54a, 0xb11b2f05, 0x593e0f05, 0x290ae042, + 0x33013130, 0x23041411, 0xe24c2622, 0xe8022b07, 0xd6fbfefc, 0x73fcf8e4, + 0x9582666d, 0xd103fc29, 0x74cde6f6, 0x41778775, 0x0c220a15, 0x3f425300, + 0x82082012, 0x5608205e, 0x0b201427, 0x0b201982, 0x00227883, 0x9a820204, + 0x006ab428, 0x5d02007a, 0x0d8506b2, 0x75066525, 0x825d0206, 0x072b0889, + 0x33112311, 0x21013711, 0x02210101, 0xfdfda536, 0x01aa018c, 0x02e3fd32, + 0x02d4fe3c, 0x3afeaf75, 0x55fdb005, 0xfdfe01ad, 0x85d5fc7b, 0x2604218d, + 0x0522f382, 0x8d922800, 0x73820220, 0x73840220, 0x2e0a2743, 0x21152125, + 0x91013311, 0x6efc9502, 0x41cacafd, 0x9424053b, 0x6a060000, 0x0e220a82, + 0x47856e00, 0x580c3441, 0xde410c6d, 0x00b02407, 0x84b05845, 0x073946ef, + 0x2208df57, 0x83040001, 0x016523e2, 0xe2820175, 0x0d850720, 0x7a076a23, + 0x200d8207, 0x220d860a, 0x830a7a0a, 0x020922f0, 0x24f18221, 0x01230113, + 0x08078213, 0x01dc0124, 0x01a301a4, 0xfe19fc47, 0x53feb552, 0xb005fc19, + 0x5c04a4fb, 0xe00150fa, 0x9efb8202, 0x7ffd6104, 0xb18820fe, 0x82170521, + 0x0009240a, 0x5101b24c, 0x918306b7, 0x410c2a50, 0xa4420c8e, 0x0775430c, + 0x0502b223, 0x21ab8200, 0x068407b2, 0x21313024, 0x87820123, 0x11013331, + 0xfd170533, 0xfdfd77fd, 0x04fb8b02, 0x82f7fb09, 0x04f33688, 0x0002000d, + 0x05ecff66, 0x00c4051e, 0x001e0010, 0x1f04b246, 0x243d8220, 0xb01004b0, + 0x06514514, 0x410cff45, 0x0c20082b, 0x820b0d4e, 0x0cc6432e, 0x02140122, + 0x2c06c743, 0x20241234, 0x07171204, 0x22230234, 0x05c94302, 0x35124008, + 0xfe941e05, 0xfeb1b3ed, 0x970197eb, 0x64011301, 0x01961301, 0xa4a8b7fd, + 0xa6bb02b9, 0xb202b5a8, 0xadbdfed6, 0xd14001ad, 0x4601d552, 0xbffeabad, + 0x01f205d5, 0xebfffe02, 0xfafef054, 0x46f60001, 0xd42c0605, 0x0a00b005, + 0x4d001300, 0x15140ab2, 0x0a23b383, 0x860cb010, 0x0cc956b3, 0x564d0120, + 0x0bb22306, 0x82450301, 0x46032011, 0x30240bc8, 0x23110131, 0x08055f47, + 0x2523042f, 0x35363221, 0x21272634, 0x02fd9101, 0x1f01f42d, 0xfefde7fe, + 0x873001d3, 0xfe7e908e, 0xfd1d02c9, 0xfeb005e3, 0xcbeed6d1, 0x8d76787f, + 0x2e958202, 0x0504ff60, 0x00c4051a, 0x00230015, 0x4a08b246, 0x082305b9, + 0x8620b010, 0x0c915195, 0x23086842, 0x19b21011, 0x2408cd42, 0xb21008b0, + 0x0c534d20, 0x17070225, 0x47062507, 0x04250a4e, 0x34071712, 0x0b4e4126, + 0x76831929, 0xcafea4fa, 0x41b0463d, 0xb1390652, 0x961301b4, 0xa8b8fe01, + 0xb902b9a3, 0x02b5a9a7, 0xd1fecfb2, 0xf594c359, 0x0d56410d, 0xfefef628, + 0xec55eaff, 0x5541f6fe, 0x05de2c09, 0x000e00b0, 0xb25a0017, 0x58191805, + 0x10200637, 0x0420bf86, 0x4908f854, 0xb2230a62, 0x8304020f, 0x540f2027, + 0xb2230b25, 0x470f010b, 0x0e260698, 0x1004b0d0, 0xd74617b2, 0x0663410d, + 0x01070625, 0x41012115, 0x41080766, 0xe6feab02, 0xfc0002fd, 0x7e8d1201, + 0xf1fe4701, 0x0401c2fd, 0x84859080, 0x3102f5fe, 0xb005cffd, 0xc592d6e2, + 0x0da1fd35, 0x7081fc02, 0x00028075, 0x4a000100, 0x8a04ecff, 0x2700c405, + 0x11b26300, 0x21452928, 0x0c785108, 0xb6821d20, 0x3e0f1d27, 0x1d02b259, + 0x23218209, 0x1d090eb2, 0xb0210682, 0x0c9d4609, 0xa38b0220, 0x8422b221, + 0x1db02129, 0x290ee04e, 0x27242634, 0x24343526, 0xd1593233, 0x07f44e0c, + 0x0808cf59, 0xfe878d41, 0x01c768a0, 0xee98e51f, 0x858ffc88, 0x0194897c, + 0xfe60ce54, 0xfe9eefe9, 0xa4fd93f7, 0x01858499, 0x6a686077, 0xb0c97d41, + 0x7ecf70e4, 0x5f6a8172, 0x81656b50, 0xd7b670a7, 0x7c89ce75, 0x82006b88, + 0x002d2adb, 0x05b00400, 0x000700b0, 0x12ad462e, 0x09450220, 0x06b02206, + 0x0ba54d10, 0x47d00421, 0x353107c5, 0xfeb00421, 0x3efefb3a, 0xe4048304, + 0xe4041cfb, 0x245382cc, 0x04ecff7d, 0x245382bd, 0xb23c0010, 0x06815704, + 0x58450023, 0x0c2f41b0, 0x460c604d, 0x314908fb, 0x0131080b, 0x23001411, + 0x11350022, 0x16141133, 0x11112033, 0xd7febd04, 0xdafefaf7, 0x019094fc, + 0xfcb00524, 0xf1fee833, 0x03ed0b01, 0x9232fccc, 0x0334019a, 0x247b82c6, + 0x05000012, 0x227b821d, 0x4e380006, 0x234b0ca1, 0x0cec440c, 0x2508d244, + 0x11030100, 0xd9823912, 0x01210138, 0x02210123, 0x01720195, 0xf5f4fd16, + 0x1501f6fd, 0x73043d01, 0x578250fa, 0x30000126, 0xe5060000, 0x0c260982, + 0x05b26000, 0xf9520e0d, 0x0c414515, 0x2415b748, 0xb0584500, 0x08bd5606, + 0xb2217b84, 0x20068505, 0x8206840a, 0x33132189, 0x02828982, 0x13332608, + 0x0a053301, 0xb0fefbe0, 0xfeebfef2, 0xb0fef3e5, 0x1601e2fb, 0x046801d4, + 0x0450fa48, 0x05d9fb27, 0x04bafbb0, 0x24ff8246, 0x04000029, 0x209d82e9, + 0x0767470b, 0x7d48f88c, 0x0c91460c, 0x89820720, 0x3e0f0727, 0x0100b259, + 0x21d28204, 0x068506b2, 0x06000322, 0x92480d83, 0x051a4105, 0x01210122, + 0x28080284, 0x32018902, 0x48fe2401, 0xd9fec201, 0xc6fec7fe, 0xc301dafe, + 0x240147fe, 0x0e02a203, 0x22fd2efd, 0xeafd1602, 0xd202de02, 0x20958200, + 0x20958207, 0x229582d6, 0x42310008, 0x958c0565, 0xca4a7b84, 0x85888510, + 0x23113d73, 0x02210111, 0x014f016f, 0xfe18fe18, 0x190117fe, 0xb202fe02, + 0xe8fd68fc, 0x98031802, 0x50246183, 0x8c040000, 0x09226182, 0x61854400, + 0xd147548c, 0x04b22312, 0xda820200, 0x1007b024, 0x364405b2, 0x09b22308, + 0x14820705, 0x2531303e, 0x35211521, 0x21352101, 0x03820115, 0x02c4fb0a, + 0x0414fdf1, 0xa4caca1f, 0xa0cc4004, 0x84306f83, 0x1c02bcfe, 0x07008e06, + 0xb0002200, 0x07b02f04, 0x570f714b, 0xc282095b, 0x33112335, 0x21112115, + 0xa5a51c02, 0x980168fe, 0xa9f9d005, 0x83d207bd, 0xff142447, 0x82640383, + 0x000325b7, 0x02b00013, 0x2005a94f, 0x066f5400, 0x13313036, 0x14230133, + 0xf06002f0, 0xd3f9b005, 0x0c000100, 0xa601bcfe, 0x25207584, 0x01232d84, + 0x8b02b02f, 0x01b021bf, 0x200d6a4b, 0x31748213, 0x23113335, 0xfe9a010c, + 0x06a7a766, 0xbd2ef88e, 0x77835706, 0xd9023524, 0x77823503, 0x27000622, + 0x460c2743, 0xd02409d3, 0x030701b2, 0x22054256, 0x82d005b0, 0x230322c4, + 0x318e8201, 0xceb2b501, 0x01ab2b01, 0xa604cd2a, 0xd70233fe, 0x978229fd, + 0x41ff032a, 0x00009803, 0x1b000300, 0x43057d41, 0xce5d0a54, 0x31302d07, + 0x21352105, 0x6bfc9803, 0xbfbf9503, 0x31258383, 0x0902d104, 0x29358306, + 0x01b00024, 0x010fb22f, 0x12525d01, 0x0fb42905, 0x02031f03, 0x0100b25d, + 0x19248183, 0x182f00b0, 0x22088082, 0x02210123, 0xf2feca09, 0xd1041501, + 0x00002f01, 0xff5a0002, 0x04fb03ec, 0x001e004e, 0xb2850029, 0x832b2a17, + 0x471720af, 0x1725090b, 0x17b11b2f, 0x0699591b, 0x4f0cef42, 0x02220826, + 0x34820417, 0x840bb221, 0x0bb02506, 0x1017b02f, 0x220b2b4f, 0x820f0b12, + 0x09402e1e, 0x121c120c, 0x123c122c, 0x04b05d04, 0x0b9e5410, 0xb2100b24, + 0xe3890723, 0x27262131, 0x26222306, 0x33243435, 0x26343533, 0x58062223, + 0x172907d4, 0x15171411, 0x37363225, 0x05a25f35, 0x03033e08, 0xa8740c10, + 0x0101cea3, 0x605e95ef, 0x76f36a53, 0xe2be7dcb, 0xfdfd2903, 0x83207f48, + 0x1f5d8887, 0x89ba7946, 0x5447b9ad, 0x59405365, 0xadbf589b, 0x579218fe, + 0x3b46af11, 0x46565ecc, 0x2efd8253, 0x04ecff7c, 0x00000632, 0x001b000f, + 0x5a13b264, 0x13200597, 0x20059f48, 0x054a4209, 0x1b2f0c24, 0x00410cb1, + 0x08324d07, 0x220c7a44, 0x82030c05, 0x0ab221e1, 0xb0200684, 0x5a10714f, + 0x142f0cb5, 0x27222302, 0x33112307, 0x32333611, 0x83271112, 0x110723e0, + 0xd5823316, 0x32042f08, 0x6abec5e1, 0x69f3dc0c, 0xf3e2c6b2, 0x409e767c, + 0x7c729f41, 0xfc120202, 0x7589d6fe, 0xd2fd0006, 0xfedafe7c, 0xb0b007f8, + 0x8d42fe8a, 0xb159acaa, 0xf5032b05, 0x1c004e04, 0x00b24b00, 0x49451e1d, + 0x820f2008, 0x870f20b4, 0x08a952b4, 0x23092554, 0x0f0803b2, 0xb2232c82, + 0x82080f13, 0x0fb02406, 0x4316b210, 0x302208c1, 0x8c822531, 0x820e3321, + 0x110027a8, 0x33003435, 0x18501632, 0x0246080a, 0x04785b39, 0xca7604e5, + 0xf6fee375, 0xc1e40801, 0x04e506f3, 0x80765c77, 0x6aae7f01, 0x66af654e, + 0x03012601, 0x2901f719, 0x785db7e1, 0xb027aeab, 0x020000ad, 0xecff4f00, + 0x00060304, 0x19000e00, 0x17b26400, 0x75831b1a, 0xb0101727, 0xb000d003, + 0x05674106, 0xb2820320, 0xb2870320, 0x0c820c20, 0xdd4b0c20, 0x22bf8807, + 0x820c0305, 0x0ab22137, 0xb0210684, 0x0cf9550c, 0xbb480320, 0x1344080d, + 0x32331234, 0x11331117, 0x23062723, 0x14370222, 0x37323316, 0x22232611, + 0xc3e84f06, 0xdcf36aac, 0xbeb66d0c, 0x757ff3eb, 0x95434595, 0x25028076, + 0x782f01fa, 0x00fa2a02, 0x32018470, 0x85b9a5f2, 0xbb82ce01, 0x5320b983, + 0x0b2cb982, 0x15004e04, 0x83001d00, 0x1f1e16b2, 0xb0248182, 0x08b01016, + 0x84066b49, 0x43b6879c, 0x1a220812, 0x27830800, 0xb42f1a33, 0x1acf1abf, + 0x5fb45d02, 0x021a6f1a, 0x1a1fb471, 0x2206832f, 0x82ff1aef, 0x8cb22606, + 0xb25d011a, 0x08fa420c, 0x4e52b020, 0x12b2280c, 0x12110008, 0x4108b039, + 0x05230d9b, 0x56350022, 0x122405d1, 0x16211511, 0x4008d683, 0x03060617, + 0x21070622, 0x02262635, 0xe1fee759, 0xdd8be27d, 0x0b3dfdf1, 0x69a7779d, + 0xa4d94183, 0x01117b64, 0x147208cf, 0x1ef22301, 0xfe8effa2, 0x62fefee6, + 0x7d879c86, 0x9f036b61, 0x7a127d8c, 0x06c5487d, 0x06d6022b, 0x00140015, + 0x1507b253, 0x08494216, 0x2120df84, 0x8f0bff43, 0x04b025ec, 0xd010b010, + 0x210b6552, 0xb583d001, 0x220dba51, 0x82333523, 0x333c08b6, 0x26071732, + 0x15152223, 0x11231533, 0xc8a5a5d2, 0x064840b4, 0xdcae3528, 0xb48603dc, + 0x12c4b463, 0x60b308be, 0x007afcb4, 0x52000200, 0x0c0456fe, 0x19004e04, + 0x83002400, 0x262522b2, 0xb0249382, 0x0bb01022, 0x870b3b4c, 0x2f06248c, + 0x8706b11b, 0x820b200c, 0x110b210c, 0x1720b386, 0x17270c82, 0xb2593e0f, + 0x83170305, 0x0cec5041, 0x110fb222, 0xb2211483, 0x201b8515, 0x0b3e5817, + 0x1003b023, 0x0ba45cb2, 0x20055242, 0x06b14f37, 0x16372727, 0x35363233, + 0x0e5d4235, 0xed524b08, 0x0b6ab9c4, 0xe1f7fedb, 0x733be377, 0x8c79a470, + 0xf1beaf69, 0x937685f2, 0x78934547, 0xfc250285, 0x6d812d01, 0xf6d5e7fb, + 0x85925063, 0x75497f83, 0xa3f62e01, 0xdc017ebb, 0x0100be7b, 0x00007900, + 0x0006f803, 0x42001000, 0xf7490ab2, 0x43102006, 0x0220051f, 0x25069457, + 0x584500b0, 0x165c0db0, 0x0b874407, 0x1002b024, 0xc6430ab2, 0x3601270a, + 0x11132033, 0x62441123, 0x11233e05, 0x776c0133, 0x055a01b6, 0x925e61f3, + 0x03f3f348, 0x75fe8ac4, 0xba023dfd, 0xfc825d70, 0x2f7482fb, 0x7d000200, + 0x90010000, 0x0300d505, 0x3e000d00, 0x41175567, 0x01200766, 0x8206af4d, + 0x0cb02677, 0x2f0cb0d0, 0x095e67b2, 0x67062251, 0x7f3e0958, 0xfefef3f3, + 0x48488447, 0x3a044784, 0x4a381901, 0x4937384a, 0x02000049, 0x4bfeb5ff, + 0x73828501, 0x16000c28, 0x03b24900, 0x1b601817, 0x07cd4c06, 0x200c8045, + 0x23738204, 0x593e1104, 0x2a0a155f, 0xb0100cb0, 0x15b0d015, 0x580fb22f, + 0x302f085b, 0x14110131, 0x27222306, 0x32331635, 0x89031137, 0xa57a2987, + 0x263e439f, 0x15037930, 0xfb298c87, 0x11afa666, 0x048409c0, 0x299689a3, + 0x007d0001, 0x06360400, 0x6d510000, 0x0708430d, 0x670cf543, 0x6d510c95, + 0x51082009, 0x0d850c6d, 0x08146d51, 0x6cdc012a, 0x014cf3f3, 0xfe24012b, + 0xfebd016e, 0x6fd001e7, 0x00069ffe, 0x015f8afc, 0xfd3dfe51, 0x00010089, + 0x0100008c, 0x0000067f, 0x870d9752, 0x0776448d, 0x22067441, 0x82f3f37f, + 0x2c35822a, 0x0600007c, 0x004e0479, 0xb277001d, 0x0a295604, 0x240c6a45, + 0xb11b2f07, 0x0cd34307, 0x3d650c87, 0x8215200c, 0x51152026, 0x0328116f, + 0x3912111b, 0x150705b2, 0x5706084a, 0x18280a0e, 0x013130d0, 0x32333617, + 0x16210383, 0x06884217, 0x07063e08, 0x26112313, 0x11072223, 0x61011123, + 0xd9c67207, 0xb3d67650, 0x5af302af, 0x15695368, 0xbe05f301, 0x04f33d92, + 0xa685713a, 0xfdc1c6a6, 0x67c00239, 0xfd485960, 0xbfc8021a, 0x04f0fc77, + 0x0723433a, 0x1024d582, 0x0bb25300, 0x8c0a1b4d, 0x820020d5, 0x870020ae, + 0x820e20c8, 0x870e200c, 0x08a64bbb, 0x030e0122, 0x21056942, 0x34430bb2, + 0x43ad820b, 0x012c0c35, 0xc378075e, 0xf3065201, 0x48936559, 0x7d2c9982, + 0xfd7dfe91, 0x67bd0235, 0xfefc8563, 0xdd469082, 0x823d2006, 0x000f2891, + 0xb243001a, 0x681c1b0c, 0xb021057c, 0x0b8f4f18, 0x5c0fda46, 0x04200bb6, + 0x200dd061, 0x05b15c13, 0x1417172d, 0x22230606, 0x14173500, 0x49363216, + 0x2d08050a, 0x94e47e4f, 0x0b1101db, 0x96e57b01, 0xf3edfee5, 0x8d89f68a, + 0x028c7779, 0x89ff9f27, 0x39e9e6fe, 0x018afca0, 0xa709fe31, 0xa4b9c0bd, + 0x9b82bdc0, 0x60fe7c24, 0x9b863004, 0x13b26e22, 0xe1489b85, 0x45002306, + 0x5d43b058, 0x2f09240c, 0x4509b11b, 0x45450c52, 0x088d4a07, 0x2430eb48, + 0x33112311, 0x0feb4817, 0x30042e08, 0x6bb2c0e4, 0x6b0ae0f3, 0xf2e1c6b8, + 0x41957881, 0x83749642, 0xfefb1202, 0xfffd75d5, 0x826eda05, 0xfafed9fe, + 0x7bbea206, 0xbb7e20fe, 0x20c78200, 0x20c7824f, 0x24c78202, 0x0019000e, + 0x0e41486b, 0x8c081369, 0x0cfe48ba, 0x2954c787, 0x0c4b4808, 0x480b8b41, + 0x37211448, 0x45c68233, 0x2a080eea, 0xb5c6e84f, 0xf3d80e6a, 0xeac2aa6a, + 0x907483f3, 0x748e4646, 0xfe260285, 0x6b7f2a01, 0xfc0126fa, 0xf62f0170, + 0x017bbda6, 0x43ba76ec, 0x0221058b, 0x26bf82b4, 0xb246000d, 0x470f0e09, + 0xb8460d5f, 0x200c870c, 0x06305605, 0x6a0bb021, 0x09220cdb, 0x3c82050b, + 0x01313022, 0x3d064443, 0x33361733, 0xb3021732, 0x3aa73330, 0x5806e8f3, + 0x0322349c, 0xfd80085c, 0x793a041c, 0x79820e8d, 0xecff4b24, 0x7982ca03, + 0x69002626, 0x282709b2, 0x870d7b51, 0x821c206c, 0x0f1c276c, 0x02b2593e, + 0x2182091c, 0x1002b027, 0xb0d016b0, 0x0bdf5a09, 0x160db223, 0x2b1a8210, + 0x1c0d0cb4, 0xb05d020d, 0x24b2101c, 0x23083743, 0x022421b2, 0x03251b83, + 0x02211321, 0x0a556b5d, 0x6b323321, 0x16200b52, 0x21065466, 0x76623526, + 0x023d0805, 0x53f86bdb, 0xc2b6ecb6, 0x5668f3ef, 0x015e6550, 0xf24fa31e, + 0x74d085c4, 0x637805ec, 0x26016460, 0x28344441, 0xbc8ca758, 0x5d4699c0, + 0x3e383e4a, 0x577a573f, 0xa860b592, 0x495d5661, 0x2cdb8200, 0x02ecff08, + 0x00410572, 0xb2520014, 0x0ab54800, 0xce821320, 0xdb871320, 0x26082c47, + 0x01b01013, 0x8200b0d0, 0xb02f2202, 0x0b265f01, 0x590db021, 0xd0480bd1, + 0x08c48205, 0x15331134, 0x16141123, 0x15373233, 0x11202306, 0x33352311, + 0xbfad0111, 0x2a3f31bf, 0xfe4d532b, 0x05b2b2e8, 0xb4f9fe41, 0x373ea4fd, + 0x0117bc0a, 0xb4650235, 0x95820701, 0xecff772a, 0x3a04f703, 0x53001000, + 0x2308c547, 0xb0584500, 0x840c6a45, 0x46a28795, 0x0f200c42, 0x0f27bc82, + 0xb2593e0f, 0x410d0200, 0xd647058b, 0x0625290c, 0x35262223, 0x14113311, + 0x06829882, 0x0c03233a, 0xb5b0c56b, 0x3eb1abf3, 0x7e6ae5f3, 0xbd02c3ce, + 0x7fce46fd, 0xc6fb0903, 0x16248b82, 0xda030000, 0xcd518b82, 0x0c6a4214, + 0x220fe34c, 0x510500b2, 0x133506cd, 0x01230133, 0xe5fa0133, 0xd389fefb, + 0x01fc86fe, 0xfb060334, 0x825482c6, 0x0021245f, 0x82cc0500, 0x14cb510a, + 0x420c8243, 0x504d14e4, 0x0b002115, 0xb2217983, 0x20068505, 0x2206840a, + 0x83013130, 0x03032187, 0x23088a82, 0x04331313, 0xfeedac33, 0xe4e8c8d9, + 0xedd8fec8, 0x01b7deaf, 0xfbeb024f, 0xfde702c6, 0xfd3a0419, 0x00e3021d, + 0x1f209b82, 0xe820fb82, 0xc9519b82, 0x2487870d, 0xb11b2f0a, 0x14d94e0a, + 0xc9510720, 0x040a2608, 0xb2391211, 0x51068506, 0x13260fc9, 0x21010121, + 0x05830303, 0xce01022e, 0xb5fe0e01, 0xf4fe5601, 0xf2fed7d8, 0xb6320782, + 0xd6020c01, 0xebfd6401, 0x7201dbfd, 0x25028efe, 0x91821502, 0x4bfe0c24, + 0x9182d603, 0x3f000f24, 0x295a00b2, 0x0caf4d0a, 0x7e820520, 0x3e110527, + 0x0500b259, 0x059d4d0f, 0xd001b024, 0x206105b0, 0x3130220b, 0x087d8201, + 0x22230230, 0x32173527, 0x01373736, 0xdcf70121, 0x52fe0301, 0x4035ed63, + 0x1b5d5c2e, 0x0184fe23, 0x025c0106, 0xfe22fbde, 0x03bc12ef, 0x045d4f43, + 0x81820035, 0x00005224, 0x8182c003, 0x420de551, 0xaa540f87, 0x28e5510a, + 0x40028031, 0x250292fc, 0x4f03e5fd, 0x029fc2c2, 0x839ac4d7, 0xfe382e6f, + 0x06910298, 0x0017003d, 0x1812b236, 0x22cf8219, 0x4a0cb000, 0x002005d1, + 0x0021e782, 0x22e78217, 0x820c0006, 0x06b02417, 0x4d05b22f, 0xb223080c, + 0x44060512, 0x240805e7, 0x34350324, 0x35323523, 0x37363635, 0x15070617, + 0x15160714, 0x02171615, 0x079ffe61, 0xb503c1c1, 0x06ad30b0, 0x370282ad, + 0x016398fe, 0xb2e1d560, 0xdeb4d4e2, 0xfa388c32, 0x5c5be1d8, 0x38fad5e3, + 0xae248583, 0x5501f2fe, 0x2b18ad6a, 0x33112301, 0xa7a75501, 0xbe06f2fe, + 0x1b202d83, 0x7520b382, 0x1820b382, 0x0522b382, 0xb3841a19, 0xb3850b20, + 0xb3821820, 0xb3831820, 0x0b181122, 0xb0241782, 0x12b22f11, 0x0522b389, + 0xb3841112, 0x3736172c, 0x26373435, 0x27263535, 0xad821637, 0x33143d08, + 0x15152215, 0x1b070614, 0xb6b604b0, 0xb630b004, 0xb3c2c2b2, 0xff39dbb5, + 0x5656e7d0, 0x39ffcfea, 0xb9e5338c, 0xe1b2e1c8, 0x33e5bbc5, 0x75000100, + 0xdc048301, 0x17002f03, 0x11b23f00, 0x25063541, 0x03b22f0f, 0x5f820f18, + 0x2f03b024, 0xb0440fb0, 0x1003260c, 0xb0d00bb0, 0x0cea5903, 0xb0100f2d, + 0x3130d017, 0x23061401, 0x51022e22, 0x3f080645, 0x021e3233, 0x35363233, + 0x8ebedc04, 0x439a7d4a, 0xc14d4326, 0x854a94b6, 0x43274391, 0xb0120354, + 0x218938df, 0xdbab5468, 0x7022843b, 0x00020054, 0x0194fe86, 0x004d0499, + 0x000f0003, 0x1007b23e, 0xb024de83, 0x00b01007, 0x4406d948, 0x032c0cc4, + 0x03b11b2f, 0xb0593e17, 0x07b2100d, 0x250ee663, 0x33133130, 0x8c842113, + 0x35263408, 0x32333634, 0x18d1aa16, 0x0701fffe, 0x48424148, 0x48414248, + 0xfefb9602, 0x4b383705, 0x4b37384b, 0x0001004b, 0x040bff64, 0x0026050a, + 0xb25d0020, 0x6b22211b, 0xc2430d2d, 0x0d665c0c, 0x0a03b222, 0x0a22a484, + 0x8c73b010, 0x10112b05, 0xb0d014b0, 0x18b22f14, 0x45820a11, 0x1011b022, + 0x250c025b, 0x37363225, 0xe7710633, 0x35022405, 0x72123435, 0x41080507, + 0x26262317, 0x07032223, 0x4f021614, 0xe4067859, 0xc892c504, 0xb7ccccb7, + 0x04b99ec8, 0x5b7607e4, 0x7f0110e6, 0x885068ae, 0xeaea1ccd, 0xdc1f0122, + 0x2001d51c, 0x1ce0e122, 0x75609cd8, 0xb048c8fe, 0xc38200ad, 0x00005e2e, + 0xc3057c04, 0x65001f00, 0x21201ab2, 0x1224c388, 0x12b11b2f, 0x5e07ad55, + 0x04200817, 0x26084d47, 0xb2d008b0, 0x5f12051e, 0x1f200677, 0x0c291789, + 0x101eb0d0, 0xb2d00fb0, 0x201d8516, 0x0b925a12, 0x01313035, 0x21071417, + 0x33352107, 0x27353636, 0x27333523, 0x47203634, 0x4908087e, 0x01152117, + 0x024007fd, 0xe7fb01b8, 0x072b2752, 0xfa089ba1, 0xf5e89601, 0x67595e69, + 0x02370109, 0x5587b056, 0x6f09caca, 0xf2c7b95b, 0xb8daeaca, 0x6882695f, + 0x0200c7f2, 0xe5ff5d00, 0xf1044f05, 0x28001b00, 0x02b23f00, 0x93462a29, + 0x1fb02105, 0x2d0b6975, 0xb0593e0f, 0x10b0d010, 0x1002b02f, 0x114320b2, + 0x10b02408, 0x8826b210, 0x3082080d, 0x23062531, 0x27072722, 0x34352637, + 0x17372737, 0x17323336, 0x16071737, 0x17071415, 0x16140107, 0x36363216, + 0x22262634, 0x3d040606, 0x9ecacb9f, 0x64878d81, 0x8e8d906d, 0x9bc2c09b, + 0x6b948e91, 0xfc8e8b62, 0xdcbe6e78, 0xbd6d6dbe, 0x6b6dbede, 0x90847e7f, + 0xc8c59c89, 0x919093a5, 0x91947573, 0xc1ca9f97, 0x02918d9c, 0x75ce787b, + 0xcceece76, 0x00cc7575, 0x19000100, 0xc0040000, 0x1600b005, 0x5b557200, + 0x2f162405, 0x4116b11b, 0x124a0780, 0x0c002208, 0x06dc5116, 0xb2d00123, + 0x330c850f, 0x13b02f0f, 0x2f13b0d0, 0x1f130fb4, 0xb05d0213, 0x04b0d004, + 0x10231282, 0x540412b2, 0xb02407b1, 0x0fb0d006, 0x23076d42, 0x0eb2100f, + 0x0a211989, 0x057c57d0, 0x84152121, 0x05127001, 0x3521353a, 0x02210121, + 0x013b016d, 0x0177fe18, 0x01a3fe0d, 0xfca3fe5d, 0x62019efe, 0x19200382, + 0x193a1282, 0x7c023403, 0x8a9836fd, 0x01d3fe97, 0x988a972d, 0x0200ca02, + 0xf2fe8800, 0xc5826d01, 0x07000324, 0xc7821800, 0x20059044, 0x06c46206, + 0x0105b22a, 0x31302b03, 0x11331113, 0x332e6682, 0xe5e5e588, 0x1b03f2fe, + 0xc803e5fc, 0x3d82f602, 0x26fe5a30, 0xc4058c04, 0x3d002f00, 0x20b28200, + 0xea833f3e, 0xb0102027, 0xb000d030, 0x204a8507, 0x274a8220, 0x593e1f20, + 0x072039b2, 0x39201d83, 0x230b715d, 0x133902b2, 0x2006e34d, 0x0890420e, + 0x0e0bb222, 0xb2211483, 0x23308532, 0x2cb21032, 0x1a221b89, 0x63852c32, + 0x8927b221, 0x2c242214, 0x2f148227, 0x14013130, 0x14151607, 0x24222304, + 0x16143735, 0x2d051265, 0x35022e27, 0x26263734, 0x33243435, 0x89750432, + 0x16162d0a, 0x06272625, 0x1f161415, 0x34353602, 0x8108c782, 0xf2fe87ab, + 0xe0fef6ea, 0x79889cf2, 0xbcbb868d, 0x41a95dbe, 0xe6130144, 0xf30c01f0, + 0x8b7b7891, 0xc2830178, 0x51cdfd5a, 0x95636c4c, 0x88732eb3, 0x59b8c701, + 0xc6adb964, 0x6e01cfd9, 0x4d4f5f78, 0x6e33375b, 0x5ab86d9a, 0xaa648832, + 0x6acce1cc, 0x54525f80, 0x99716857, 0x281c156e, 0x2f56517c, 0x752f1035, + 0x02006151, 0xdf045d00, 0xcc052303, 0x11000800, 0xb0002200, 0x0fb22f07, + 0xb25d0107, 0xfc410502, 0xd00b2408, 0x421007b0, 0x302b05fa, 0x36341331, + 0x06141632, 0x87252622, 0x435d2908, 0x76444476, 0x44c80143, 0x44290783, + 0x44325605, 0x44446444, 0x3e068531, 0x57000300, 0xe205ecff, 0x1a00c405, + 0x36002800, 0x1fb28e00, 0x12113837, 0x101fb039, 0x83d009b0, 0x43332005, + 0x33310665, 0x33b11b2f, 0xb0593e0f, 0x2db0d02d, 0x3302b22f, 0x2c26832d, + 0x0fb42f02, 0x02021f02, 0x2d09b25d, 0x26108333, 0x00b42f09, 0x82091009, + 0x090d2210, 0x21108202, 0x5c6810b2, 0x02b02408, 0x8817b210, 0x1ab2230d, + 0x1f820902, 0x102db025, 0x88081fb2, 0x103323cd, 0x0d8825b2, 0x01313027, + 0x26200614, 0x05af4535, 0x20078f41, 0x05ae4115, 0x02342535, 0x04222324, + 0x04121002, 0x25122420, 0x20241234, 0x60101204, 0x7c08054e, 0xfeaf5e04, + 0x9ebfbdc0, 0x5c9cada3, 0x68675c58, 0x015a595b, 0xeefe96a6, 0xeffe9fa3, + 0x11019b9c, 0x13014001, 0xbbeffa98, 0x80014b01, 0xbbbb4a01, 0xc1c2b8fe, + 0x02bcb7fe, 0xd5a29854, 0xd5ae71b4, 0x536095a5, 0x76757688, 0x85625186, + 0xab1d01a6, 0xfee0fea4, 0xa7e0feac, 0xa72001aa, 0xc75a01ca, 0xfea6fec7, + 0xc9a6fe6c, 0x005a01c8, 0x028d0002, 0x051103b3, 0x001a00c4, 0xb28f0024, + 0x0527540d, 0xb0100d23, 0x0639411c, 0x1b2f142b, 0x3e1f14b1, 0x2503b259, + 0x063d4714, 0xb0d00027, 0x01b22f00, 0x210f8303, 0x06840ab2, 0x2f0ab027, + 0xb21014b0, 0x0920410d, 0x0d0a1022, 0x21082e82, 0x0110ccb2, 0x0c13405d, + 0x2c101c10, 0x4c103c10, 0x6c105c10, 0x8c107c10, 0xb25d0910, 0x710110ba, + 0xdc6903b0, 0x100a230c, 0x42881fb2, 0x01313033, 0x22230627, 0x36343526, + 0x34353333, 0x15062223, 0x080a8227, 0x15163271, 0x25171411, 0x35373632, + 0x15060623, 0x11600214, 0x83767c4d, 0x7466ada8, 0xafad4941, 0x1a9a8988, + 0x5428a0fe, 0x564c6a1b, 0x5244c102, 0x796e697b, 0x30337f33, 0x9181680e, + 0x61c4fe84, 0x19248251, 0x313c0189, 0x00ffff58, 0x038a0057, 0x00a90385, + 0xeb7a0126, 0x01070000, 0x0052017a, 0x00010000, 0x0376017f, 0x002503c2, + 0x001a0005, 0x7a2f04b0, 0xb02105ec, 0x0b484e04, 0x23329c82, 0x21352111, + 0xfdc8c203, 0x01430385, 0xab040176, 0x8f420400, 0x000d3508, 0x0031001b, + 0xb29d003a, 0x113c3b0a, 0x0ab03912, 0xd012b010, 0x31200583, 0x97420584, + 0x0cc16107, 0x1b2f0a2c, 0x3e0f0ab1, 0x1003b059, 0x474212b2, 0x21348208, + 0x0d8818b2, 0x0a1db223, 0x06ae7a03, 0x0a031f22, 0x1f2c0983, 0x1f00b42f, + 0x5d021f10, 0x1f1d32b2, 0x32231083, 0x891cb22f, 0x1c25222f, 0x282f8432, + 0xd02cb010, 0xb2101fb0, 0x221a883a, 0x42133130, 0x93420c77, 0x8211200e, + 0x163231df, 0x16071415, 0x17161416, 0x35262315, 0x27232634, 0x21066b44, + 0x7e425723, 0x1105210f, 0x380fa242, 0x019725fd, 0x78ac9919, 0x0a073441, + 0x4d420d9b, 0x5d458f9e, 0x028d5d47, 0x0e8442d9, 0xa442cb20, 0x5b2c080e, + 0x5203affe, 0x3f757d87, 0x44a36f1d, 0xa0221017, 0x3e86434c, 0x013b4636, + 0x87000100, 0x5e031205, 0x0300b005, 0xb0001100, 0x02b22f01, 0x7508957b, + 0x033a05b1, 0x0229fd5e, 0x9e1205d7, 0x7f000200, 0x8b02af03, 0x0900c405, + 0x39001300, 0x3d6300b2, 0x06d64206, 0x26082765, 0x0ab0d00a, 0x4205b22f, + 0xb0220875, 0xf5431000, 0x0855820a, 0x14163233, 0x26222306, 0x32133634, + 0x26343536, 0x16140622, 0x9a6a8701, 0x9b6d6c98, 0x45356b9d, 0x49486a45, + 0xdc9ec405, 0x9edc9b9b, 0x354778fe, 0x684c4c34, 0x2c7d8248, 0x0301005f, + 0x00fc04f3, 0x000f000b, 0x05eb7646, 0x250b7956, 0x00b01009, 0xfb76b0d0, + 0x0db0230f, 0x1f46b210, 0x0e052c0a, 0x39121106, 0x1b050bb4, 0x775d0205, + 0x20080d17, 0x21352101, 0x57019c02, 0xfed8a9fe, 0xd865019b, 0xaffc3201, + 0x83035103, 0x017cfec7, 0x7901c784, 0x2ff882fb, 0x3c000100, 0xb2029b02, + 0x1700bb05, 0x08b25900, 0x2006094b, 0x74878200, 0x00290c93, 0x00b11b2f, + 0xb2593e13, 0x08054116, 0x0002b223, 0x237a8216, 0x000f03b2, 0x2105434d, + 0x1b8908b2, 0x14840c20, 0x8413b221, 0x23968306, 0x35360135, 0x08086a5c, + 0x1632332f, 0x020f1415, 0xfdb20221, 0x711d019c, 0x423a3436, 0x8f87a9ba, + 0x8c626a9c, 0x9b027301, 0x6705017d, 0x42352a43, 0x80997436, 0x57666b73, + 0x2ea58271, 0x028f0237, 0x00ba05a9, 0xb27d0024, 0x4926251e, 0x0d2008e9, + 0x0d209882, 0x20076848, 0x200c8217, 0x22a58317, 0x820d1701, 0xb07c3721, + 0xb6182f01, 0x01500140, 0x71030160, 0x010190b2, 0x100db05d, 0xa68906b2, + 0x83010921, 0x01b02127, 0x230b306e, 0x012312b2, 0xb2213c82, 0x2443841b, + 0xb21017b0, 0x8230881e, 0x323321c9, 0x0720c78e, 0x68067251, 0x36080761, + 0x01232734, 0x3684510c, 0xba41303e, 0xa38f82a5, 0x8fb19587, 0x45baab87, + 0x863d3f3c, 0x616c045c, 0x23273523, 0x69797c63, 0x8e293377, 0x717f7e6a, + 0x2a373526, 0x82000165, 0x047031e3, 0x064802d1, 0x00030000, 0x02b00023, + 0x020fb22f, 0x0036b082, 0x2f00b0d0, 0x1f000fb4, 0xb05d0200, 0x03b01002, + 0x03b019d0, 0x8982182f, 0x2301212d, 0x15013301, 0x06c3ebfe, 0x82d1fe00, + 0xfe922c3f, 0x041f0460, 0x0012003a, 0x790db260, 0x002206fd, 0x3f825845, + 0x55b11b21, 0x072108aa, 0x0a8d562f, 0x0c821020, 0x59111021, 0xf25806c7, + 0x0868440c, 0xc6510d20, 0x0bb2220b, 0x057b600d, 0x16110123, 0x061c5116, + 0x06272808, 0x11272223, 0x84011123, 0xa86a5902, 0x07dff33b, 0x4d79935c, + 0xfd3a04f2, 0x79828d84, 0xc6fb1203, 0xfe376b56, 0x73da053e, 0x032905f5, + 0x00b00556, 0xb22b000a, 0x0a217902, 0x5b0c8a62, 0x260808e3, 0x11080001, + 0x31303912, 0x22231121, 0x24343524, 0x02112133, 0xfee65084, 0xe60a01f7, + 0x08022101, 0xffd5d6fe, 0x820050fa, 0x028e2657, 0x03a90145, 0x22578252, + 0x8608b216, 0x2f022d57, 0x2b0a08b1, 0xdc1bd858, 0x13313059, 0x33069f58, + 0x8e262223, 0x4e4b864a, 0x024c4140, 0x4e4e3aca, 0x4a4a3b3a, 0x6d2e3f82, + 0xc90141fe, 0x0e000300, 0x09b23400, 0x7582100f, 0x5608355d, 0x062308da, + 0x8607b110, 0x0db2234f, 0x23820e07, 0x0d01b222, 0x30220683, 0x03422531, + 0x27200805, 0x34353632, 0x01372726, 0xac960b3e, 0x4742079b, 0x03205047, + 0x69921b36, 0x2a2f8976, 0x8b05232d, 0x802c6982, 0x0202a002, 0x0600b305, + 0x01b23900, 0x780f9d72, 0x13260ca3, 0x04b2593e, 0x83680005, 0x03b22105, + 0x2c0b8342, 0x35071123, 0x02023325, 0x6f01c9b9, 0x35508213, 0x7792303a, + 0x77000200, 0x2c03b202, 0x0c00c405, 0x40001a00, 0x895609b2, 0x10092205, + 0x07e759b0, 0x3d7a0220, 0x201a8206, 0x05ca4802, 0x2518bc48, 0x34133130, + 0xa37e2036, 0x4237200e, 0x3f0806f9, 0x3601bf77, 0x9e9dbcc0, 0x505dafbe, + 0x5d015b4e, 0x045d4e4f, 0xc2c3a061, 0xc39f48a6, 0x6205a3c4, 0x50616c6e, + 0x666d6e61, 0x00ffff00, 0x038a005d, 0x00a90399, 0x097b0126, 0x01070000, + 0x007e017b, 0x592e1783, 0x83050000, 0x2700ab05, 0xd9ffd501, 0x07829802, + 0x1b017c2e, 0x07010800, 0xc502d801, 0x10000000, 0x250d1576, 0xffff3130, + 0x33825000, 0xae05cc22, 0x00232b83, 0x840800f0, 0x02d0223b, 0x2233829b, + 0x891a03d6, 0x82092033, 0x1f0923e6, 0x3384593e, 0x33826720, 0xbb05fc22, + 0xa8205f84, 0xd82c3384, 0x00003e03, 0xd7010701, 0x9b023000, 0x994b6787, + 0x31303507, 0x42000200, 0xa5037ffe, 0x19004e04, 0x61002300, 0x252410b2, + 0x21053e73, 0x18461db0, 0x82212006, 0x4f212060, 0x10200721, 0x10280c82, + 0xb0593e17, 0x1db21021, 0x230e934f, 0x100003b2, 0x22187a73, 0x82001016, + 0x3130271b, 0x07060601, 0xf4490607, 0x06332106, 0x0805ce48, 0x36373725, + 0x14133737, 0x35262206, 0x16323634, 0x35027602, 0x625a6749, 0xf36a5859, + 0xcec2ef02, 0x4e5c9be2, 0x5bf7020a, 0x02360560, 0x4f917c95, 0x5e6a616a, + 0xb153645d, 0xa5b8c9d0, 0x73485da3, 0xea4f0135, 0x02002f08, 0x0000f6ff, + 0xb0055707, 0x12000f00, 0x43677700, 0x0c3f6b12, 0x2008e866, 0x05e46d11, + 0xb22f1123, 0x09966902, 0x17510620, 0x0bb2210b, 0x0b212285, 0x0a746d2f, + 0x4600b021, 0x12200ca1, 0x30242284, 0x03212131, 0x01240182, 0x13211521, + 0x46080384, 0x07032101, 0x0f7efc57, 0xfeb80afe, 0x034303de, 0x117afde0, + 0xe4fd2402, 0xfa970214, 0x1b7901ed, 0xacfe5401, 0xfec5b005, 0x36fec568, + 0x88026701, 0x00010000, 0x03d6004d, 0x008604ec, 0x0038000b, 0xb22f03b0, + 0x42030c09, 0x0a2106c8, 0x23098309, 0x090304b2, 0xb2231082, 0x82040a01, + 0x03b02906, 0xd005b010, 0x0a0407b2, 0x103e2484, 0x30d00bb0, 0x01011331, + 0x17010137, 0x01070101, 0x3c014d01, 0x0194c4fe, 0x943c013b, 0x0484c4fe, + 0x01c5fe2a, 0x0142016c, 0xbefe9642, 0xfe3b0484, 0x410196be, 0x0000bffe, + 0xff690003, 0x052205a1, 0x001700ee, 0x00290020, 0x6310b266, 0x102505c9, + 0xd01db010, 0x200582b0, 0x13957526, 0x21084b41, 0x9183101a, 0x8423b221, + 0x23b02406, 0x831bb010, 0xee401834, 0x1ab02a0a, 0xd024b010, 0xb21004b0, + 0x0df56a26, 0x22230428, 0x37230727, 0x43721126, 0x176c0805, 0x16073337, + 0x17140513, 0x22232601, 0x34050702, 0x33160127, 0x05351232, 0xedfe9422, + 0x5b84a4b4, 0x96c391a9, 0xc5b21401, 0x93a7578f, 0x44fc019d, 0x57f60147, + 0x02b9a487, 0xfe2cbf02, 0xa9694e17, 0xd6b202b5, 0x4badbdfe, 0x01c3ee96, + 0x01d54367, 0x8f65af44, 0xc3fec1f3, 0x0380cf4b, 0xfffe553a, 0x72a608eb, + 0x0136dcfc, 0x0000f600, 0x2d056572, 0x00b0057e, 0x0014000c, 0x1502b257, + 0x65721116, 0x490f2005, 0x00230f24, 0x46b05845, 0xb2230734, 0x83000a01, + 0x2f012327, 0x09850eb2, 0x5e2f0e21, 0x01200b4f, 0x2d0d7672, 0x32331101, + 0x04141504, 0x23112323, 0x0c821311, 0x2634363e, 0xf1870127, 0xfe1201f4, + 0xf3f2f3ee, 0x917df6f3, 0xb0057a8c, 0xc8eee8fe, 0xd4feefc7, 0x25390982, + 0xde821afe, 0x00000284, 0xff880001, 0x069b04ec, 0x002c0015, 0x2d23b25b, + 0x0819482e, 0x1b2f0524, 0xc05d05b1, 0x0c5c5d07, 0x22086046, 0x7b15050e, + 0xb2210546, 0x0873411c, 0x1522b223, 0x05ed6b05, 0x4418b220, 0x21220bc5, + 0x584c1123, 0x0e142505, 0x1e141502, 0x06260382, 0x27262223, 0x5a4f1637, + 0x022e2305, 0xe0483435, 0x075b0805, 0xe5f27a01, 0x1bd7bbce, 0xb2411645, + 0x50c6d951, 0x2d3126ab, 0x5a61367f, 0x7e51ae46, 0x04b8505c, 0xeed65104, + 0x623ea9bb, 0x2c274171, 0x4b899454, 0x1927b9ab, 0x56251cc3, 0x885b3143, + 0xc9585088, 0xf761514d, 0x00030000, 0x06ecff48, 0x00500484, 0x00340029, + 0xb2ca003c, 0x413e3d02, 0x2d26067b, 0x1002b0d0, 0x814138b0, 0x0c3f6606, + 0x2808d25a, 0x00b0d000, 0x050cb22f, 0x28338317, 0x8fb22f0c, 0xb05d010c, + 0x0b6d5a17, 0xb0290d82, 0x1bb0d01b, 0x0038b22f, 0x2c25831b, 0x1fb42f38, + 0x02382f38, 0x38efb471, 0x220683ff, 0x836f385f, 0x38bf2a06, 0x5d0238cf, + 0x01388cb2, 0x0b78525d, 0xb2100023, 0x08354123, 0x1005b022, 0x240a2e41, + 0xb2100cb0, 0x0894522f, 0x101bb024, 0x298835b2, 0x05313022, 0x20067e77, + 0x05b44d35, 0xb54d2620, 0x36172508, 0x15123217, 0x23067363, 0x06061737, + 0x0809c14d, 0x2201167d, 0x35210706, 0xe6042634, 0xd6418cfd, 0xeec8b086, + 0x585fbfe9, 0xfdf2735b, 0x836fdfc5, 0xfdeed4c8, 0x86980949, 0x493d6b89, + 0x98fcd146, 0xc42d883a, 0x035d7868, 0x107f632b, 0x146dc401, 0xb0544da1, + 0x47ac9e9c, 0x4259675b, 0x85b99213, 0xfdfe0287, 0x9e8b89eb, 0x38a6223a, + 0x2b3bb840, 0x465f02d1, 0xe7024f41, 0x711e7f8a, 0x0002007a, 0x04ecff67, + 0x002c0640, 0x002b001d, 0x7c07b265, 0x07230541, 0x4128b010, 0x19240673, + 0x19b11b2f, 0x20075b42, 0x310c8207, 0x593e0f07, 0x19070fb2, 0xb0391211, + 0x11b22f0f, 0x0983070f, 0x755e1920, 0x0fb0210b, 0x220bed62, 0x7f1007b0, + 0x25080ab5, 0x12013130, 0x02141511, 0x26222306, 0x36343526, 0x17323336, + 0x27072726, 0x37272637, 0x17371716, 0x26262703, 0x24462223, 0x03580807, + 0xe57efe42, 0x7ee28a8c, 0x9284ce71, 0xcc7e3171, 0xa27eac4e, 0xb4b1ee4b, + 0x20018f4e, 0x8b7e4e7b, 0x896f6e8d, 0xf7fe1705, 0xa6526ffe, 0x7e92f9fe, + 0xe79588e2, 0x7aa95b7d, 0x52726d87, 0x8732c32a, 0x19fd6d78, 0xa8383012, + 0xc8a87e95, 0x030000ad, 0x93004300, 0xcc043704, 0x0d260982, 0x52001900, + 0x3f6604b2, 0x10042505, 0xb0d000b0, 0x11200582, 0x047bf782, 0x1003230d, + 0x0d4909b1, 0x46042007, 0x10220af6, 0x168711b1, 0x16881720, 0x2123de82, + 0x4d012135, 0x03200826, 0x83064a43, 0x37042dee, 0xf4030cfc, 0x4a4409fe, + 0x4a43444a, 0x43200082, 0x02330985, 0xb201d446, 0x4b4b724c, 0x4afc4c72, + 0x3a4c4c3a, 0x824a4a39, 0xff4f329f, 0x043d0477, 0x001500bb, 0x0025001d, + 0x2604b266, 0x05214927, 0x841bb021, 0x602320a9, 0xef5b1311, 0x04182208, + 0x212d820f, 0x068420b2, 0x1020b024, 0x348319b0, 0x270aae56, 0xb01018b0, + 0x0fb0d021, 0x210bdb42, 0x2e603130, 0x37172705, 0x11160733, 0xb5820614, + 0x23072725, 0x45132637, 0x06200583, 0x08068245, 0x7e4f3656, 0x586a94e4, + 0xc4669147, 0x5d96e57b, 0x6691485a, 0x0140f3ce, 0x77392f2b, 0x3a09028c, + 0x332bd8fe, 0x2702897b, 0x2289ff9f, 0xfe99d08f, 0x8afca0c0, 0x96cf931e, + 0x629c3601, 0xbd166102, 0xfd5d94a7, 0x00c011a7, 0x82000200, 0x370460fe, + 0x0f000006, 0x64001a00, 0x690e5160, 0x06241333, 0x06b11b2f, 0x69454760, + 0x042e1033, 0xb2c2e337, 0x6af3f36b, 0xf3e3c5b0, 0x46607683, 0xfef73107, + 0xfffd75d1, 0xd7fda007, 0xfedafe77, 0xbaa605fa, 0x2c084760, 0x0500001f, + 0x00b0059d, 0x00170013, 0x056b486b, 0x680c4a4e, 0x142b086c, 0x12110f08, + 0x2f14b039, 0x841410b2, 0x2f102909, 0xb0d000b0, 0x17b21010, 0x2b093b44, + 0x08b0d003, 0xd005b010, 0xb21014b0, 0x0af34218, 0xb0101723, 0x282a830a, + 0xb0d00db0, 0x12b0100f, 0x1f4218d0, 0x11420809, 0x35231123, 0x11331133, + 0x01331121, 0x05213521, 0xfc7f7f1e, 0x7cfc75fd, 0x8b02fc7c, 0x0279fcfc, + 0x0475fd8b, 0xf4fba2ae, 0x79fd8702, 0x01a20c04, 0x01fefe02, 0xbaa2fd02, + 0x8f000100, 0x82010000, 0x05643a04, 0x0cbb630e, 0x593e0f22, 0x22060564, + 0x82f3f382, 0x2435822a, 0x0400008e, 0x220a826b, 0x855f000c, 0x2f0424ef, + 0x8704b11b, 0x22c96435, 0x38720620, 0x2f062d05, 0x2f061fb4, 0xb2710206, + 0x5d01068f, 0x0bb94118, 0x06010a22, 0x82052b4a, 0x82d982db, 0x012008d7, + 0xef012101, 0x55f2f26f, 0x2c015001, 0xb90161fe, 0xac01cbfe, 0x3a0454fe, + 0xb00150fe, 0xd3fdf3fd, 0x22209782, 0x36269782, 0x0d00b005, 0x4b185b00, + 0xd76f12fa, 0x0c012108, 0xb02a5c83, 0x00b02f01, 0x1001b0d0, 0x7d4102b2, + 0x4d06200c, 0x3c080bff, 0xb01003b0, 0x09b0d008, 0x1000b0d0, 0xb0d00bb0, + 0x3130d00a, 0x07153701, 0x21152111, 0x37350711, 0xa1013311, 0x9502eaea, + 0x82826efc, 0x476703fd, 0xf6fd4793, 0x278702ca, 0x96022793, 0x05cb5e00, + 0x062e0227, 0x000b0000, 0x2491854a, 0xb11b2f0a, 0x0cfc680a, 0x593e0f24, + 0xb14901b2, 0x22919705, 0x8407b0d0, 0xd0092180, 0x80868c82, 0x7e862320, + 0x94949a34, 0xf38686f3, 0x92357903, 0x0219fd35, 0x2f922f90, 0x7982de02, + 0x4bfe902e, 0xb0050905, 0x67001300, 0x151406b2, 0x71154178, 0xd56211ef, + 0x00b0240f, 0x4eb05845, 0x04200812, 0x230b315e, 0x0c000db2, 0xb2225682, + 0xd74b0e12, 0x051f6706, 0x33163725, 0x76353532, 0x24080679, 0xa9be0905, + 0x280e3c46, 0x81fd7b3a, 0x7f02fcfc, 0x18fab005, 0xc711c6b7, 0x0431b80c, + 0x05ebfb15, 0x04ecfbb0, 0x2ead8214, 0x044bfe7e, 0x004e0406, 0xb261001a, + 0x881c1b15, 0x198165ad, 0x1b2f0a24, 0xad870ab1, 0x08884b18, 0x03180122, + 0xb0223b82, 0x2e6e100a, 0x03b0220a, 0xf8431810, 0x0641660a, 0x8a171621, + 0x08cf68ad, 0x5c013d08, 0xb0c4730d, 0xa6bb01b5, 0x280e3a45, 0x695d7c3b, + 0x04f34b91, 0xd6aa963a, 0xb41bfdd2, 0x0cc611c2, 0x78d902b0, 0xe0fc6770, + 0x02003a04, 0xecff6400, 0xc4052d07, 0x23001700, 0x01b29100, 0x2305374d, + 0x1ab01001, 0x20133f77, 0x20b0820e, 0x07f04e0e, 0x490ca460, 0xb021079e, + 0x0c1c630e, 0x0e001222, 0x1221cb83, 0x21bd8a2f, 0x946c00b0, 0x6ed9830b, + 0xb022090a, 0x5e4b100c, 0x3130230a, 0x3b762121, 0x34112805, 0x32332412, + 0x7c152117, 0x05200650, 0x0806b66c, 0x1411075c, 0xfc2d0716, 0xa779a79d, + 0x0294f7fe, 0xa80b0191, 0x5c03a77b, 0x56024cfd, 0xbb02aafd, 0x68637dfb, + 0xafa15b72, 0x9314b201, 0x01aa0d01, 0x1201ac3a, 0xfecc1496, 0x40fec86e, + 0x38040d1c, 0xfebccf0e, 0x00d1c1ca, 0x5b000300, 0xf206ecff, 0x1e004f04, + 0x32002a00, 0x19b29b00, 0x0d483433, 0x24b02705, 0x1019b0d0, 0x5f6b2eb0, + 0x0c264413, 0x1b2f1724, 0x4f6717b1, 0x821b2007, 0x821b200c, 0x05b2230c, + 0x47821708, 0x172fb223, 0x2c068208, 0xb42f2fb0, 0x2f2f2f1f, 0x8cb27102, + 0x0de56c2f, 0x210ce649, 0x358419b2, 0xd022b024, 0x724803b0, 0x2bb02b0b, + 0x133130d0, 0x32330034, 0x77493617, 0x3736270a, 0x23060617, 0x03822722, + 0x17110023, 0xba461814, 0x49252009, 0x68080680, 0xe00f015b, 0xb74186f9, + 0xfdeed66d, 0x75910b56, 0x4f478f59, 0xf778cd47, 0xe3f6868c, 0x86f2f2fe, + 0x87867779, 0x03887578, 0x147855e1, 0x0271b501, 0x2f01f827, 0x015e54b1, + 0x88ecfdfe, 0x322a9e8b, 0xae413f9e, 0x012d01ae, 0xbaaa0902, 0xbea6c0b9, + 0x7989baba, 0x007a6f19, 0x8b000100, 0x95020000, 0x0c001506, 0x03b23200, + 0x09b5740d, 0x1b2f0424, 0x8a6904b1, 0x43b0200f, 0x30250c7c, 0x34113331, + 0x07fc6c36, 0xc28b1138, 0x19593fb0, 0x04a3322a, 0x15c3b69c, 0xfbba0bb9, + 0x00020068, 0xdf79ff51, 0x00162605, 0xb25b001e, 0x05df7900, 0x8c411720, + 0x0ca34606, 0x28078242, 0x000f05b2, 0xb0391211, 0x0f0f6005, 0x210d7742, + 0xf47f1005, 0x20052f0c, 0x21351100, 0x22232626, 0x37270707, 0x0e823336, + 0x14155108, 0x32270402, 0x15213736, 0xb8021614, 0xbdfedcfe, 0xdf05d003, + 0x3497a7cc, 0xdab02131, 0x6b013a01, 0xa9e5fea2, 0xfd12be96, 0x0114ba2f, + 0x89490160, 0x1334f0e0, 0xfe480fc6, 0x6bb7fe8b, 0xafc3fec3, 0x1fbddad4, + 0x0100bfb9, 0x4bfee4ff, 0x1506d302, 0x7122c382, 0x797e14b2, 0x2f15240a, + 0x4115b11b, 0x10200725, 0x10200c82, 0x20078146, 0x200c821d, 0x0c89641d, + 0x593e1124, 0x2e771db0, 0x69c2820c, 0xb02a09a4, 0x0eb01000, 0xd00fb0d0, + 0xd98d15b0, 0x44230121, 0x16250726, 0x11353233, 0x0b726e23, 0x15074b08, + 0xc9840233, 0x3648a4b5, 0x1244070f, 0xc2a5a578, 0x195b3db1, 0x019d3b26, + 0xfc8603c9, 0x11c0b035, 0xae0a03bf, 0x62b4ca03, 0xbc15c3b6, 0x0067ad0a, + 0xff580002, 0x06aa05ec, 0x0018002e, 0xb25b0026, 0x11282704, 0x04b03912, + 0xc549b010, 0x550d2007, 0x4b4f0bdd, 0x0d0f2208, 0x06674b04, 0xa9581620, + 0x0db02208, 0x0ac44d10, 0x9c4c4382, 0x3130210a, 0x2a0c867b, 0x36173233, + 0x14333536, 0x7a160706, 0x10240f3f, 0xb4edfe94, 0x30083b7a, 0x4c4fa2ff, + 0x577c79bb, 0xa8b8fd04, 0xb902b9a4, 0x073b4fa8, 0x4001ad22, 0x3205927b, + 0x82830da8, 0xa723d1a4, 0xfef612df, 0x54ebfffe, 0x4ff6feec, 0x4f2a0637, + 0xbb04ecff, 0x1700a804, 0xd9822200, 0x24231422, 0x1420b183, 0x4809f573, + 0x14200c22, 0x1427e682, 0xb2593e0f, 0x63140406, 0x0d2006a7, 0x1420d989, + 0x830b8341, 0x0b167bd9, 0x88069a4a, 0x141522d0, 0x07ba4306, 0x3536323c, + 0x22232634, 0xe47d4f06, 0x358ae194, 0x6758a730, 0xe77b023f, 0xecfee395, + 0xd56a8af2, 0xa12c0807, 0x139589fd, 0xb386726a, 0x1d9e7d25, 0x018afca0, + 0x0901012e, 0xb9c0bda7, 0x00bdbda7, 0x7d000100, 0x3d06ecff, 0x18000106, + 0x0cb25400, 0x2406a963, 0xb0584500, 0x20b28218, 0x07be4518, 0x0c821120, + 0x08604d18, 0x2208ed5f, 0x50180c01, 0x08200604, 0x0c20cc89, 0x200e7c46, + 0x79b98615, 0x6d261147, 0xc5bbb55e, 0x4c79d7fe, 0x0adc280a, 0xd6e4a182, + 0x79a5fd09, 0x772d1253, 0x2805ecff, 0x19009304, 0x07b26100, 0xfb4d181a, + 0x0c3f6309, 0x1808697c, 0x290bcb40, 0xb0100db0, 0x15b2d013, 0xad830813, + 0xb22f1523, 0x22ad8803, 0x841506b2, 0x46082014, 0x30270b88, 0x06140131, + 0x5c231107, 0x11200578, 0x82072568, 0x373727c8, 0xa28f2805, 0x2c6806e5, + 0x41482a08, 0x93040205, 0xfc0ba5b2, 0x0b3668cf, 0x42078831, 0x01004c4c, + 0x4bfeb5ff, 0x3a049301, 0x82000c00, 0x0aef4474, 0x200c316c, 0x118f6f04, + 0x37088182, 0x23060611, 0x16372722, 0x11353233, 0xb8019301, 0x0f3846a7, + 0x047c3a27, 0xb285fb3a, 0x0dbf11c2, 0x006c04c0, 0x59000200, 0xf803ecff, + 0x16004f04, 0x5e001e00, 0x201f08b2, 0x0822e283, 0xf444b010, 0x0cc46d07, + 0x2108984b, 0xf584000c, 0x732f0c21, 0xb0210d2f, 0x0c6c4708, 0xb2100c23, + 0x08294a1a, 0x322a9282, 0x14151500, 0x22270606, 0xfc443502, 0x07062505, + 0x13363627, 0x0807f444, 0x01e40033, 0x86da7b14, 0xaa02efd5, 0x56778f0b, + 0x464f4e8b, 0x785691d2, 0x714bfe13, 0xd4fe4f04, 0xfb9a1ff6, 0x0101018d, + 0xa18888ed, 0x3e9e3527, 0x8e60fc43, 0x06174674, 0xe0049435, 0x01064303, + 0x45000800, 0x2f04b000, 0x01040fb2, 0x8350b25d, 0x82702004, 0x02b02f04, + 0x2f02b0d0, 0x19d001b0, 0x182f01b0, 0x286204b0, 0x0fb42a06, 0x02071f07, + 0x0703b25d, 0x23f48304, 0x05b01001, 0x05222182, 0xaa82182f, 0x2723153d, + 0x01352307, 0xc3430333, 0x01c19596, 0xeb048f0f, 0x0d9c9c0b, 0x00001401, + 0x82720001, 0x8434206d, 0x8825206d, 0x05de5d6d, 0x010fb424, 0x5282011f, + 0x01040022, 0x08245283, 0x2f08b0d0, 0x373d4d82, 0x23011533, 0x01333501, + 0xfed092d2, 0xebfe96e9, 0x9b6605ce, 0x01e9fe0a, 0xff000918, 0x088f5cff, + 0x70000623, 0x2d5f8300, 0x02cc0475, 0x00e605fb, 0x002f000b, 0xcd8203b0, + 0x5d010332, 0xb0d006b0, 0x0fb42f06, 0x02061f06, 0x1003b05d, 0x270a4a5b, + 0xb01006b0, 0x0bb0d00b, 0x143e6983, 0x35262006, 0x32161433, 0xfb023536, + 0xb0dafeb0, 0x4a844bb6, 0x9c7ee605, 0x49427e9c, 0x5d834249, 0xdf04812e, + 0xd5058701, 0x1d000900, 0x0b0a03b2, 0x0020a782, 0xb222a582, 0x5461080f, + 0x0910590c, 0x81262225, 0x82447e44, 0x59053302, 0x35474735, 0x00464634, + 0x78000200, 0x33028d04, 0x45822a06, 0x2a001425, 0x8205b000, 0x820520a5, + 0xd01327a5, 0xb22f13b0, 0xcd600a00, 0x10052308, 0x0d880db2, 0x200b085d, + 0x07394807, 0x06223208, 0x805d5601, 0x7d61607d, 0x2e42117f, 0x623f412f, + 0x7b2a063f, 0xaa7878aa, 0x412fd07b, 0x432e3040, 0x00010043, 0x0152fe29, + 0x003c00a1, 0xb222000f, 0x0ab5690f, 0xd54a0a20, 0x05b22106, 0x280ac45d, + 0x15060621, 0x37323314, 0x062a5717, 0x8c013908, 0x2c474a57, 0x5c49152e, + 0x38f4745f, 0x1744315e, 0x5b6e2c8e, 0x01006cb5, 0xdb047a00, 0xf5055703, + 0x40001500, 0x2f03b000, 0xb0d008b0, 0x0fb62f08, 0x2f081f08, 0xb05d0308, + 0x2005d567, 0x2217820b, 0x880fb210, 0x21168261, 0x0d8912b2, 0xb0100f23, + 0x0de66715, 0x08056260, 0x36323334, 0x7f570335, 0x69392760, 0x35261a2b, + 0x395f7f95, 0x362634a1, 0x926ee905, 0x390c3c11, 0x966e082e, 0x002f395a, + 0x49000200, 0x5603d104, 0x0300ff05, 0x87830700, 0x2b1ed95b, 0xb01000b0, + 0x05b0d005, 0x1002b02f, 0x82051742, 0xb0230890, 0xb019d007, 0x30182f07, + 0x01330131, 0x03330323, 0xee680223, 0x90c5f6fe, 0x05b9dee9, 0x01d2feff, + 0x82d2fe2e, 0xfe823369, 0xffec016a, 0x000b00be, 0x003d0017, 0xb02f18b0, + 0xf782d003, 0x000f403a, 0x20031003, 0x40033003, 0x60035003, 0xb05d0703, + 0x0fb0d00f, 0x0909b22f, 0x2308ca41, 0x15b21003, 0x30220d88, 0xa2511731, + 0x083f640a, 0x22232f08, 0x4e698206, 0x496a6a49, 0x3065694e, 0x2d2d2122, + 0xee302221, 0x4b616349, 0x48605e4a, 0x222d2e21, 0x00303024, 0x8efc0100, + 0x66fed104, 0xc95c0006, 0x07357b05, 0x07245618, 0x43100121, 0x586305b2, + 0x05347b06, 0x7b66fe21, 0x01260934, 0xd1045efd, 0x3f8736ff, 0x24072f41, + 0x01b0d001, 0x0683432f, 0x2110095d, 0x095d21fe, 0xff230808, 0x0473fcff, + 0x0550ffdb, 0x000700f5, 0x00f9fba4, 0xfd010000, 0xfee6043e, 0x007f0699, + 0x0025000e, 0x412f00b0, 0xb2210558, 0x053a7e01, 0xf1450720, 0x010d2109, + 0x0806bd4d, 0x36362731, 0x37233435, 0x14151632, 0xfd150706, 0x41490751, + 0xaba90796, 0xe604484e, 0x231c0592, 0x58687b48, 0x450a4e3c, 0xfc020000, + 0xffe4040c, 0x82ee0534, 0x000723ed, 0xa4820037, 0x080f5718, 0xca41ea82, + 0xd0062d05, 0xb62f06b0, 0x061f060f, 0x5d03062f, 0x2a059541, 0xb01000b0, + 0xb019d004, 0x41182f04, 0x01370503, 0xfe330323, 0xd5fed007, 0x22020601, + 0x04faf5c3, 0xfe0a01e4, 0x830a01f6, 0xfe1c31bf, 0xff2ffe94, 0x0008008b, + 0x02b00011, 0x0506b22f, 0x2207b941, 0x65053130, 0xfd21070b, 0x05115a1c, + 0x4735f126, 0x46466a47, 0x00273782, 0x01e904c6, 0x824106e2, 0x8317209b, + 0x83998237, 0x0c475efd, 0x2303332b, 0x8cdf0301, 0xfe410690, 0x262782a8, + 0x03df0467, 0x82af06ba, 0x000c2809, 0x003b0015, 0x452f14b0, 0x80410862, + 0x14b02114, 0x8a06a144, 0x0fb02294, 0x82d382d0, 0x659b8859, 0x012e08b0, + 0x9282e5ee, 0x7644a8fe, 0x44764343, 0xbe655602, 0xaf062405, 0x652fd6fe, + 0xff220cb9, 0xd55d00ff, 0x06022406, 0x83007800, 0x009b2acb, 0x05370400, + 0x000500b0, 0x0a67512b, 0x10924718, 0xd84a0420, 0x0442180b, 0x37042a07, + 0x03fc60fd, 0xfbe4049c, 0x2641821c, 0x00190002, 0x82a00500, 0x00032409, + 0x182f0006, 0x23171747, 0xb2593e0f, 0x2209346a, 0x420206b2, 0x2308061b, + 0x25210133, 0x6f020121, 0xfa3e02f3, 0x02550179, 0x0598fee0, 0xca50fab0, + 0x0300bb03, 0xecff5b00, 0xc4051305, 0x14260982, 0x76002200, 0xfb4908b2, + 0x10082505, 0xb0d001b0, 0xd5690582, 0x0c6c5007, 0x35087b47, 0x11100802, + 0xb07c3912, 0xb4182f02, 0x02700260, 0x30b45d02, 0x06824002, 0x0200b224, + 0x13527101, 0x10b0210a, 0x200c5c56, 0x0bf07d08, 0x20056f55, 0x7b461805, + 0x033c081d, 0x0140fea3, 0x947001c0, 0xb0b3edfe, 0x0399eefe, 0x01140196, + 0x96130164, 0xa9b7fc01, 0xbb02b9a4, 0x02b5a9a6, 0xd689c279, 0xaaadbdfe, + 0x5dcd3c01, 0xaf4401d5, 0xd5bffeab, 0x0501ef05, 0x0a834618, 0x2000012a, + 0x12050000, 0x0600b005, 0x07394118, 0x200cb264, 0x07c47801, 0x08c24718, + 0x593e0f26, 0x010300b2, 0x08c84218, 0x01332008, 0xfe980221, 0x01f1fe97, + 0xff01f5fe, 0x4404f0fe, 0xb005bcfb, 0x000050fa, 0x006c0003, 0x822e0400, + 0x0003265b, 0x000b0007, 0x05a9414b, 0x180c2e60, 0x22133741, 0x4d020805, + 0x5a1805b6, 0x08210b37, 0x0ce57110, 0x5c213721, 0x03200589, 0x6c3a0782, + 0x3efcc203, 0xfdf60264, 0x9903570a, 0xcaca67fc, 0x03c64d03, 0x0100cc29, + 0xdb829b00, 0x7f821420, 0x38000722, 0x06207b85, 0x20060e6a, 0x085961b0, + 0x7f07a74f, 0x062108bb, 0x0a305d10, 0x21313026, 0x11211123, 0x05270382, + 0x7ffdfc14, 0x427904fc, 0x01220683, 0xdb824700, 0x5b824d20, 0x3c000c22, + 0x0320d792, 0x03206882, 0xf3415b82, 0xd005220b, 0x21c58cb0, 0xff6a07b0, + 0x21152505, 0x35010135, 0x2508c882, 0xfe1c0301, 0xfbbc0275, 0xfec901fa, + 0xfde20337, 0x0288016b, 0xcafafdd0, 0x02420297, 0xfdcc983f, 0x030000ff, + 0xd3824a00, 0x7782ae20, 0x1c001528, 0x6c002300, 0xa9510bb2, 0x100b2505, + 0xb0d019b0, 0x47180582, 0x142007a5, 0x14208182, 0x5b075e43, 0x132f08db, + 0x12110a14, 0x2f13b039, 0xb2d000b0, 0x83140a09, 0x2f09290c, 0xb0d00cb0, + 0x21b21009, 0x8308e759, 0x4c13204b, 0x20200cb9, 0x1626ab83, 0x14151604, + 0x0e6e0706, 0x24610805, 0x24361026, 0x01333537, 0x11171614, 0x34050606, + 0x36112726, 0xa17c0336, 0x888e0301, 0xfda9857c, 0x8ffcfea2, 0xa403018e, + 0xaac6fdfd, 0x03a79693, 0x9194a674, 0x03ff04a9, 0x9a9efe8f, 0x034d48f6, + 0x8c01a9a9, 0xff3e01fa, 0xfdb1038f, 0x02b0a01f, 0xb704ae02, 0x04b6a09f, + 0xb30252fd, 0x00010000, 0x20e98244, 0x24e9825c, 0xb25c0017, 0x0adb6400, + 0x6c0cb04c, 0x47180cab, 0x6a7a0cd9, 0x0b152208, 0x051c4c16, 0xd000b024, + 0x4f1815b0, 0x09200c42, 0x362ed583, 0x33113536, 0x07000611, 0x26112311, + 0x0b822700, 0xd1821620, 0x03333108, 0xfd90834c, 0xf6e9fe03, 0xe8fef0fc, + 0x8f01fc04, 0x4302fc80, 0x01a7be17, 0xf606fef1, 0xfe19cffe, 0x1775018a, + 0x01f53001, 0x9d0bfeff, 0x6c0318c2, 0x6b28b383, 0xdd040000, 0x2500c305, + 0x0722b382, 0x77822726, 0x24051c42, 0xb11b2f1a, 0x078d411a, 0x0c820f20, + 0x78420f20, 0x82242007, 0x8324200c, 0x100f210c, 0x0bce5b18, 0x83d00e21, + 0x571a20ad, 0x11260c37, 0xd022b010, 0xb38223b0, 0x12362522, 0x2a07cf61, + 0x17121415, 0x33352115, 0x5e350226, 0x5f080563, 0x15151204, 0x33070214, + 0xdf022115, 0x9d017b74, 0x7f9b8e90, 0xd807fe77, 0x018e786b, 0x01a5a405, + 0x6b779006, 0xcf10fed4, 0xe7100120, 0xd9daca6d, 0xfeeb64cd, 0xcbcf1eeb, + 0x9e1f0167, 0x1d01b662, 0xe2fe9e9f, 0xfe9765b5, 0x00cb67dc, 0x56000200, + 0x7904ebff, 0x16004e04, 0x79002100, 0x23221fb2, 0xb024d382, 0x13b0101f, + 0x76067a51, 0x924c0c4b, 0xa540180c, 0x42032015, 0xb2230864, 0x820c130a, + 0x15b2214c, 0xb0210684, 0x0c6f420c, 0x12451320, 0x1611210e, 0x2306344a, + 0x22230627, 0x1027ea82, 0x17323312, 0x18140137, 0x0808b840, 0x03fd033a, + 0x180a1146, 0x35a24c33, 0xe3c3c166, 0x67b5c4e4, 0x7a1cfe13, 0x46468c76, + 0x047f738a, 0x7bfafc3a, 0xa31eb404, 0xf81d01a2, 0x010a010d, 0xfd839736, + 0x88ad9ebf, 0xc58ec701, 0x962ee582, 0x6a0477fe, 0x1400c405, 0x65002800, + 0xc56f27b2, 0x10272305, 0xe58200b0, 0x45180f20, 0xb0200d34, 0x2508177a, + 0xb2593e0f, 0xc3830027, 0x2f27b024, 0xd88924b2, 0x27240622, 0xb021d882, + 0x0ce44500, 0x1e20df82, 0x30222288, 0x9c480131, 0x16162305, 0xd1821415, + 0x2311272d, 0x36363411, 0x23263401, 0x83150622, 0x365c08ec, 0x27263435, + 0x32333523, 0xf2cf6902, 0x82795863, 0x7aa5d1f2, 0x01d97cf2, 0x605d714c, + 0x719d5881, 0x7b677a89, 0xc405d448, 0x9b5fb2d8, 0x82bd2c30, 0xfe53eccd, + 0x73a90538, 0x6dfe70c1, 0x687e765a, 0x8952e5fc, 0x01916d6e, 0x010000b9, + 0x5ffe2000, 0x3a04f503, 0x38000800, 0x0a0900b2, 0x0d534818, 0x66075d52, + 0xba4e0c5d, 0x07002208, 0x05ec4504, 0x01331322, 0x2a08a582, 0x0e023301, + 0x8ffefbec, 0xfb8ffef3, 0xff023b01, 0x35fef0fb, 0x0b04d001, 0x00020000, + 0x04ecff54, 0x00200638, 0x002b001f, 0x5d16b262, 0x16200579, 0x24091152, + 0xb11b2f03, 0x07e55203, 0x0c821620, 0x0d6b1620, 0x41092006, 0xb2230818, + 0x8203160e, 0x0eb0246e, 0x8929b22f, 0x291d2214, 0x057b700e, 0x310c1852, + 0x33363413, 0x15171632, 0x06222326, 0x16171415, 0x40511712, 0x36342607, + 0x26262737, 0x083a6f13, 0x06224f08, 0x49b7d4d0, 0x69974f71, 0xe0bc5a4e, + 0xe17a02de, 0xeefee295, 0x5b0289b8, 0x79897668, 0x6d918777, 0xea048979, + 0x1b16a591, 0x343d35c3, 0xfe4f425d, 0x9b1cccea, 0x230187f6, 0xffa50301, + 0x89280522, 0xbca27dfd, 0xcb78b6bc, 0x0100be17, 0xe7826000, 0x4d040c28, + 0x8b002700, 0x4b1816b2, 0x4d410faf, 0x82252007, 0x822520df, 0x17b223df, + 0xbc822509, 0x17b07c2f, 0x40b4182f, 0x02175017, 0x17d0b45d, 0x210682e0, + 0x824f18b2, 0x03b22308, 0x24821718, 0x210f527a, 0x14821017, 0x0d1cb226, + 0x0bb25d01, 0xb0230482, 0x42b21025, 0xb2230943, 0x82181e21, 0x04b4261e, + 0x02211421, 0x5c63185d, 0x4223200e, 0x14250549, 0x15333316, 0x08a06423, + 0x04143f08, 0x60242223, 0x61576269, 0xffbfd2f8, 0x5e597af2, 0xc7696072, + 0x667dd2d1, 0xfef28262, 0xfed5cbfc, 0x5c3201f8, 0x7924207f, 0xb5a59648, + 0x4d4f3c91, 0xad4b3c3f, 0x573f9303, 0xba9b4259, 0xfb8200b2, 0x7efe612a, + 0xb005ca03, 0x4a001e00, 0x21069350, 0x2143b000, 0x09b46113, 0x230bdb53, + 0x001c01b2, 0xb021b382, 0x23541815, 0x0115220e, 0x08a48306, 0x16171752, + 0x06141516, 0x35362707, 0x26272736, 0x10352627, 0x35213701, 0x60feca03, + 0x4b3d4656, 0x7a4f61dd, 0x025d7d52, 0x4ac4686e, 0xdc250139, 0xb005c4fd, + 0x6d0afe91, 0x5a546bba, 0x621f4218, 0x3eba4751, 0x3d466765, 0x69321b21, + 0x20018b50, 0xc3fd5101, 0x7e2eb383, 0x060461fe, 0x11004e04, 0x0cb25300, + 0x91591312, 0x2f072422, 0x5907b11b, 0x815e0791, 0x03012208, 0x213b820f, + 0x434603b0, 0x3130220b, 0x0cc17f01, 0x11073608, 0x5c011123, 0xb6c1770c, + 0x5ef303ad, 0xf3469668, 0x97833a04, 0x9cfbc5c4, 0x696e5304, 0x04effc7a, + 0x0003003a, 0x04ecff73, 0x00c4052c, 0x0016000d, 0xb279001e, 0x05dd5103, + 0xb0100324, 0x5f82d013, 0x181bb021, 0x231bf961, 0x0a030eb2, 0x7c2f8782, + 0x182f0eb0, 0x700e60b4, 0xb45d020e, 0x82400e30, 0x00b22706, 0xb071010e, + 0x4418100a, 0x0e200b6e, 0x820c8544, 0x431b20bb, 0x62180857, 0x05210f26, + 0x05745421, 0x05153308, 0x16141521, 0x04373632, 0xdfe3f82c, 0xe6f605fa, + 0xfd05f6e2, 0x7ad4013a, 0x017a6f71, 0x7b2cfed4, 0x020277e0, 0xfec4fe72, + 0x014101b6, 0x3501e92d, 0x0c824c01, 0x3023d335, 0xcecbcbce, 0xd1d02aef, + 0x0000caca, 0xffa90001, 0x826102f4, 0x000c22ef, 0x0aa54b28, 0x24072043, + 0xb11b2f09, 0x0da54b09, 0x517c9082, 0x9c01360b, 0x2b2a3e32, 0xe8fe564a, + 0xf6fc3a04, 0xbc0a363d, 0x03350117, 0x2c598211, 0x04eeff16, 0x00fb054a, + 0xb2500019, 0x07315403, 0x4705a745, 0xb02507f7, 0xb0584500, 0x20638210, + 0x21638210, 0x49470bb0, 0x0fb2260b, 0x12110b00, 0x057c5e39, 0x5400b021, + 0x50080ed5, 0x01171632, 0x37171716, 0x22230617, 0x03032726, 0x26270121, + 0x27072327, 0x6c120136, 0xab011f78, 0x11203124, 0x6d342a04, 0xf6ca2b75, + 0x8101f7fe, 0x2249225b, 0x053b031b, 0xfb5055fb, 0x010756bf, 0x580ac001, + 0xfd14026f, 0xda0f0437, 0xb602034b, 0x2caf8210, 0x0376fe64, 0x00c405d4, + 0xb256002c, 0x06e76403, 0xaf851620, 0xa2822a20, 0x3e1f2a23, 0x0a764a59, + 0x2d08b223, 0x219f832a, 0x78652f08, 0x1db2210a, 0x1d201485, 0x220ca067, + 0x7e080924, 0x063108ef, 0x33211415, 0x11202315, 0x16041614, 0x06151617, + 0x2ab48206, 0x26343536, 0x26262724, 0x74363435, 0x4f08073c, 0x8a830317, + 0x01887a57, 0xfe8c891c, 0x1901819e, 0x0251236f, 0x3583507b, 0xfdfe3f2e, + 0xa3767f4c, 0x017c6e90, 0x7d99e302, 0x5624da04, 0xfec6b84b, 0x428862e3, + 0x6d381825, 0x643bbb48, 0x23295039, 0x3520442d, 0xc49194b7, 0x618e282d, + 0x002cc5a6, 0x2d2edf82, 0xcf04f4ff, 0x14003a04, 0x0bb25c00, 0x61431615, + 0x0c1d4808, 0x2007854a, 0x08a16eb0, 0x593e0f27, 0xb21013b0, 0x08074500, + 0x180ab021, 0x2a0c6d4c, 0x0db01000, 0xd00eb0d0, 0x60d011b0, 0x707e0526, + 0x213d080c, 0x23112311, 0xa9042135, 0x263f319f, 0xfe564a2f, 0xf3b4fee8, + 0x037c04ab, 0x3eb6fd7c, 0x17bc0a37, 0x53023501, 0x7c0384fc, 0x000200be, + 0x0460fe80, 0x004e0431, 0x001a000e, 0x1b11b257, 0x21a3821c, 0xe14711b0, + 0x080d4c05, 0x430c3979, 0x226407fe, 0x00092208, 0x49348207, 0x495a0ba5, + 0x31302b0c, 0x11123201, 0x23021415, 0x99822722, 0x03003422, 0x0809805b, + 0x56021538, 0xc1e0fbe0, 0x01f36ab3, 0x95431003, 0x727c7d76, 0x4e047766, + 0xeffecbfe, 0xe5fef20f, 0x03fdfd77, 0x2101f2db, 0xad75d5fc, 0xc1c5b8b3, + 0x010000a0, 0x8afe5200, 0xb182e903, 0x4d002226, 0x24231bb2, 0x870df55e, + 0x2f1427a9, 0x1714b11b, 0x8f50593e, 0x61058205, 0xb2230a68, 0x8200231c, + 0x1cb02135, 0x210eb167, 0xad741632, 0x1604240a, 0x42141716, 0x57080728, + 0x27262627, 0x36363435, 0xedc43802, 0x71606de4, 0x2e019483, 0x7f013160, + 0x2a337f4c, 0xedee413c, 0x04dc7801, 0x61bbdd4e, 0x1aaabc74, 0x39569b83, + 0xbf484253, 0x4e376538, 0x0f2a282c, 0x27d1fe37, 0x0089fa9d, 0x52000200, + 0x7e04ecff, 0x0f003a04, 0x4c001b00, 0x1d1c07b2, 0x4a051a77, 0x0e200833, + 0x0e20b482, 0x200c7548, 0x20c1820f, 0x0bfa4f0e, 0x4407b021, 0x00290cc4, + 0xd019b010, 0x21013130, 0x07e24716, 0x00343525, 0x5c012137, 0x3b080ae3, + 0xf5fe7e04, 0x91de7aba, 0x01f0fee2, 0x4102df0c, 0x7a85c7fc, 0x75838175, + 0x76038776, 0xec8efb92, 0x012c0183, 0x01ee0c03, 0xd8fd0223, 0xbdbcbba9, + 0x00b0b39c, 0x3f000100, 0xec03ecff, 0x1024ab82, 0x01b24900, 0x0a2f4518, + 0x420c737e, 0x0f2008b9, 0xac42a38c, 0x44a68315, 0x280805c5, 0x20230617, + 0x35211103, 0xfeec0321, 0x27332b98, 0x6c502637, 0xfe05ecfe, 0x03ad03ae, + 0x3bb0fd79, 0x2cb1163b, 0x54023901, 0x248782c1, 0x04ebff80, 0x24878208, + 0xb2380012, 0x17ff6f0e, 0x1b2f0e28, 0x3e0f0eb1, 0x454bb259, 0x00b02409, + 0x5608b010, 0x460806cc, 0x32331011, 0x03263536, 0x10111633, 0x26222300, + 0x72011127, 0x039171a1, 0xfe73f16e, 0xd1cbe7fc, 0xfd3a0401, 0xe9fdfe76, + 0x1d01e7a0, 0xfee2fee6, 0xe2c1fef4, 0x009502d8, 0xfe440002, 0x04850522, + 0x001a0041, 0x6d5f0023, 0x1b240a35, 0x19b000d0, 0x2005a744, 0x207b8211, + 0x07b44111, 0x4a180620, 0x705d0b50, 0xd34a1808, 0x29958309, 0x0db0d018, + 0xd01bb010, 0x5a4e11b0, 0x31303e0b, 0x35002405, 0x17371234, 0x14070606, + 0x34111716, 0x16323336, 0x00141516, 0x13231105, 0x08be8236, 0x2223264c, + 0xfe650215, 0x7ee3fefc, 0x4c489873, 0x9e949a02, 0x87ec937c, 0xf5fedefe, + 0xa595f3f3, 0x37748d02, 0x37011c0e, 0x0501a4ff, 0xbc469253, 0x1ecda168, + 0x92778002, 0xf392fb8d, 0xfe1ad7fe, 0x19940231, 0xbf9797c1, 0x0100003e, + 0xd7824f00, 0x3a047e28, 0x44001800, 0x015b00b2, 0x850d2006, 0x821420cf, + 0x871420c2, 0x08e247cf, 0x1c471720, 0x01b02608, 0x1014b0d0, 0x2bc582b0, + 0x0fb0d006, 0xd00cb010, 0x11013130, 0x5f41a083, 0x36ae8205, 0x03002411, + 0x10113311, 0x52031105, 0x7005a793, 0xe1fe79ee, 0x82f3f3fe, 0x01f531ba, + 0x041d01f3, 0x1b7dfc3a, 0x01e2a4ce, 0xedfee314, 0xca331482, 0x0132fe1a, + 0x33011ed0, 0xed010a01, 0xa2fe18fe, 0x8282033c, 0xff6624a3, 0x822d06ec, + 0x002024a3, 0x7d1ab256, 0x4c4d0acb, 0x8218200c, 0x4e1820ad, 0x44180733, + 0x5218088e, 0x00340b58, 0x3912111c, 0xb0d00eb0, 0x13b01000, 0x2f13b0d0, + 0x18051ab2, 0x20051b46, 0x06d15702, 0x1621ab82, 0x07224216, 0x02105708, + 0x06272223, 0x10022223, 0x86e50137, 0x5b586107, 0x5f02fb60, 0x0761585a, + 0xd58df185, 0x5c5ce8cb, 0x8dd6cbe6, 0xe9fe3a04, 0x9dcbbded, 0xfe460194, + 0xcb988eaf, 0x1501efbd, 0xfec8fde8, 0x01deded2, 0xe838022e, 0x76000200, + 0x9804ecff, 0x2000c405, 0x6b002900, 0x596d0fb2, 0x100f2305, 0xc34821b0, + 0x0cfb4e06, 0x54180620, 0x24220790, 0x9c82061a, 0x2f24b022, 0x230bab48, + 0x0bb2d002, 0x06201785, 0x290cf562, 0x1eb01024, 0x101ab0d0, 0x9e4127b2, + 0x31302608, 0x15070601, 0x24c08214, 0x37113500, 0x05084411, 0x26357108, + 0x34352700, 0x16323336, 0x37361115, 0x17161401, 0x22232611, 0x3a980406, + 0xd3d5fa44, 0x82ecfefe, 0xd16d626e, 0xc50300ff, 0x4bbca7a5, 0x7daafd2a, + 0x346d046b, 0x14570243, 0xfdda750b, 0x01d40501, 0xdefe021d, 0x83868f7d, + 0x1301267c, 0xcca91bc0, 0xcefebbd0, 0x23010b0c, 0x0120a26c, 0x00499a45, + 0xe1ff0100, 0x9e040000, 0x1a00c305, 0x00b24200, 0x500adf63, 0x0d200c7d, + 0x0d27e782, 0xb2593e0f, 0x5f0d0400, 0xca470517, 0x12b0280a, 0x1004b0d0, + 0x82d017b0, 0x361321c4, 0x2507f960, 0x23110107, 0xaf820111, 0x82270721, + 0x164a0812, 0xd23f0217, 0x46607a2b, 0x280d2642, 0xd9fe1f41, 0x21dbfefc, + 0x240a2b40, 0x7d674a3c, 0x0107032c, 0x1a6064f8, 0xfd4505c2, 0x02eefd6b, + 0x45970210, 0x641bc105, 0x0200006c, 0xecff3300, 0x3a045406, 0x26001200, + 0x08b27000, 0x7f832827, 0xb0100823, 0x068f411e, 0x4211c843, 0xe6440757, + 0x44112008, 0xb2230be6, 0x83061108, 0xd00f2d42, 0xb0d010b0, 0x16b0d015, + 0x100ab0d0, 0x230a7769, 0x0a101fb2, 0x24202083, 0x2322cf83, 0x59421516, + 0x34112a08, 0x21352337, 0x21272601, 0x05814206, 0x35375b08, 0x16161533, + 0x06363233, 0xca378054, 0x5c5ceebc, 0x36c8bdee, 0xfe21066f, 0xfc3d04c5, + 0x53043cc6, 0x01665c4b, 0x5d6302fa, 0x8303534b, 0xe2feaf9e, 0xe2e2d4fe, + 0x1c012e01, 0xfdb79cb1, 0xb1ada0fc, 0x97cabe9c, 0x8feee895, 0x0100ca97, + 0xf2ff2200, 0xb005bc05, 0x6e001800, 0xdf5e11b2, 0x2f17240a, 0x1817b11b, + 0x250f1d68, 0x584500b0, 0x198213b0, 0xee831320, 0xe18c1720, 0x09170422, + 0x0423c083, 0x5409b02f, 0xb0210b67, 0x0c736d04, 0x85100021, 0x31302dfd, + 0x36112101, 0x10043233, 0x32272304, 0x0805b144, 0x23110733, 0x21352111, + 0x13fe9004, 0x01fb7294, 0xfeeefe18, 0x018c8901, 0x78868f8f, 0x047cfefd, + 0xfee4046e, 0xfef02674, 0x79bfec50, 0x20877784, 0xe40474fd, 0x2cc182cc, + 0x04ecff68, 0x00c405ef, 0xb271001f, 0x03411803, 0xad5c180a, 0x0860650c, + 0x727e0c20, 0x0c17220c, 0x08574e03, 0x40173029, 0xb45d0217, 0x4e701760, + 0x00230a5e, 0x18710117, 0x210a0a6d, 0x894d03b0, 0xde62180b, 0x6d212018, + 0x540805c3, 0xee043736, 0xf8d4fe16, 0x91f5feaf, 0x11019201, 0x2501f3b4, + 0x9412fc18, 0x08b0a18e, 0x04fefb01, 0x939dab07, 0xd9011496, 0xa5fbfee8, + 0x7bcf3601, 0xaa3a01cf, 0x9cecf6fe, 0xcad2e58e, 0x9d87e5dd, 0x00020000, + 0x0800002d, 0x00b00541, 0x00220019, 0x2309b274, 0x05e24e24, 0x60085366, + 0xdf5f0c87, 0x07b74b0c, 0x1800b223, 0x23348308, 0x18b02f00, 0x200c9941, + 0xde521810, 0x5200200c, 0x12270c3b, 0xd01bb010, 0x82d01cb0, 0x216408e2, + 0x1415021e, 0x11210704, 0x02020321, 0x35232306, 0x37023e37, 0x11112113, + 0x35363221, 0x05272634, 0x9931010d, 0xebfe7feb, 0xfecafde5, 0x630f1a42, + 0x28409ebc, 0x0a315f57, 0x01ab031c, 0x8f917e29, 0x01a1037a, 0xce87d475, + 0xe40405fd, 0xf8fecdfd, 0xca86ddfe, 0xd76a0803, 0xfdc902d1, 0x93f4fd26, + 0x028f7375, 0x9b20e982, 0x4720e982, 0x1328e982, 0x87001c00, 0x1e1d01b2, + 0x2006b65e, 0x05421814, 0x0791420b, 0x1b2f1324, 0x0c8713b1, 0x1808a14c, + 0x230bb850, 0x131000b2, 0xb228f685, 0x5d01009f, 0x020d04b2, 0x82069f42, + 0x686518e9, 0x04b02109, 0x0cd34418, 0xc84c0d20, 0x1121220e, 0x2de78233, + 0x14151616, 0x11212304, 0x11231121, 0xf8860133, 0x97012335, 0x01fc8002, + 0x7fee9c2b, 0xfdf3e3fe, 0xfc80fde0, 0x827c03fc, 0x922308f1, 0x45037c94, + 0xd2fd6b02, 0xcd85cb6e, 0xfd7a02f7, 0xfdb00586, 0x8618fe08, 0x00836f70, + 0x00310001, 0x82c80500, 0x001522e7, 0x05d14d56, 0x410c6656, 0xb02114c2, + 0x0d6a4314, 0x85141021, 0xbc6418ca, 0x00b0280a, 0xd012b010, 0x43d013b0, + 0x20220659, 0xac821504, 0x07985118, 0x35212a08, 0xfe920421, 0x018f8311, + 0xfc07010c, 0x868c9a7d, 0x048afefc, 0xfee40461, 0xe5ec1b9b, 0xca0137fe, + 0xfd1c7a8b, 0xcce4044d, 0x24a18200, 0x0598fe92, 0x22a1820d, 0x7b48000b, + 0x0c7c0895, 0x083a6208, 0x46077d41, 0xb020078e, 0x25571983, 0x0a317508, + 0x93820320, 0x11331324, 0x03831121, 0x11232008, 0x02fd9221, 0x4bfefd81, + 0x0537fefd, 0x041afbb0, 0xfe50fae6, 0x00680198, 0x00900002, 0x82c10400, + 0x000d2877, 0xb25b0016, 0x76181710, 0xb021053b, 0x133f6903, 0x20086845, + 0x0c1b410c, 0x0a0c0222, 0x02223583, 0x247cb22f, 0x0dff6909, 0x01313023, + 0x07d34121, 0x09820720, 0x3007cf41, 0xfd2c0427, 0xa02a0161, 0xebfe7cee, + 0x03d3fdef, 0x3a0d829c, 0x8c8f8029, 0xfee4047c, 0x85ca6e9f, 0x0502f8cc, + 0xfe08fdb0, 0x6e738b12, 0x82000280, 0xfe2424af, 0x82dc059a, 0x000e28af, + 0xb2650014, 0x83161512, 0x10122379, 0xaf860bb0, 0x1b2f0b23, 0x0b6518b1, + 0x82042008, 0x1704210c, 0x59066a7a, 0xb02807b3, 0x01b01004, 0x1002b0d0, + 0x4d0ba759, 0x2a4605ae, 0x100b2105, 0x820a2b4d, 0x234908b9, 0x23112111, + 0x12363303, 0x11211337, 0x11212133, 0x05020321, 0x41fcf0cf, 0x577508f4, + 0x03260f68, 0xdbfbb996, 0x57fe7002, 0x9afe1b18, 0x9afe6601, 0x01543002, + 0x8602cb41, 0x1a041afb, 0x65fe66fe, 0x00010000, 0x07000016, 0x22b7829b, + 0x427d0015, 0x5d180581, 0x73660cf4, 0x0c28580c, 0x5418b588, 0x0c830c13, + 0x2808c065, 0x11020910, 0x10b03912, 0xdf49182f, 0x04b0260a, 0x1008b2d0, + 0x27178400, 0xd00bb010, 0x100013b2, 0xcd840c82, 0x23112325, 0x82012101, + 0x6d332002, 0x210808d6, 0xfca3ff04, 0xfe9bfeaa, 0xfed501c5, 0x0132014a, + 0x96fc9d5c, 0x31015901, 0xd1014efe, 0x7402c6fe, 0x03838cfd, 0x02070327, + 0x02a0fda9, 0x22038460, 0x83f7fc59, 0xff492ed7, 0x057f04ed, 0x002900c3, + 0x2a25b286, 0x08ed4d2b, 0x200c8741, 0x075a6a17, 0x6f180b20, 0x28220c5a, + 0x2f82170b, 0x28b07c34, 0x10b2182f, 0xb45d0128, 0x28402830, 0x60b45d02, + 0x06837028, 0xb028a022, 0xb2230682, 0x82032806, 0x25b22125, 0x23084249, + 0x282511b2, 0xb0211182, 0x0b6b5717, 0x251cb223, 0x7de0851f, 0x362208f1, + 0x69183233, 0x22220aa9, 0x2d7d2626, 0x26440808, 0x33352323, 0x946c0320, + 0xfc926d7f, 0xfa8dea84, 0x6c781501, 0xd4fe817a, 0x7df99afa, 0x86789cfc, + 0xab8a8fa3, 0x040c01a2, 0x73746223, 0x67ba775b, 0xa663c4da, 0x7fab2a30, + 0xbe6ee7c4, 0x7e815e7b, 0xc86f7b65, 0x942afd83, 0x0d050000, 0x0900b005, + 0xcf5d4500, 0x82072012, 0x5e0720f6, 0x925c102a, 0x0004220c, 0x21b58202, + 0x068409b2, 0x0131303f, 0x11231133, 0x33112301, 0xfd100411, 0xfd81fdfd, + 0xfab005fd, 0xfb0d0450, 0xfbb005f3, 0x207183f2, 0x2471862d, 0xb24d0011, + 0x0a135404, 0x5c0c2b44, 0x09200cfe, 0x2106af52, 0x7c4100b0, 0x09b0220b, + 0x21531810, 0x4678820d, 0x05220c6c, 0x5946fc0d, 0x4689840d, 0x002e0f4c, + 0xff390001, 0x05dd04eb, 0x000f00b0, 0x4c18b249, 0xb04410fd, 0x00b2220f, + 0x0594490f, 0xde641020, 0x06b02105, 0x230b1e47, 0x0f060db2, 0x0808a15d, + 0x23060744, 0x33163727, 0x01373732, 0x01a00221, 0xfe190124, 0xe0642e05, + 0x3d180268, 0xfe342c6c, 0x0214010e, 0xfbf902b7, 0x06b25b48, 0x7b5c04c8, + 0x03002404, 0xc4ff4f00, 0xec051806, 0x1f001600, 0x55002800, 0x11590ab2, + 0x100a2505, 0xb0d01eb0, 0x202c0582, 0x0ab000d0, 0x2f15b02f, 0x0a1514b2, + 0xb0296982, 0x00b02f14, 0x0a0bb2d0, 0x240c8315, 0x08b02f0b, 0x0b4e5cd0, + 0x14203482, 0x080b6442, 0xd020b024, 0x32013130, 0x14151204, 0x15230402, + 0x26233523, 0x34350224, 0x35332412, 0x06220133, 0x17161415, 0x01821133, + 0x36324c08, 0x23263435, 0x01bbae03, 0xfe999916, 0x17f3bceb, 0x98ecfea9, + 0xbe14019a, 0xaafbfef3, 0x17abbbc1, 0xbfab11f3, 0x2605adbf, 0xacf0fe98, + 0x97f1feaa, 0x9601bebe, 0xadaa0d01, 0xc6971201, 0xbccf6ffe, 0x0302cdb4, + 0xcff2fc0e, 0x46d0b9b6, 0xa128051d, 0xb005bd05, 0x3b000b00, 0x46221d46, + 0x06201310, 0x21091046, 0x10460333, 0x14b02407, 0x46d1fbe8, 0xfb250510, + 0x01d5fd1c, 0x246b835f, 0x0400008e, 0x226b82ee, 0x423f0011, 0xb64412d3, + 0x0767420c, 0x010eb22a, 0x39121109, 0xb22f0eb0, 0x2909da4d, 0x11013130, + 0x23061123, 0x9b5c2420, 0x33250805, 0x04113732, 0xb0a2fcee, 0xf4fefbfe, + 0x7e01fc01, 0x05a4ae97, 0x0250fab0, 0xe8e6293d, 0x30fece01, 0x022a768b, + 0x248183a7, 0x07000098, 0x20ed8403, 0x5f819248, 0x62430ce8, 0x0899550c, + 0x2b440120, 0x05b02308, 0xfa83b0d0, 0x0a470120, 0x82332006, 0x96012907, + 0x01fcbc01, 0x95f9fcb9, 0x1a24fa86, 0x50fae604, 0x01266f82, 0xa2fe9800, + 0x0982ad07, 0x54000f25, 0x5b0bb000, 0x7c991240, 0x394d0d20, 0x2a7c8f07, + 0xb0d009b0, 0x02b0d00a, 0x893130d0, 0x03332285, 0x24898a23, 0xf9de14aa, + 0x258c89dd, 0xe0fd12fb, 0x86825e01, 0x00020027, 0x05000018, 0x069f47d4, + 0x01b25e22, 0x23059f47, 0x0eb01001, 0x221c0b7b, 0x470a0002, 0xb0240591, + 0x0cb21000, 0x20090d41, 0x0b845502, 0x200fa247, 0x15a24713, 0x8702182e, + 0xeea02a01, 0xeee9fe7d, 0x75fed4fd, 0x29320d82, 0x7c8c8f80, 0xd3fdb005, + 0xcd86c96e, 0xed0402f7, 0xa147cbfd, 0x00032608, 0x0600009b, 0x22b18258, + 0x820f000b, 0xb26d24bd, 0x841a1902, 0xb010258b, 0x02b0d00d, 0x4609076a, + 0x99710c21, 0x0c8f490c, 0x2208da6b, 0x4a0b0800, 0x1020065b, 0x0820d089, + 0x230eab47, 0x16163221, 0x2105394b, 0x374a0133, 0x0127220a, 0x09654898, + 0xc004fd27, 0x40fbfcfc, 0x21c68401, 0x66488303, 0x50fa2107, 0x490b6a48, + 0x0b260919, 0x4d001400, 0x69480eb2, 0x100e2305, 0x694801b0, 0x087a4213, + 0x87090021, 0x0a7641a5, 0xc9540920, 0x4ba58a0e, 0x012108d2, 0x8fa18a8d, + 0x0902499b, 0x6b00012c, 0xf104ecff, 0x1f00c405, 0x7b4d7f00, 0x0c9e4b0c, + 0x35086a51, 0x111c1309, 0xb07c3912, 0xb4182f09, 0x09700960, 0xd0b45d02, + 0x0683e009, 0x40093022, 0xb2240682, 0x71010900, 0x200b0949, 0x0ca2471c, + 0x03060022, 0xb0213e82, 0x0b454213, 0x090fb223, 0x05a5450c, 0x16166508, + 0x37363233, 0x26213521, 0x06222326, 0x00362307, 0x12043233, 0x02141517, + 0x00222304, 0x14680127, 0xab9c9397, 0x02fefd06, 0xa0b10802, 0xfc12958c, + 0xf2250118, 0x931001b3, 0xf4fe8f01, 0xd4fef8b0, 0x9ed90116, 0xccd7e486, + 0x9e8ce4d8, 0xa80801ee, 0x7bcdc8fe, 0xa8c7fecf, 0x00e80501, 0xa0000200, + 0x0707ecff, 0x1728eb82, 0x7e002500, 0x272612b2, 0x2006ed49, 0x0bc55f1d, + 0x49076346, 0x18630c44, 0x0c214b08, 0x0d0a0e22, 0x815a4182, 0xf36f180b, + 0x5ae5830a, 0xb0220964, 0x5e181004, 0xce6f0c28, 0x11232908, 0x11331123, + 0x24123633, 0x6b18ec84, 0x07340d5c, 0xedfe9407, 0xf8fea7b3, 0xfcb60e9e, + 0x9a06b3fc, 0xb2ad0f01, 0x13616b18, 0x1c01982d, 0x05a3fdbd, 0xc971fdb0, + 0x18a53501, 0x8212666b, 0x002030fd, 0x055f0400, 0x000c00b0, 0xb2610015, + 0x49171610, 0x0a2006ce, 0x1813655b, 0x630c4e41, 0x112208c7, 0x3483000a, + 0x6a181120, 0x05220c1e, 0x14831101, 0x8b4e0a20, 0x3044080b, 0x21112131, + 0x26012101, 0x37243411, 0x14011121, 0x11333316, 0x03062223, 0xfee6fe62, + 0x01f1fee7, 0x1301fe45, 0xfdef01f6, 0xeb8a8a04, 0x02888ceb, 0x02e0fd20, + 0x1101786b, 0xfa02e9d1, 0x7be90350, 0x8600028a, 0x5b2eb382, 0x3c04ebff, + 0x1a001306, 0x54002600, 0xc5510eb2, 0x100e2105, 0x2408195c, 0xb11b2f11, + 0x10c57c11, 0x07110022, 0x2006db43, 0x05ac5819, 0x200a8741, 0x0d865507, + 0x12320136, 0x00141515, 0x11002223, 0x37121035, 0x33353636, 0x07060614, + 0x36210282, 0x08ad7c17, 0x26345a08, 0xf6cc7a02, 0xdfe5f5fe, 0xf6f8eefe, + 0x42c4518a, 0x9f98a688, 0x7693911b, 0x797a8486, 0xfe038585, 0x0ceaeffe, + 0x01defeea, 0x46000128, 0x98015e01, 0x363f1c33, 0x234f7e65, 0x9591a420, + 0x9ca59fc3, 0x8cb0afae, 0x000300a3, 0x0400008f, 0x003a043a, 0x0015000e, + 0xb278001c, 0x05234f02, 0xb0100223, 0x0ccd4415, 0xd7820120, 0xb4790120, + 0x16b2230f, 0xd7820001, 0x16b07c2f, 0x40b4182f, 0x02165016, 0x16d0b45d, + 0x210682e0, 0x3b5a0fb2, 0x08b22308, 0x7418160f, 0x03411476, 0x31302409, + 0x61211133, 0x01200b78, 0x3e080e82, 0x25233435, 0x34353233, 0x018f2327, + 0x5de8deb7, 0xdf7c6a5b, 0x01f8fed1, 0xfebebb0a, 0xc4cfc8f9, 0x9b3a04d3, + 0x20774b91, 0x975b8616, 0xfecd019e, 0xae8786f3, 0x0004807a, 0x00850001, + 0x824d0300, 0x0dd368d3, 0x714cbc87, 0x14d36808, 0xfe4d032a, 0xc802f22a, + 0x8afc7603, 0x02264182, 0xbefe2700, 0x0982c504, 0x14000e24, 0x8f4d5b00, + 0xd004210a, 0x08115618, 0x7a2f0421, 0x9b480a99, 0x45002008, 0x062909c4, + 0xd007b0d0, 0xb0100cb0, 0x21088209, 0x854db010, 0x45042005, 0x3e080dd9, + 0x37363637, 0x33112113, 0x21112311, 0x21132311, 0x07211121, 0x45658102, + 0xef020e07, 0x4afdf296, 0x760101f6, 0xeffe9f01, 0x71c20e07, 0x9e019ecb, + 0xfcfd88fc, 0xbefe4201, 0xa7020402, 0x82d6fecf, 0x001e24f5, 0x825c0600, + 0x001522a9, 0x0a814d82, 0x0c4e5a18, 0x6a540c87, 0x23814d0c, 0x11021122, + 0x2305814d, 0x5d01108f, 0x2729864d, 0x01012103, 0x11331321, 0x13200182, + 0x043e0a83, 0x80f38135, 0x01d6fef9, 0x01acfe67, 0xf372f529, 0x2901f673, + 0x6901adfe, 0xb301d2fe, 0x03834dfe, 0x02330227, 0x0157fe07, 0x240383a9, + 0xcafdfcfd, 0x2cd98200, 0x03ecff4d, 0x004d04c4, 0xb28d0027, 0x0ad7611e, + 0x1b2f2524, 0x127c25b1, 0x3e0f260c, 0x2519b259, 0x2fac8208, 0x2f19b07c, + 0x1940b418, 0x5d021950, 0xe019d0b4, 0xb2210682, 0x09934216, 0x19160322, + 0x21057e55, 0x148910b2, 0x10160d22, 0xb42b1482, 0x0d130d03, 0x25b05d02, + 0x891eb210, 0x1921221b, 0x2b1b821e, 0x210b0940, 0x212b211b, 0x5d04213b, + 0x6405b372, 0x7b4d0527, 0x1836200f, 0x080ccf4a, 0x57b00338, 0xcbf2ba4f, + 0xf272cc7c, 0x69595a76, 0xb4ae605c, 0x50525ea3, 0xb9f0f26e, 0x1203e0c9, + 0x41247948, 0x53b195ba, 0x59426999, 0x464f4353, 0x428402af, 0x8f3c4f4a, + 0xfb82a4b7, 0x00008626, 0x3a041204, 0x5b0e814d, 0xd8420ca4, 0x0d814d10, + 0x814d0720, 0x4d068405, 0x03340b81, 0xfef2f220, 0x04f2f258, 0x02c6fb3a, + 0x042efdd2, 0x002efd3a, 0x8f207182, 0x65207182, 0x0c227182, 0x47426800, + 0x0cdf4205, 0x420c5279, 0x0b3e0c3a, 0x0bb11b2f, 0xb2593e0f, 0x11040206, + 0xb07c3912, 0xb4182f06, 0x06e306d3, 0x43b45d02, 0x06825306, 0x0613b222, + 0x210c6e6b, 0x827d0ab2, 0x7bfd2f14, 0x016bf3f3, 0xfe2c012b, 0xfea80179, + 0x827d01c4, 0xfdfa2209, 0x20a183cc, 0x20a18221, 0x24a18214, 0xb24d000f, + 0x0ad97004, 0x4e0c9959, 0x71490c23, 0x0c234e09, 0x4b0cf769, 0x213a05cf, + 0x23060203, 0x36372723, 0x04133736, 0xcefef314, 0xb0ab1314, 0x5032014b, + 0x72820a49, 0x03c6fb2f, 0xfe87fe76, 0x05caedf0, 0x01e5ad0b, 0x062f41ce, + 0x826f0521, 0x000c228d, 0x052f4159, 0x240c2a45, 0xb11b2f0b, 0x07a1410b, + 0x50083156, 0x5f4910ec, 0x445c1809, 0x8408200c, 0x2799820d, 0x23112101, + 0x01230111, 0x213d0582, 0x4001ff02, 0xfef33001, 0xd5fea5d6, 0x013201f3, + 0xfb0f032b, 0xfdcc02c6, 0xfdd00234, 0x053d7f30, 0x00008624, 0x0a821104, + 0x7e000b22, 0x185c9385, 0x435c180c, 0x0c57470c, 0x20080e78, 0x05574709, + 0x2f092408, 0xcf09bfb4, 0xb25d0209, 0x710109bf, 0x3f092fb4, 0xb2720209, + 0x7201095f, 0xff09efb4, 0xb4710209, 0x822f091f, 0x8fb22806, 0xb45d0109, + 0x839f098f, 0x09a6531e, 0x3808a76b, 0x11211133, 0xf3110433, 0xf3f35bfe, + 0x01f3a501, 0x044bfeb5, 0x013dfe3a, 0x0ae142c3, 0x460d0d6c, 0x77180f6a, + 0xb0200c2a, 0x27160d6c, 0xfef31204, 0x8c03f35a, 0x2a06bd45, 0x00230001, + 0x04d00300, 0x6d07003a, 0x07410745, 0xe570180c, 0x05b02118, 0x3405f254, + 0x35211123, 0xfed00321, 0xa5fef3a1, 0x7903ad03, 0x790387fc, 0x335282c1, + 0x60fe5400, 0x00067f05, 0x24001a00, 0x7f002f00, 0x313007b2, 0x27064b5f, + 0x07b0d020, 0xd02ab010, 0x15216a18, 0x240c7941, 0xb11b2f13, 0x07cd6013, + 0x520c6f56, 0x0a21084f, 0x0a586610, 0x1810b021, 0x260c1d46, 0x1eb0d028, + 0x822db010, 0x10132da9, 0x17323312, 0x36113311, 0x11123233, 0x2507e860, + 0x02222306, 0x6b182527, 0x936908a9, 0x545c080a, 0x3e4cbbd1, 0xba5640f2, + 0x53b7d4d3, 0x4f3df245, 0x0409d1af, 0x2d6a7437, 0xdc332125, 0x6a6cbafc, + 0x2a22212d, 0x0e027068, 0x37010901, 0xfece011c, 0xcbfe202e, 0xfef3e0fe, + 0x56fe1ee6, 0x011aa601, 0xb63ce303, 0x3afd0dc7, 0xa24b010a, 0xc9020aa9, + 0x0100c10a, 0xbffe8600, 0x3a04a504, 0x2005c34f, 0x0a5b4e08, 0x0cad5e18, + 0x200cca61, 0x0c5e630f, 0xc34fb020, 0xf386360f, 0x93f3a601, 0xd2fcdd14, + 0x88fc3a04, 0x88fc7803, 0x4101fdfd, 0x2a6b8200, 0x0300005f, 0x003b04e0, + 0x52480011, 0x09220c25, 0x64181b2f, 0xaf7b090a, 0x08ca4f0c, 0x09010d2a, + 0x7c391211, 0x182f0db0, 0x250a8770, 0x23213130, 0x60180611, 0x200807a2, + 0x37323316, 0xe0033311, 0xde685ef3, 0x6c69f3ea, 0x01f36462, 0xc7d51669, + 0xb4fe4c01, 0x02176276, 0x2483830c, 0x06000086, 0x4fef8403, 0xea430bc5, + 0x14a6450c, 0x2827c54f, 0xf3520179, 0xfaf25301, 0x23fc8783, 0xc6fb7803, + 0x01266f82, 0xbffe7e00, 0x0982b406, 0x4b000f22, 0x44088448, 0x03240cfb, + 0x03b11b2f, 0xc54f7c94, 0x4f092016, 0x712013bc, 0xb9248085, 0xbbfadd14, + 0x84418389, 0x267d8205, 0x001f0002, 0x82ea0400, 0x000d2609, 0xb25b0015, + 0x05bf4b00, 0x7907b84f, 0x8a710c70, 0x0c002a08, 0x39121108, 0xb02f00b0, + 0x0c375a0c, 0x0cde4c18, 0x5e08b021, 0x3e080b65, 0x33013130, 0x15161632, + 0x21070614, 0x21352111, 0x32331111, 0x27263436, 0x85ee4a02, 0xc4ec67c6, + 0xc8fe1dfe, 0x59ed2b02, 0x02566567, 0x6ea65ce2, 0x0301caa7, 0xe5fdc476, + 0xa459a3fe, 0x4a00015f, 0x052105e3, 0x2aa782c9, 0x000f000b, 0xb26d0017, + 0x43191807, 0x0d2406ad, 0x1007b0d0, 0x088b7818, 0x630c9d43, 0xb14f0c0c, + 0x860e2016, 0x4fb220cc, 0xbb891ab1, 0x8506b14f, 0x820121bd, 0xf326bd87, + 0xf3f34704, 0xc08cb9fb, 0xfb3a0425, 0x893a04c6, 0x000226c3, 0x0400008f, + 0x26c38422, 0xb24d0013, 0x8315140e, 0x0aad4fc1, 0x6e41bb8c, 0x870a2009, + 0x0aad4fa1, 0xad4f0820, 0x41a18a0e, 0x9d8a075b, 0x9389978e, 0x5100012e, + 0xe803ecff, 0x20004e04, 0x10b27d00, 0x480a2161, 0xd8440c23, 0x4b768208, + 0xb2230913, 0x8210081e, 0xb07c2fc1, 0xb4182f1e, 0x1e501e40, 0x03b25d02, + 0x1282001e, 0x031cb226, 0x0bb25d01, 0x1b200483, 0x73087e49, 0xb2230d98, + 0x82181b15, 0x04b43129, 0x02151415, 0x0131305d, 0x23150622, 0x33363634, + 0x20062e7b, 0x090b5723, 0x0805bc4f, 0x5501023d, 0xca74e576, 0x0b01dc72, + 0x7b91dc79, 0x76e56ec8, 0x0c7e6656, 0x5301acfe, 0x8b037e0e, 0xaf644f69, + 0xfcd2fe68, 0x88fc9b19, 0x5d75ba67, 0xa8899977, 0x00008f84, 0xff910002, + 0x823806ec, 0x001426e1, 0xb285001f, 0x21881815, 0x0c1a4910, 0x240c5467, + 0xb11b2f11, 0x796a1811, 0x13112111, 0x0120f584, 0xd029f582, 0x0201e001, + 0x0140b45d, 0x18068250, 0x200b4b44, 0x0c127c0c, 0x43180420, 0x01280d71, + 0x33243633, 0x17170032, 0x2605937e, 0x23112327, 0x18013311, 0x08096a69, + 0xcc840132, 0xcb0a011b, 0x0b1101db, 0x96e57b01, 0x15f3fed2, 0x01f3f3ca, + 0x88f68ab9, 0x8c77788d, 0xf8cf8702, 0x39e9e6fe, 0x018afca0, 0x3cfed404, + 0xd8fd3a04, 0x3008997e, 0x00270002, 0x04df0300, 0x000d003a, 0xb2610016, + 0x058d5314, 0xb0101423, 0x06914f04, 0x490c6544, 0x05200c61, 0x0520ef82, + 0xb223ef82, 0x82010012, 0x12b022e2, 0x0a0c652f, 0x0307b223, 0x20148312, + 0x0b285f00, 0x2a056f49, 0x13230323, 0x34352626, 0x4f033736, 0x3a080892, + 0xe7e3f2df, 0x6b64fffc, 0x65bcc6e9, 0x59e0ef4f, 0xfb3a046a, 0xfe8d01c6, + 0x2ab50173, 0xc197659c, 0x44a0fe02, 0x5a380155, 0xff010000, 0x034bfedb, + 0x000006f8, 0xb28b0021, 0x82232215, 0xb0002265, 0x057c461e, 0x200c9c41, + 0x06f57a0a, 0x687fb020, 0x2fac8208, 0xaf1e9fb6, 0x031ebf1e, 0x1e2fb25d, + 0x0fb25d01, 0x21220483, 0x44821e18, 0x2f21b022, 0x230afe68, 0x041802b2, + 0x11f34518, 0xd75d0420, 0x00b0280b, 0xd01ab010, 0x5e1021b0, 0x152406e0, + 0x13203336, 0x07d84118, 0x35323322, 0x08ff4518, 0x35234c08, 0x15333533, + 0xfe770221, 0x01b677f5, 0xa6b9055a, 0x270f3a46, 0x5e617b3b, 0x9ef34892, + 0x0b01f39e, 0x8ae9ad04, 0xfefc75fe, 0xbf11c4b2, 0xed02bf0d, 0xfc825d70, + 0xabad04fb, 0x0100a8a8, 0xecff5400, 0x4e04f903, 0x7a001d00, 0x181e16b2, + 0x67097f8b, 0xff430c17, 0x08844e09, 0x0f19b222, 0x2609164d, 0x192f191f, + 0x43b27102, 0xb223095f, 0x821b0003, 0x04b426e0, 0x02031403, 0x5973185d, + 0x13b2230d, 0x1b821619, 0x131cb226, 0x0bb25d01, 0x30210482, 0x6a731831, + 0x214c0818, 0x02122115, 0x0678593e, 0xca7803e4, 0xf8fee474, 0xc0e40801, + 0x07e404f5, 0x7d6e5b76, 0xfe5b010a, 0x68ae19a6, 0x64b06650, 0x02012701, + 0x2901f719, 0x7560b6e2, 0xfea88d94, 0x020000ec, 0x00001e00, 0x3a049a06, + 0x1f001600, 0x09b27900, 0x20056d43, 0x09515509, 0x450c7d42, 0x27660c92, + 0x7f012008, 0x01230566, 0x4600b02f, 0xc5730c5f, 0x4301200d, 0x08200c61, + 0x0dc76c18, 0x33110122, 0x23086d46, 0x07060203, 0x82060c4c, 0x32440816, + 0x26343536, 0xf8fa0327, 0xc3e9e5c3, 0xe6fe19fe, 0xafa81315, 0x5232024e, + 0x02140a47, 0x6858edf3, 0x3a045664, 0xbc0387fe, 0x02c1a09f, 0x87fe7603, + 0x01eef2fe, 0xaf0b05ca, 0xfdce01e3, 0x58c1fec5, 0x0151484d, 0x8620e782, + 0xb120e782, 0x1226e782, 0x82001b00, 0x876901b2, 0x73012005, 0x022409bb, + 0x02b11b2f, 0x6d14ab4f, 0xf4890c44, 0x110b1129, 0x01b03912, 0x8504b22f, + 0x2f042209, 0x0e5218b0, 0x04b0210c, 0x210b7843, 0x9e600bb0, 0x3130250b, + 0x33112101, 0x1123f38a, 0x87331123, 0x012325ec, 0xf3a50179, 0x5b2def87, + 0x9802f3f3, 0x64665aed, 0x019f025b, 0x25e8879b, 0x23fedd01, 0xdf833a04, + 0x464b5a32, 0x01000054, 0x0000eeff, 0x0006f803, 0x79001800, 0x08df4218, + 0x93431520, 0x82072012, 0x450720e7, 0xcd880723, 0x0115bf25, 0x832fb25d, + 0x830f2004, 0x0f182204, 0x20dc8315, 0x0d8f4318, 0x83070421, 0x46d68214, + 0x00270ad7, 0xd011b010, 0x601018b0, 0x814306b0, 0x43232005, 0x8b241078, + 0xb677e1fe, 0x08507218, 0xf38b8b29, 0xb5041f01, 0x18fe8af1, 0x34095572, + 0xa1aab504, 0x000100a1, 0x049afe86, 0x003a0412, 0x0045000b, 0x13d14ab0, + 0x180c6749, 0x22092652, 0x49b05845, 0x1e5912e4, 0x11232d09, 0x79011121, + 0xfef3a601, 0xb2fef3b5, 0x25055a49, 0x9afec6fb, 0xbd4d6601, 0xff882c05, + 0x05c106eb, 0x001e00b0, 0x1806b260, 0x5d0a8d46, 0x8a640c03, 0x778d180c, + 0x2f04240c, 0x1804b11b, 0x22108676, 0x6d040006, 0x1a210e25, 0x219283d0, + 0x6f680614, 0x35262405, 0x67113311, 0x9e8205ae, 0x38080886, 0xd2f9c106, + 0xe9716de5, 0x67fdf3cf, 0x0172695e, 0x61636d01, 0xfbb0056e, 0xa5eed6ff, + 0x04d5efa5, 0x75fcfb01, 0x04778182, 0x74fcfb03, 0x04797f83, 0x00010003, + 0x05ebff70, 0x94c882ed, 0x07d542bd, 0x840c1d4a, 0x0c254cbd, 0x1520bd91, + 0x0620bd95, 0xc688bd92, 0xed052608, 0xc7bdda01, 0xb8cb6660, 0x4654f3d5, + 0x5cf46653, 0x045b4a4f, 0xc14efd3a, 0xdd8e8edc, 0xfdaf02c3, 0x6c6c7251, + 0x31078972, 0xe0ff0200, 0x21040000, 0x12001806, 0x71001b00, 0x9b4315b2, + 0x10152105, 0x24082f62, 0xb11b2f0f, 0x07df550f, 0x2208e541, 0x46090f12, + 0x336f06f4, 0x02b22109, 0x02291485, 0x1000b02f, 0xb0d00bb0, 0x06215a12, + 0x4513b221, 0xb0210895, 0x118a4309, 0x26077c44, 0x11333523, 0x43211133, + 0x4108078a, 0xfea30227, 0xe5c4f7de, 0x12fec0e5, 0x01f3aeae, 0xeddefe22, + 0x5763655b, 0xc9fe3a04, 0xadaece03, 0x3a0404d3, 0xfe3301ab, 0xfe5bfdcd, + 0x55596582, 0x01000269, 0xedff9800, 0xc505cd06, 0x8e002500, 0xf7780eb2, + 0x8224200a, 0x182420c5, 0x870ccb67, 0x0758590c, 0x4500b025, 0x8222b058, + 0x0f222726, 0x00b2593e, 0xdf832422, 0xb22f002a, 0x7101001f, 0x1c2408b2, + 0x05200e83, 0x820c7b5b, 0xd00f21e4, 0x605eea82, 0xd012230b, 0x25471cb0, + 0x18b2210b, 0x30223984, 0x5f580131, 0x17002205, 0x055a5923, 0x2608dd66, + 0x23000633, 0x48022422, 0x580806d7, 0x960bb594, 0xf1ab0901, 0xfc182601, + 0xa18e9312, 0xe9010bab, 0xa80216fe, 0x149695a2, 0xd3fe16fc, 0xf8feacf8, + 0xfcb40393, 0xbe4f03fc, 0xfe9b1d01, 0x8b9deffa, 0xe1c3ccdd, 0xe99c86f2, + 0x01a1fbfe, 0x74fdca34, 0x0000b005, 0xff860001, 0x04ba05ec, 0x0023004e, + 0x240db292, 0x08c76125, 0x200c2448, 0x20ef8223, 0x07884223, 0x07224c18, + 0x4500b025, 0x8220b058, 0x0f202719, 0x0eb2593e, 0x61591b04, 0x0e402a08, + 0x5d020e50, 0xb0d000b0, 0x0b6c6004, 0x0e08b223, 0x2223820b, 0x57100eb0, + 0xb0210a05, 0x0c24681b, 0x0f131622, 0x0f262283, 0xd01eb010, 0xd4493130, + 0x41162005, 0x0320050c, 0x24090b41, 0x2223020e, 0x060a4124, 0x149d7926, + 0xc1d20401, 0x28054c47, 0x7c011adb, 0x7d0a85fe, 0x076a476e, 0xfed32d08, + 0xf39e14fd, 0xde7102f3, 0x60b6e2ff, 0xabe6fe75, 0x50688e8a, 0xfe64b066, + 0x043afedc, 0x0200003a, 0x00001c00, 0xb0051705, 0x0e000b00, 0x20072566, + 0x20d58208, 0x07f94108, 0x650ccc53, 0x0d221580, 0xb5830208, 0x89630d20, + 0x840e200f, 0x077c6317, 0x21032008, 0x21013301, 0x03032101, 0x73e17e83, + 0x02fafe8f, 0x0002f506, 0xe0fdfafe, 0x01a85301, 0x8356feaa, 0xb0052703, + 0x680250fa, 0x9983f801, 0x00000a24, 0xa4824504, 0x10000b22, 0xd854998c, + 0x21999614, 0x99860802, 0x230a9e5e, 0x0fb2d004, 0x2320998d, 0x03829982, + 0x07270339, 0xc35de402, 0x01f7685b, 0xab01e7a9, 0xf85cfef7, 0x01191964, + 0x83e9fe17, 0x3a043903, 0xc401c6fb, 0x64640601, 0xac000200, 0x30070000, + 0x1300b005, 0x7c001600, 0x18054b53, 0x180cde87, 0x450c156b, 0xb0201479, + 0x840b987a, 0x0845690c, 0x04021522, 0x200c027d, 0x09184406, 0xb0d00a29, + 0x0eb01006, 0x8416b2d0, 0x31302323, 0xbb822101, 0x23032123, 0x22018211, + 0x68132103, 0x23080536, 0xa8010321, 0x2b016801, 0xfe0002f5, 0xe27e8efa, + 0xfafe8f72, 0xfcdbfe98, 0x016202fc, 0x6702a953, 0x50fa4903, 0x2a077141, + 0x55feab01, 0xb8fcb005, 0x8200f901, 0x009d26d7, 0x04180600, 0x22d7823a, + 0x8a7f0018, 0x077341d7, 0x9345d784, 0x21d79a1c, 0xee4b1000, 0xb02f2305, + 0x3367d001, 0xd00b300b, 0xb0d007b0, 0x14b01001, 0xd015b0d0, 0x831217b2, + 0x24da82fe, 0x01331333, 0x21da8623, 0xd24c1323, 0x33210805, 0x01072703, + 0xe7f8fe90, 0x6af7ab01, 0x685bc35d, 0xf3ba6df7, 0xf8ed01f3, 0x01191964, + 0xfb7602c4, 0x07af41c6, 0x2105b341, 0xb1418afd, 0x82802006, 0x056e34d9, + 0x001a00b0, 0xb27a001d, 0x111f1e1b, 0x1bb03912, 0x180db010, 0x180b6758, + 0x910f7582, 0x6c1320cc, 0xb2220692, 0xa5831900, 0x2f00b022, 0x2c0b296e, + 0x0fb0d00e, 0x1000b0d0, 0xb2d018b0, 0x2020851b, 0x0ec66b19, 0x1716162a, + 0x26112311, 0x07232326, 0x23220782, 0x06830622, 0x36363f08, 0x01210121, + 0x7a042113, 0xfc05f1fe, 0x688f7602, 0x8f7efc06, 0x03fc0375, 0xfe0f01fa, + 0xfde40485, 0x2ffee98e, 0xd9042803, 0x018dfed8, 0x0b6f816c, 0x5c02affd, + 0x90fe7e6e, 0xdbe16c01, 0xe5828802, 0x0200a92a, 0x00008200, 0x3a046405, + 0xd76ae390, 0x82052007, 0x550520bc, 0x414a1442, 0x2ee3880c, 0x11000504, + 0x04b03912, 0xd007b02f, 0x591004b0, 0x5a6d0a14, 0x1bb22105, 0x05202085, + 0x3324e38d, 0x37363635, 0xea82cf82, 0x35231525, 0x88272626, 0x821520ea, + 0x823908e3, 0xfeccc502, 0xfef403eb, 0x02bec6ea, 0x725e01f3, 0x2df2012f, + 0x01036079, 0xd6fe9585, 0x0dd2ceb2, 0x24fedb01, 0xb3c7d311, 0x02727fb1, + 0x015ffe03, 0xba7c6ea4, 0x22016902, 0x30e18200, 0x080000a3, 0x00b005b3, + 0x00230020, 0x241cb297, 0x229f8325, 0x18b0101c, 0x6307c54e, 0x6a610c18, + 0x0cd0560c, 0x4f0c9449, 0x192a0c93, 0x19b11b2f, 0xb2593e0f, 0xfb840709, + 0xb04e0920, 0x09b0300b, 0xd00db010, 0xb01003b0, 0x17b0d01c, 0x8521b2d0, + 0x5f0b2023, 0x212a0d32, 0x21373411, 0x33112311, 0x04412111, 0x0fef4105, + 0x21130131, 0xfe3bc502, 0x03fcfc9f, 0x0487fe30, 0x4184fee5, 0x053807f5, + 0x73917ffc, 0xe9080203, 0x60012efe, 0x9afd65a1, 0x7bfdb005, 0x78fd8502, + 0x3708f841, 0x02adfd09, 0xfe7c715c, 0x01390391, 0x020000aa, 0x00008f00, + 0x3a047607, 0x20061141, 0x0511411d, 0x11411d20, 0xae74180e, 0x30114114, + 0x11410b20, 0x09815108, 0x850f1141, 0x0f114123, 0x41363521, 0x16420d11, + 0x95023712, 0xb7fe3501, 0xa502f3f3, 0xf403ecfe, 0xbec5eafe, 0x5e01f202, + 0x1c422e73, 0x94b02f0a, 0x0458fe64, 0x0127fe3a, 0x1124fed9, 0x2142c6d4, + 0xfe283014, 0x07aa0340, 0x00270088, 0xb2a70030, 0x63323102, 0x28240685, + 0x2cb000d0, 0x24056d4c, 0xb11b2f05, 0xc8661805, 0x076e570c, 0x20080a42, + 0x0c0e6205, 0x11052622, 0x7c2b4582, 0x182f26b0, 0x012610b2, 0x8240b25d, + 0x60b42604, 0x02267026, 0x0ae37e5d, 0x230cb223, 0x22278226, 0x181011b0, + 0x320a0d55, 0x012c0fb2, 0x102cb05d, 0xb0d029b0, 0x0fb42f29, 0x82291f29, + 0x2c282234, 0x33298329, 0x30b0d030, 0x0131302f, 0x21232634, 0x04322135, + 0x07061415, 0x04380482, 0x15062323, 0x26071714, 0x36342726, 0x36363337, + 0x23213435, 0x03203335, 0x07ff4c18, 0x96024c08, 0xe5fe7a85, 0x01ed1501, + 0x016e7d0b, 0xe8f7fe0c, 0x52987a35, 0xb102a284, 0x89723fa4, 0x8989cffe, + 0x93941001, 0x97eafecf, 0x04ceebfe, 0xc76a5e21, 0xa370b5cf, 0xc5fe572c, + 0x6b6303e8, 0xb7289941, 0x028b867f, 0xf3657d01, 0x189f03c7, 0x2e07404d, + 0xfe330002, 0x06880348, 0x0027001c, 0x41950030, 0x4e421a3b, 0x2f172407, + 0x4117b11b, 0x1220073b, 0x12250c82, 0xb0593e0f, 0xc6661805, 0x1225220c, + 0x29e98205, 0x2f25b07c, 0x2540b418, 0xfc822550, 0x3e422420, 0x0cb22108, + 0x2005af42, 0x0b314112, 0x21112c41, 0x2c412c29, 0x09294105, 0x14151624, + 0x04830706, 0x200d2941, 0x06294132, 0x29413220, 0x74640809, 0xe4fe6973, + 0xf8dc1701, 0xf6d95761, 0x907e36d0, 0x02968251, 0x6c35a1a9, 0x91f9fe77, + 0x92a0e295, 0x96e9fed0, 0x02cdebfe, 0xb9473cfe, 0x774f8da5, 0x96ac4224, + 0x6b6204af, 0xb6309141, 0x01877d70, 0xa9943f50, 0x0b9b1203, 0x1701eafe, + 0x0300000a, 0xecff5f00, 0xc4051705, 0x17001000, 0x66001e00, 0x201f04b2, + 0x04259e83, 0xd011b010, 0x200582b0, 0x06514618, 0x480c8a4d, 0x0c200803, + 0x230be05f, 0x0c0414b2, 0x7c243b82, 0x182f14b0, 0xfe713a82, 0x1014230b, + 0x27411cb2, 0x56531808, 0x0420330e, 0x22011712, 0x26210706, 0x36320326, + 0x16162137, 0x48181705, 0xfd33115b, 0x08b6a0a4, 0xb408bc02, 0x0ab39fa0, + 0xb80a44fd, 0x18d6b202, 0x2b0f6048, 0xd9f0ef01, 0xcafbeedb, 0xead9dee5, + 0x4f30db83, 0x3d04ecff, 0x0f004e04, 0x1d001600, 0x04b26700, 0x82052747, + 0x841020d5, 0xcd5018db, 0x0c1f4b07, 0x5608ab66, 0xb22109ef, 0x2bd8861b, + 0xb4182f1b, 0x1b501b40, 0x13b25d02, 0xea83ce88, 0x2509ba77, 0x34133130, + 0xbd543636, 0x0111210a, 0x1320d485, 0x4608e285, 0x94e47d4f, 0x0b1301da, + 0x95e77b01, 0x01ecfee3, 0x10856bf7, 0x8410fffd, 0x10856a6b, 0x85100002, + 0xfda12702, 0xeae7fe89, 0x8afca039, 0x01012e01, 0x899293fe, 0xdd029388, + 0x95828295, 0x00010000, 0x04000010, 0x82c205f3, 0xb24622d3, 0x0a175e02, + 0x0c5e4818, 0x1b2f0f24, 0x73180fb1, 0x01271045, 0x12110f0c, 0x1806b039, + 0x220eff40, 0x82133717, 0x172c08b0, 0x07062307, 0x21012301, 0x1b1b6102, + 0x7a9c35e4, 0x5418022d, 0xf498fe27, 0x0d010efe, 0x6f728b01, 0x97acf702, + 0x7c02d701, 0xb00594fb, 0x20208782, 0x18258782, 0x11004e04, 0x6c878200, + 0x05200ac3, 0x610b9547, 0x407a0c83, 0x05012208, 0x06594d0e, 0x0b4a0a20, + 0x31302208, 0x27878201, 0x17323312, 0x22232607, 0x3a088984, 0x14e30133, + 0xcf5a7a14, 0x0c172743, 0x0d3b2220, 0xfed3f6fe, 0x6e01fb92, 0xbe016161, + 0xc0162201, 0xfc2a3606, 0x003a04e2, 0xff5f0002, 0x06170576, 0x0013002e, + 0xb2550027, 0x85292805, 0x0805785e, 0x5e0c5466, 0x0626089f, 0x100db0d0, + 0x058310b0, 0x881ab221, 0x17b02488, 0x1803b0d0, 0x820b407d, 0x369c8245, + 0x15070010, 0x00263523, 0x00103503, 0x15333537, 0x27110016, 0x82272634, + 0x06062613, 0x16141515, 0x08138217, 0x3536364b, 0xf3fe1705, 0xfee8c6e9, + 0x120103ef, 0x01eac6e9, 0x7882fd0d, 0x848579c6, 0x8079c67b, 0xdafeb202, + 0x7e238bfe, 0x7301237e, 0x01551d01, 0x237a0124, 0xfe237271, 0x06d9fe86, + 0x6023f5ce, 0xcff52361, 0x25fdc74c, 0xf6235f60, 0x26d582cf, 0x0488ff4f, + 0x82b4043d, 0x002526d5, 0x2603b258, 0x20d58327, 0x09c95903, 0x580c9851, + 0x20820881, 0x1024d882, 0xd00db010, 0x200e4b5d, 0x20d88414, 0x26e9891d, + 0x3130d01a, 0x84123413, 0x821220ce, 0x840220c4, 0x350222e2, 0x88c88201, + 0x08da84db, 0xbddd4f55, 0xdfddbfb8, 0xddbbb8bf, 0x5a525002, 0x4fb8505a, + 0xb84f5658, 0x01da2702, 0x6d6e1f26, 0xddd8fe1f, 0xd9fedb11, 0x1f6c6b1d, + 0xfedd2601, 0x97b51ea7, 0x601fb282, 0x95b22160, 0x6821ae83, 0x00030000, + 0x06ebff88, 0x003f07b5, 0x003d002a, 0xb2ba0046, 0x83484730, 0x103025cf, + 0xb0d009b0, 0x45200582, 0x51066744, 0x784c0cff, 0x0c49530c, 0x1b2f0b22, + 0x7f058861, 0xb0210518, 0x0ffc5312, 0x2309d141, 0x120b1eb2, 0x23276a83, + 0x1013b0d0, 0x82d02ab0, 0x36b02e2b, 0x2f36b0d0, 0xb0d02cb0, 0x2bb22f2c, + 0x114f1808, 0x2cb02a07, 0xd032b010, 0xb22f32b0, 0x2e138c39, 0x42b0d042, + 0xd046b02f, 0x302f46b0, 0x18320131, 0x2c07f35c, 0x26222306, 0x36341127, + 0x06221533, 0x07565215, 0x11333f08, 0x32331616, 0x34113536, 0x15132326, + 0x022e2223, 0x15152223, 0x33343523, 0x01021e32, 0x33353736, 0x07061415, + 0xf2cef404, 0xe3d0f101, 0xcee37272, 0xcff304f0, 0x5f66665f, 0x01f57269, + 0x09836871, 0x216a5a08, 0x30bf8a53, 0xeb866814, 0x6fc94625, 0x034129fe, + 0x053b60a9, 0xfdddfab0, 0x9efbddea, 0x02d5f69e, 0xccfddd20, 0xedfd808e, + 0x77818e80, 0x79fe8201, 0x808e8073, 0x8e801302, 0x2386e301, 0x10680a4b, + 0x4f0fdc22, 0x5287fe1a, 0x3167683c, 0x00001f78, 0xff740003, 0x05d105eb, + 0x067f41e3, 0x09b2af22, 0x25057f41, 0x3ab01009, 0x0582b0d0, 0x7f414620, + 0x0c134d06, 0x3408484b, 0x00b01012, 0x2f00b0d0, 0xb0100bb0, 0x09b2d007, + 0x12110b12, 0x35744139, 0xb0d02d23, 0x0c74412d, 0x74412d20, 0x10362612, + 0xb0d041b0, 0x0c744141, 0xc5531520, 0x08744108, 0x16141526, 0x37363233, + 0x2107d979, 0x74413535, 0x3a4d081d, 0xd401dcba, 0x6361c5b5, 0x04d3b2c2, + 0x5b49bbdc, 0x5e504353, 0x5e01ec01, 0x5b544251, 0x5324bd49, 0x152cc18a, + 0x25eb8768, 0xfe70c546, 0xa9034130, 0x47043b60, 0xccf8cce5, 0xe09191e7, + 0xcd0301c5, 0x7c75c3e7, 0x70757cf5, 0x6acaca6a, 0x2e0a8470, 0x2386e701, + 0x1068094c, 0x4e0fdc22, 0x4185fe1b, 0x02300770, 0xebff8800, 0x1107c106, + 0x26001e00, 0x06b27d00, 0x20054369, 0x09c94a06, 0x570c9344, 0x042508e7, + 0x0806b2d0, 0x06b5650d, 0xaa431120, 0x100d2c09, 0xb0d015b0, 0x11b02f15, + 0x821ab010, 0xb0102708, 0x1eb0d01e, 0x1782b02f, 0xb0d0252c, 0x26b02f25, + 0x2f26b0d0, 0xb64220b2, 0x83262009, 0x23b0226a, 0x20fe542f, 0x21352527, + 0x23152117, 0x14065535, 0x0339fc27, 0xa6fe0155, 0x1b0e55b5, 0x7a7ae726, + 0x02007f7f, 0x21051355, 0xf184b105, 0xf18a8920, 0x59422520, 0x49f18406, + 0x0e55076c, 0x2f1e240c, 0x4f1eb11b, 0xb2231c87, 0x55150806, 0xfd8910d9, + 0xb0d01f23, 0x20fd8c1f, 0xae4c181f, 0x11012108, 0x871c3e55, 0x144655fd, + 0x039dfc27, 0xb2fe0438, 0x1b4e55b5, 0x7b7bfc22, 0x012efd82, 0x8cfe6600, + 0xc505b604, 0x53001800, 0x0f7c17b2, 0x180a200a, 0x200b3fa9, 0x200c8200, + 0x10cb7600, 0xb0100a26, 0x0ab0d00e, 0x200cef7b, 0x0bbd5902, 0x01313032, + 0x00261123, 0x12341135, 0x00203324, 0x21102315, 0x08057144, 0x03331730, + 0xffd3fb34, 0x01018d00, 0x010001a3, 0xddfefc1f, 0x8aa9a98c, 0x018cfe9f, + 0x47012066, 0xaf1101f9, 0xfe9b1801, 0x2601e9f7, 0xedfebcdf, 0x2482dfb6, + 0xfe5c0029, 0x04f30389, 0x821a004e, 0x7e1920a9, 0x5d5f0a43, 0x20a9980c, + 0x18a9840f, 0x820ad8a3, 0x7c9718a9, 0x28a98509, 0x34353502, 0x32333636, + 0xec431816, 0x1737080b, 0xf3d50233, 0xdb79d3b3, 0x6fc67c92, 0x715874e5, + 0x98707e82, 0x6a0189fe, 0xdc230120, 0x89fc9b1c, 0x5b76bb67, 0x1ba8bd7a, + 0x0002bba1, 0x006d0001, 0x05930400, 0x8213003e, 0x0eb02101, 0x220a5859, + 0x82593e0f, 0x07052865, 0x13230325, 0x84053725, 0x03332103, 0x49080f82, + 0x21015b02, 0xb5ddfe48, 0xdffee1af, 0xca250147, 0x0149defe, 0xe4acb923, + 0xfe4c2501, 0xacc101e0, 0xc1feaa80, 0x80ab8e01, 0xab6801ab, 0x4601ab82, + 0x7fab6bfe, 0xfc0100aa, 0xffa20466, 0x00fd0539, 0x00110007, 0xb22f00b0, + 0x0f460603, 0x37678207, 0x21372715, 0xfd151727, 0x0201b117, 0x05b10122, + 0xee017e20, 0x00dc016c, 0x73363782, 0x6dff1705, 0x0f001506, 0xb0002e00, + 0x07b02f0b, 0x2f07b0d0, 0x824300b2, 0x100b2c09, 0xb0d004b0, 0x0bb02f04, + 0x880cb210, 0x08548216, 0x15153227, 0x23343523, 0x23070422, 0x24363335, + 0x88ee7ffe, 0xe2fe366a, 0x7927298b, 0x15061801, 0x681022dc, 0x01860177, + 0x35658277, 0x16057bfd, 0x600672fe, 0x0c000500, 0x2f01b000, 0xb0d005b0, + 0x43822f05, 0x07333534, 0x7bfd0717, 0x523b01bd, 0x9684dc05, 0x01004470, + 0x2b82a5fd, 0x2b879c20, 0x452f0321, 0x2b8205b2, 0x2737273a, 0xf7fd1533, + 0xbd013b52, 0x70441605, 0x08008496, 0xc4fe24fa, 0xaf05bf01, 0x1a385582, + 0x35002700, 0x4f004200, 0x6a005c00, 0xb0007a00, 0x53b02f45, 0x2f60b02f, + 0x07d4b018, 0x18070b54, 0x2a0bf557, 0x10b01045, 0x1045b0d0, 0x47094cb2, + 0x1726083d, 0x1053b0d0, 0x05831eb0, 0x895ab221, 0xd0252616, 0xb01060b0, + 0x2105832b, 0x168967b2, 0xb0d03226, 0x3fb21038, 0xa7821088, 0x32363422, + 0x23083142, 0x33363401, 0x13200d89, 0x22200d88, 0x08ebb018, 0x26342323, + 0x8c0d8523, 0x860c8c35, 0x89268242, 0x3f348341, 0xbe7311fd, 0x30337074, + 0xde01332e, 0x755f5d74, 0x2c2e3571, 0x5d754833, 0x3570745f, 0xcbfe335c, + 0x09821382, 0x332d2e24, 0x28874ffd, 0x744dfd22, 0xfe213286, 0x202887de, + 0x83088235, 0x332d333b, 0x6854f304, 0x372e5468, 0xebfe3035, 0x55676854, + 0x09823431, 0x6755092a, 0x34315468, 0xf9fd2e37, 0x09831d83, 0x85e4fe21, + 0x2e372327, 0x31881a05, 0x5521278a, 0x083b8567, 0xfa08002d, 0x0163fe4d, + 0x00c6058c, 0x00090004, 0x0013000e, 0x001d0018, 0x00270022, 0x21b0002f, + 0x2f16b02f, 0xb02f12b0, 0x1bb02f0b, 0x4326b02f, 0x2e52051e, 0x0239080c, + 0x02b11b2f, 0x30593e11, 0x03170531, 0x27031323, 0x01033313, 0x25150537, + 0x35250705, 0x25370105, 0x07010517, 0x03252705, 0x13370327, 0x07131701, + 0x0b50fe03, 0x3a46607a, 0x0804820c, 0x0d1d023c, 0xa6fe4d01, 0xfe0d75fb, + 0x035a01b3, 0x4001029c, 0xfcdbfe44, 0xc0fe02f3, 0x2b260145, 0xc6419411, + 0x94116003, 0x0e3cc442, 0x6101adfe, 0x010ea204, 0xfea0fe52, 0x627c0c11, + 0x04833b47, 0x10ae013c, 0xfcc84499, 0x4599118e, 0x02e402c8, 0xfe454601, + 0x02e3fcd5, 0x0147bbfe, 0x815a002b, 0x00622608, 0x001b0012, 0x12815a74, + 0x7b0c1d47, 0x8e5a0c4b, 0x11b02107, 0x0bbb4918, 0x0d02b223, 0x082c7509, + 0xd00bb027, 0xb0d00cb0, 0x0c124a02, 0x221d845a, 0x5a153335, 0x05232084, + 0x5afefd05, 0x05260584, 0xb2b2ab05, 0x825a90fc, 0x02002b07, 0x00009400, + 0xb005d904, 0xcf820e00, 0x04b24d22, 0x2005515b, 0x09d55f04, 0x670c7276, + 0x162708a6, 0x12110103, 0x5816b039, 0x03200c6a, 0x340e2d5b, 0x21112311, + 0x14150432, 0x27071707, 0x36132306, 0x27263435, 0x3c128221, 0x01372737, + 0x2d02fd91, 0x751f01f4, 0x79886d7a, 0x901cf9aa, 0x01c9fe7e, 0x733a4f30, + 0x5a9d186e, 0x77c13207, 0x37966487, 0x4a354301, 0xfe028d76, 0x64801604, + 0x18ad8200, 0x2807798c, 0x00220013, 0x2317b26e, 0x05897b24, 0x4710b021, + 0x546806a9, 0x0cb6470c, 0x61620a20, 0x5e07200b, 0xb22306da, 0x82071009, + 0x0eb22141, 0xb0210684, 0x0c786010, 0x4d550720, 0x8601200d, 0x272221c7, + 0x3322d782, 0x95183617, 0xd3820d69, 0x0436172c, 0x6f6a6e30, 0xb2705968, + 0x8c18f36b, 0x462e0c85, 0x596e6a32, 0xf4120222, 0x78637a97, 0x8c187536, + 0x2136108c, 0x5867647b, 0x8f000100, 0x34040000, 0x07001007, 0x01b23200, + 0x055b0908, 0x10085a0d, 0x31142071, 0x34043311, 0x02fd58fd, 0xe404f3b2, + 0xb0051cfb, 0x57826001, 0x00007e26, 0x73055b03, 0x2b205782, 0x7112336e, + 0x11291d71, 0xfe5b0333, 0xeb01f316, 0x05b66bf2, 0x00390122, 0x9b2e5182, + 0x9d04c6fe, 0x1400b005, 0x0fb25b00, 0xa9841615, 0xcb430920, 0x0c087605, + 0x2008c853, 0x0cb27f13, 0x83130321, 0x03b027dc, 0x1009b02f, 0x8f500ab2, + 0x10032109, 0x600a6965, 0x3a0805fa, 0x10110020, 0x32272300, 0x25023536, + 0x11231123, 0xfd370421, 0x2201a860, 0xf6fe3c01, 0x888301f3, 0xbcabfe02, + 0x049c03fc, 0xfe5ffee4, 0xfeecfecd, 0xbad6fef4, 0x7b01c2b3, 0x8287fd09, + 0x0001309f, 0x03e2fe7e, 0x003a04db, 0xb24a0015, 0x8417160b, 0x850a20a9, + 0xcb4818a9, 0x0836530c, 0xa98d1420, 0x820a1421, 0x20a98232, 0x095451b2, + 0x152e9883, 0x15002033, 0x07060614, 0x34353627, 0x99842326, 0x46032208, + 0x01492bfe, 0x5e200101, 0xde5573ab, 0xf34e8e9b, 0x7603c802, 0xddfafee5, + 0x1d8dc260, 0x81d44aae, 0x05ed5b97, 0x90000126, 0x36050000, 0x14229f82, + 0x637a6100, 0x0cb15212, 0x720cf85b, 0x0f2208bf, 0x97830c0a, 0xb22f0f26, + 0x5d010f9f, 0x230a4676, 0x0f0801b2, 0x05311983, 0x100fb0d0, 0x30d012b0, + 0x21020931, 0x23152301, 0x08a38335, 0x33113327, 0x33153335, 0xfe0d0501, + 0xfead017c, 0x41d3fec1, 0xfdfd59a3, 0x0137a359, 0xfdb0051b, 0x02f5fc5b, + 0xfde9e96d, 0x330b8293, 0x02fefe9a, 0x01000066, 0x00008e00, 0x3a04ae04, + 0x5c001400, 0x5743ab85, 0x0c44410c, 0x0cab4e18, 0x59180320, 0xf67607cd, + 0x18b02005, 0x220c1075, 0x510901b2, 0xd022054a, 0xa6880eb0, 0xa68e0320, + 0x04132608, 0x01c4fe94, 0xd8cbfe56, 0xf2579b2f, 0x279b57f2, 0xfd3a04cf, + 0x01c8fdfe, 0xfeb2b2ac, 0xfe3a0454, 0x01c7c750, 0x28a382b0, 0x06000034, + 0x00b005a2, 0x074f410e, 0x4a0c5452, 0x4f410cc9, 0x2bca840c, 0xb2593e0f, + 0x11020608, 0x08b03912, 0x200ba976, 0x086e18b0, 0x0cb2230c, 0x40180801, + 0x2b0809c3, 0x11213521, 0x01210133, 0xb6032101, 0x27fefcad, 0x018bd502, + 0xfe3601ad, 0xfe1f020c, 0xfd7002d0, 0xc4ec0490, 0x64029cfd, 0x09fd47fd, + 0x3d269f82, 0xa8050000, 0x9f823a04, 0x43416b20, 0x0ce96e05, 0x950cbf4a, + 0x0a09219f, 0x09299f84, 0x092fb22f, 0x8cb27101, 0x0de87309, 0x0021a98e, + 0x08a99409, 0xf27b4020, 0x88026afe, 0x012a016c, 0x0178fe2d, 0x01c5fea8, + 0x0354feac, 0x50fec476, 0xf9fdb001, 0xa982cdfd, 0x0000942a, 0xb0058307, + 0x87000d00, 0x42124f5d, 0xeb5d0c99, 0x02012215, 0x06ee6406, 0x82019f21, + 0x016f21a4, 0xdf20ae82, 0x0f240483, 0xb2720101, 0x71221382, 0x0e823fb2, + 0x012fb428, 0x7202013f, 0x24827cb2, 0x5602b021, 0xb0210baa, 0x0ee65301, + 0x21112124, 0x79752115, 0x33113905, 0x8b029101, 0x95fd6703, 0xfd75fdfc, + 0x025203fd, 0x13fbc35e, 0x79fd8702, 0x26054760, 0x0500007e, 0x823a0466, + 0x5d6620bd, 0xd6621235, 0x20bd960c, 0x25bd830c, 0x2f01b07c, 0xfb69b418, + 0x329cac05, 0x02a50171, 0xf3a3fe50, 0xf3f35bfe, 0xc3017702, 0x718afcc4, + 0x0027054d, 0xfe9b0001, 0x82ef07c4, 0x00162ca6, 0x1710b268, 0x39121118, + 0x4407b000, 0x20640589, 0x6d49180c, 0x45002208, 0x8a531858, 0x01b22308, + 0x56410715, 0x07b02405, 0x4508b210, 0x49660932, 0x5615200d, 0x30230bd5, + 0x45330131, 0x1126103e, 0x05211123, 0x40457d14, 0xfc91280c, 0x04fc7ffd, + 0x45410379, 0x89200e41, 0x82054346, 0xfe7e2cbb, 0x04ba06e6, 0x0018003a, + 0x4e12b257, 0x72650623, 0x8c771806, 0xbf56180c, 0x45bb8209, 0xb2230752, + 0x85081701, 0x0add45bb, 0x6a17b021, 0x50450e6d, 0x09514509, 0x042fac83, + 0x07017d0a, 0xab5d2c01, 0x69755573, 0x727f9aa5, 0x02310543, 0xdefbfe94, + 0x1d8ebf61, 0x678f28ad, 0x36fe9782, 0x05127803, 0x00020033, 0x05ebff67, + 0x00c505d7, 0x00320025, 0x3316b285, 0x227b8334, 0x18b01016, 0x4907ad7a, + 0x1d240ca1, 0x1db11b2f, 0x27116e5e, 0x2f00b0d0, 0x1d0402b2, 0x18069949, + 0x200c8082, 0x0f596ab0, 0x4418b220, 0xb027091c, 0x29b01002, 0x181db0d0, + 0x2b0dc0bb, 0x06272205, 0x02242223, 0x12343527, 0x27057353, 0x33121415, + 0x11263732, 0x332d1082, 0x15111232, 0x33160710, 0x17161401, 0x08118236, + 0x2223266e, 0xd7051506, 0xb794b3df, 0xa9d4febb, 0x8ce17d03, 0xb2db7e66, + 0xede22931, 0xbbf3c2b8, 0x8efd6a5c, 0x60a26365, 0x155e5458, 0x01ae4747, + 0xafc9bf36, 0xd4a11e01, 0xd7b8bde1, 0xcb07f9fe, 0xf0cb4401, 0xbffe3501, + 0xfec6fafe, 0x0214cada, 0x48d58419, 0xd509018f, 0xa1afabae, 0x61000200, + 0xc904ebff, 0x22004e04, 0x8c002e00, 0x302f04b2, 0x5d063359, 0x0b2207b9, + 0x11751b2f, 0x821a2009, 0x501a200c, 0x002014de, 0x00271982, 0xb2593e0f, + 0x411a0402, 0x0b200624, 0x680c6f64, 0x00240dd3, 0x0322b210, 0x29086e4d, + 0x25b01002, 0x101ab0d0, 0x27522bb2, 0x31302108, 0x26052441, 0x34351100, + 0x56153312, 0x3322059a, 0x88182637, 0x15280728, 0x33160714, 0x36171401, + 0x5e081082, 0x06222326, 0xbac90415, 0xe5907a93, 0xaadbd4fe, 0x7d9a4b40, + 0x94b68f25, 0x4d81bd96, 0x780efe58, 0x32313d63, 0x3936123b, 0x04014201, + 0x0c01cf42, 0x7b9404ca, 0x02cca649, 0xbb7ae295, 0x77cdffea, 0x011194d3, + 0x636caa8f, 0x876b7ba9, 0x01006a78, 0xa1fe2d00, 0xb005b706, 0x4f000f00, + 0x430db000, 0x7c630592, 0x07254211, 0x080b7318, 0x52180220, 0x05240cd6, + 0x100eb0d0, 0x080bca7e, 0x30d00a2b, 0x35210131, 0x11211521, 0x11331121, + 0x11230333, 0xfe8d0121, 0xfebe03a0, 0xfc81029f, 0xfbe714b0, 0xc4ec04d1, + 0x04defbc4, 0xff4218e6, 0xfe262609, 0x043a05bf, 0x208b823a, 0x578b884b, + 0x0f200c2f, 0x07075f18, 0x34450320, 0xd000230c, 0x7e8c0fb0, 0xb0100328, + 0x06b0d008, 0x8784b010, 0x87822320, 0x87887f82, 0x02f51b25, 0x7301dbc3, + 0x032606bf, 0xfdc3c377, 0xc173034b, 0x00802c0a, 0x05e10400, 0x001800b0, + 0x4305b24f, 0x551806ef, 0x084108ef, 0x0cd75f07, 0x29071541, 0x000e05b2, + 0xb0391211, 0x7e832f05, 0x4b180520, 0x11290c6a, 0x013130d0, 0x16171611, + 0x21878217, 0x04823736, 0x06112323, 0x05845e07, 0x01113e08, 0x354f027d, + 0x646ca36e, 0x7060fdfd, 0x01faf6a3, 0x2cfeb005, 0x05273998, 0xdcfe2b01, + 0xa702190a, 0x3c0250fa, 0xe5eb0a18, 0x01dfea06, 0x000100cd, 0x03000074, + 0x003b04f5, 0xb2510016, 0x064f4506, 0xa053a383, 0x0cf2450c, 0x2108be4c, + 0xee5b010f, 0x2f0f2205, 0xf9551818, 0x04b0210a, 0x20083349, 0x20988a21, + 0x86b18233, 0x032708af, 0x3145f3f5, 0x01beb6a3, 0xa38201f2, 0x01f33b3b, + 0x8a050e69, 0xb1d0138b, 0xb0fe5001, 0x0b011fac, 0x0e06effe, 0x82000c02, + 0x00852c9d, 0x05e50400, 0x001100b0, 0x5a05b246, 0x83840a65, 0x5f074141, + 0x1f4e0cfa, 0x05b22207, 0x06414101, 0x220a9c63, 0x83333130, 0x20332283, + 0x06b66204, 0x1107222a, 0xb2a0fc85, 0x0c010501, 0x08cd4418, 0xc3fd2208, + 0xfee9e629, 0x8bd00133, 0x59fd2a76, 0x00020000, 0x05e9ff16, 0x00c405bc, + 0x0024001c, 0x2516b264, 0x060b4526, 0x2307ed43, 0xb11b2f0e, 0x08927418, + 0x2208d343, 0x830e001e, 0x2f1e2227, 0x0a2d53b2, 0xb0d00428, 0x0ab0101e, + 0x5718b0d0, 0xb0210cbe, 0x0d74610e, 0x0020052e, 0x26263511, 0x17143335, + 0x17241234, 0x6b080d82, 0x14152115, 0x37323316, 0x01060617, 0x26343521, + 0x03062223, 0xfed2fedc, 0xb5a79baa, 0x0801948d, 0x0108019e, 0xcb98fc22, + 0x31acb1bd, 0x05fed843, 0x949a6c02, 0x0117b08e, 0x3c2b0154, 0xb6aad418, + 0x1c01ae2a, 0x9cfe01a0, 0x3584b9fe, 0xc546d7ca, 0x6c032e28, 0xddc0b81f, + 0xcbff0200, 0x8b04ecff, 0x1a004e04, 0x8c002100, 0x232220b2, 0x2020b583, + 0x4a09675a, 0xdd880ca8, 0x0d001c22, 0x1c332783, 0x1cbfb42f, 0x5d021ccf, + 0x6f1c5fb4, 0xb471021c, 0x822f1c1f, 0x8fb22806, 0xb45d011c, 0x83ff1cef, + 0x4711200b, 0xfe820967, 0xfe871c20, 0xb6441520, 0x17b22108, 0x0d214c85, + 0xb9ab1810, 0x2205240c, 0x41272724, 0x36280505, 0x12323324, 0x16211511, + 0x08090341, 0x22262631, 0xd4d80206, 0x0314e6fe, 0x68a98682, 0xbb07011f, + 0x3dfdf1dd, 0xa8779d0b, 0xda418467, 0xcf016dfe, 0x7aca7208, 0x32d1fb14, + 0x9593c11d, 0x18f3c530, 0x360a5ea1, 0x7a129602, 0x00008c7d, 0xfe900001, + 0x05ed04bf, 0x001600b0, 0x4215b266, 0x102006ff, 0x1805bc44, 0x440c5453, + 0x0f3a11c9, 0x07b2593e, 0x12110204, 0x07b07c39, 0x00b4182f, 0x02071007, + 0xd00ab05d, 0x3f4810b0, 0x07b0240b, 0x8816b210, 0x313022ea, 0x8a791801, + 0x16400809, 0x00101500, 0x11202723, 0x01212502, 0xfdfd0895, 0x01b20171, + 0xe922fe32, 0xf0fe0001, 0x090101f4, 0xfeaefe02, 0xfd7102f8, 0xfdb0058f, + 0xfd5c02a4, 0xd7fe1f8a, 0xfef3fef9, 0x6f01c2d3, 0x00067a01, 0x8e26bf82, + 0x4304eafe, 0xbf823a04, 0x0db25922, 0x0f49bf86, 0x0c7d5d06, 0x6e0ccf43, + 0x14220887, 0xbf840f15, 0xbf821420, 0x50144025, 0x435d0214, 0xb2230a2d, + 0x4b0e1400, 0x16210501, 0x06a54d16, 0x26342723, 0x08bf8827, 0xafcd0222, + 0x73aa5ebc, 0x8d02e055, 0xf2f2ae8b, 0x01410155, 0x2961022d, 0xba60ade3, + 0x47ad1c88, 0x098576ca, 0x21055e4c, 0xa983b001, 0x4bfe9b2c, 0xb0051305, + 0x74001400, 0x5b180ab2, 0xf15b0aa7, 0x0c28510c, 0x18084d4e, 0x260856b0, + 0xb2593e11, 0x84120002, 0xe96818b3, 0xdaa21810, 0x02b0210d, 0x6e0b5057, + 0x14200798, 0x09fe7018, 0x11212508, 0x97011123, 0xbefd7f02, 0x0e3c45a9, + 0xfd7b3e24, 0xb005fc81, 0x7d0283fd, 0xc6b718fa, 0xba0cc711, 0x97fd9802, + 0x2506114b, 0x09044bfe, 0xbb823a04, 0x0bb26d22, 0x0e79bb8f, 0x20bb9614, + 0x25bb8903, 0x02500240, 0xb4a35d02, 0xb48e0620, 0xa501713f, 0xa6ba01f3, + 0x270f3a45, 0x5bfe7c3b, 0xfe3a04f3, 0xfbc3013d, 0x11c1b385, 0x01c00dbf, + 0x2cac82e7, 0x0200003a, 0xebff5100, 0xc4051e05, 0xc5711800, 0x0745451c, + 0x1b2f0829, 0x3e0f08b1, 0x720db259, 0x0d23055e, 0x5800b02f, 0x71180c92, + 0x0d220dc5, 0x625db210, 0x31302a09, 0x11002001, 0x04021415, 0x18078227, + 0x350ac276, 0x37363201, 0x16141521, 0x40017102, 0xfea06d01, 0xdcfea9e3, + 0x7618bdfe, 0x3e0808c2, 0x2901a61b, 0xfd12be96, 0xc405ba2f, 0xb6fe8cfe, + 0xc2fec16b, 0x600101b1, 0xe0894901, 0xc61334f0, 0xfcfa4a0d, 0xb91fbdda, + 0x010000bf, 0xebff5b00, 0xb0054b04, 0x6b001b00, 0x1d1c0bb2, 0x4d391211, + 0xb15c125a, 0x0c564808, 0x0204b223, 0x232f8200, 0x020b1bb2, 0x7c290682, + 0x182f1bb0, 0xb2d005b0, 0x210e8410, 0x434b0bb0, 0x1bb0240b, 0x4419b210, + 0x7b4808b0, 0x01172705, 0x14151616, 0x72772304, 0x35330809, 0x23232634, + 0xfdff0235, 0x01910392, 0xdac886fe, 0x8beae5fe, 0x87fc7ee2, 0x99907968, + 0xe4048c91, 0x4ffea3cc, 0xc5c2ea18, 0x83bf67e8, 0x647f805f, 0x83ac8594, + 0xfe5d26c3, 0x04460475, 0x20c3823a, 0x20c3885c, 0x056d440b, 0x1b2f0227, + 0x3e1b02b1, 0x79421859, 0x04b2220a, 0x86af8300, 0xc4b582b6, 0xf45208b4, + 0x8c039bfd, 0xcb88fe01, 0xebeafed7, 0xf37be489, 0x947a6c89, 0x038f939a, + 0xfe9bc476, 0xbfe91943, 0xbf68eac2, 0x80856081, 0xab839669, 0x3400ffff, + 0x89044bfe, 0x2600b005, 0x0052b000, 0xde012600, 0x070029a4, 0x3501af01, + 0xffff0000, 0x49fe2d00, 0xd182a203, 0xeb00262c, 0x27000055, 0x9dffde01, + 0x1f847aff, 0xfeff0b25, 0x82000200, 0x83042132, 0x0b283d82, 0x50001400, + 0x161504b2, 0x7b06294b, 0xc9470742, 0x08ec500c, 0x03010022, 0x20058b6f, + 0xf06218b0, 0x00b0210c, 0x2b0ed679, 0x21113311, 0x35262622, 0x01372434, + 0x2d080982, 0x16141506, 0xfd860317, 0xee9ddafd, 0xeb150180, 0xd7fe3401, + 0x798b927c, 0x15029b03, 0xd47450fa, 0x03fccc88, 0x06022ffd, 0x91747589, + 0x9d820003, 0x00006824, 0x9d82b006, 0x21001826, 0x07b26000, 0x2405fb46, + 0x19b01007, 0x586b18d0, 0x08fb4612, 0x00080727, 0xb0391211, 0x0e807507, + 0x8511b221, 0xd0192317, 0x1d4307b0, 0x19b02a0b, 0xd021b010, 0x22213130, + 0x20a88324, 0x2eb48221, 0x37363633, 0x33272636, 0x06071616, 0x87250706, + 0x720224ba, 0x84e2feec, 0xfc3308b7, 0x056c5e4b, 0xf51d2102, 0x0402261f, + 0xb1feccf3, 0x907dd6fe, 0xd3fd7a8e, 0x0203face, 0x021afb15, 0xd94a7d8a, + 0x45cc5e4c, 0xca03fcd4, 0x748a0602, 0x82019275, 0xff5e31cf, 0x067f06e7, + 0x001f0018, 0xb283002b, 0x112d2c19, 0x7e82a782, 0xcf862a20, 0x1b2f0624, + 0xd97106b1, 0x0c104b07, 0x5b181820, 0x032115e4, 0x20418318, 0x0cfa6f18, + 0x14841020, 0x841ab221, 0x03b02106, 0x220bba48, 0x18101cb0, 0x200c9d84, + 0x07b57f13, 0x84160621, 0x332733f2, 0x0e071617, 0x27042302, 0x02222306, + 0x23260127, 0xd8480622, 0x27610805, 0xa3c3e45e, 0x4e02f365, 0x04827443, + 0x17ec4004, 0x7d02032f, 0xfffe8ce2, 0xb9cb6b55, 0xae020be0, 0x7f738347, + 0x458d767a, 0x010e0206, 0x7836010a, 0x4ffb4202, 0xb702694f, 0x59d5bea9, + 0xf9a883b7, 0xb3b70485, 0x01de0501, 0xcdc16851, 0x4472aa9e, 0x3c000100, + 0xe305e7ff, 0x2900b005, 0x23b26300, 0xd752182a, 0xff4e1809, 0x08ff710c, + 0x092a0122, 0x20065f4f, 0x08ae4700, 0x1809b021, 0x200ebb63, 0x22228301, + 0x48b21022, 0x1a210abc, 0x23378322, 0x35133130, 0x2a05db68, 0x16213521, + 0x07141504, 0x88151316, 0x841620f5, 0x26063bf5, 0x26343527, 0x93a7e623, + 0xfef3fe84, 0xfa6401a5, 0xf6ff0601, 0x333c0105, 0xf3827265, 0x1af53108, + 0x7a02022b, 0xb2a78ada, 0x02677c08, 0x6d01cd62, 0x01cdd175, 0x64e6ccd3, + 0x4dfefe3f, 0xb6024939, 0x62d5bea3, 0xf8a967ca, 0xaaa70485, 0x007e6e3e, + 0x2f2de382, 0xfe04e2ff, 0x24003a04, 0x0fb26000, 0xdf901825, 0x2f1d2409, + 0x461db11b, 0x564c0799, 0xb6421808, 0x07b22309, 0xcb821d0e, 0x2516b222, + 0xb0240683, 0x14b22f16, 0x2108f544, 0x5b181db0, 0x22220c62, 0x29821614, + 0x25313023, 0x06c34106, 0x0622cd82, 0xcd842306, 0x27232326, 0x34353633, + 0x45080682, 0x10161621, 0x03171607, 0x5a4e0201, 0x41040360, 0x01182dec, + 0x9ebce904, 0xe6a208a0, 0xcbb9c202, 0x140106ff, 0xb9b0e4cb, 0x0258eb06, + 0xa9967f8f, 0xcc398086, 0x837103f2, 0x04bd7f48, 0x02c39683, 0x4acafea6, + 0xd182ac30, 0xbafe482e, 0xb0053704, 0x5f002200, 0x24230bb2, 0x00227a82, + 0x234517b0, 0x0cb84105, 0xe1821b20, 0x3e0f1b27, 0x0901b259, 0x26b8411b, + 0x4b101b21, 0x30220a8b, 0xbb821331, 0x2122bc82, 0xb1412721, 0x15332908, + 0x27070614, 0x23373636, 0x0805ab41, 0xce01973b, 0xebfe8191, 0x0103eafe, + 0x0301ef2e, 0xcd03e3e4, 0x24835a64, 0x3ca30838, 0x02747e03, 0x7301c35c, + 0x03c3eb6f, 0x66dfc9dc, 0x86f6fe47, 0x4bd863ac, 0x4977394d, 0x7184b131, + 0x26cb8285, 0x04a9fe74, 0x843a041a, 0x860620cb, 0x8a1820cb, 0x07a041cb, + 0x08ea4d18, 0x1c090122, 0x8e41cb87, 0x0d844209, 0x01001022, 0x1c202283, + 0x840bb546, 0x353224cb, 0x82232634, 0x173228cb, 0x07141516, 0x8d151716, + 0x233808cc, 0xd2e101b3, 0xe1fe636b, 0xe3200104, 0xb1ad6a78, 0x5568bb02, + 0x06382683, 0xc3012ba6, 0x8eb39b01, 0x64c1534a, 0x4f9e9259, 0xac24c33c, + 0x4d47da65, 0x1e4f7e3d, 0x00a65483, 0x4226c782, 0x7f07ebff, 0xc782b005, + 0x00b26222, 0x5a18c786, 0x41480834, 0x2f1f2807, 0x0f1fb11b, 0x18b0593e, + 0x200cf945, 0x0cdf4f0d, 0x210c7c68, 0x8f411fb0, 0x17b2230b, 0xd8820d1f, + 0x01313030, 0x02020321, 0x35230706, 0x13363637, 0x59652113, 0x36372305, + 0x45433327, 0x22460805, 0x07043526, 0x0e1861fe, 0x4a9cb961, 0x0f687a28, + 0x4c8e031c, 0x047f6e3f, 0x1cf64104, 0x7f020229, 0xc6c38ce0, 0xe0fde304, + 0xd3fef6fe, 0x03ca028a, 0x1c01df09, 0xbcfbdf02, 0xa7b46452, 0xc766d8bb, + 0x84fba766, 0xd582bdc1, 0xebff402a, 0x3a045a06, 0x62002100, 0x4506f74c, + 0xee4e05f5, 0x821e200c, 0x871e20d5, 0x7e0520d5, 0xb0210601, 0x20d58c0c, + 0x2b6f1805, 0x4b1e200c, 0xb2230bfe, 0x880c1e16, 0x20d482d5, 0x20d48227, + 0x24d48237, 0x32331616, 0x45d48336, 0x45080510, 0x03272622, 0x13f7fe17, + 0x53ada811, 0x49503202, 0xe102140a, 0x58455101, 0x40040467, 0x033016ec, + 0x7dc77002, 0x0301c7c2, 0xfe9afe74, 0xca03f4e9, 0xe5ad0b05, 0x2bfdce01, + 0x99a06452, 0xb150c8b5, 0x7ce69b7c, 0xd382b9be, 0xe7ff942d, 0xb0058607, + 0x65001d00, 0x7d1e14b2, 0x654b093b, 0x8219200c, 0x6e1920c6, 0xe0870c33, + 0x19821120, 0x0c821120, 0x4504b221, 0xb2230803, 0x82170009, 0x1cb221c1, + 0xb0210684, 0x4783181c, 0x3130240b, 0x45141101, 0x06240dda, 0x21352726, + 0x08053070, 0x0a051131, 0x7e703e4d, 0xf6410404, 0x02032f17, 0xbb8ee27c, + 0x82fd09c3, 0x7e02fcfc, 0xbcfbb005, 0xb3026056, 0x59d8bba6, 0xf7a883b7, + 0xc3c00487, 0x4b97fdff, 0x0020057f, 0x772ec782, 0x5c06e3ff, 0x1c003a04, + 0x1bb27800, 0xc55b1e1d, 0x0f4b180d, 0x200c870c, 0x20ba8202, 0x20c78702, + 0x200c821a, 0x220c821a, 0x4d0807b2, 0xd02909a1, 0x0207e007, 0x0740b45d, + 0x49068250, 0xb0210a67, 0x0b56481a, 0x8412b221, 0x87da8232, 0x113321c6, + 0x080ec845, 0x03030439, 0xf350fe1a, 0xf3b001f3, 0x5e465202, 0x40040364, + 0x022b1aeb, 0x7ec77002, 0x01138afe, 0x0446feba, 0x0143fe3a, 0x522dfdbd, + 0x91a60266, 0xbf5dceaf, 0x7ce69b61, 0x82840108, 0xff5d2ed9, 0x05bb04eb, + 0x002100c5, 0x2200b247, 0xf5a71823, 0x10d3500d, 0x4d100921, 0x6a180a91, + 0xb2210d2f, 0x06a1581a, 0x24220528, 0x34112702, 0x3e6b2412, 0x41152007, + 0x3f080e94, 0xfeacbb02, 0x9a029beb, 0xdfad1701, 0xa2863f88, 0x9ec4c59d, + 0x0303837d, 0x1327f535, 0xea810201, 0x18019c15, 0xaf0f01ad, 0x599e1d01, + 0xbce744b8, 0xe9b600ff, 0x95748502, 0x5858b1cc, 0x006ecd8b, 0x552eb582, + 0xe703ebff, 0x1e004e04, 0x13b24400, 0xb588201f, 0x0c104218, 0x47089569, + 0xb2230941, 0x82130b05, 0x13b0212c, 0x2d0d807e, 0x37363625, 0x16332734, + 0x23060607, 0x2f640022, 0x05fb6b06, 0x15153608, 0x5a021614, 0x13024551, + 0x04021deb, 0xfee7b5d2, 0x92e27ce2, 0x632e60bb, 0x948b728a, 0x474302af, + 0x528c6777, 0x3101b0a0, 0xfa971ef8, 0x3abd428b, 0x9a20a4bd, 0x2ca382bf, + 0x05e7ff21, 0x00b0055a, 0xb24d0019, 0x996b1805, 0x58452207, 0x0ccc76b0, + 0x08fb6f18, 0x270c214c, 0xb0d004b0, 0x16b0d005, 0x0c988718, 0x02160e22, + 0x2306ba43, 0x21152135, 0x44095341, 0x062a0587, 0xe3012726, 0x80043efe, + 0xe5423efe, 0xf5200806, 0x02032b1b, 0xbb8ce27d, 0xe30409c3, 0x87fccdcd, + 0xb6026054, 0x62d8bba3, 0xf9a867ca, 0xc3c00485, 0x4428a382, 0xcb04e3ff, + 0x17003a04, 0x1821a383, 0x0dc54c19, 0x230c1d67, 0xb0593e0f, 0x1520a393, + 0x1520a38d, 0x3308a398, 0x04230606, 0xfe890103, 0xfe8b03bb, 0x5e4552ad, + 0x40040363, 0x01192ceb, 0xfec2f104, 0x77031389, 0xf0fdc3c3, 0x84026454, + 0x7c9e9374, 0xf2cc377e, 0x00840108, 0x812ea182, 0xff04ebff, 0x2800c505, + 0x26b27300, 0xa1882a29, 0x1b2f1622, 0x099aa118, 0x2008e941, 0x09274403, + 0x0b162422, 0x7c2b2c82, 0x182f24b0, 0x012473b2, 0x8360b25d, 0x09d65704, + 0x0306b223, 0x23208225, 0x242510b2, 0x18054053, 0x230af749, 0x1e241bb2, + 0x35056b41, 0x32331614, 0x14333536, 0x20230406, 0x25343524, 0x34352626, + 0x4b662124, 0x1458080a, 0x23153321, 0x7f010622, 0xae8699b7, 0xfdfe8dfc, + 0xfef3fea0, 0x760e01bf, 0x012f0182, 0x8bfa9709, 0x907ca3fd, 0xb63301aa, + 0x01a39dbf, 0x817e6598, 0x69be825e, 0x57fdc4e9, 0xc562a631, 0x77ba69db, + 0x63737559, 0x0070c8d9, 0x67000200, 0xd6026f04, 0x0500d705, 0x1b000d00, + 0x2709c565, 0xb0d001b0, 0x0bb02f01, 0x0806c065, 0x0131303b, 0x03153313, + 0x15330123, 0x26071716, 0x70930135, 0xfe5de6d3, 0x4c03b1d4, 0x9804b050, + 0xfe153f01, 0x5f5401c1, 0x5a48467b, 0xffff00be, 0x09024700, 0xcd025402, + 0x11000600, 0x2f0f9300, 0x046d029d, 0x00310399, 0xe0970146, 0x40cd4c00, + 0x81242383, 0xd1056d02, 0x85231385, 0x84666600, 0x04210813, 0x99033ffe, + 0x27000000, 0x01004300, 0x0601fefe, 0x00014300, 0xb6001c00, 0x02100200, + 0x5d030220, 0x270683b4, 0x80b67102, 0xa0029002, 0x30330f82, 0x00010031, + 0x01200463, 0x001a0696, 0xb21d0008, 0x410a0908, 0x002708bf, 0x00b11b2f, + 0x66593e21, 0xd3820594, 0x07061739, 0x36352315, 0x7c1a0136, 0x01d5035b, + 0x4d1a0667, 0x8a989085, 0x8200d160, 0x04332645, 0x06650100, 0x20459000, + 0x20458204, 0x3d458304, 0x00b0d000, 0x1331302f, 0x35373627, 0x06141533, + 0x035a7caf, 0x000469d5, 0x9e92834d, 0x4384678a, 0xd6fe3226, 0xca006401, + 0x18204382, 0x09248988, 0x0d04b22f, 0x86096067, 0x0606323e, 0x03557bad, + 0xfe6601da, 0x947f4ed6, 0xd05d8593, 0x20838200, 0x2083824a, 0x2083847c, + 0x0a8e4d16, 0x3808c28b, 0x07171615, 0x35352626, 0x5a031f01, 0x06694d7c, + 0x868f9e00, 0x67d13e4d, 0x00ffff8a, 0x0220046c, 0x001a06ef, 0x096c0126, + 0x01070000, 0x0059016c, 0x00ffff00, 0x02000440, 0x235582c0, 0x0d6d0126, + 0x24081783, 0x005b016d, 0x00020000, 0x02c2fe32, 0x00ff00aa, 0x00120009, + 0x130bb221, 0x39121114, 0xb0100bb0, 0xb000d005, 0x22b58b13, 0x88d00eb0, + 0x070623f7, 0x01411706, 0x7fb12107, 0x3739c283, 0x587ff831, 0xfe66da04, + 0x9d894ec2, 0x726cbac9, 0x8e4e4164, 0x63b6cb96, 0x27d182dd, 0x04000040, + 0x00b0051e, 0x15917a18, 0x2022ce5e, 0x0c77480a, 0x82d00421, 0xaebe189d, + 0x33113a09, 0x1e042111, 0xfef388fe, 0xf373018d, 0x72037801, 0x72038efc, + 0xfe7601c8, 0x247b828a, 0x0460fe5c, 0x207b8239, 0x07e37b13, 0x5f0c865e, + 0x4a180c3d, 0x02250c17, 0x02b11b2f, 0x06d64911, 0x180c6b57, 0x2008494f, + 0x08044406, 0x100eb022, 0x2a0a4661, 0xb0d009b0, 0x11b0d010, 0x1806b0d0, + 0x27086563, 0x23112121, 0x21352111, 0xb0820384, 0x09821520, 0x83390421, + 0x018e23b4, 0x0382fe72, 0xfe2bb882, 0xfe780188, 0xc2a00160, 0x83c4b402, + 0xfdc423bd, 0xc182004c, 0x06028839, 0xdb034402, 0x16000d00, 0x0f0e03b2, + 0x00391211, 0xb12f03b0, 0x182b0a0a, 0x2109ad9b, 0x9a183233, 0x2d08077c, + 0x64798827, 0x67777867, 0x03027963, 0x79795f03, 0x775e2562, 0xff005d73, + 0xff8a00ff, 0x016f03f5, 0x00260000, 0x00000312, 0x01120007, 0x178600cd, + 0x88280521, 0x85272017, 0x221f8317, 0x83008603, 0x02472e7f, 0x02210109, + 0x000300cd, 0x0400b218, 0x487f8605, 0x29080a48, 0x23013130, 0x21013335, + 0x0902dada, 0x060000c4, 0xecff4a00, 0xc4055f07, 0x23001500, 0x34002700, + 0x4e004100, 0x28b2b800, 0x3b82504f, 0x1028b025, 0x83d002b0, 0x841b2005, + 0x84262005, 0x84352005, 0xd0472505, 0x2f24b000, 0x4907d867, 0x58540cae, + 0xd0032108, 0xb223fc82, 0x83120305, 0xd007314b, 0xb02f07b0, 0x0eb01012, + 0x2f0eb0d0, 0x031210b2, 0x2306f94f, 0x20b0d020, 0xb2221883, 0x7543022b, + 0x03b02407, 0x8932b210, 0x102b290d, 0xb0d038b0, 0x3fb01032, 0x10222a82, + 0x198945b2, 0xb2101923, 0x820d884c, 0x183420db, 0x200732b4, 0x098b6f15, + 0x69013521, 0x1184059a, 0x01352626, 0x03170127, 0x2605c245, 0x22263435, + 0x8b051506, 0x8b01200c, 0x032b080c, 0x9688ac2f, 0x86954e4e, 0x978aa9af, + 0x8a944e4e, 0xa81bfdac, 0xabab8a85, 0x01aa8588, 0xc7027d77, 0x3e4fb07d, + 0x7c4e4a40, 0x86c7014d, 0xfb340808, 0x3e3f4d4e, 0x4b7e4d4c, 0xaa826501, + 0x8ca76f6f, 0x6eaa8147, 0x0386aa6e, 0xaaaa837b, 0xa9824689, 0x1bfc89a9, + 0x48720448, 0x574438fc, 0x464b4c52, 0x4a4a5454, 0x21080988, 0x5545ea02, + 0x46484955, 0x00495756, 0x6c000100, 0x33028a00, 0x0600a903, 0xb0001000, + 0x02b22f05, 0x835d0507, 0x37e98205, 0x35012313, 0x3c013301, 0xe0fea7f7, + 0x02a72001, 0x0171fe19, 0x86011386, 0x54203783, 0x1b203782, 0x00233787, + 0x7b03b22f, 0x033d0537, 0x1331302f, 0x23011501, 0x01fb0313, 0xa7e0fe20, + 0xa903f7f7, 0xfe137afe, 0x018f017a, 0x306f8290, 0x036d002d, 0x00270571, + 0x00090003, 0xb02f00b0, 0x24308202, 0x17012737, 0x20ea83aa, 0x34b5836d, + 0x00ffff00, 0x02930235, 0x03a805be, 0x00d80107, 0x00930200, 0x05f94413, + 0x2308f94e, 0x3130d00d, 0x692c8583, 0xff028c02, 0x0f00ba05, 0x0ab25300, + 0x4b0a0776, 0x4d570ce7, 0x2f0d250c, 0x130db11b, 0x2006c743, 0x200c8207, + 0x230c8207, 0x0d0301b2, 0x0323f583, 0x5e0ab210, 0x302e085a, 0x36170131, + 0x11112033, 0x23261123, 0x06820722, 0x2001013c, 0x0301904b, 0x637d05c5, + 0xac05c527, 0xc9fe8779, 0xda0109fe, 0xd2fd59ad, 0xdb822003, 0x00005f2e, + 0xc3057c04, 0x8e002700, 0x29281fb2, 0x20087346, 0x20668217, 0x07d34a17, + 0x0c820620, 0x3e0f0627, 0x0627b259, 0x24218217, 0xb22f27b0, 0x085e420d, + 0xd001b025, 0x181006b0, 0x270a7a60, 0xb0d009b0, 0x10b01027, 0x232f0584, + 0x2f23b0d0, 0x1f230fb6, 0x03232f23, 0x8925b25d, 0x82112036, 0xb0102619, + 0x17b0d014, 0x0c4e4810, 0x481e2321, 0x2127054e, 0x21071417, 0x18352107, + 0x220879ab, 0x18333523, 0x080f7dab, 0x21172137, 0xd0fe3203, 0xb8024002, + 0x52e7fb01, 0xa5022b27, 0x979c04a0, 0x9601fa05, 0x5f69f5e8, 0x01066758, + 0x05c6fe3f, 0xd4013501, 0xca55872e, 0x5b6f09ca, 0x90799137, 0x8cab18a1, + 0x90a13c07, 0x00050079, 0x06000021, 0x00b0054f, 0x001f001b, 0x00260023, + 0xb2bd0029, 0x822b2a0a, 0x0ab02586, 0xd01fb010, 0x21200583, 0x26200584, + 0x28210584, 0x9f7d18d0, 0x0c304112, 0x1b2f0c24, 0xd14c0cb1, 0x82092007, + 0x8209200c, 0x05b2230c, 0x1a5e1a09, 0xd0012b06, 0xb22f01b0, 0x5d01010f, + 0xbc4103b2, 0x05b02408, 0x8907b210, 0x8225200d, 0xb0d0236b, 0x1682d00e, + 0xd01db023, 0x2c8082b0, 0x03b0d011, 0xd01eb010, 0xb0d022b0, 0x3c418212, + 0xd019b010, 0xb0d027b0, 0x09b0d015, 0xd024b010, 0xb01017b0, 0x3130d029, + 0x23153301, 0x2a038215, 0x21012311, 0x23112311, 0x82353335, 0x33112103, + 0x33210d82, 0x2c0b8201, 0x23273305, 0x01233501, 0x77052733, 0x260082d8, + 0xfec9fefd, 0x82d3fcad, 0x01fc3e00, 0xfb570135, 0xf39471fe, 0x5fee67fe, + 0x2f8c028f, 0x2b2ba3fd, 0x97a0c503, 0x0112fea0, 0x820383ee, 0x0122080a, + 0x0115feeb, 0x97defceb, 0x7efe9797, 0x44d7014b, 0x98000200, 0x3a06ecff, + 0x1e00b005, 0xa2002500, 0xf37621b2, 0x10212105, 0x2408996a, 0xb11b2f15, + 0x074f4215, 0x0c821920, 0x8e181920, 0x416714ab, 0x8213200c, 0x0f132426, + 0x18b0593e, 0x180db88e, 0x2a154073, 0x151320b2, 0xb0391211, 0x73b22f20, + 0x1d290a7e, 0xd01cb010, 0xb02f1cb0, 0x0b197815, 0x01313022, 0x0c137618, + 0x0606232d, 0x23112307, 0x16322111, 0x82113317, 0x015c0801, 0x34113233, + 0x33062327, 0x263f32bf, 0xfe4d532f, 0xf41c78e8, 0x01fa9eca, 0x18fdd48c, + 0xfbbff275, 0xe6f4925f, 0xfd8603a0, 0x0a383da4, 0x350117bc, 0xbbad6502, + 0x05e5fd03, 0x01b3c3b0, 0xfef9fe07, 0xf70001ad, 0xffff0006, 0xecff9400, + 0xb0053c08, 0x36002600, 0x07000000, 0x72045700, 0x35200784, 0x53200c82, + 0x1f321782, 0x27002300, 0x2e002b00, 0x34003100, 0x32b2eb00, 0xc5833635, + 0xb0103225, 0x82b0d01e, 0x84222005, 0x84272005, 0x842a2005, 0x842e2005, + 0x18302005, 0x2413236c, 0xb11b2f1f, 0x0764411f, 0x0c821b20, 0x0c871b20, + 0x51086578, 0x0f2608fb, 0x09b2593e, 0x6c830210, 0x9c700920, 0x0fb22706, + 0xb05d0105, 0x8842d001, 0x4409200e, 0x21080b61, 0xb0d02db0, 0x30b0d00e, + 0xd012b0d0, 0xb01009b0, 0x29b0d025, 0xd021b0d0, 0xb0d015b0, 0x26b01007, + 0xa582b0d0, 0x1638b482, 0x1001b0d0, 0xb0d01db0, 0x10b0d019, 0xd02fb010, + 0xb0d02cb0, 0x32b0101f, 0x34321784, 0x013130d0, 0x03331321, 0x07231533, + 0x03211533, 0x03840323, 0x27333524, 0x15823523, 0x1b821320, 0x37330124, + 0x03840523, 0x01232722, 0x4e080a82, 0x07012337, 0x01980433, 0x62fb5731, + 0xe425bf9a, 0xf37ef7fe, 0x92f2fe90, 0xfdfe7ff2, 0x94b925de, 0x0158fb62, + 0xfdd46c34, 0xea2a9fce, 0x219f0e03, 0xbaa6fee9, 0xb001652a, 0x32fd5626, + 0xa701552f, 0x07041008, 0x57fea901, 0xfda0a2a0, 0x832502db, 0x830a8203, + 0xa9012411, 0x83a215fd, 0xfe200800, 0xb9b9be00, 0x001f0102, 0x007c0002, + 0x04100600, 0x000d003a, 0xb26b001b, 0x111d1c08, 0x08b03912, 0x1809cf42, + 0x240ced4d, 0xb11b2f16, 0x07cf4216, 0x2308c85a, 0xb0584500, 0x4208bf55, + 0x00200a93, 0x220c064e, 0x82091105, 0x10b2235a, 0xf6441109, 0x16322905, + 0x11231117, 0x21232634, 0x01270682, 0x21113311, 0x82373632, 0x06450806, + 0x0c032306, 0xf302aebb, 0xaefe695a, 0xf39901f3, 0x596a5001, 0xef01f401, + 0xc03a04dc, 0x01b5fecb, 0xfc636d42, 0xfb3a048a, 0xfdd602c6, 0x026861ed, + 0xbc57fdae, 0x000100d5, 0x04edff5e, 0x00c30530, 0xb28a0023, 0x5b481815, + 0x0c154e0a, 0x2108a344, 0x8e831623, 0x2f23b024, 0xaa4500b2, 0x63092009, + 0x10280d6a, 0xb0d00cb0, 0x0eb01023, 0x132e0584, 0x2f13b0d0, 0x1f130fb6, + 0x03132f13, 0xad18b25d, 0x16200a1c, 0x2e0b8c56, 0xb01013b0, 0x10b0d01e, + 0xd020b010, 0x60013130, 0x23230710, 0x44030020, 0x362106a0, 0x08447c00, + 0x82152121, 0x03550801, 0x069cfe6a, 0x5f6e98a3, 0xff80781c, 0x08dafe00, + 0xadacacac, 0xfd2c010d, 0x661c856a, 0x09a29765, 0x9cfe6301, 0x0f026401, + 0xcc21acae, 0x0120011d, 0x8d808d02, 0x1f1b01ff, 0xa4ac22cd, 0x0000808d, + 0x00210004, 0x05d40500, 0x001a00b0, 0x0024001f, 0xb2e30029, 0x05d7450c, + 0xb0100c25, 0x82b0d01c, 0x84232005, 0x07d14505, 0x290cd263, 0xb11b2f01, + 0x593e0f01, 0x3b440bb0, 0x38be820b, 0x402f20b0, 0x10200013, 0x30202020, + 0x50204020, 0x70206020, 0x09208020, 0x3ae0835d, 0xb0b62f1e, 0xd01ec01e, + 0x405d031e, 0x101e000b, 0x301e201e, 0x051e401e, 0x4526b25d, 0x273509db, + 0x2f27b0d0, 0x27300f40, 0x27502740, 0x27702760, 0x27902780, 0xbb5e1807, + 0x1026320c, 0xb0d003b0, 0x06b0101e, 0x1020b0d0, 0xb2d00fb0, 0x823f8912, + 0xd01d23bb, 0x198407b0, 0x25840a20, 0xb0d01422, 0x17243182, 0x013130d0, + 0x280af245, 0x17043221, 0x17231533, 0x2d048207, 0x01230606, 0x21152127, + 0x27262125, 0x08820121, 0xd6013224, 0x0082b8fd, 0x2d025308, 0x3c0101ad, + 0x0102bde4, 0xfa36e1bc, 0x031501bd, 0x4302befd, 0xf001bdfd, 0xc8fe7246, + 0x0cfef401, 0x027b3101, 0x03e3fd1d, 0xa048a01f, 0x81880901, 0xa02226a0, + 0xc201857d, 0x3be84828, 0x373bfe02, 0x28000100, 0x0c040000, 0x1a00b005, + 0x16b26d00, 0x47481c1b, 0x0c014b08, 0x20081647, 0x0b535219, 0xd001b026, + 0xb01019b0, 0x1421c182, 0x22f3832f, 0x7fb21014, 0xfe820aa3, 0x4b101421, + 0x0920061c, 0x22085957, 0x60090db2, 0x233606e1, 0x07331716, 0x07060623, + 0x01211501, 0x36323327, 0x21372137, 0x04822326, 0xd9033508, 0xca0f33da, + 0xdc169732, 0xfed201c9, 0x0103fee1, 0x168370fd, 0x0133e6fd, 0xfed831e3, + 0xae0336f3, 0x654bf904, 0x11afa5b6, 0x020ddffd, 0x4c5d9951, 0x00cc9bb6, + 0x2124cb82, 0x5104ecff, 0x1e24cb82, 0x1bb29100, 0x240a3153, 0xb11b2f11, + 0x974c1811, 0x3e0f260c, 0x1113b259, 0x2fed8205, 0xb02f13b0, 0x17b0d017, + 0x1700b22f, 0x18b25d01, 0x2609574d, 0x08b0d019, 0x8209b0d0, 0xb0102c1b, + 0x0bb0d016, 0xd00ab0d0, 0x181013b0, 0x270a50de, 0xb0d015b0, 0x0db0d00c, + 0xb0251683, 0x0fb0d012, 0x21ef83d0, 0xa75f1005, 0x1eb2220a, 0x061f4405, + 0x0206152b, 0x27222304, 0x37350711, 0x25038235, 0x37153311, 0x03830715, + 0x3636112e, 0x51043535, 0xedfe9602, 0xdc8c6bb2, 0xfc210082, 0x080082e1, + 0x02b2aa22, 0xfed259ff, 0x0214abc3, 0x57c7575d, 0x57c85789, 0x5ad73b01, + 0x5a895ac8, 0xfbfd59c8, 0x4df8fc02, 0x4f29f383, 0x0f050000, 0x17003a04, + 0x37871800, 0x0cde6a0d, 0x440c4546, 0x5e570ce7, 0x15b22307, 0x4a18170b, + 0x0c200c34, 0x27090841, 0x3130d009, 0x13001601, 0x2406f066, 0x06061123, + 0x080b8215, 0x37001236, 0x28033335, 0x040301e0, 0x728101f3, 0xf38271f3, + 0xdf040103, 0x296a03f3, 0xecfe92fe, 0xefc5b8bf, 0x026afd2a, 0xc7f32a95, + 0x1401bab1, 0xd12b7001, 0x28000200, 0x332caf82, 0x1600b005, 0x78001f00, + 0x212018b2, 0x18207583, 0x09474918, 0x200c224f, 0x06605602, 0x0206b223, + 0x2127830c, 0xae4a2f06, 0xd0012f0b, 0xb01006b0, 0x0ab0d00a, 0x0a0fb22f, + 0x49185d01, 0x14200b49, 0x15201b84, 0x10281b82, 0xb0d017b0, 0x1fb2100c, + 0x3023d088, 0x82212531, 0x06bd44bf, 0x3221112d, 0x04141504, 0x21152107, + 0x73322101, 0x032505ec, 0xfcbefe33, 0x080082cd, 0xf12d0242, 0xeefe2001, + 0x01c4fef4, 0x01befe42, 0x8d90882d, 0xe7c4fe7c, 0x6bcbe7e7, 0xfbc802cb, + 0x03f1d4d0, 0x7e36016b, 0x038e707d, 0x70000400, 0x8905ecff, 0x1900c505, + 0x34002600, 0x94003800, 0x3a391ab2, 0x1a25b783, 0xd000b010, 0x200582b0, + 0x27058427, 0xb000d037, 0x37b02f35, 0x2012625b, 0x27f18224, 0x593e0f24, + 0xb01009b0, 0x22056e4e, 0x8303090d, 0x10092142, 0x230ba145, 0x16b21003, + 0x2308e645, 0x090319b2, 0x242c2283, 0xd01db010, 0xb02f1db0, 0x2ab21024, + 0xb0241d88, 0x31b2101d, 0xb2180d88, 0xf98218c7, 0x2309574e, 0x17352620, + 0x0808384e, 0x06222323, 0x01270515, 0x9fb10217, 0x9ea200ff, 0xaaa18082, + 0x42343641, 0x01406a43, 0x8887ae18, 0xe8fea7ad, 0xd2e818ab, 0xfbfd3d08, + 0x7ec7027e, 0x92732504, 0x82478aa7, 0x357394ab, 0x4a4a5440, 0x31435545, + 0xa68640fd, 0x16d1e818, 0x4c000232, 0x9003ebff, 0x1700f905, 0x5a002100, + 0x232201b2, 0x0124cf83, 0xd018b010, 0x0d8a5c18, 0x593e0f26, 0x000c06b2, + 0x44070b42, 0xb0210856, 0x0fdf6713, 0x3c830620, 0x3a0ff741, 0x35262205, + 0x32352306, 0x36361137, 0x15163233, 0x07021415, 0x33161415, 0x6b363603, + 0x4e08059f, 0xe1db0207, 0x616061ed, 0x9ab20360, 0xb2d7ac88, 0x4dd46c68, + 0x56202b57, 0xe5eb1503, 0x0118bb13, 0xb4d6bfe9, 0xfead269b, 0x8e4d67a9, + 0x4b44027a, 0x3f2966cc, 0x0000b240, 0x00900004, 0x05c20700, 0x000300c0, + 0x001d000f, 0xb2a60027, 0x8329281e, 0x101e25a7, 0xb0d001b0, 0x88680582, + 0x82102005, 0x450028d1, 0x2f26b058, 0x4426b11b, 0x24200793, 0x0b385118, + 0x8c180620, 0x21200bb6, 0x21200c82, 0x5b07904c, 0xdc8208ee, 0xb0d00d31, + 0x02b02f0d, 0x2f02b0d0, 0x010200b2, 0x4101b25d, 0xb02408e3, 0x13b2100d, + 0x06230d89, 0x881ab210, 0x20b2230d, 0x95822124, 0x1f25b223, 0x08685726, + 0x36340128, 0x15151620, 0xf6410614, 0x21012510, 0x11231101, 0x5a080482, + 0xfd970733, 0xfd61029f, 0x3801be76, 0xc2febabf, 0x515cafbd, 0x505c5b4f, + 0xc7fe5c4f, 0x0dfef4fe, 0x010b01f4, 0x9c01f2f6, 0x9f2f0295, 0x4ea6c0c1, + 0xa2c2c29c, 0x6c6c6006, 0x6d5f5163, 0xa3fb626d, 0xf6fb0a04, 0xf3fbb005, + 0x00000d04, 0x036d0002, 0x05570494, 0x000c00b0, 0x4d6d0014, 0xf48c0592, + 0x18087a4f, 0x2608c479, 0xb2593e1f, 0x82061501, 0x01b021b2, 0x0921ef82, + 0x22098201, 0x840103b2, 0xd0042510, 0x090108b2, 0x10291a84, 0xb0d00bb0, + 0x0db11006, 0x059f520a, 0x1001b034, 0xb0d00fb0, 0x11b0100d, 0xd012b0d0, + 0x03013130, 0xd1820323, 0x13133327, 0x01231133, 0x080a8223, 0x2135232b, + 0x3e7ce803, 0x81896f7c, 0xfe6f8585, 0x8d758a11, 0x09058c01, 0x74018bfe, + 0x1c028cfe, 0x7d0183fe, 0xbd01e4fd, 0xbb0145fe, 0x2cbb835f, 0x04ecff96, + 0x004e0491, 0x001c0015, 0xd7681862, 0x4116200a, 0xd55306d7, 0x08bf440c, + 0x020a1922, 0x1924a083, 0x0a0fb22f, 0x24081452, 0x13b21002, 0x210d870c, + 0x228515b2, 0xb2100a23, 0x08228816, 0x25313065, 0x26222306, 0x12343502, + 0x16323336, 0x21151716, 0x32331611, 0x07220137, 0x26112111, 0xbbb71404, + 0x9087f491, 0xe38584f8, 0x00fd0384, 0xacc49a77, 0x7a9790fe, 0x5e731c02, + 0x01019d72, 0x03018f93, 0x90f38b9f, 0x6eb8fe3e, 0x7a2a037a, 0x1e01ebfe, + 0x00ffff71, 0x05f5ff59, 0x009905cb, 0xffd50127, 0x828602d9, 0x007c2e07, + 0x010000fb, 0x03dc0107, 0x00000021, 0x0d934110, 0x82313021, 0xff542633, + 0x056806f5, 0x242b82b4, 0x021d00d7, 0x22078294, 0x86a8017c, 0x89be2033, + 0x2f0d2733, 0x1f0db11b, 0x3384593e, 0x33825b20, 0xa8055c22, 0xd9242b82, + 0x93020c00, 0x8c203384, 0xb2203386, 0x01203389, 0x01203382, 0x58203387, + 0x1a223382, 0x2b82a305, 0x2200db24, 0x33848e02, 0x33863320, 0xae187020, + 0x003c136d, 0xff620002, 0x054304eb, 0x001900f5, 0xb25b0026, 0x11282713, + 0x13b03912, 0xd020b010, 0x088e7018, 0x2107924e, 0x1c5b00b2, 0x2f002305, + 0x098502b2, 0x02510b20, 0x6400200c, 0x13210c46, 0x0c1e6b10, 0x17320127, + 0x22232626, 0x299e1807, 0x064a5b09, 0x63171221, 0x59080654, 0x26353536, + 0xae380226, 0x84c51a77, 0x3c1d8b7c, 0x0d018f6e, 0xe37a2701, 0xf3fee394, + 0x857bf4fe, 0x85797a84, 0x04048b16, 0x35e5c27d, 0xfe2c19b7, 0x3572fe4e, + 0xa7d3fec1, 0x0df72401, 0xc21201df, 0xb09aa4a7, 0x4c55c5d0, 0x0001005f, + 0x041bffa6, 0x00b005f4, 0x00270007, 0x2b4604b0, 0x08264305, 0xb0100425, + 0x18b0d001, 0x240eb064, 0x21112305, 0x2e038211, 0xfdf4f404, 0x4e04f399, + 0xfad405e5, 0x8295062c, 0xfe40244b, 0x82c104f3, 0x000c254b, 0x03b00035, + 0x08204b85, 0x07a65318, 0xb2100322, 0x2009a562, 0xb89018b0, 0xfd8f3e22, + 0xfb4403ee, 0xfd4f027f, 0xfc4704b1, 0x021202f6, 0xc373fd43, 0x02c80297, + 0xfdc398c6, 0x276f8273, 0x036d029e, 0x003103ef, 0x178beb18, 0xfcef0328, + 0x025103af, 0x2b82c46d, 0x00003b24, 0x9b829204, 0x3c000824, 0x3d5900b2, + 0x064f6b06, 0x20071942, 0xd5c618b0, 0x3e0f2308, 0xaa66b259, 0x70072006, + 0x303f0b36, 0x33010131, 0x23032301, 0x41022135, 0xfed97801, 0xd1d8c517, + 0x2b016701, 0x50fa8504, 0x82c54102, 0xff5e3b89, 0x04df07ec, 0x001a004e, + 0x0039002a, 0x3a07b272, 0x3912113b, 0xb01007b0, 0x0583d022, 0xc1433220, + 0x18042006, 0x200be858, 0x06035209, 0x1004b02c, 0xb0d016b0, 0x07b22f16, + 0x36830416, 0xb0d01226, 0x14b22f12, 0x16200c85, 0x820b0953, 0x18b2202a, + 0x2809b980, 0xb0d02eb0, 0x37b0101e, 0x08a182d0, 0x06061429, 0x27262223, + 0x26222102, 0x34353526, 0x20333612, 0x32211213, 0x07171616, 0x22232634, + 0x15070607, 0x33161716, 0x55353632, 0x372405c3, 0x27263537, 0x78081882, + 0x80df0706, 0xe98d90e6, 0xdffeaa55, 0x8181e58f, 0x24018ee4, 0x2401a9a9, + 0x0181e48e, 0xa47a92ef, 0x0f0f286e, 0x799f6b2e, 0x925dfa95, 0x2bac697b, + 0x6e280f07, 0x029279a4, 0x90fd9811, 0xb6fea7a3, 0x1599ff8e, 0x8f000198, + 0x4701b9fe, 0x0497fd8f, 0x4ac9c69a, 0x55452442, 0x05a2c3c3, 0x90b3c39d, + 0x4a42241a, 0x0000c3c9, 0xfeafff01, 0x06a8024b, 0x00150015, 0x1602b23d, + 0x080d4c17, 0x1b2f0e24, 0xc5660eb1, 0x3e11220c, 0x0b765859, 0x1b630e20, + 0x6b05200d, 0x372308f5, 0x4e363411, 0x2d08061e, 0xb6900115, 0x123f42aa, + 0x028a252c, 0x593fb2c0, 0xa3322a19, 0x13b6b04f, 0x049d0dbd, 0x15c3b3f4, + 0x00b80bb9, 0x65000200, 0x15040101, 0x8382fa03, 0x78002b24, 0x516710b2, + 0x10102805, 0x00d01cb0, 0x492f19b0, 0xb0240515, 0x08b0d008, 0x10220b82, + 0x08820ab0, 0x210b4b60, 0xe16203b0, 0x0db0280b, 0xd015b010, 0x4d1019b0, + 0x088305e1, 0xb0d02023, 0xf166181e, 0x6719200c, 0xb03e0b40, 0x2bb01023, + 0x133130d0, 0x36333636, 0x33161717, 0x06153732, 0x27272223, 0x06220726, + 0x15941507, 0x30653a08, 0x4c524284, 0x8451469c, 0x517f6665, 0x544f9846, + 0x30308742, 0x4f544280, 0x87514698, 0x51836665, 0x524c9c46, 0x03308442, + 0x0238328e, 0x7e204e22, 0x4c206ad9, 0x3c420224, 0x210f82cb, 0x0f844c24, + 0x82224e21, 0x0100300f, 0x80009100, 0xc304ef03, 0x37001300, 0x7e13b000, + 0x04260ca7, 0x1013b0d0, 0x058407b0, 0xb0d00f24, 0xdb7b2f0f, 0x08b0210a, + 0x10221082, 0xba820bb0, 0x07210129, 0x35233727, 0x82213721, 0x17490803, + 0x21153307, 0xef032107, 0x6d80e2fd, 0x2101b05d, 0x0261fe7e, 0x636e8610, + 0x7dd1febd, 0x6401ac01, 0xc9a63ee4, 0x3eedcadf, 0xffdfcaaf, 0x003c00ff, + 0x048d0313, 0x0067006b, 0x00000020, 0x3900408b, 0x0107009a, 0xfd9eff97, + 0x201d82a6, 0x201d8280, 0x201d84e0, 0x3b1d8c22, 0x00a6fde2, 0x00240002, + 0x05eb0300, 0x000500b0, 0xb2380009, 0x110b0a06, 0x06b03912, 0x0ee56118, + 0x6a07f148, 0x06220877, 0x27820300, 0x8408b221, 0x302b0806, 0x01330131, + 0x01012301, 0x01131303, 0x8301c4a4, 0xfec580fe, 0xede1017e, 0xb005ecf2, + 0x29fd27fd, 0xd601d702, 0x29fe2afe, 0x8200d701, 0x00a1308f, 0x05bc01ab, + 0x00270007, 0x001a0012, 0x830701b6, 0x07042107, 0x2406ed57, 0x3130dc11, + 0x30978200, 0x027f0263, 0x0039043e, 0x00070003, 0x0800b22a, 0x256f8209, + 0x00d005b0, 0x534502b0, 0x3e1b220a, 0x201a8259, 0x06026b02, 0x82d00421, + 0x11232389, 0x03830133, 0x9d9d003c, 0x9d9d3e01, 0xba017f02, 0xba0146fe, + 0x45000100, 0x5a0167ff, 0x08000601, 0x99450c00, 0xb0d02505, 0x31302f00, + 0x3006965c, 0x80c50606, 0x01c90349, 0x734d9953, 0x5d4f647b, 0x32a982ba, + 0x0500002d, 0x0015061a, 0x004a0026, 0x00070000, 0x8244024a, 0x00022607, + 0x04000018, 0x26178217, 0x001b0017, 0x5209b273, 0x092005ad, 0x24090d6b, + 0xb11b2f09, 0x07774309, 0x0c820420, 0xad520420, 0x0ce27607, 0x19821720, + 0x254a1720, 0x82192007, 0x8319200c, 0x1004240c, 0x71d013b0, 0xb0270a09, + 0x09b0d001, 0x4d0fb210, 0x33370a08, 0x33352311, 0x33023e35, 0x07171632, + 0x06222326, 0x15331515, 0x82211123, 0xbd2a08f7, 0x6a01a5a5, 0x935088c2, + 0x728a254f, 0xd5d5646f, 0xf3f36702, 0x4ab48603, 0x225cb67f, 0x6130c91a, + 0xfcb44461, 0x003a047a, 0xdd820001, 0x822c0421, 0x001624c5, 0x7412b263, + 0x12200ad1, 0x12208982, 0xe15cbd87, 0x0856450c, 0x58450023, 0x081f62b0, + 0x88461220, 0x100e270c, 0xb0d005b0, 0x7b18100e, 0xb0250a70, 0x3130d008, + 0x85a78201, 0x052257a6, 0x3336362e, 0x23110532, 0x4a663903, 0xf3dcdcc4, + 0xd72ab682, 0x44017ac4, 0x0e3f05f3, 0xa2825bb8, 0x6127b382, 0xfa30c3b7, + 0x8302001b, 0x930621a9, 0x282fa982, 0xb5002c00, 0x2e2d14b2, 0xb0391211, + 0x6bb01014, 0x082007ad, 0x0820b182, 0x9784b187, 0x2b200c87, 0x2b201982, + 0x20077c41, 0x200c8221, 0x710c8721, 0xa3410cf4, 0x8228200c, 0x41282026, + 0x25200796, 0x25200c82, 0x2a200c87, 0x2a200c82, 0x21210c83, 0x2e751810, + 0x26b0240a, 0x4401b0d0, 0x16200fcf, 0x0dce4118, 0x4505b141, 0x15210953, + 0x11be4121, 0x21112329, 0x11232111, 0x18a5d233, 0x210854d4, 0xcc417401, + 0x88263806, 0xd5646f73, 0x8cfef3d5, 0xf3f3ce04, 0x63b48603, 0xbe12c4b4, + 0x4160b308, 0x03210dd7, 0x09db4186, 0x06930629, 0x00270015, 0x5a13b2a5, + 0xa6180a67, 0x36410cc3, 0x0c02410c, 0x0cd84218, 0xf5821f20, 0x36411f20, + 0x82272007, 0x4127200c, 0x2420070f, 0x2307f64e, 0xb0584500, 0x200ac042, + 0x775b18b2, 0x4508200a, 0x15200ce6, 0x2a0b1641, 0xb01001b0, 0x22b0d026, + 0x413130d0, 0x2042121f, 0x42112006, 0x21210a37, 0x0d1b4111, 0x42053142, + 0xfe210540, 0x0a15418c, 0x42053942, 0xfc31094a, 0x0001007a, 0x04ecff2d, + 0x001506d1, 0xb2850024, 0x0a016c13, 0x0c2d6518, 0x200ca043, 0x025e1823, + 0x082b590b, 0x18102321, 0x200a0d66, 0x151e59b0, 0x2482b020, 0x1809ba50, + 0x260be45f, 0x18b0100e, 0x4419b0d0, 0x142005aa, 0x2606a946, 0x23111120, + 0x83353335, 0x431120ea, 0x342b051e, 0x16323336, 0x04331117, 0x5931bfcb, + 0xb2330613, 0xa36c45b2, 0xc2a5a5f3, 0x72f165b0, 0xfd8603bf, 0x59373ea4, + 0xb42f060d, 0xfbb920f8, 0xb4860367, 0x38c3b662, 0x828efe31, 0xff4b31ed, + 0x068006ec, 0x004c0018, 0x4d46b2a7, 0x3912114e, 0x20051e4c, 0x20d38247, + 0x071e4347, 0x0c824020, 0xda414020, 0x0c074107, 0x19824b20, 0x92184b20, + 0xb0250f05, 0xb0584500, 0x2519822c, 0x593e0f2c, 0x07414bb0, 0x10b4560c, + 0xb0d00d27, 0x47b0d00e, 0x0b2f6d10, 0xb2104023, 0x09fd4f20, 0xb2102c23, + 0x250d8834, 0x23013130, 0xb8471411, 0x27262f06, 0x33352311, 0x23263435, + 0x14150622, 0xc518021e, 0x415f0c49, 0x35262705, 0x33161633, 0x24823632, + 0x26272628, 0x33363435, 0x06851732, 0x1515163f, 0xbf790633, 0x532f2671, + 0x0190874d, 0x5860acac, 0x211d584f, 0x5668f41c, 0x015e6550, 0xa0cf181e, + 0x6b2b080c, 0xecb653f8, 0x2d4d5bb6, 0xdec9aed9, 0xfd8603bf, 0xbc0a88b7, + 0x02a2aa17, 0x6258b44e, 0x3a455469, 0x4d796669, 0x3e4a5d46, 0x183f3e38, + 0x080ab9cf, 0x44413b55, 0xa7582834, 0x6c17bc8c, 0xcaa5814f, 0x16004fc5, + 0x72fe5900, 0xae05ec07, 0x1a000d00, 0x37002800, 0x43003d00, 0x4f004900, + 0x5a005600, 0x62005e00, 0x6a006600, 0x76006e00, 0x7e007a00, 0x86008200, + 0x8e008a00, 0x10b2c001, 0x1211908f, 0x1010b039, 0x83d000b0, 0x841b2005, + 0x84302005, 0x843c2005, 0x843e2005, 0x84462005, 0x844a2005, 0x84502005, + 0x84572005, 0x845b2005, 0x84612005, 0x84632005, 0x84672005, 0x846d2005, + 0x84702005, 0x84772005, 0x847b2005, 0x847f2005, 0x84842005, 0x84882005, + 0xd08c2405, 0x473db000, 0x462f0554, 0x46b11b2f, 0xb2593e1f, 0x2b03447d, + 0x82797cb2, 0x81782104, 0x80210482, 0x22048239, 0x833d460a, 0x2f0a21a9, + 0x2806cc49, 0x0eb0d00e, 0x100ab02f, 0x05d548b0, 0x0f0e6f22, 0x7c271e82, + 0x182f6fb0, 0x4f0b50b2, 0x50210920, 0x2235846f, 0x881eb210, 0x03b02414, + 0x8925b210, 0x100f320d, 0xb0d029b0, 0x0eb02f29, 0xd02eb010, 0xb22f2eb0, + 0x281c8934, 0x6bb0103d, 0xd067b0d0, 0x23dc82b0, 0x3fb2d03e, 0x36087a4f, + 0xb0d065b0, 0x6db0d069, 0xd03cb0d0, 0xb01039b0, 0x46b0d041, 0x8947b210, + 0xd05b261f, 0xb0d057b0, 0x3016834a, 0xb0d060b0, 0x58b0d05c, 0xd04bb0d0, + 0xb01044b0, 0x22ba824e, 0x8951b210, 0x10472965, 0xb0d05fb0, 0x76b2100f, + 0x21081389, 0x84b01078, 0x1079b0d0, 0xb0d085b0, 0x88b0107c, 0x107db0d0, + 0xb0d089b0, 0x8cb01080, 0x1081b0d0, 0x1d4c8db0, 0x22232405, 0x43352726, + 0x132805af, 0x16323311, 0x16071415, 0x23210482, 0x05be4201, 0x1614152b, + 0x35363233, 0x14113301, 0x222a8206, 0x84143335, 0x1120080e, 0x15331533, + 0x35333521, 0x11011133, 0x15231521, 0x11213525, 0x15013523, 0x34353233, + 0x21351327, 0x03851c82, 0x0b8a0120, 0x1d831320, 0x23232623, 0x07065501, + 0x25200782, 0x4c080b8a, 0x64813703, 0x7e028066, 0x02806568, 0x7262bc43, + 0xd0343254, 0x414a8ffe, 0x424a4a40, 0xba034940, 0x5852695c, 0x29685d6d, + 0x71c4f936, 0xc72805c4, 0x016df86f, 0xec05c435, 0xfc6f3601, 0x62677e5c, + 0xfd1601cb, 0xfd15015b, 0x0214015c, 0x280b890a, 0x3a765dbc, 0xf1fc5d3c, + 0x22008471, 0x846f2207, 0xd4013d00, 0x5e787962, 0x787c5f75, 0x02b3fe5e, + 0x544d4925, 0x2d460d20, 0x4548019b, 0x70454e4e, 0x28080483, 0x86fe4f01, + 0x53515d4e, 0xfc2c365b, 0xca3b01c9, 0xfeca7171, 0x011f06c5, 0xa9a9741d, + 0xa9e3fe74, 0x53a9b6fc, 0x4a030452, 0x21008474, 0x5e8438f9, 0xc403712e, + 0xfe1e2950, 0xfa7efcd3, 0x7ef915fc, 0x25080685, 0x5c000500, 0xd707d5fd, + 0x03007308, 0x20001c00, 0x28002400, 0xb0004c00, 0x25b02f21, 0xd000b02f, + 0xb02f00b0, 0x59531021, 0x02202206, 0x059b5e00, 0x28065955, 0x04b0d004, + 0x000db22f, 0x21158302, 0xfb582f0d, 0x07b22305, 0x0f821404, 0x1419b223, + 0x29068204, 0x03093130, 0x37363405, 0x75443636, 0x33072105, 0x2c056b54, + 0x06060714, 0x15231715, 0x15330333, 0x08038323, 0x03180452, 0xfc41fcbf, + 0x1e0f0444, 0xa75c4a24, 0x02a09095, 0x2b3a02cb, 0x5b5d3839, 0xcacaca2f, + 0x0204044b, 0x52060404, 0x31fc31fc, 0x3af1cf03, 0x8727183a, 0x8b97804a, + 0x4034337f, 0x413c5f34, 0xaa5b4c5c, 0x0a044cfd, 0x0100049e, 0x00003a00, + 0xb005ea03, 0x3ca3f518, 0xea032408, 0x02f4d4fd, 0x0344fd2c, 0xfa2905b0, + 0xc3ed04d7, 0x00020000, 0x0456fe4f, 0x004e0417, 0x0026001b, 0x511fb283, + 0x1f23055b, 0x4f0cb010, 0x72180b2d, 0x0c241414, 0x0cb11b2f, 0x2007c566, + 0x06ec7418, 0x0406b228, 0x39121118, 0xa54d0cb0, 0x10b2220b, 0x21148312, + 0x1b8516b2, 0xac571820, 0x04b0210b, 0x390bc45b, 0x34133130, 0x32333636, + 0x11333717, 0x22230014, 0x16372726, 0x35363233, 0x0b820635, 0x14372622, + 0x53080c82, 0x23261137, 0x6d4f0622, 0x69bf85cd, 0xfbfed110, 0x49b955ef, + 0x8e908235, 0x7fae6a83, 0x8ff372cc, 0x45469578, 0x028d7c94, 0x8dfba026, + 0x1cfc7286, 0x2ff6fef6, 0x9c4cb02d, 0x8c77169b, 0xc09f9dfc, 0x7bd90181, + 0x010000c1, 0x4bfeb0ff, 0xcd008e01, 0x2e000d00, 0x2008fb66, 0x05dd440e, + 0xcd820520, 0xda820520, 0x4b0ab221, 0xb02e084b, 0x0db0100e, 0x2f0db0d0, + 0x11253130, 0x8f820714, 0x35389a84, 0x708e0111, 0x3846955b, 0x7c3d240e, + 0xc8f7fecd, 0xc6114f62, 0x0501b20c, 0x002e6182, 0x019afe5c, 0x00b5004f, + 0x00120003, 0xa51804b0, 0x3b080cbb, 0x23013130, 0x4f013311, 0x9afef3f3, + 0x02001b02, 0xd0047500, 0xdc06f702, 0x20000c00, 0xb0007b00, 0x06b02f03, + 0x2f06b0d0, 0x060f0b40, 0x062f061f, 0x064f063f, 0x03b05d05, 0x0609b210, + 0x26086054, 0x0cb01006, 0x820cb0d0, 0xb0102e2a, 0x10b0d010, 0xd013b02f, + 0x402f13b0, 0x05f45d0d, 0x4f133f29, 0x06135f13, 0x5010b05d, 0xb02406db, + 0x1ab21013, 0x08365118, 0xb2211682, 0x200d891d, 0x06005e1a, 0x20061422, + 0x08128818, 0x82141321, 0x264008e7, 0x15062223, 0x33363427, 0x32331632, + 0xf7023536, 0xb0defeb0, 0x48464caf, 0x475f904a, 0x1f2a8138, 0x4561682a, + 0x1e2c882f, 0x65b0052c, 0x35657b7b, 0x01333c3a, 0x476b4b0f, 0x4d1b2532, + 0x2432476c, 0xd52add84, 0x0807f602, 0x1c000d00, 0xdd845900, 0xb0d00723, + 0x28dd8307, 0x2f071f07, 0x4f073f07, 0x20dd8507, 0x20dd890a, 0x06704107, + 0x0882b020, 0x2d054146, 0x14b0d014, 0x0e0fb22f, 0x39121114, 0xbf4515b2, + 0x1bb22308, 0x11820f0e, 0x01313022, 0x3521ae84, 0x05474533, 0x18272721, + 0x080b37a8, 0xf602072e, 0xaf9291af, 0x454450ad, 0x4808df4d, 0x9e07923f, + 0x01444e9f, 0x7962b005, 0x39346279, 0x7619333a, 0x361a1702, 0x2f445060, + 0x003a083a, 0xd324b384, 0x7e060003, 0x1122b382, 0x91415d00, 0x57b38a1b, + 0x088208b8, 0x84059141, 0x0f403cb9, 0x0e1f0e0f, 0x0e3f0e2f, 0x0e5f0e4f, + 0x5d070e6f, 0xb01010b0, 0xb019d011, 0x90182f11, 0x07333db7, 0xaf000323, + 0xb1b19596, 0x4c47494c, 0x80a9b665, 0x7c61b005, 0x3c34637a, 0xc0ce343c, + 0xe72d9984, 0xd1065c03, 0x1a000600, 0xb0008d00, 0x07674701, 0x50820420, + 0x182f0423, 0xdea918b0, 0x10033f07, 0xb0d005b0, 0x09402f05, 0x051f050f, + 0x053f052f, 0x02b25d04, 0x12110305, 0xd00ab039, 0x18820ab0, 0x4f0a3f29, + 0x6f0a5f0a, 0x425d040a, 0xa98205dd, 0x0d1f0d2c, 0x0d3f0d2f, 0x0d5f0d4f, + 0xa9820d6f, 0x5c420a20, 0x100d2307, 0x9e4114b2, 0x100a2309, 0x0d8917b2, + 0xb0101424, 0xc982d01a, 0x07272326, 0x37332523, 0x08123742, 0xc15c0329, + 0x01c1b2b3, 0x59ba932a, 0x247b313d, 0x595a291b, 0x267f2a3c, 0xe7042c1a, + 0xdfed8e8e, 0x2c425f3e, 0x6040181b, 0x851c2d41, 0x0a0423e1, 0xe182cb06, + 0x60001522, 0x0321e1b0, 0x27e18305, 0x07b01001, 0x2f07b0d0, 0xb223d885, + 0x820d0708, 0x0eb22115, 0xb223b388, 0x42070814, 0xb4850536, 0x2f421720, + 0x08af860d, 0xb9bb1628, 0x81383f07, 0x498c8907, 0xe7040138, 0x74faa2a2, + 0x1d18057d, 0x4b59693e, 0x3b074137, 0x4cff0200, 0x5c03da04, 0xab828306, + 0x5b000a27, 0x2f03b000, 0x128741b0, 0xb0d00123, 0x07d24301, 0xd2430920, + 0x5d042507, 0x060302b2, 0x52052c68, 0x072206f1, 0xb28219d0, 0x08b01823, + 0x05a14110, 0x0a0fb628, 0x0a2f0a1f, 0x5b415d03, 0x05230808, 0x03330323, + 0x9f9fd55c, 0xa12301d4, 0xd79d87fe, 0x8eda04dd, 0x015cfa8e, 0x0002000b, + 0x04e7047a, 0x8a90068b, 0xd005248b, 0x462f05b0, 0x403005f6, 0x1f000f09, + 0x3f002f00, 0xb05d0400, 0x02b01003, 0x02266b82, 0x04b2182f, 0x83830003, + 0x0e820620, 0x182f0622, 0x09241983, 0x2f09b0d0, 0x2a053d41, 0x1f070fb6, + 0x03072f07, 0x8309b05d, 0xb0192492, 0x82182f0a, 0x3320088b, 0x07272305, + 0x03330123, 0xa19d0123, 0x9fd42301, 0x3303d59f, 0x059dd8de, 0x8e8efae1, + 0xf5fea901, 0x20054143, 0x3c4143d4, 0xb0d01124, 0x62602f11, 0x12414305, + 0xb0101123, 0x20b28210, 0x11414310, 0x17332522, 0x260b4143, 0x72b794fe, + 0x43b10580, 0xcd2c0742, 0x010000c0, 0x69049400, 0x2b06a901, 0x6f108d6f, + 0x073513d3, 0x36343523, 0x3f832601, 0x55d30102, 0x6d532b06, 0x5985867c, + 0x27e183b6, 0x04000009, 0x008d0494, 0x0ff3f718, 0x146a1d20, 0x0c417506, + 0xad690620, 0x04092707, 0x39121102, 0xfd5309b0, 0x0ab2210b, 0x2b081484, + 0x21253130, 0x33012307, 0x21012301, 0xfe3f0303, 0x01f55f1e, 0xd501dfd7, + 0x0106fef6, 0xf9f9aa54, 0x73fb8d04, 0xba01b201, 0x76000300, 0x0a207b82, + 0x0e2a7b82, 0x1f001600, 0x1eb2a400, 0x55832120, 0xb0101e25, 0x82b0d002, + 0x47112005, 0x012006c1, 0x01207682, 0xde849087, 0x593e0f26, 0x000117b2, + 0x22082d83, 0xafb42f17, 0x0217bf17, 0x176fb45d, 0x7102177f, 0x0117ffb2, + 0x170fb271, 0x8fb47201, 0x02179f17, 0x825fb272, 0xcfb2210b, 0x3f201583, + 0xb4230482, 0x832f171f, 0x17bf222d, 0x521c83cf, 0xb223096b, 0x83170f08, + 0x18002050, 0x210ce140, 0x426a1001, 0xaf83180a, 0x11032710, 0x35363233, + 0x347a2734, 0x26440805, 0x01762323, 0x59ebdeaf, 0xe270605b, 0x66e4e2dd, + 0xd4fab464, 0x6567635b, 0xa58d04c6, 0x23834f9c, 0xa3638f17, 0xfefb01ab, + 0x9e4155c7, 0x4802aa05, 0x00464f45, 0x4f000100, 0x4304f0ff, 0x1b009d04, + 0x03b24e00, 0x0ac54018, 0xf7820b20, 0xf7870b20, 0x22088f54, 0x83030b0f, + 0x560b20a6, 0x03200c45, 0x230bf662, 0x0b031bb2, 0x33051744, 0x22230406, + 0x34351100, 0x32333636, 0x26231704, 0x11202326, 0x0805a44b, 0x42043746, + 0xd9f7fe11, 0x7eecfeec, 0x01d69cec, 0x0cf31404, 0xedfe727d, 0x7c788786, + 0xbf84010d, 0x012c01d5, 0xffa9440b, 0x70c2da8a, 0x488efe69, 0x7062b5b9, + 0x76000200, 0x2a040000, 0x0b008d04, 0x46001300, 0x151413b2, 0xb0246682, + 0x02b01013, 0x221ba941, 0x181001b0, 0x7f0bab8a, 0x33280eaf, 0x04322111, + 0x14151716, 0x2f08ab82, 0x20331103, 0x25103513, 0xa47b0176, 0x02900301, + 0xa8f9fe8f, 0x47018283, 0x04c9fe06, 0x9ffb8a8d, 0x8bfea33d, 0xf9fcc903, + 0x01435c01, 0x01000860, 0x03218f83, 0x208f84b5, 0x0a115c4e, 0x20073241, + 0x06275904, 0x060bb223, 0x20a88304, 0x0bae420b, 0x5304b021, 0x847a0ccb, + 0x3130260c, 0x21112101, 0x37038615, 0x0afe5f03, 0xc1fc4c02, 0xb7fd3c03, + 0xf801f601, 0x04c2cafe, 0xf2fec48d, 0x9e207f86, 0x09227f82, 0x7f854000, + 0x3b437284, 0x43b2200f, 0x7f83132e, 0x9c490620, 0x20718408, 0x2e738523, + 0x0efe5b03, 0xfd2803f3, 0x01f201cb, 0x8325fedb, 0x82d5206b, 0xff542c6b, + 0x044804f0, 0x001c009d, 0x781ab25c, 0x0a200afd, 0x0a20e582, 0x22102542, + 0x830a030e, 0x100a23f2, 0x648811b2, 0x1803b021, 0x210b8655, 0x22851bb2, + 0x182f1b21, 0x2c0cdc42, 0x21060725, 0x35110022, 0x32330010, 0x09324216, + 0x37203a08, 0x21352335, 0x96174804, 0xfef8d5fe, 0xf41601dc, 0xed19fad7, + 0xfe6c7912, 0x2801a0e4, 0xeb01f946, 0x018b1893, 0x4109012e, 0x2c010901, + 0x5c64c0c3, 0xb74089fe, 0xb1c839ba, 0x05274100, 0x04680427, 0x000b008d, + 0x12a74186, 0xdf43c18c, 0x18b02007, 0x26081c95, 0xb2593e0f, 0x44000609, + 0xb42d0570, 0x09bf09af, 0x3fb25d02, 0xb2710109, 0x820483cf, 0xb2722209, + 0x2e0983ff, 0x7201090f, 0x7f096fb4, 0xb4710209, 0x83ef09df, 0x835f2026, + 0x091c2212, 0x5c0b832c, 0x30220942, 0x885c2131, 0x11332e05, 0x04331121, + 0xf4fdf368, 0x0c02f3f3, 0x056e41f3, 0x0111fe23, 0x20b382ef, 0x20b88285, + 0x22b38277, 0x851d0003, 0x2f0224b3, 0x4402b11b, 0x4a840f86, 0x77013324, + 0x2a82f2f2, 0x24243582, 0x6403f0ff, 0x0e260a82, 0x05b22200, 0x8b52100f, + 0x82052008, 0x8305203c, 0x410b20c9, 0x3021088e, 0x0e284f31, 0xf3710235, + 0xe1cab2e3, 0x574bb7f4, 0xe0fc8d04, 0xafc0cfae, 0x415d5ead, 0x0c220b3f, + 0x67424b00, 0x82082012, 0x4208205b, 0xb0250f74, 0xb0584500, 0x1263180b, + 0x02062207, 0x298a8204, 0xb01006b0, 0x0ab2d001, 0x1e440601, 0x11072105, + 0x0945f818, 0x87f0013f, 0x016ef3f3, 0xfe2c014f, 0xfed30143, 0x83db01de, + 0x8d04a8fe, 0x0186fdfd, 0xfdf7fd7d, 0x05c5417c, 0x82940321, 0x000522db, + 0x20859228, 0x206b8202, 0x05fd5c02, 0x3007df4b, 0x21253130, 0x33112115, + 0x2b026901, 0xc2f3e2fc, 0x052341c2, 0x00007624, 0x0a828f05, 0x60000e24, + 0x234101b2, 0x8200200a, 0x8c002041, 0x0fc943c7, 0xee84d484, 0x18079755, + 0x22089a67, 0x82040001, 0x07b221d4, 0x0a200685, 0x30220684, 0xf8180931, + 0x23080d37, 0x015101b2, 0xf23e014e, 0xa8a0fe19, 0xf219a1fe, 0xb5fc8d04, + 0x73fb4b03, 0x3a023b01, 0x70038bfc, 0xc5fecbfd, 0x0421a388, 0x220a8267, + 0x85450009, 0x820520eb, 0x8705209c, 0x0c71418f, 0x450cb142, 0x022208a6, + 0xf8180005, 0x04221530, 0x6e42f267, 0x03f22405, 0x82e5fc1b, 0x03e43781, + 0x0200001c, 0xf0ff4f00, 0x9d046f04, 0x1c000e00, 0x03b24600, 0x56491e1d, + 0x45122006, 0x0d46065b, 0x46b02014, 0x5f181006, 0x10210c78, 0x05ff4500, + 0x33361226, 0x27110032, 0x080ca551, 0xfe6f0433, 0xfeeceddf, 0x9bf085da, + 0xf22001f0, 0x98868896, 0x94888799, 0xf8fe2c02, 0x3501ccfe, 0xac2e0c01, + 0xfe8b0701, 0x08f5fec7, 0xb7c0c0b7, 0xc3c7b235, 0x2ea783b6, 0x04000076, + 0x008d042c, 0x0013000a, 0x4604b24d, 0x04200503, 0x24096f4f, 0xb11b2f03, + 0x07284103, 0xe96a0120, 0x18b22006, 0x181725f8, 0x6a09074d, 0x212b055f, + 0x14151632, 0x33270706, 0x82353632, 0x232008ae, 0x01f36901, 0xf1fdd4e5, + 0x68f2fed4, 0xf3657977, 0x67fe9901, 0xadd58d04, 0xc403c6a9, 0x69575458, + 0x4c2c9183, 0x6c0430ff, 0x14009d04, 0x46002200, 0x0a23b318, 0x39411f20, + 0x82112006, 0x41112084, 0x0f240cba, 0x11b0593e, 0x200c296a, 0x0d7f6708, + 0x06140125, 0x62071707, 0x272205db, 0x3f413435, 0x6c3b0814, 0x9dcf636e, + 0x3432f6fe, 0x0184f29a, 0xef9cf182, 0x97f12201, 0x97978689, 0x02958988, + 0x48f1a32c, 0x09c98898, 0xaa01018b, 0x0501ab39, 0xfec8fe8e, 0xc0b708f4, + 0xb033b6c3, 0x47b6c3c9, 0x3934064b, 0x0d008d04, 0x61001600, 0x181705b2, + 0xb0391211, 0x0fb01005, 0x430bb750, 0xf3420c0d, 0x820d2007, 0x820d20cf, + 0x0eb2230c, 0x34830402, 0xd7460e20, 0x0ab2230b, 0x14830e00, 0x0c4b5318, + 0x01313023, 0x05857023, 0x07141526, 0x01211501, 0x08075e41, 0xdf480239, + 0xdac801f3, 0x1201e1f0, 0x34fefcfe, 0x696c6cd5, 0xa901d56f, 0x8d0457fe, + 0x5bebaab7, 0x020b25fe, 0x514e5f6b, 0x00010060, 0x03f0ff3e, 0x009d04ef, + 0xb2630025, 0x44272609, 0x092008d9, 0x09208d82, 0x4218a787, 0x032208b4, + 0x2182091c, 0x090db223, 0x1806821c, 0x210d47ac, 0x451803b0, 0x21200c2b, + 0xb0212984, 0x0bf25e1c, 0x3423af82, 0x56262426, 0x232007e4, 0x2305b842, + 0x16171614, 0x0a778a18, 0x32214b08, 0x68020336, 0x53b0cffe, 0xfed2c3f6, + 0x5f6578f3, 0xdd8f716e, 0x8accf8c0, 0x01f47ee5, 0x016f6100, 0x4c4f4232, + 0x925c8362, 0x51a0c8bb, 0x3a404d5d, 0xb236234c, 0x5dae998e, 0x4ac071aa, + 0x24000100, 0x16040000, 0x07008d04, 0x95462e00, 0x07cf4412, 0x1006b022, + 0x220ace77, 0x47d004b0, 0x353107ab, 0xfe160421, 0x83fef37e, 0xc903f203, + 0xc90337fc, 0x245382c4, 0x04f0ff67, 0x2653821e, 0xb235000f, 0x4111100c, + 0x31440825, 0x0898480c, 0x230ac36a, 0x0fb01008, 0x11245a83, 0x24200414, + 0x07937a18, 0x11372008, 0xfffe1e04, 0x00ff4afe, 0xe56c7ef1, 0xfd8d0404, + 0xdde0be01, 0xfdff02c1, 0xd4687300, 0x82000703, 0x82092071, 0x827220c5, + 0x6bf61871, 0x0c804308, 0x1b2f0724, 0x9d4107b1, 0x08844607, 0x05030122, + 0x3e050146, 0x21013717, 0x21012301, 0x12132a02, 0x01012201, 0xfef646fe, + 0x01010147, 0x034b4d38, 0x4573fb57, 0x2824050b, 0xe5050000, 0x0c200a82, + 0x0ce98918, 0x870c5043, 0x15a4440c, 0x58450023, 0x083b4cb0, 0x03010022, + 0xb2217b82, 0x20068505, 0xfaf7180a, 0x1803200b, 0x3e072ee6, 0xfeecaf4a, + 0xdbd8ebe6, 0xece6feeb, 0x01d6d8b1, 0xfb62032b, 0xfc410373, 0xfc8d04bf, + 0x8264039c, 0x821520f5, 0x824a20f5, 0x000b2293, 0x05bb4153, 0x480c244c, + 0x2e630c51, 0x1807200c, 0x2207a05e, 0x83040100, 0x85062086, 0x00032206, + 0x480d8306, 0x30220566, 0xe6180131, 0x23080b2d, 0x1c01f227, 0x8c0189fe, + 0xfaffe0fe, 0x8101e4fe, 0x1a0188fe, 0x9301fa02, 0xb5fdbefd, 0x67fe9901, + 0x42024b02, 0x05209182, 0x36209182, 0x8c0b8741, 0x0c874191, 0x8508ff41, + 0x686f8284, 0x013b05c7, 0x011d0221, 0xfe0b010e, 0x64fef25d, 0x7a020b01, + 0x07fd1302, 0xa1016cfe, 0x8200ec02, 0x00412461, 0x82f30300, 0x18092061, + 0x440cf3f7, 0xac420f22, 0x18b2200a, 0x0827f3f7, 0x7b027826, 0x6c024efc, + 0xa00395fd, 0x038dc2c2, 0x008ac43c, 0x4b000200, 0xaa02f5ff, 0x0d002003, + 0x46001700, 0x191803b2, 0x20069146, 0x06a14410, 0x1b2f0a25, 0x4e190ab1, + 0x03200628, 0x03210c82, 0x200c820f, 0x0f076c0a, 0xdb6b1520, 0x2223230d, + 0x43583526, 0x152c0805, 0x22233427, 0x33141507, 0xaa023732, 0x9f92909e, + 0xa090919e, 0x037275bb, 0x01046f77, 0xaaaa9f3e, 0xae9d989e, 0xa90c9ead, + 0x9aa9b89f, 0x8020ff82, 0x02239482, 0x18001303, 0x20081bb8, 0x20738205, + 0x20808705, 0x066a4601, 0x1005b023, 0x050557b0, 0x788a0320, 0x11232132, + 0x33253507, 0xc9b90202, 0x02136f01, 0x7792303a, 0x3c205182, 0xb2205182, + 0x1721e182, 0xafda1800, 0x47588712, 0xd06c07df, 0x1602280b, 0x39121100, + 0x830f03b2, 0x0fb02206, 0x64bf1810, 0x0cb2230a, 0x1b830f00, 0x06841520, + 0x21313024, 0xda183521, 0x7d2128af, 0xadda1801, 0xf5ff2312, 0xa382a902, + 0x7f002424, 0xcb5d1eb2, 0x820d200a, 0x870d20ef, 0x611720a3, 0xb223065f, + 0x820d1700, 0xb07c347c, 0xb4182f00, 0x00600050, 0x80b67102, 0xa0009000, + 0x185d0300, 0x220eafda, 0x4e06000a, 0x242006ee, 0x22082741, 0x842412b2, + 0x101723d0, 0x14891eb2, 0x08874118, 0x25059159, 0x23150622, 0xfd593634, + 0x54152006, 0x34270cb1, 0x0c012327, 0x18368451, 0x2114afda, 0xda18d201, + 0x022a18af, 0x00003500, 0x1503be02, 0x0f190a00, 0xe0870ee7, 0x22083243, + 0x83040901, 0x2f0123b6, 0xa18802b2, 0xd006b02c, 0xb01001b0, 0x08b2d00b, + 0x7646060b, 0x05e85805, 0x33013208, 0x23152315, 0x01272135, 0x35330133, + 0x5f5f0207, 0x9afebb5f, 0xbd6d0109, 0x0eba8bfe, 0xa3973a01, 0xf90179a3, + 0x16f225fe, 0x00010000, 0x02f5ff4f, 0x248382ae, 0xb26a001a, 0x0a69720d, + 0x1b2f0224, 0x888702b1, 0x7c470d20, 0x02b02206, 0x48d91810, 0x07b2230a, + 0x78820d02, 0x2f07b024, 0x968818b2, 0x1805b223, 0x6c148307, 0xb2230ced, + 0x82181311, 0x1ab22314, 0x06821318, 0x13313027, 0x21152113, 0x054e4107, + 0x22230626, 0x16332726, 0x08066641, 0x3462072f, 0xacfeec01, 0x83473e14, + 0x818ca38c, 0x05b902ad, 0x42437572, 0x7f013543, 0x94969601, 0x787a861b, + 0x52638499, 0x2844387d, 0x00020000, 0x2cbd824d, 0x002203b9, 0x001e0013, + 0x1f14b25b, 0x06396220, 0x6f180c20, 0xc5870b45, 0x21082f73, 0x976d1000, + 0x0ab96e0a, 0xc5881420, 0x6d0cb021, 0x30250b9e, 0x22150131, 0x25af8a06, + 0x36343535, 0x12820333, 0x14153808, 0x35363233, 0x91320234, 0x6b470d89, + 0x86a88775, 0xdef0ab93, 0x0f422d96, 0x0344357f, 0x625f9922, 0x777a8e45, + 0x319ba799, 0x57fee8d2, 0x91241724, 0x00743646, 0x82360001, 0x03ae22bc, + 0x0e195a15, 0x8547a887, 0x10052308, 0x938804b2, 0x6a7fb220, 0x3a8c8205, + 0x21012301, 0xae022135, 0x01c4adfe, 0x024cfe53, 0xfdac0278, 0x967f0254, + 0x44030000, 0x132b08bf, 0x24001c00, 0x07b29600, 0x69112625, 0x1426054f, + 0x1007b0d0, 0x1f4a22b0, 0x2070870b, 0x07204607, 0x11072222, 0x7c382d82, + 0x182f22b0, 0x902280b6, 0x0322a022, 0x2250b45d, 0x71022260, 0x102200b4, + 0x40290683, 0x02225022, 0x22d0b45d, 0x210d82e0, 0x9e8919b2, 0x19220222, + 0xb2233b82, 0x8522190c, 0x41b22070, 0x11210a4e, 0x74e21810, 0x0714210d, + 0x2206d348, 0x48373435, 0x5d0806f0, 0x34363201, 0x14062226, 0x22341316, + 0x32161415, 0x71970236, 0x8c8ea184, 0x9b7184a4, 0xfe9b8281, 0x414035e4, + 0x9740406a, 0x316033c4, 0x37744102, 0x7a6a803d, 0x3d806b79, 0x76697437, + 0x33e0fd76, 0x5a30305a, 0x56ab0133, 0x30302756, 0x46000200, 0xa302f7ff, + 0x13002003, 0x60001f00, 0x655314b2, 0x10142305, 0x501808b0, 0xff870bd1, + 0x08a47d18, 0x08100222, 0x0227ff84, 0x10b0182f, 0x8811b210, 0x02b022dd, + 0x20cf8b10, 0x0e1e4208, 0x22230622, 0x172bc686, 0x07061415, 0x36323523, + 0x5c373227, 0xcc82056a, 0xe7013708, 0x877e5a42, 0xa28b84aa, 0x13e0dc02, + 0x4e63798f, 0x33344223, 0x36013c41, 0x787d8a39, 0x3b97a6a4, 0x9301d9d7, + 0x4534ac52, 0x394e4148, 0x01004437, 0x87029000, 0xab6b2d03, 0xfd2d311b, + 0x029d0263, 0x0300aa87, 0x48049600, 0x9506a202, 0x0f310982, 0x4e001b00, + 0x2f0db000, 0xb0d019b0, 0x07b22f19, 0x08765a09, 0xb0d00223, 0x07525602, + 0x52560f20, 0x004f2707, 0x006f005f, 0xde825d07, 0xd003b025, 0x8203b019, + 0x100d23f7, 0x368813b2, 0x01313026, 0x07230733, 0x8306fa44, 0x593720e6, + 0x2e0805a7, 0x22232634, 0xe6bc0106, 0x6e8295f5, 0x696c4c4e, 0x636b514f, + 0x30242534, 0x34252430, 0xdec29506, 0x4d65644e, 0x4b62634a, 0x25313125, + 0x82333327, 0xfe0a329b, 0x041b044a, 0x0029004e, 0x00430036, 0x4408b29b, + 0x06057a45, 0xb0d03026, 0x3ab01008, 0x200b8371, 0x0661471b, 0x1b2f1625, + 0x821116b1, 0x1026260c, 0xb0d028b0, 0x411e1928, 0x08b2230b, 0x41842616, + 0x0fb22f24, 0x09830816, 0xb22f0f23, 0x086a5035, 0x351bb223, 0x2214820f, + 0x84081fb2, 0x10162325, 0x175c30b2, 0x10082309, 0x0d893ab2, 0xb2102623, + 0x820d8841, 0x162325f2, 0x06141515, 0x2727ed82, 0x17141506, 0x85161633, + 0x4224200d, 0x372105ad, 0x06cc4726, 0x01211723, 0x28208206, 0x36323316, + 0x25273435, 0x089c7303, 0x06227d08, 0x8a1b0415, 0x80ce733a, 0x73254551, + 0x8fcac3c2, 0xfed99afa, 0x7532b6f5, 0xc7fc645a, 0x71014b55, 0x312430fd, + 0xac867288, 0x40eafe93, 0x7758597a, 0x0375b875, 0x166955a0, 0x125fa964, + 0x034a2f23, 0x588e9a01, 0x799b62a6, 0x483259a5, 0x9e315177, 0xcaa2165f, + 0x13e5fb14, 0x4d423048, 0x096b405e, 0x4bb30202, 0x124e6766, 0x4d66664a, + 0x56000200, 0x5f04ebff, 0x10004e04, 0x6e001d00, 0x0a077f18, 0x53410920, + 0x2f092406, 0x4109b11b, 0x4d180753, 0x6b440cd6, 0x1f621808, 0x0900270c, + 0x39121102, 0x06840bb2, 0x7702b021, 0x09230c5e, 0x411bb210, 0x53080a2c, + 0x22230625, 0x10353502, 0x17323312, 0x13033337, 0x16140123, 0x37363233, + 0x23262635, 0x63030622, 0xe6c7f26e, 0x71e9c7e8, 0x736cdd1c, 0x7cc7fddd, + 0x177c6074, 0x73637d11, 0x01d9c47f, 0x010ff420, 0xd736010a, 0xfde2fdc3, + 0xa0f901e4, 0x2fa6abac, 0x00c5b9a5, 0x9b2ed182, 0xf2040000, 0x1600b005, + 0x61001e00, 0xd94518b2, 0x6a182005, 0x411809b7, 0x06490cd2, 0x20c48308, + 0x27eb820f, 0x593e0f0f, 0x010317b2, 0x4a052c57, 0x09220b1d, 0xd1491700, + 0xcd7b1805, 0x0a854f0a, 0x16074e08, 0x17141513, 0x27262115, 0x23263435, + 0x36322125, 0x21213435, 0x02fc9701, 0xf7fff529, 0xfe4705e5, 0x7b043bfc, + 0x01d3fe70, 0xfe819014, 0x02e3fef8, 0x05aafd56, 0xe3cdd9b0, 0xf6fe4565, + 0x1a3da973, 0x7479b831, 0x6d71ca80, 0x010000e6, 0x21c58200, 0xc5823005, + 0x58000c22, 0x1805b14b, 0x52214b5b, 0x2f2215c3, 0x97181fb2, 0x023d234f, + 0xfcfcac43, 0x01ac018b, 0x020cfe36, 0x02d0fe20, 0x0590fd70, 0x029cfdb0, + 0xfd47fd64, 0x28918309, 0x04000081, 0x00000635, 0x07434c0c, 0x0c1cd018, + 0x0ccd8f18, 0x530c1a42, 0x07270855, 0x12110208, 0x4f07b039, 0x945b0e7f, + 0x23112807, 0x33113311, 0x82012101, 0x6fe23c02, 0x0169f2f2, 0xfe1c010f, + 0xfe8f019f, 0xfed901e6, 0xfc000627, 0xfe9e019c, 0x41b5fd11, 0x1226061d, + 0x0b00b005, 0x1d414c00, 0x0cd44105, 0xa6180720, 0xe1410b71, 0xb768180c, + 0x03002208, 0x218b8201, 0x068505b2, 0x4d000921, 0x838b06e0, 0xfcfc973b, + 0x01190206, 0x02a5fd38, 0x02c8fe7f, 0x0566fd9a, 0x027ffdb0, 0xfd35fd81, + 0x070f411b, 0x18062224, 0x838c0a00, 0x20074067, 0x63b31806, 0x20838c0b, + 0x06827009, 0x0600b222, 0x06858385, 0x838c0820, 0x3a050641, 0x01f2f273, + 0xfe2a0159, 0xfedc0150, 0xfeeb01db, 0xfc180615, 0xfe9e0184, 0x83bafd0c, + 0xff3e2e81, 0x05ef0313, 0x002a0073, 0x2b13b26f, 0x1563502c, 0x089d5518, + 0x09220322, 0x23055c50, 0xb0d00cb0, 0x210c0159, 0xed6f09b0, 0x10b2230b, + 0x28831318, 0xb0102226, 0x22b0d01f, 0x230b4d6f, 0x280326b2, 0x6f501a82, + 0x3537230a, 0x72181533, 0x725009a4, 0x15072807, 0x26263523, 0x50143335, + 0xcf240974, 0xcba6a0a9, 0x24087550, 0xbda0aec3, 0x0c7550e3, 0x10b48627, + 0xc015dcd9, 0x0979508d, 0x11ac8629, 0xc713e1e1, 0x834ac09a, 0x00382eeb, + 0x041a0400, 0x001f009d, 0x201bb26e, 0x3d4f1821, 0x10b14f0d, 0x05131f22, + 0xb0212182, 0x0c3d7f1f, 0x7f180520, 0xb0340bc4, 0x08b0d007, 0x1000b0d0, + 0xb0d00cb0, 0x0eb0101f, 0x1013b0d0, 0x220be87b, 0x851a1f17, 0x162130ea, + 0x21072107, 0x36363335, 0x35232727, 0x18262733, 0x080a5671, 0x2117173c, + 0x85fe4703, 0x98025006, 0x0a65fc01, 0x01032b29, 0x06039ba0, 0xd9c2bfd8, + 0x4d5057f3, 0x01040557, 0xb2e50180, 0x0bc3c370, 0x93077d93, 0xd4eece69, + 0x7e6a61bc, 0x01006979, 0xd1820e00, 0x8d043f29, 0x95001800, 0x831900b2, + 0x05ca426c, 0x240c084f, 0xb11b2f18, 0x55de8718, 0x002208bd, 0x9b82180c, + 0x0c09b223, 0x22068201, 0x4d2f09b0, 0x403a05c1, 0x1f040f0d, 0x3f042f04, + 0x5f044f04, 0xb65d0604, 0x04df04cf, 0x5d0304ef, 0x401806b2, 0x0a200c42, + 0xf5820d89, 0xee5f0920, 0x10062507, 0xb0d013b0, 0x4f071773, 0x33250565, + 0x15072115, 0x22018221, 0x82213523, 0x27200801, 0x01333521, 0x01250221, + 0xfe0b010f, 0xdafed5be, 0xfe360110, 0xcafef2ca, 0xfe093601, 0xbefedcd3, + 0x2d06854f, 0x2a1d93b7, 0x91d9d991, 0x02931136, 0xeb820049, 0x00007624, + 0xeb829703, 0x32000526, 0x070601b2, 0x0d8b5218, 0x820f8d59, 0x114a1883, + 0x11212f0d, 0x03211123, 0xf3d2fd97, 0xc9032103, 0x488237fc, 0x00020022, + 0x2807c951, 0x00080003, 0x0905b23c, 0x0611540a, 0xb9460220, 0x14805806, + 0x0005b223, 0x18278202, 0x080a6d63, 0x21313021, 0x03330121, 0x21030727, + 0x97fb7204, 0x69f6b901, 0x01de1312, 0xfe8d04e3, 0xfd4d4bc9, 0x5603006f, + 0x0329086b, 0x20001200, 0x07b27600, 0x06a84a21, 0xd001b026, 0xb01007b0, + 0x24072b78, 0xb11b2f0f, 0x20cd870f, 0x260c8207, 0x593e0f07, 0x830f03b2, + 0xb07c2fef, 0xb4182f03, 0x03700360, 0x30b45d02, 0x06824003, 0x0300b224, + 0xe98a7101, 0x0419b020, 0x58820caa, 0x230d6846, 0x05213521, 0x271ba156, + 0x5afe3803, 0x3701a601, 0x2314a756, 0x76c3df01, 0x201ca956, 0x084f4101, + 0x38000826, 0x0a0907b2, 0x4108a341, 0x6f5a1447, 0x0207220d, 0x412e8200, + 0x25080549, 0x27012101, 0xfe0a0107, 0xf6b901ff, 0xfffeba01, 0x1312defe, + 0x73fb8d04, 0x4d4b5603, 0x42000300, 0x55030000, 0x09828d04, 0x0b000728, + 0x04b25e00, 0x7f550d0c, 0x00b02405, 0x4b04b0d0, 0x93520965, 0x0853500c, + 0x2209945a, 0x830a07b2, 0x07b02473, 0x4804b22f, 0xb0220853, 0xc474100a, + 0x268f830a, 0x21032135, 0x82132135, 0x55032b03, 0x1303edfc, 0x027efd49, + 0x09834982, 0x3801c326, 0xc40a01c4, 0x21069d42, 0x93826204, 0x3f000722, + 0x0cef7018, 0x1b2f0624, 0x545906b1, 0x08d04514, 0x5b0eb177, 0x21280628, + 0xfdf46204, 0xec03f3fb, 0x2207ad42, 0x82440001, 0x82e620f7, 0x000c2563, + 0x0d00b24b, 0x0961d718, 0x590ce954, 0x0120080e, 0xf953d288, 0x08b02306, + 0x9c66b210, 0x2efc8209, 0x39121108, 0x01013130, 0x35211521, 0x82350101, + 0x01280806, 0xe6fe9002, 0x5efc7002, 0xc1fe3f01, 0xbafd7c03, 0x45021601, + 0x98c47ffe, 0xa601b701, 0x8ffec498, 0x50000300, 0x4d050000, 0x11288582, + 0x1c001600, 0x08b26f00, 0x24053759, 0x14b01008, 0x216282d0, 0x3b431ab0, + 0x82102006, 0x541020f9, 0x0f250cb2, 0x0fb2593e, 0x29758310, 0xb02f0fb0, + 0x09b2d000, 0x7c441008, 0xd0062206, 0x1b7418b0, 0x0fb0210c, 0x820bb156, + 0x14b02553, 0xd01bb010, 0x5b08ad82, 0x14150416, 0x23150704, 0x35242635, + 0x35372434, 0x05020133, 0x34050411, 0x24112726, 0x01f04903, 0xede9fe14, + 0xeafef0f3, 0xf3ef1701, 0x0104f9fd, 0x03ecfe18, 0x01829019, 0x0f150412, + 0xfad0caf6, 0x0f6c6d0f, 0xf7cdd0f9, 0xb7fd780d, 0x0215fdfe, 0x85fb152a, + 0xd6fd0a81, 0x01000015, 0x0320db84, 0x1822db82, 0x4f454b00, 0x8212200c, + 0x451220cb, 0x16221042, 0xbe83120c, 0xcb831620, 0x1012b02a, 0xb0d017b0, + 0x16b0d004, 0x200c9370, 0x2fb3830a, 0x11353636, 0x07061133, 0x23110706, + 0x03022611, 0x34080c82, 0x11171614, 0x7f230333, 0x6801f36e, 0xe3f3fa7d, + 0x70f302fb, 0xdd01f37d, 0x01a7c218, 0xe3cdfe2f, 0xfe1daf93, 0x161701e8, + 0x00012a01, 0xd1fe3601, 0x0218c0a8, 0x2ca182af, 0x0400005f, 0x009d0484, + 0xb25c0023, 0x01461807, 0x8219200a, 0x871920a1, 0x4a0f20a1, 0xb0240684, + 0xb0584500, 0x2207bc47, 0x5e100fb0, 0x0e260b99, 0xd000b0d0, 0x591819b0, + 0x11260c33, 0xd020b010, 0xb28221b0, 0xb2822520, 0x2006404e, 0x24aa8215, + 0x33352115, 0x06d56026, 0x15004008, 0x07061415, 0x02211533, 0x946c78ad, + 0x76948a8d, 0xb030fe74, 0x9cf283bd, 0x632a01ea, 0x2ffeb659, 0xb0c922c8, + 0xa9ac9e2b, 0xc7b128a4, 0x9bc4c823, 0x91162701, 0xe3fe84ec, 0xdf8d19ed, + 0x8200c44a, 0xff242cc5, 0x045205ec, 0x0019008d, 0x1816b26b, 0x870f2356, + 0x820e20c5, 0x590e20c5, 0x18200781, 0x18200c82, 0x168c5518, 0x0208b223, + 0x058a4d0e, 0x100eb024, 0xf56f0fb2, 0x08b02108, 0x2c0b4442, 0x21013130, + 0x21152135, 0x32333615, 0x21c28216, 0xf05a3523, 0x222a0805, 0x01231107, + 0x03a6fe7e, 0x8aa0fead, 0xf0f0da8d, 0x747673eb, 0xf3858175, 0xc4c4c903, + 0xc6d427ee, 0x54bdc0bc, 0x26677269, 0x3962e7fd, 0x001d240a, 0x1803b28f, + 0x570ad959, 0xb2201486, 0x21133962, 0x4e6215b2, 0x2f152d05, 0x0115ffb2, + 0x150fb271, 0x3fb27201, 0xcf200983, 0xb42f0482, 0x157f156f, 0xafb47102, + 0x0215bf15, 0x835fb25d, 0x838f201c, 0xbd661804, 0x03b02109, 0x200c6448, + 0x197a621d, 0x82032221, 0x161624ef, 0x62363233, 0xfb28147c, 0xfe800116, + 0x837e0a80, 0x37138162, 0x9f94c4cf, 0x02007062, 0x00002400, 0x8d041507, + 0x20001700, 0x04b27600, 0x2405b746, 0x18b01004, 0x056b48d0, 0x560c1b43, + 0x00210893, 0x090b5f45, 0x7d12b021, 0x0b200c4f, 0x0b4c5918, 0x1214b229, + 0x39121103, 0x182f14b0, 0x820b6745, 0x0c555de1, 0x07061437, 0x03211121, + 0x23060206, 0x36373723, 0x21133736, 0x16323311, 0x050c6425, 0x23264008, + 0xcff91507, 0xa4fe15fe, 0xac580b0e, 0x26013491, 0x150c4e60, 0xdaec3b03, + 0xf140fdfa, 0x66767567, 0xd2ab7f01, 0xfec90302, 0xfffeef9c, 0x0702cd75, + 0x2b02ed9f, 0x0cd06cfe, 0x536b8efe, 0x5c006351, 0x0721051b, 0x25e58218, + 0x001c0013, 0xb718b2c1, 0x132411bf, 0x13b11b2f, 0x870cf857, 0x8210200c, + 0x5c102019, 0x00221028, 0xd6831310, 0xb42f002f, 0x00bf00af, 0x3fb25d02, + 0xb2710100, 0x820483cf, 0xb2722709, 0x7201005f, 0x0e83ffb2, 0x09820f20, + 0x006fb42a, 0x7102007f, 0xef00dfb4, 0xb4232b82, 0x822f001f, 0x9fb22106, + 0xb2231982, 0x83020d04, 0x2f042448, 0x771000b0, 0xb0210aa7, 0x0c164f04, + 0xe9420d20, 0x33112d0f, 0x16323311, 0x06141516, 0x21112123, 0x0d699718, + 0x01692108, 0x8cf2f3fd, 0xd2ff6fd2, 0x03fe1ffe, 0xf002f3f3, 0x767567f1, + 0x019e0266, 0x5f6cfeef, 0xd0af70ab, 0x21059661, 0x1f41a8fd, 0x00012e07, + 0x05000024, 0x008d0452, 0xb2570015, 0x0a057c12, 0x240cfa5a, 0xb11b2f14, + 0x0f0a4114, 0x1003b022, 0x250b5e47, 0x08b2d000, 0xae430314, 0x0a8f4405, + 0x200c9d43, 0x22af8217, 0x43232634, 0x86270b99, 0x04ebde8e, 0x437474f3, + 0xed350697, 0xfecbcf26, 0x7c5a0198, 0xe7fd2669, 0x00010000, 0x049ffe76, + 0x269f8261, 0xb24f000b, 0x820d0c03, 0x0dcc795f, 0x4807ad41, 0x89481413, + 0x4708200d, 0xb0260838, 0x3130d009, 0x8d822121, 0x62112121, 0x612c05b8, + 0xfef38afe, 0x0502f37e, 0x019ffef3, 0xfc236f82, 0x42ca0336, 0x0421053d, + 0x267d8428, 0xb25e0014, 0x84161508, 0x09a15fdf, 0x4d61758c, 0x46561808, + 0x03b2230c, 0x3583080a, 0xb02f0323, 0x0cbd6508, 0x080cbc7c, 0x0131303d, + 0x16331521, 0x23061016, 0x01211121, 0x34353632, 0x11232726, 0xb7fdb203, + 0xf8f4cffc, 0x031ffed9, 0x68a8fe3c, 0xf6667073, 0x03e0cb03, 0xcca8fec4, + 0x36fc8d04, 0x5d4f5463, 0x829cfe01, 0xfe2724a9, 0x821505af, 0x000f28a9, + 0xb25b0015, 0x66171613, 0x0524064f, 0x0db000d0, 0x5c0ac96e, 0x63620c5e, + 0x06f64c0d, 0xb0100d24, 0xab82d00a, 0xd010b027, 0xb0d011b0, 0x0b1d6705, + 0x37313025, 0x1837023e, 0x081065aa, 0x424a8233, 0x030c0523, 0xfcf2963d, + 0x0101f3f7, 0xfef00174, 0xc30d07a1, 0x7eb48651, 0x36fcc101, 0x5101ecfd, + 0x1402affe, 0xfefc0603, 0x000100ae, 0x0600001a, 0x24ab821f, 0xb29e0015, + 0x0a734201, 0x240c5d60, 0xb11b2f0e, 0x14dd410e, 0x0c157518, 0x200c9844, + 0x20338215, 0x22d48315, 0x830e030c, 0x2f0c2dff, 0x010c3fb2, 0x0c5fb271, + 0xcfb27201, 0xb4300982, 0x0cbf0caf, 0x8fb45d02, 0x020c9f0c, 0xd00fb072, + 0x250b7478, 0x08b2d004, 0x3782040f, 0x0113b223, 0x0542490f, 0x82112321, + 0x21032101, 0x0d83aa18, 0x5ff50338, 0xfefc60f3, 0xfe5c01d3, 0xf71e01c4, + 0xf754f354, 0xc2fe1e01, 0x12825e01, 0x2bfed523, 0x27038201, 0x39025402, + 0xe00120fe, 0xfd240383, 0x00a3fdd0, 0x422cf582, 0xe703f0ff, 0x27009d04, + 0x26b28a00, 0x420a5d79, 0x1f7b0c43, 0x4e0a2008, 0xb2230b90, 0x82160a06, + 0x26b22190, 0xb0250684, 0xcfb22f26, 0x20d68226, 0x2804823f, 0xbf26afb4, + 0xb25d0226, 0x220b82ff, 0x82260fb2, 0x835f20e7, 0x42232004, 0xb22308eb, + 0x83262310, 0x161c223b, 0x175c180a, 0x31302110, 0x20066e74, 0x078a5523, + 0x1616072d, 0x23041415, 0x26272622, 0x54163335, 0x3f080582, 0x36333523, + 0x6b70e202, 0xf3f3665b, 0x6ef4d8c3, 0xfe6e6f5d, 0xaf5ddcfe, 0x0bf37c3f, + 0xe07477ca, 0x03c79a94, 0x464f4643, 0xa7b3943c, 0x278a5b96, 0x9f5b9124, + 0x5b2f2db5, 0x4857939f, 0x04b003a6, 0x2b05e34d, 0x8d046e04, 0x4c000900, + 0x0b0a00b2, 0x0d355b18, 0x4f0c4b4a, 0xb0200fae, 0x0c0e4218, 0x00030422, + 0xb2233b82, 0x41080509, 0x333c059f, 0x01112311, 0x11331123, 0xf3f37b03, + 0xf3f3eefd, 0x73fb8d04, 0xddfc2303, 0xe0fc8d04, 0x40207786, 0x0c227782, + 0x594b7700, 0x0c8f6419, 0x4f0c9e52, 0x06220854, 0x70820502, 0x2f06b02e, + 0x01063fb2, 0x065fb271, 0xcfb27201, 0xb42d0982, 0x06bf06af, 0x8fb45d02, + 0x02069f06, 0x0a4c4272, 0x1966b220, 0x52232008, 0xd33c0b37, 0x63f3f36a, + 0x1d013801, 0xad0172fe, 0xd501d1fe, 0x8d042bfe, 0xe00120fe, 0xaefdc5fd, + 0x20064761, 0x26af8255, 0xb24d0010, 0x41121104, 0x31521527, 0x00b02114, + 0x200cc150, 0x0b6a4409, 0x24068954, 0x06020603, 0x06664707, 0x55042508, + 0x0fa4fef3, 0x8caa570c, 0x6227013a, 0x04160c4a, 0x0373fb8d, 0xed9ffec9, + 0x0178fefe, 0xa00b04cd, 0x002b02e6, 0x1f249182, 0x3904ecff, 0x0f249182, + 0x00b24300, 0x4e0a8561, 0x064e0ccf, 0x0706450c, 0x0801b223, 0x7dc0820f, + 0x87820ad2, 0x13172008, 0x020e0121, 0x17372723, 0x21013732, 0xf3132902, + 0x70fe0a01, 0x5a7e5a38, 0x60570166, 0x825bfe33, 0x374b2e1d, 0x7efc7902, + 0x0538697e, 0x036104c0, 0x2485837f, 0x05affe76, 0x24858224, 0xb242000b, + 0x06054609, 0xd5440320, 0x0c0e6005, 0x610c4b43, 0xf84508a3, 0xd000280a, + 0x33253130, 0x45112303, 0x623407f8, 0xfcdd14c2, 0x0502f343, 0xecfdc3f4, + 0x8d045101, 0xca0336fc, 0x4121f782, 0x05d16200, 0x46001122, 0x111fa818, + 0x650c2248, 0x0d2210a0, 0xf7820901, 0x4e0db021, 0x30200b7d, 0x071da818, + 0x33112723, 0x05ba7411, 0x1604333c, 0xea8186f3, 0x6ff301f0, 0xf3858279, + 0xd226aa01, 0xfe6601d1, 0x266c779e, 0xbb421f02, 0x0e062105, 0x4122f384, + 0xf38607b2, 0x90080c43, 0x0ae84e74, 0xb0100324, 0x2f4fd006, 0x06b02405, + 0x460ab010, 0x332005eb, 0x062af287, 0xf368fa0e, 0x01f35f01, 0xed85f360, + 0x7624f186, 0xd106affe, 0x0f246f82, 0x0bb24100, 0x4106e941, 0x3f5e1363, + 0x44002008, 0xb0270863, 0x09b0d00d, 0x8307b0d0, 0x0eb0216c, 0x830e6241, + 0x0f062677, 0xfadd14c2, 0x41768596, 0x7b840b69, 0x0a000226, 0x1b050000, + 0x0c287b82, 0x5e001500, 0x171608b2, 0x20066747, 0x068b4a14, 0x450ce441, + 0x072008f2, 0x230b7e4a, 0x03070ab2, 0x0a233583, 0x4d03b02f, 0xc0540da9, + 0x3130220b, 0x05734a01, 0x11213525, 0x47163233, 0x05330868, 0xfecff91b, + 0x02a2fe15, 0xf9dbeb52, 0x756632fe, 0x4af96271, 0xc430065c, 0xfed06cfe, + 0x4f536b9a, 0x8efe0263, 0x7600ffff, 0xa920ab82, 0x262aab82, 0x00000802, + 0xc2010700, 0x07823204, 0x4805d16d, 0x4d22072b, 0x2b4803b2, 0x48032005, + 0x3150092b, 0x07b22314, 0xf8560604, 0x41132006, 0x034a094e, 0x20b2840c, + 0x83ae8223, 0x2ab189b0, 0xd2ff2804, 0xf2f31ffe, 0x886fd28c, 0xd0af29af, + 0x6cfe8d04, 0xd4feab5f, 0x002eae86, 0x3c000100, 0x3004f0ff, 0x1d009d04, + 0xd94c8700, 0x0cdf4b0c, 0x1b2f1a2b, 0x3e0f1ab1, 0x1a00b259, 0x218f8212, + 0x8c8803b2, 0x1209b223, 0x05cc4f1a, 0x2008246c, 0x071a6c71, 0x6c06416c, + 0xb2240832, 0x7201095f, 0x0b5f7818, 0x41181220, 0xb2210bd1, 0x8249840e, + 0x05ba4ccf, 0x21352128, 0x06222302, 0xa6182307, 0x42080b8f, 0x2f012724, + 0x82787c0d, 0x7ffe0a80, 0xfb168001, 0xf30c7d72, 0xd6040114, 0x0c1701e2, + 0x9bea7b01, 0x0ff8fedc, 0x62708401, 0x01c4949f, 0xc2706931, 0xf0e8feda, + 0x88ffa975, 0x0000bada, 0xff760002, 0x824106f0, 0x001328eb, 0xb2af0021, + 0x83232204, 0x180420b9, 0x50096343, 0xda4d0cbb, 0x0c176b14, 0x080db223, + 0x05ca430b, 0xafb42008, 0x020dbf0d, 0x0d6fb45d, 0x71020d7f, 0x010dffb2, + 0x0d0fb271, 0x8fb47201, 0x020d9f0d, 0x825fb272, 0xcfb2210b, 0x3f201583, + 0xb4230482, 0x822f0d1f, 0x4110832d, 0x10230c0e, 0x4117b210, 0xb0210858, + 0x0d107103, 0x00100125, 0x18002223, 0x21070074, 0x676a0036, 0x41063011, + 0xdeeddffe, 0xbc13e2fe, 0x14bcf2f2, 0x6adc1d01, 0x102a126d, 0x041efee2, + 0xe918fe8d, 0x706a0f01, 0x0002260e, 0x04000043, 0x06654312, 0x06b25a22, + 0x21056543, 0x59181006, 0x654308ff, 0x088a580c, 0x07091128, 0xb0391211, + 0x64522f11, 0x0a01220b, 0x09305811, 0x224a0720, 0x3343080d, 0x34352601, + 0x11213336, 0x03231123, 0x33161413, 0x22231133, 0x16014306, 0x01d3f0d6, + 0xe6f1f3cc, 0xdd6b612e, 0x026b61dd, 0xa3d1560a, 0x0173fbb9, 0x0344febc, + 0x01594a22, 0x0000574a, 0x000a0001, 0x82ff0300, 0x000d26a5, 0x0e01b250, + 0x15f7670f, 0x1b2f022b, 0x3e0f02b1, 0x0207b259, 0x063f4308, 0x1f500420, + 0xd0012309, 0x794208b0, 0x07b0260b, 0xd00cb010, 0x05ba6930, 0x3335233f, + 0x21152111, 0xa7023311, 0xd4d4f3d6, 0xd2fd2103, 0xfee601d6, 0xaae6011a, + 0xfec4fd01, 0x248383c7, 0x06affe1a, 0x2483826d, 0xb2a40019, 0x06c75008, + 0x4a060b45, 0x62460ca4, 0x00b02407, 0x18b05845, 0x6a0ce844, 0x17220859, + 0xa0831109, 0xb22f1726, 0x7101173f, 0x73094273, 0x5a73076b, 0x42072006, + 0xb2230817, 0x56170700, 0x4f4805ae, 0x25c1830a, 0x0fb2d00b, 0x4c840717, + 0x12b0102b, 0x1011b0d0, 0xb0d014b0, 0x26d78318, 0x23113313, 0x4a032311, + 0x042611ae, 0xd0beeec1, 0xb04afdab, 0x5d022812, 0xedfd65fe, 0x4a015101, + 0x002f12b2, 0xfe760001, 0x047c04af, 0x0010008d, 0x4800b288, 0x04200689, + 0x24057147, 0xb11b2f0c, 0x0c92520c, 0x01410c87, 0x08a6680c, 0x0c090d22, + 0x24054443, 0x010d3fb2, 0x092a4371, 0x43075343, 0xa5470642, 0x00b22309, + 0x31830d08, 0x41100621, 0x30230a01, 0x84010131, 0x490120e5, 0x02280851, + 0xc8210193, 0xc2fe9bd0, 0x23075549, 0x70fe5202, 0x5749d387, 0x05474705, + 0x82fe0421, 0x001426c9, 0x1505b280, 0x084f4216, 0xc6821420, 0xb9871420, + 0x200c9c45, 0x20198211, 0x07ee4e11, 0x2109165c, 0xf94f1411, 0x05f24f05, + 0x01005f28, 0x00cfb272, 0x08507101, 0x8fb42a06, 0x02009f00, 0xd004b072, + 0x0df774b0, 0xb2d00c25, 0x4a000c08, 0x352306af, 0x5b331533, 0x232305bf, + 0x84352315, 0x012508c9, 0x37a34769, 0x1c013801, 0xae0172fe, 0xc2fed1fe, + 0xf347a33e, 0xdead02f3, 0xfde001de, 0x01affdc4, 0xfecbcbd5, 0x053f6a2b, + 0x00002424, 0x0a824e05, 0x85000e24, 0xef6f09b2, 0x0cb9430a, 0x4a0c0449, + 0x5a180ccf, 0x082208e9, 0x90820702, 0x2f08b02a, 0x01083fb2, 0x085fb271, + 0x0982cb83, 0x08afb42b, 0x5d0208bf, 0x9f088fb4, 0x0ccf4a08, 0x4f07b021, + 0x84180bec, 0x02271767, 0xfef36ae1, 0x4a5302a0, 0x03240ee2, 0x20fec3ca, + 0x0033cc85, 0xff4f0002, 0x049805eb, 0x002300a5, 0xb28c002e, 0x83302f15, + 0x10152189, 0x08013419, 0x1b2f1b24, 0xa64e1bb1, 0x1466570c, 0x2109f757, + 0x7f181b04, 0x134d25dd, 0x02b02a09, 0xd026b010, 0xb2101bb0, 0x0876432c, + 0x05313038, 0x23062722, 0x35030020, 0x15330034, 0x15150622, 0x33331614, + 0x0f822637, 0x3233122d, 0x10151712, 0x01331607, 0x63361710, 0x56080581, + 0xe3980511, 0xfea991ae, 0x04acfeda, 0x71db0801, 0x1bc0cb7f, 0xdc02c01b, + 0x01ddc6bf, 0xfd5c5fa3, 0x01a2be94, 0x10b35b53, 0x3c013e39, 0xfe3a1801, + 0xb4cc2e01, 0xcdcb26b1, 0x1e01aa02, 0x0d01ea2c, 0x48ecfcfe, 0x0badfffe, + 0xf4fed201, 0x35f3786f, 0xd2fe90a0, 0x6a00ffff, 0x263c07fb, 0x0000d201, + 0xde010700, 0xd5fe3b00, 0x15000100, 0x8b04affe, 0x0f008d04, 0x0ab25a00, + 0x20069d49, 0x058f4307, 0x4b0c145c, 0x0b200c97, 0x4406b472, 0xb2260c9e, + 0x110b0f00, 0xbb513912, 0x0ab2230a, 0x9f420f0b, 0x21132105, 0x21066443, + 0x09820303, 0x6b022121, 0x092306b0, 0x6b92cfc4, 0xfe250fb1, 0x01edfd77, + 0x0ab56b51, 0xaffe2424, 0xa1842e06, 0x09b25c22, 0x0220a186, 0x0a7e5018, + 0x410cfe55, 0xea5a0fd2, 0x1808200b, 0x240bec4f, 0xb0d00ab0, 0x078b5d0b, + 0x4bd00d21, 0x250808bd, 0x15213521, 0x11211121, 0xc46a0533, 0x44fcde14, + 0xa203a4fe, 0x0602acfe, 0xecfdc3f2, 0xc9035101, 0xfafcc4c4, 0xeb6bca03, + 0x16042106, 0x17249782, 0x04b24f00, 0x0a136c18, 0x240cc644, 0xb11b2f16, + 0x10544b16, 0x0c011029, 0xb0391211, 0x45b22f10, 0xb027099e, 0x10b0d004, + 0x8213b010, 0x2321298a, 0x15070611, 0x26263523, 0x0805d54b, 0x3335172d, + 0x11373615, 0xf3160433, 0xcca3564c, 0x54f302cf, 0x584aa356, 0x16aa01f3, + 0x0dc8cc0a, 0x6a01bfd1, 0x696b9ffe, 0x09f2f30c, 0x831f0218, 0x0076249b, + 0x824b0400, 0x0f654c9b, 0x540cd241, 0x96470c88, 0x10042208, 0x239b8301, + 0x0db22f04, 0x260ac342, 0x36113313, 0x18163233, 0x080a65cb, 0x86f3762f, + 0xf3efed80, 0x85817475, 0xfe8d04f3, 0xd1d62656, 0x61019efe, 0xfd26697c, + 0x000200e0, 0x05f0ff0a, 0x00a304a8, 0x0023001b, 0x240db264, 0x23548325, + 0x1db0100d, 0x5106794b, 0x73430c86, 0x0e202208, 0x20278300, 0x7d7f1820, + 0xd003290c, 0xb01020b0, 0x00b0d00a, 0x200ce359, 0xd44a180e, 0x0548080d, + 0x26270020, 0x14333526, 0x023e1716, 0x11002033, 0x21122115, 0x17373732, + 0x22030606, 0x35210706, 0xc9032634, 0xc0fefafe, 0xc1bfae0c, 0x8f095854, + 0x000191f1, 0xc0fc1701, 0x864f0112, 0x3b412f73, 0xa080a1c5, 0x954c0208, + 0xea3dff82, 0x5dbbdd0b, 0xe4920c76, 0xfee5fe7e, 0xd0fe95f7, 0x21ba122b, + 0xa5ee032c, 0x9586168c, 0x24dd8200, 0x04f0ff4f, 0x24dd8281, 0x001e0016, + 0x69ed185e, 0x0c7f5017, 0x3ba37b18, 0x14151725, 0x82230606, 0x354b08d2, + 0x23262621, 0x27070722, 0x32133636, 0x15213736, 0x39021614, 0x3b010b01, + 0x96f98c02, 0xebfefefe, 0xb3073f03, 0x2d7686a6, 0x98c94041, 0xfd0a9e81, + 0xa30494b4, 0x7af9dcfe, 0x0188f99b, 0x9508011c, 0x112c9a96, 0xfc2b22ba, + 0x848ea312, 0x00012ec9, 0x03ecff42, 0x008d04e8, 0xb2690019, 0x17595912, + 0x2008ef43, 0x0b687102, 0x0204b22a, 0x39121100, 0x020b19b2, 0xb0270682, + 0x05b02f19, 0x850fb2d0, 0x0df4740c, 0xb2101923, 0x08454918, 0x01313025, + 0x18213521, 0x22099d7b, 0x52163335, 0x2e080510, 0x02352323, 0x03defd8d, + 0xc6fe0152, 0x00ffc2a2, 0xf3f7d0df, 0x73657104, 0x037df173, 0xfe9bc4c9, + 0x8bbf14c0, 0xa1b9c0a8, 0x535a5049, 0x5f00bbb0, 0x0e260923, 0x1c001500, + 0x91757e00, 0xd00f230a, 0x235f03b0, 0x15904b09, 0x5a7ca282, 0x0b13220a, + 0x2fc48203, 0x2f13b07c, 0x1360b418, 0x5d021370, 0x401330b4, 0xb2290682, + 0x5d0113f0, 0x011300b2, 0x18528271, 0x220b094f, 0x58b21013, 0x275f0c73, + 0x2201230d, 0x9f180706, 0xc975091b, 0xf0fd300d, 0x020e9479, 0x78930e36, + 0xfd0e9179, 0x75950fcc, 0x012b12d1, 0x95959d7f, 0x9ddbfc9d, 0x629d9393, + 0x27240b8b, 0x25b2ae00, 0x240ae553, 0xb11b2f1d, 0x10695c1d, 0x0c1d0622, + 0xb03dcd82, 0x0fb22f06, 0xb05d0106, 0x01b0d001, 0x01cfb22f, 0x09405d01, + 0x012f011f, 0x014f013f, 0x82d48204, 0x02b22110, 0x23099961, 0x07b21006, + 0x5d0c546c, 0xb03609fd, 0x0fb0d00e, 0x1007b0d0, 0xb0d011b0, 0x13b01006, + 0x1002b0d0, 0x578216b0, 0x18b01028, 0x101db0d0, 0x2d4424b2, 0x21b22308, + 0x7d820124, 0x210cb22c, 0x31305d01, 0x21152101, 0x04821517, 0xd2620620, + 0x23372406, 0x62353335, 0x012c11d5, 0xfe8301c4, 0x7b010382, 0x261273fe, + 0x0805da62, 0x9612343c, 0x999e03a1, 0xbfd80601, 0x54f3d7c4, 0x05574d53, + 0x4292ba02, 0x35459316, 0x6c0ec3c3, 0x924a0e93, 0xd0eece27, 0x7e675ab6, + 0x01000079, 0xf0ff4600, 0x9e04b003, 0xa0002200, 0x76180ab2, 0x84450aef, + 0x08e8440c, 0x09162222, 0xb030a582, 0x0fb22f22, 0xb45d0122, 0x22202210, + 0x00b25d02, 0x500cb662, 0x00290afd, 0xd00cb010, 0xb01022b0, 0x3105840e, + 0x13b0d013, 0x13cfb22f, 0x1fb65d01, 0x3f132f13, 0x3b820313, 0xb2200d82, + 0x1b036318, 0xb0d01d26, 0x1fb01010, 0x0c036318, 0x27242226, 0x35333523, + 0x362b0382, 0x17323336, 0x22232607, 0x82152107, 0x034c0801, 0x1183fe4e, + 0x79506f7b, 0xd46e761b, 0x971afffe, 0x1a989292, 0x7a6cd3ff, 0xd6755b16, + 0xfe7c0122, 0x0183017d, 0x1c686a84, 0xc4d01fbf, 0xc3935c92, 0x1cbf20d6, + 0x005c93d6, 0x76000400, 0xc7070000, 0x03009e04, 0x1d000f00, 0xaa002700, + 0x23495c18, 0x24074542, 0xb11b2f24, 0x14c04a24, 0x5c182120, 0xb6282249, + 0x02100200, 0x5d030220, 0x200ab56e, 0x0c5f6fb0, 0x6c06b021, 0x5c180b8f, + 0x25230f4d, 0x18213521, 0x49114d5c, 0x0624051b, 0x01230115, 0x3b069b5a, + 0xc5fd8807, 0x8afd3b02, 0xc03601bf, 0xc1cafebe, 0x50535aaf, 0x4f5d0258, + 0xa6fe5d4e, 0x3807be79, 0xf20195c8, 0x9cb8b996, 0xb8b89648, 0x6557059b, + 0x57535462, 0xfc5b6364, 0x0dd779b4, 0x0000282e, 0x8d04aa04, 0x1e001500, + 0x0db28c00, 0x2305bd69, 0x17b0100d, 0x4706ab46, 0x2f610cd1, 0x03062108, + 0x20076343, 0x08fa4205, 0x1801b021, 0x18094f60, 0x31085643, 0x9f0a8fb6, + 0x030aaf0a, 0x0a1fb45d, 0x71020a2f, 0x2f8909b2, 0x2f841320, 0xb0d01429, + 0x16b0100a, 0x4f0cb0d0, 0x25210dba, 0x63601821, 0x1016240c, 0x78210706, + 0xf6240b1a, 0xd0f3f5fe, 0x33080082, 0xf6d1eb01, 0xf6fec8ed, 0xf5fe0b01, + 0x757361f8, 0x9999f95e, 0xb74db699, 0xfed33a02, 0x4d05cdb4, 0x55670401, + 0x02006556, 0xecff7c00, 0x00064604, 0x1a000f00, 0x246b0019, 0x300c0559, + 0xb11b2f06, 0x593e0f06, 0x030c05b2, 0xb2391211, 0x8306840a, 0x0a6252b3, + 0x280ce467, 0x14013130, 0x27222302, 0x9f291907, 0x04320813, 0xc0c7f346, + 0xf3d2116d, 0xf0ccb269, 0x9a7b8bf3, 0x7a994744, 0xf411028a, 0x7a8ecffe, + 0xd2fd0006, 0xfed6fe7c, 0xbba608fa, 0x8737fe85, 0x010000bc, 0xbd825000, + 0x4e040028, 0x4b001d00, 0x4b5f17b2, 0x2052180a, 0x0826560c, 0x23094654, + 0x100803b2, 0x1420b083, 0x51054b62, 0xb6180c2d, 0x35250b32, 0x36363435, + 0x06537f33, 0x0805a84b, 0x5a420233, 0x04e4067a, 0xe674ca7a, 0xe17af2fe, + 0x06f4c398, 0x5c7807e4, 0xae858579, 0xb0664f69, 0xfe2b0164, 0x87fb9e19, + 0x765fb4e4, 0xad1bb2b3, 0x000200b0, 0x2aa5824f, 0x00000617, 0x001c0011, + 0x621ab264, 0x1a2005ed, 0x4b050b6c, 0x52180659, 0xd14f0cde, 0x0d4c4b07, + 0x0d040622, 0x0b20b283, 0xb0200684, 0x210cae5d, 0xcf5f04b0, 0x3130220b, + 0x2cb58413, 0x11331117, 0x23062723, 0x35262622, 0xc44a1837, 0x703c080a, + 0x6aac82cd, 0x6c11d3f3, 0x74cb7ebb, 0x947b8df3, 0x7d924646, 0x9f26028d, + 0x02778cfd, 0x7500fa29, 0x9bfd8c89, 0x81c29d01, 0xc17dd701, 0x00ffff00, + 0x0200005b, 0x00b505b2, 0xb3150006, 0x2e05bb7b, 0x045504ec, 0x000f004e, + 0xb2430019, 0x821b1a04, 0x43828297, 0xcc8c081d, 0x7c08d958, 0x2b820935, + 0x870a9d52, 0x150024ae, 0x82061415, 0x003e08ad, 0x16141735, 0x34353632, + 0x4c062226, 0xe696eb82, 0xed7f2001, 0xe1fee698, 0x93fc95f2, 0x0295f897, + 0x8bfd9f27, 0x0dfccdfe, 0x018dfc9d, 0xa009fe31, 0x9fb5c4c4, 0x0200c6c5, + 0x60fe7c00, 0x97824404, 0x1b001028, 0x19b26e00, 0x97831d1c, 0x18101921, + 0x24084dad, 0xb11b2f0d, 0x07456e0d, 0x0c525f18, 0x19820720, 0x6f110721, + 0x765606b3, 0x0d062208, 0x21418204, 0x06840bb2, 0x5f0db021, 0x04200c2e, + 0x840eeb47, 0x274508ba, 0x33112311, 0x32333617, 0x34071712, 0x07222326, + 0x32331611, 0x6f440436, 0x6cb181c8, 0x6c0ed9f3, 0x0aefc1ba, 0x927c91f1, + 0x78934544, 0x9e110293, 0xfe748afd, 0x71da0500, 0xecebfe85, 0x78c29f27, + 0xc37817fe, 0x20c98200, 0x20c9824f, 0x20c98616, 0x20c98a6b, 0x0b677c04, + 0x141f4d18, 0xc9820920, 0xc9870920, 0x42081a52, 0xb2210c3b, 0x0cff5514, + 0x180bb248, 0x2609074d, 0x23061123, 0x42270222, 0x2c080b37, 0xb786cd6f, + 0xf3d2116b, 0xf6beaa6a, 0x7893f20b, 0x8c484690, 0x26028f7e, 0x828afca2, + 0x0126fa6e, 0x1c0170fc, 0xc59e27e2, 0x73f40176, 0x24c583c6, 0x04ecff53, + 0x24c5820b, 0x001e0016, 0x12134b7c, 0x4b0cad6d, 0x1b3a08f1, 0x12110008, + 0x2f1bb039, 0xcf1bbfb4, 0xb45d021b, 0x1b6f1b5f, 0x1fb47102, 0x06822f1b, + 0x1b8fb228, 0xefb45d01, 0x0b83ff1b, 0x424a0c20, 0x0e095108, 0xfe540820, + 0x3130220b, 0x9a7a1805, 0x15122808, 0x16162115, 0x4c363233, 0x35080b05, + 0xfef27602, 0x8be27dcf, 0x3efdf1dd, 0x558da90f, 0x3f3a3192, 0x7c66a7bd, + 0x73d00110, 0xf7280114, 0x8bf99e21, 0x7bf7f4fe, 0x202f9d85, 0x033932a6, + 0x1a7c8d9f, 0xe1837f70, 0x56fe5124, 0xe1820404, 0x24001926, 0x22b28300, + 0x2105ab74, 0x2b191022, 0x00208241, 0x0dc64e18, 0xc8410220, 0x514d080a, + 0x6bbdc3e7, 0xfafed011, 0x37af57ed, 0x8e837535, 0xbeae6a82, 0x7381f2ea, + 0x94444397, 0x26028076, 0x862b01fd, 0xf210fc72, 0x212efefe, 0x94963fb0, + 0x2f017622, 0x85b7a8f6, 0xb57fd101, 0x00010000, 0x05ebff6b, 0x00c50526, + 0xb240001d, 0x0a75450c, 0x1b2f0c24, 0x5b180cb1, 0x0d460f8b, 0x421a2011, + 0x3020087e, 0x151f3f19, 0x15024208, 0x33121415, 0x05373632, 0xd2fe1724, + 0xdcfeb6f9, 0x019e01a0, 0x01fbb720, 0x16fd1734, 0xccac90a3, 0x9b91acd2, + 0xe9da0116, 0x01b4fafe, 0xd53cd245, 0xfeb44a01, 0x9298e9f3, 0x34efe6fe, + 0x8fe4feeb, 0x26a58a96, 0xb2550020, 0x5322210c, 0xa598088d, 0x640aa044, + 0xb2210c3d, 0x05d64620, 0x6b2f2021, 0x25350c0a, 0x22230406, 0x35270224, + 0x33241234, 0x23170432, 0x02222102, 0x08b98607, 0x35211143, 0x46260521, + 0xc0b0dcfe, 0x02adcefe, 0xb723019f, 0x1f2b01f8, 0xe9fe2ef9, 0xe803d3aa, + 0x1f9b64bc, 0x1f02ddfe, 0xb2725fbc, 0x31d14801, 0xb64f01d9, 0x0701e3f0, + 0x33e9e5fe, 0x30dffeec, 0xc01b0124, 0x05457200, 0x0517052b, 0x000b00b0, + 0xb2460015, 0x05475703, 0x40180320, 0x0124096f, 0x01b11b2f, 0x106b7e18, + 0xfd610120, 0x5a00200c, 0x40080ba3, 0x11333130, 0x12043221, 0x02141517, + 0x11030704, 0x35123233, 0x23023435, 0xc8be019b, 0x03b24101, 0xccc0feb0, + 0xf8dcaec4, 0xb005daf1, 0xc8c3feb1, 0xbffecc38, 0xe40403b2, 0x0e01e6fb, + 0x01ea26f0, 0x2a95830c, 0x05ebff6b, 0x00c50572, 0x82200011, 0x09cf6595, + 0x2007c94f, 0x2095820d, 0x7d95870d, 0xb14608c9, 0x421d2010, 0x8e820b07, + 0x220b4d41, 0x82071712, 0x02222695, 0x16141515, 0x08a48216, 0x72053740, + 0xb4d8fea6, 0xaad8feb2, 0x2a01a501, 0x2601b2b4, 0xdcfb04a8, 0x66dfa9ad, + 0xd8a46eb6, 0xcec3020a, 0xbabab0fe, 0x31c94e01, 0xc04d01cb, 0xc6b9feb7, + 0x2201e412, 0x25e8dbfe, 0x0186f193, 0xb785da09, 0xb7840320, 0x23001422, + 0x0820b782, 0x23058150, 0x20b01008, 0x20065545, 0x20b78210, 0x63b78710, + 0x10210863, 0x0b576610, 0xb2100823, 0x24b78d20, 0x25071707, 0x21bb8806, + 0xba8f0420, 0x72053538, 0xa5ef8997, 0x3e43d5fe, 0xaadafeb3, 0x2801a702, + 0x27016801, 0xbe8201a8, 0xdeaa3008, 0xae6fb566, 0xcac602d9, 0xc062bdfe, + 0xb70df594, 0x2ecb4d01, 0xbb5201d0, 0xceaffeb7, 0x1f01ec05, 0x1defddfe, + 0x0184f297, 0x0000f520, 0x82970001, 0x04ef26c6, 0x0006008c, 0x053a6732, + 0x450c5160, 0x04280842, 0x12110500, 0x2f04b039, 0x350a5d5b, 0x23213130, + 0x25350511, 0xf3ef0233, 0x39029bfe, 0x7a69031f, 0x5382d0cd, 0x00006e2c, + 0x9e042c04, 0x59001900, 0xef4f09b2, 0x0c7e580a, 0x18205a88, 0xb223fc88, + 0x82001802, 0x03b22365, 0x06821100, 0x1011b022, 0x210ac54a, 0x14840cb2, + 0x1117b222, 0x25058e56, 0x01352121, 0x0e6a3636, 0x23380806, 0x33363634, + 0x14151632, 0x21010706, 0x60fc2c04, 0x3946fb01, 0x7b675a69, 0x85d779f3, + 0x6e57eaca, 0x4902b1fe, 0x3fba019f, 0x5a484063, 0xbc736078, 0x5a9cb76a, + 0xd6fe669f, 0x2a06c752, 0xc4059703, 0x32000700, 0x180803b2, 0x5709159e, + 0x2c590c56, 0x10062108, 0x0a846418, 0x31302108, 0x21113301, 0x21112311, + 0xfdf3a402, 0x2e02f3d2, 0x05fec405, 0x8d0437fc, 0x0f000100, 0xf203a3fe, + 0x19220982, 0xf5505900, 0x2f0c2e08, 0x584500b0, 0x1b2f02b0, 0x3e1d02b1, + 0x0a395459, 0x2306a47f, 0x020c05b2, 0x0524fb83, 0x100cb02f, 0x240a8a66, + 0xb21005b0, 0x9f6f1817, 0x19b22208, 0x06d87317, 0x21352125, 0x83160115, + 0x230424f9, 0x50372722, 0x400805e4, 0x35232326, 0xbafd9e02, 0x9dfe7703, + 0xfe90dbab, 0xcec7b0f2, 0xa4ad9d39, 0x48b7aac4, 0x8fc4c903, 0xf71a80fe, + 0x84f3a3b0, 0xb858b667, 0x7b929692, 0x00020000, 0x04c4fe35, 0x008c048b, + 0x000e000a, 0x05094252, 0x0cd24318, 0x4b0c8b57, 0xff4a08a5, 0x06b02c09, + 0xd005b010, 0xb22f05b0, 0x83000608, 0x100028c1, 0xb2d00cb0, 0x8202090d, + 0x303d080c, 0x15332531, 0x11231123, 0x33012721, 0x07112101, 0xb6b6d503, + 0x0658fdf2, 0xfdfaa602, 0x17aa0164, 0xc5fec3c2, 0x03943b01, 0x0236fcf9, + 0xff002a80, 0x024b00ff, 0x05aa028d, 0x010703b8, 0x209e82d4, 0xed781898, + 0x2f0a2c07, 0x1f0ab11b, 0x10b0593e, 0x833130d0, 0x02352627, 0x05be0298, + 0x202782ad, 0x18278bd8, 0x820d1579, 0x824f204f, 0x84ae204f, 0x84d92027, + 0x85102027, 0x07ee44e3, 0x82313021, 0x824d2023, 0x05b92223, 0x204b82ba, + 0x204b8bda, 0x20738200, 0x20738300, 0x20738614, 0x85738236, 0x8bdb204b, + 0x8205204b, 0x82052027, 0x894b8427, 0x84dc20bf, 0x85192023, 0x1811206f, + 0x2307e26f, 0x11b0d019, 0x8305a64f, 0x024624c5, 0x84a3028f, 0x8bdd20ed, + 0x82082079, 0x8208202d, 0x1ab02151, 0x00377983, 0xfe660001, 0x041e04a0, + 0x001c008c, 0x1d19b25d, 0x3912111e, 0x570eb000, 0xc4180d49, 0x01210c78, + 0x2222820e, 0x522f07b0, 0xb2230a45, 0x83190705, 0x09651814, 0x11b2220c, + 0x22148313, 0x7e191cb2, 0x03240a8e, 0x12363736, 0x4205414b, 0x36080959, + 0x87070622, 0xfd29035a, 0x86652d9a, 0xf585edcf, 0x4ab5e4a5, 0xab8fbd84, + 0x6653788e, 0x0375011b, 0xaafed217, 0xfe020232, 0xf398e4f7, 0x63b27582, + 0xa28794b3, 0x82003b35, 0xfe4324bb, 0x821004c4, 0x000625bb, 0x01b00025, + 0x8b0dd667, 0x180020b4, 0x7d079544, 0x230805d4, 0xb6fd1004, 0xfd3e02f3, + 0x04cd0332, 0x05befa06, 0x0200c305, 0xf0ff4f00, 0x9d046d06, 0x1e001400, + 0x16b29100, 0x20054d4f, 0x09254916, 0x530c465a, 0x00240c9a, 0x00b11b2f, + 0x42071f5b, 0x0b2008d4, 0x230bd146, 0x0b0010b2, 0x20063a57, 0x089b4411, + 0x1000b022, 0x0bd45e18, 0x26560220, 0x180a200c, 0x2c0dc284, 0x22052121, + 0x34351100, 0x05333612, 0x3f4e1821, 0x37052307, 0xef4d2711, 0x06390805, + 0xfe47fd6d, 0xdafeecad, 0x019bf085, 0xfdb80253, 0xfef601b7, 0xfb4c020a, + 0x86cfcdf4, 0x01109998, 0x2e0c0135, 0x8b0701ac, 0xf2fec410, 0x0fcafec3, + 0x09140308, 0xb235b7c0, 0x2ef982c7, 0x04b4fe73, 0x00a00454, 0x00240018, + 0x4a1fb253, 0x1f20051f, 0x2005a961, 0x0ee35c14, 0x49551420, 0x1419220c, + 0x24d5820c, 0x2f19b07c, 0x9d701818, 0x7270180b, 0x3205270e, 0x23063736, + 0xa64e0222, 0x11002405, 0x44021415, 0x13210559, 0x071f5132, 0x16144108, + 0xbd98e901, 0xd1aa7219, 0x87da7bf7, 0x911401f1, 0x9eb2f3fe, 0xd17d2f84, + 0x7f8852b0, 0x898a876d, 0x015abec8, 0xed99e512, 0xfed1fe80, 0xfee5cef6, + 0xb63cb2b2, 0x78e9012f, 0xb1b4a5ac, 0x00b08a92, 0x6224c782, 0x8504ebff, + 0x0d28c782, 0x46001a00, 0x1c1b03b2, 0xb0219b82, 0x090f5103, 0x500cc141, + 0x4e180822, 0x816e10c8, 0x31303309, 0x23001001, 0x35022622, 0x32330010, + 0x34071216, 0x075b2026, 0x08d18205, 0xfe850442, 0xf39ef3e3, 0xf21f0182, + 0xf281f29f, 0x99f6fe9b, 0x9785869a, 0xfe3e0202, 0x8ec4fee9, 0x01c70c01, + 0x8e3e0116, 0xb8a7f3fe, 0x2cbac8c7, 0xb4c5cdb5, 0xb5ffffff, 0x93014bfe, + 0x06023a04, 0x00009b00, 0x002b0f91, 0x0100008f, 0x003a0482, 0x848c0006, + 0xfefb221f, 0x200f845c, 0x820f8326, 0xd2a32415, 0x8dffff0a, 0x01002325, + 0xf9827600, 0x9c04162a, 0x65002100, 0x232201b2, 0x2408454a, 0xb11b2f15, + 0x07125315, 0x0c821f20, 0xa6421f20, 0x6d102007, 0x1f2007cd, 0x230b7c46, + 0x151f0ab2, 0x23063464, 0x08b2d019, 0x21081c46, 0x9e4915b0, 0x4625200d, + 0x4d080914, 0x22232613, 0x11231115, 0x32333636, 0x16031716, 0x06141516, + 0x01272223, 0x4d484beb, 0x54747c5c, 0xb15146ca, 0xcfd101ef, 0xf968cd78, + 0xafd9aaa1, 0x31db6c7c, 0x47585265, 0x390101a3, 0x021cfdf9, 0x61d5d7f0, + 0x17d4fe6f, 0xcaaf81a4, 0xdb820036, 0x02472008, 0x02540209, 0x000602cd, + 0x00000011, 0x00f7ff02, 0x05f00400, 0x000f00b0, 0xb282001d, 0x831f1e10, + 0x101023a0, 0x0f4906b0, 0x92b81806, 0x0801480c, 0x5c480320, 0x2f032d05, + 0x0103cfb2, 0x033fb25d, 0x6fb27101, 0x1f200483, 0x9f200483, 0x0f251383, + 0xb2720103, 0x099c4d02, 0xb0d01123, 0x0bb96100, 0x7d05b021, 0xb02b0b83, + 0x1db01003, 0x333130d0, 0x4a352311, 0x1530059d, 0x04021415, 0x11231323, + 0x35363233, 0x23263435, 0x2e080982, 0x01bbbbb2, 0x2b01c1ae, 0xcffea5a4, + 0xa3e53fc5, 0xc4ced5cb, 0x8c02e5b1, 0xac7a02aa, 0x49ccc4fe, 0xaac6fecf, + 0x3efe8c02, 0xed46f0fd, 0x4052fefa, 0x012ee1df, 0x0000d4ff, 0x00061604, + 0x74001800, 0xbb790cb2, 0xbbc61806, 0x152f2529, 0x0fb25d01, 0x18290483, + 0x1211150f, 0x2f18b039, 0x11c418b2, 0x0f04210b, 0x04201483, 0x270e4b4c, + 0xb0d011b0, 0x13b01018, 0x2305e362, 0x13203336, 0x0809696f, 0x35231132, + 0x15333533, 0xe7710233, 0x5a01b677, 0x5e61f305, 0xc3f34892, 0x04e7f3c3, + 0x8afdfec7, 0x3dfd75fe, 0x5d70ba02, 0x04fbfc82, 0x8f8faac7, 0x2d000100, + 0xb024c182, 0x0f00b005, 0x4807bd7c, 0x78490831, 0x3e0f2608, 0x0a0fb259, + 0x208b8302, 0x28a08b0f, 0xb0d004b0, 0x06b0100f, 0x0d6e77d0, 0x080e7d63, + 0x1521352f, 0x03331121, 0xd3fbcfb9, 0x043efed3, 0xcf3afe83, 0xeefc1203, + 0x01aa1203, 0xfecccc28, 0xff0100d8, 0x02ecffe8, 0x00410585, 0xb272001c, + 0x06a54700, 0x1b247d83, 0x1bb11b2f, 0x61076351, 0x1b2608a8, 0xd001b010, + 0x134c1bb0, 0x8304200c, 0x17b02510, 0x2f17b0d0, 0x21055549, 0x641817b0, + 0x08230c56, 0x4111b0d0, 0x1b2f0c46, 0xd01cb010, 0x302f1cb0, 0x33110131, + 0x82152315, 0x14112103, 0x0d6b6518, 0x35234408, 0xad011133, 0xd8d8bfbf, + 0x2b2a3f31, 0xe8fe4d53, 0xb2b2d2d2, 0xf9fe4105, 0xfeaaa5b4, 0x0a373ef3, + 0x350117bc, 0xa5aa1601, 0xff0701b4, 0x001200ff, 0x07420500, 0x00260236, + 0x01000025, 0x01440007, 0x49360123, 0x04200787, 0x0426ca82, 0xb0593e1f, + 0x8749dc0c, 0x222d8f05, 0x89c20175, 0x08f6432d, 0x2d8c0d20, 0x5b883720, + 0xc3009d22, 0x0f205b92, 0x2c202d8c, 0xa42c2d88, 0x3701c500, 0xb0000900, + 0x16b02f04, 0x0220238c, 0x6a222388, 0x5182ee00, 0x75491620, 0x26ad8805, + 0x1bb0dc12, 0x883130d0, 0x889420dd, 0x01a2262f, 0x006a0158, 0x2353840c, + 0x15b0dc10, 0xb120258b, 0x00272585, 0x01df0107, 0x821c015e, 0xfe66263d, + 0x05eb043c, 0x2a1782c4, 0x00000027, 0x01790007, 0x82fbffc9, 0x00942617, + 0x074c0400, 0x2017823d, 0x05334129, 0x01e80023, 0x0733413d, 0x1b2f0628, + 0x3e1f06b1, 0x0541b059, 0x222d8f07, 0x92870175, 0x860e202d, 0x202d85e1, + 0x225b883e, 0x9288009d, 0x8c10202d, 0x8809202d, 0x006a222d, 0x412d82b3, + 0x8988060f, 0xb0dc1323, 0x21e9841c, 0xaf82c8ff, 0xb984a020, 0xb9852d20, + 0x8997ff21, 0x8202205d, 0x830220b9, 0x860520b9, 0x00a3245d, 0x8a7d0200, + 0x0075222d, 0x202d8935, 0x202d8203, 0x202d8303, 0x212d8506, 0x2d82cbff, + 0x83077a21, 0x225b85b9, 0x9237ff9d, 0x8608205b, 0x82bf202d, 0x0785212d, + 0x2d85b983, 0x62ff6a22, 0x8988b989, 0xb0dc0b23, 0x27b98414, 0x00009400, + 0x2c071705, 0x3220e982, 0xa422b984, 0x1d42ee00, 0x2f052305, 0x538515b0, + 0xff660027, 0x071e05ec, 0x20238236, 0x22238433, 0x423a0144, 0xbe51096f, + 0x96202008, 0x0175222d, 0x202d89d9, 0x20dd820d, 0x20dd830d, 0x202d8c21, + 0x225b8837, 0x92da009d, 0x8c23205b, 0x85ad832d, 0x00a42289, 0x20ad82dc, + 0x05a74213, 0x22205b88, 0x02202d8c, 0x6a225b88, 0xd5420501, 0x23b78809, + 0x2fb0dc26, 0x24050b41, 0x04ecff7d, 0x20e784bd, 0x20e78639, 0x4d8b8911, + 0x12200813, 0x2d8f5d86, 0xb0017522, 0x09202d82, 0x2f228b82, 0x238c13b0, + 0x5185dd83, 0xb1009d22, 0x67415192, 0x83518507, 0x202d85af, 0x21dd826a, + 0x75420036, 0x237f8806, 0x21b0dc18, 0x0724af85, 0xd6040000, 0x3d20af84, + 0x7522af84, 0x5d898701, 0x20088a52, 0x2a8b860b, 0x03ecff5a, 0x020006fb, + 0x84450026, 0x0044242d, 0x430000ad, 0x1729075d, 0x17b11b2f, 0xb0593e1b, + 0x222d962b, 0x824c0175, 0x23dd822d, 0x2cb02f17, 0x0120238c, 0x06235186, + 0x914d9d00, 0x8b2e204f, 0xf605212b, 0xa4222b88, 0x7b90014f, 0x2b8c2d20, + 0x2b88cc20, 0x00786a22, 0x88070541, 0xdc3123a7, 0x05413ab0, 0x20d78505, + 0x24d7885e, 0x00e200a2, 0x232f9034, 0x37b0dc2f, 0x7c202f8b, 0x00312f85, + 0x00df0107, 0xffe7ffe8, 0xfe4f00ff, 0x04f5033c, 0x2017824e, 0x26e98247, + 0x01790007, 0x82fbff3d, 0xff532617, 0x060b04ec, 0x20178200, 0x06374149, + 0x3741a120, 0x2f082909, 0x1b08b11b, 0x1fb0593e, 0x2d8fbb86, 0x40017522, + 0x22053741, 0x43b02f08, 0x23850721, 0x51860120, 0x9d000623, 0x08374141, + 0xc3424f88, 0x212b8407, 0x2b88cc05, 0x416c6a21, 0x2b88080b, 0xb0dc2523, + 0x21db842e, 0xa182b4ff, 0xf9058c22, 0x8c202d82, 0x06240982, 0xf9834400, + 0x20076541, 0x20a98202, 0x44a98302, 0x8f240785, 0x69020000, 0x75212b8a, + 0x202b8821, 0x202b8203, 0x442b8303, 0xb7200783, 0x66222b82, 0x5786fa05, + 0x9d000725, 0x88ff23ff, 0x4459882d, 0xab200783, 0x71222d82, 0x2d88c505, + 0x4eff6a22, 0xc7422d82, 0x442d8806, 0x79260983, 0xf8030000, 0x2f82f605, + 0xb5845220, 0x0155a42a, 0xb0000900, 0x1cb02f03, 0x26065541, 0x04ecff4f, + 0x8200063d, 0x41532021, 0xb6200683, 0x5a098341, 0x2d9708de, 0x55017522, + 0xf1462d82, 0x8c1d2005, 0x86012051, 0x00062351, 0x8341569d, 0x414f8808, + 0x7d8407d3, 0x7d839f84, 0xa4000623, 0x239f8458, 0x26b02f04, 0x05214d8b, + 0x229f88cc, 0x8281006a, 0x0b3f4771, 0x593e1b32, 0xb0dc22b0, 0x3130d02b, + 0x7700ffff, 0xf703ecff, 0x5920cf84, 0xaf20cf86, 0x0724cf89, 0x07b11b2f, + 0x69442f83, 0x222d8f07, 0x854e0175, 0x440620cf, 0x23850969, 0x5183cf83, + 0x4f20cf82, 0x4f88cf88, 0x84076744, 0x85ad842b, 0x7a6a212b, 0x88085342, + 0x0965442b, 0x4bfe0c24, 0xab84d603, 0xab845d20, 0x16017522, 0x01227d85, + 0xa187b02f, 0x51842384, 0x06232383, 0x88426a00, 0x820f2051, 0x830f20cd, + 0xdc1723cd, 0x174820b0, 0xea06210a, 0x24083d48, 0x01be0070, 0x181b493a, + 0xecff5a26, 0xb405fb03, 0x23080d44, 0x00044870, 0x20058744, 0x0cbd482a, + 0x4f881c20, 0xf600a022, 0x48120f49, 0x4f850709, 0x2f44e620, 0x00a02208, + 0x12074580, 0x5b832d20, 0x00020033, 0x0552fe12, 0x00b00542, 0x00190016, + 0x1a19b274, 0x06c35c1b, 0x934d1620, 0x82162006, 0x561620de, 0x2d7b07a3, + 0x8201200c, 0x4e012019, 0x0c200784, 0x0c240c82, 0xb2593e11, 0x0a428a18, + 0xb010012b, 0x11b0d011, 0x1417b22f, 0x21558316, 0x23512f17, 0x19b2230a, + 0x14821416, 0x01313038, 0x06062301, 0x32331415, 0x23061737, 0x34352622, + 0x03210337, 0x04820121, 0x1b033508, 0x573e2702, 0x2e2c474a, 0x5f5c4915, + 0xfd739574, 0xf9fe76cc, 0x01622602, 0xb005d3a6, 0x5e3850fa, 0x8e174431, + 0x8d5b6e2c, 0xfe490162, 0xfcb005ad, 0x005c026f, 0x5a30d382, 0xfb0352fe, + 0x2d004e04, 0xa6003800, 0x3a3917b2, 0x10227d84, 0xd3862fb0, 0x24086445, + 0xb0584500, 0x20b98229, 0x0f8a5d29, 0x1983b020, 0x19821e20, 0xe0841e20, + 0x00b0d026, 0x1702b22f, 0x84059d5d, 0x0bb02606, 0x1017b02f, 0x0abe65b2, + 0x0f0b1222, 0x40306682, 0x1c120c09, 0x3c122c12, 0xb05d0412, 0x24b21029, + 0x2309784f, 0x2eb21004, 0x23093052, 0x32b2100b, 0x30240d88, 0x27262531, + 0x1b224b19, 0x310e2241, 0x37363203, 0x06222335, 0x02161415, 0x740d0bff, + 0x4b19a3a8, 0x2a201031, 0x3e093841, 0x207f4876, 0x5d888783, 0x79451907, + 0xb9ad89ba, 0x53655447, 0x589b5940, 0x18feadbf, 0x41115792, 0x8c330846, + 0x3b460801, 0x46565ecc, 0x00ffff53, 0x04ecff66, 0x4a4b07eb, 0x012c05c3, + 0x01750007, 0x004b01c0, 0x0cb00009, 0x2609e745, 0x03ecff4f, 0x460006f5, + 0x23840551, 0x00002928, 0xb0000900, 0x2f462f0f, 0x20478508, 0x2247884c, + 0x82c1009d, 0x48132047, 0x5b4905d1, 0x20518510, 0x23518601, 0x2a9d0006, + 0x4308e543, 0xb5440867, 0x20598507, 0x24598829, 0x01a701a1, 0x07654354, + 0xc1445988, 0xf503230a, 0xab88de05, 0x1001a122, 0x8786a982, 0x25205b88, + 0x82095949, 0x22b589fd, 0x88d8009e, 0x07b946fd, 0x9e21ab8f, 0x49fb8741, + 0x942607fb, 0xd2040000, 0x73823e07, 0x0000282a, 0x9e000701, 0x3d016700, + 0xb0247582, 0x1ab02f01, 0x27095945, 0x02065b05, 0x48002600, 0x012d2383, + 0x040104a2, 0x000600fc, 0x302f1eb0, 0x07334c31, 0x4bf10621, 0x702408a9, + 0x41018300, 0x4718334c, 0xb420054d, 0x22084d47, 0x83043c70, 0x2f08236f, + 0xf94b1eb0, 0x8823200c, 0x00a0224f, 0x096d4bbb, 0x4d08f94b, 0x4f85075b, + 0x4f88e620, 0x4774a021, 0xed8b11c9, 0x1b074c22, 0xa1245988, 0x46016e01, + 0x1420a990, 0x210b4748, 0x7548de05, 0x01a12208, 0x098f4127, 0x2008f947, + 0x312d8326, 0x94000100, 0x4c0452fe, 0x1b00b005, 0x11b28000, 0x15531d1c, + 0x0c9d4408, 0x1b2f0f24, 0xc9430fb1, 0x07b74414, 0x441ab221, 0x1a210589, + 0x0a7e712f, 0x5314b021, 0xb0260b37, 0x0fb0d003, 0x9018b210, 0xb02109d4, + 0x0dbe5516, 0x11210124, 0x8f431521, 0x1837200e, 0x25070564, 0x02aafde7, + 0x7a436fbb, 0xfd872d09, 0xfdb10393, 0x0256024c, 0xca40fe8a, 0x3b086943, + 0xb0055f86, 0x006efecc, 0x53000200, 0x0b046dfe, 0x23004e04, 0xa5002b00, + 0x2d2c11b2, 0x7005db5a, 0x19200833, 0x1920d482, 0x0c895018, 0x2250e187, + 0x02b22307, 0x34831911, 0x45100c21, 0xb2230a7c, 0x83111928, 0x2f283814, + 0x2f281fb4, 0xb4710228, 0x28cf28bf, 0x8fb25d02, 0xb45d0128, 0x836f285f, + 0x28ef2212, 0x210682ff, 0x38531db2, 0x1810200a, 0x210aa1d4, 0x438523b2, + 0x5a691920, 0x3130240b, 0x45070625, 0x26220eb0, 0x10562700, 0x6aab1805, + 0x22012b08, 0x35210706, 0xfa032626, 0x0d417149, 0xcf502409, 0x6006fbfe, + 0x3d3105f7, 0xa7779d0b, 0x64c5fe69, 0xcf01117b, 0x6ab87208, 0x081c4133, + 0x0d526638, 0x3ad71301, 0xfe8effa2, 0x62fefee6, 0x02879c86, 0x127d8c56, + 0x414f7d7a, 0x09e54e08, 0x9f009e22, 0x2012bd42, 0x0cab4a11, 0x2909874a, + 0x0000589e, 0x08b00009, 0xc343b02f, 0xff6a3207, 0x07f004ec, 0x0026024c, + 0x0100002b, 0x009d0007, 0x099d44be, 0x1b2f0b24, 0xcb4d0bb1, 0xfe52250b, + 0x060c0456, 0x4b204f83, 0x06232d82, 0x43409d00, 0x514a080d, 0x86272008, + 0x2059857b, 0x22598831, 0x92f100a0, 0x84878759, 0xe6052159, 0x59852d82, + 0x9173a021, 0x8c282059, 0x88292059, 0x01a12259, 0x09f744a4, 0x8787b388, + 0xde205985, 0x07245986, 0x2601a100, 0x88096743, 0x872d20b5, 0xf9fd255b, + 0xc405f004, 0x002a5b85, 0x01a20107, 0xff92febb, 0x458400ff, 0x87a90621, + 0xb9012545, 0x7e002701, 0x2006c34a, 0x09594429, 0x07180523, 0x2123823e, + 0x4b41002c, 0x41e22005, 0x0720099b, 0x079c5018, 0x26078150, 0x03000079, + 0x825e07f8, 0x864c202d, 0x0117222d, 0x2051835d, 0x08f34910, 0x00b3ff27, + 0x07900200, 0x4f238233, 0xa42405eb, 0x3e0139ff, 0x50075144, 0x07200847, + 0xff217f85, 0x222d829f, 0x4bef057c, 0xa4240895, 0xfaff25ff, 0x02225183, + 0xcf44b02f, 0xb9ff2106, 0x90222382, 0x5188f106, 0x32ff7022, 0x50094d45, + 0xff210fc7, 0x205184a5, 0x245188ad, 0xff1eff70, 0x176f4cfd, 0x82dfff21, + 0x0765222d, 0x225b8823, 0x896affa0, 0x875b88ff, 0x82cb20ad, 0x0551222d, + 0x225b88df, 0x4c56ffa0, 0x2d861271, 0xfe170027, 0x059f0158, 0x2f5b85b0, + 0xa3000600, 0xffff06ee, 0x52fe0000, 0xd5059001, 0x4d281582, 0x06000000, + 0x00d7a300, 0x9d261582, 0xa3010000, 0x87881b07, 0x1c00a122, 0x88098745, + 0x07995387, 0xecffa32a, 0xb0052606, 0x2d002600, 0x07254382, 0x42022e00, + 0x23458300, 0x034bfe7d, 0x17825b82, 0x07245b83, 0x0b024e00, 0x2d2a1784, + 0xab04ecff, 0x26023707, 0xb7412e00, 0x68012105, 0x5d098b4a, 0x9341090b, + 0xfeb52406, 0x846b024b, 0x859b20e5, 0x28ff232d, 0xa347deff, 0x3e1b230c, + 0xaf43b059, 0xfd942407, 0x841805f9, 0x832f20e5, 0xa2012f8b, 0x92fe9d01, + 0x7d00ffff, 0x3604f9fd, 0x73820006, 0x17864f20, 0x17842d20, 0x00009426, + 0x36072604, 0x30201782, 0x75225d84, 0x8b892900, 0x4d085554, 0x002706b5, + 0x0200008a, 0x82910762, 0x8650202d, 0x011a222d, 0x0c4d4291, 0x8b822120, + 0x2006114e, 0x218b8200, 0x8b842604, 0x00215b82, 0x208b8207, 0x2473846d, + 0x01f9fd55, 0x828b847f, 0x21178345, 0x8b891000, 0x82b10521, 0x268b845d, + 0x0a02a201, 0x5e00ab04, 0x65560647, 0x31302107, 0x8c20cd82, 0xe7258782, + 0x26000206, 0x82878400, 0x048d2259, 0x242987fc, 0xb11b2f08, 0x47878208, + 0x838a08fb, 0x01a10025, 0x86d4fdca, 0x06eb2241, 0x21418500, 0x17820700, + 0xaffd6422, 0x23051d45, 0x36071705, 0x2208eb52, 0x41eb0175, 0x2d5e090f, + 0x07f94108, 0x00007926, 0x0006f803, 0x2406954e, 0x01750007, 0x05f74c52, + 0x81430320, 0x94002708, 0x1705f9fd, 0x5185b005, 0x0121ed83, 0x26ed84dc, + 0x03f9fd79, 0x854e04f8, 0x2017843b, 0x53178441, 0x3720056d, 0x9e228188, + 0x81890301, 0x85105d48, 0x4f012081, 0x9e220817, 0x5344006a, 0x06c94d06, + 0x00a5ff22, 0x0320a383, 0x07262186, 0x60ffa201, 0x2b41fd04, 0x2f152407, + 0x4115b11b, 0x6626072b, 0x1e05ecff, 0x0b53ea06, 0x00702208, 0x09734dd5, + 0x2313674a, 0xb4053d04, 0x22081d4f, 0x56045170, 0x1b200631, 0x200c5b53, + 0x224f881c, 0x890d01a0, 0x454f88c9, 0x414f07bf, 0x4fe62005, 0xa022081f, + 0x734d8900, 0x086f4f09, 0x84078349, 0x350721ab, 0xa5225b88, 0xb7536301, + 0x08e55309, 0xb0dc2123, 0x054f4e25, 0xff205d85, 0xa5225d88, 0x7d4fdf00, + 0x531d2012, 0x94260837, 0xde040000, 0x2f823607, 0xe9423620, 0x71012105, + 0x1f505f82, 0x07774a05, 0x00007c23, 0x05bb4b02, 0x23855620, 0x82ad0021, + 0x22238253, 0x56b02f0b, 0xfd250825, 0x05de04f9, 0x314785b0, 0xa2010700, + 0x92fe6e01, 0x4f00ffff, 0xb402f9fd, 0x17824e04, 0x17833b82, 0x430a0021, + 0xde220803, 0x77883707, 0x89009e22, 0x1c207788, 0x20065741, 0x22778238, + 0x850106fa, 0x0601263b, 0x00c69e00, 0x20758500, 0x24218612, 0x04ecff4a, + 0x20bd848a, 0x21998537, 0x45858e01, 0xb02f0923, 0x2623862a, 0x03ecff4b, + 0x820006ca, 0x86572045, 0x853a2023, 0x462382bd, 0x4785078f, 0x47858d83, + 0x8f009d22, 0x8d129b54, 0x83978351, 0x00062351, 0x81473b9d, 0x0c5a1808, + 0x25598808, 0x8a0441fe, 0x7d82c405, 0x00315982, 0x01790007, 0xff00009d, + 0xfe4b00ff, 0x04ca0338, 0x8495854e, 0xff442217, 0x221782f7, 0x8bf9fd4a, + 0xa201252f, 0x92fe8901, 0x4b221782, 0x2f8bf9fd, 0x30201782, 0xb98f1784, + 0xa6009e22, 0x54080141, 0x0141079b, 0x26af8905, 0x0000529e, 0x82b00009, + 0x07e154ff, 0x75822d20, 0xb005b022, 0x38248d82, 0x07000000, 0x77205d82, + 0x08265d84, 0x7202f9fd, 0x17824105, 0x17855820, 0x84c80021, 0xfe2d2317, + 0x2f8a0444, 0x8b22d582, 0xa5820300, 0x41fe0824, 0x2f89a502, 0x00790023, + 0x26ed84dc, 0x0400002d, 0x853707b0, 0x0701255f, 0x98009e00, 0x2012eb43, + 0x06b1410d, 0xecff0829, 0x83062703, 0x86002600, 0xcd012675, 0xffff7d05, + 0x05135600, 0x26022c2c, 0x00003900, 0xa4000701, 0xf156b300, 0x08206709, + 0x5107354c, 0xf62005d9, 0x59202d82, 0x06232d82, 0x5551a400, 0x0d200865, + 0x87076c6d, 0x2159842b, 0x5988ea06, 0xac007025, 0x56003a01, 0x714605bf, + 0x204f8507, 0x224f88b4, 0x4c044a70, 0xa5520cb1, 0x214f840b, 0x4f881c07, + 0xe400a022, 0x8d124f42, 0x86e620a9, 0x00072459, 0x538200a0, 0xab8c1201, + 0x88940721, 0x01a2225b, 0x056f5a46, 0xb02f0023, 0x08955a16, 0x0621ad84, + 0x2953885e, 0x00e400a2, 0x000c0034, 0x258b06b0, 0x3520a785, 0xa5224b88, + 0x5d443a01, 0x08514109, 0xb0dc1323, 0x08ab5317, 0x052e0423, 0x225588ff, + 0x82d800a5, 0x825585a9, 0x82152025, 0x01003025, 0x89fe7d00, 0xb005bd04, + 0x57001f00, 0x18201cb2, 0x24098958, 0xb11b2f18, 0x071f5218, 0x08329b18, + 0x087c9818, 0x593e172b, 0x181304b2, 0xb2391211, 0x090a5109, 0x38791320, + 0x18b0210b, 0x2205e964, 0x4c141101, 0x20311059, 0x33113500, 0x33161411, + 0x04111120, 0x3d7e85bd, 0x070d524f, 0x00ff3633, 0x94fcdbfe, 0x05240190, + 0x9832fcb0, 0x59293de4, 0x050d5237, 0x0145552e, 0xcd03eb0c, 0x9a9232fc, + 0xc6033401, 0x7726bb82, 0xf70352fe, 0xbb823a04, 0x1ab26622, 0x0752bb8a, + 0x8212200c, 0x181220c8, 0x8310a390, 0x820a20c8, 0x110a2119, 0x0520c882, + 0x1f29c189, 0xd00fb010, 0xb02f0fb0, 0x0b097112, 0x6017b021, 0x21200559, + 0x510e204d, 0xc98305db, 0x37323322, 0x03210682, 0x09144de2, 0x6b05922a, + 0xf3b5b0c5, 0xf33eb1ab, 0x0808024d, 0x62618c25, 0x02c3ce7e, 0xce46fdbd, + 0xfb09037f, 0x00ffffc6, 0x06000030, 0x023707e5, 0x003b0026, 0x00070100, + 0x46a8019d, 0xe74a128f, 0x21002706, 0xcc050000, 0x2d820106, 0x2d865b20, + 0x7d420a20, 0x820b2009, 0x490b20cf, 0x67590b77, 0x595b8305, 0x9d220567, + 0x67598800, 0xfe0c241a, 0x84d6034b, 0x050b555b, 0x51179d21, 0xd74211a3, + 0x20598507, 0x85878202, 0x006a2259, 0x098b42b3, 0x23089148, 0x19b0dc10, + 0x26058b42, 0x04000050, 0x8236078c, 0x843e202f, 0x017522b7, 0x4c898983, + 0xc1480843, 0x00522607, 0x06c00300, 0x202d8200, 0x202d865e, 0x1263431b, + 0x5b852d87, 0x5b881420, 0x6a01a124, 0xed433f01, 0x465b8807, 0x5b840785, + 0x88de0521, 0x01a1225b, 0x09374d02, 0x87084556, 0x205b852d, 0x225b8837, + 0x459b009e, 0x072305b1, 0x450eb02f, 0x51840601, 0x86010621, 0x00062451, + 0x8200339e, 0x89b02051, 0xf6ff2721, 0x57070000, 0x21824207, 0xcf858120, + 0x01bb0223, 0x0c8f4442, 0x593e1f22, 0x2408b55c, 0x06ecff48, 0x204f8484, + 0x222d8686, 0x56010071, 0x3f200639, 0x692a7386, 0x2205a1ff, 0x26028007, + 0x23858300, 0x01e00123, 0x44518780, 0x5346080b, 0xff4f2607, 0x053d0477, + 0x202d82fe, 0x222d8689, 0x56feff30, 0x1b200cb7, 0x874e7f82, 0xa6ff2b06, + 0x2a040000, 0x26028d04, 0x2d83bd01, 0xffde012f, 0x006eff16, 0x1fb20046, + 0xb2710117, 0x1804836f, 0x29086677, 0xbf17afb6, 0x0317cf17, 0x1282b272, + 0x5fb27226, 0xb6720117, 0xdf251083, 0xb2710317, 0x2a2a823f, 0xef17dfb4, + 0xb45d0217, 0x822f171f, 0x31302306, 0x5fdfffff, 0x82240021, 0x841620bf, + 0x82cd20bf, 0x01062cbf, 0x00be32de, 0x00b20008, 0x835d010b, 0x0900217f, + 0x94221f82, 0xdf821e06, 0x1f82ba20, 0x44000726, 0x1e00c700, 0x200c0d41, + 0x0ae1601d, 0x75222d8f, 0x2d896601, 0x4708356d, 0x2d85070d, 0x5b861f20, + 0x9d000623, 0x43599167, 0x2b8507cb, 0x2b881420, 0x1f69a422, 0x840edd60, + 0xea052121, 0x6a22a988, 0x7b829200, 0x830b9d59, 0x09dd60a9, 0x06212f84, + 0x252f887c, 0x00fc00a2, 0x2f8f0052, 0xb0dc1023, 0x05954318, 0x99202f85, + 0x00312f85, 0x01df0107, 0xff040002, 0xfe4f00ff, 0x04430441, 0x3417829d, + 0x000000bc, 0x01790007, 0xff00006b, 0x007600ff, 0x06b50300, 0x2017821e, + 0x063941be, 0x0b419620, 0x08386d09, 0x8f070b41, 0x0175222d, 0x182d8935, + 0x4308fe43, 0x2d850745, 0x5b861f20, 0x9d000623, 0x08394136, 0xbf4a5988, + 0x212b8407, 0x2b88ea05, 0x1e616a22, 0x2b88e587, 0x2009e360, 0x20ab82a6, + 0x20b5847e, 0x21b585c2, 0x878975ff, 0x936d0220, 0x05b02106, 0x24065943, + 0x02000083, 0x232d885b, 0x13750006, 0x03208788, 0x03212b82, 0x094b4e1d, + 0x82a9ff21, 0x0658212b, 0x5985b383, 0x15ff9d22, 0xa74e5992, 0x9dff2106, + 0x63202d82, 0x2d85b584, 0x40ff6a22, 0x8809cd41, 0x095d5c87, 0x00007626, + 0x14066704, 0xc720e582, 0xa428b784, 0x1f008800, 0xb0000900, 0x240ae160, + 0x04f0ff4f, 0x20ad846f, 0x222384c8, 0x89d50044, 0x08016b81, 0x8f079f4c, + 0x0175222d, 0x4b2d8274, 0x335c05a5, 0x83518309, 0x235183d3, 0x759d0006, + 0x4f88ff88, 0xe3562120, 0x832b8308, 0x212b85a1, 0x9f8477a4, 0xb02f0b22, + 0x20064b44, 0x84718400, 0x229f85f3, 0x89a0006a, 0x234f88f3, 0x2db0dc24, + 0x20059142, 0x20cf8267, 0x20cf841e, 0x20cf86ce, 0x25cf89b5, 0xb11b2f08, + 0x57501d08, 0x222d8f0a, 0x89540175, 0x5644182d, 0x07cb4508, 0xd9832d85, + 0x5b82ce20, 0x5520d982, 0x5988d988, 0x8407df46, 0x85b7842b, 0x006a2287, + 0x88b78980, 0x09195c2d, 0x00000524, 0xb7843604, 0x754dd220, 0x2d012105, + 0x43188989, 0xd160081a, 0x82092007, 0x0594222d, 0x08f943d2, 0x22627022, + 0x201e7f44, 0x08d34304, 0x9a00a022, 0x04275989, 0x04b11b2f, 0x46593e1d, + 0x002f058b, 0xfe090002, 0x04940452, 0x0016008d, 0x5b710019, 0x771812f5, + 0x3d570c65, 0x00b02407, 0x5bb05845, 0xb22325f5, 0x5b001417, 0x002012f2, + 0x2c17f25b, 0x23072127, 0x03210301, 0xd501bf02, 0x091b4936, 0xfe599d2f, + 0x01f55f1e, 0x54013cd7, 0xfb8d04aa, 0x08204973, 0xeb619234, 0xfd8d04f9, + 0x00ba0125, 0x4f00ffff, 0x4304f0ff, 0x87441e06, 0x07012505, 0x63017500, + 0x4208af42, 0x43220bd3, 0x23861f06, 0x9d000623, 0x11af4264, 0xaf422020, + 0x0543220a, 0x244f88fc, 0x004a01a1, 0x07794127, 0x660a8d42, 0x7d8505db, + 0x9e225989, 0xd14e1e7b, 0x244f8706, 0x0400006a, 0x277b842a, 0x010000bd, + 0xf89e0006, 0x01232184, 0x8618b02f, 0x05a94471, 0xa944d220, 0x31702108, + 0x4508e941, 0x0420162f, 0xa0212b88, 0x88c98869, 0x073b462b, 0xc9835785, + 0x22058945, 0x891c01a1, 0x202d88c9, 0x06655914, 0x52fe7626, 0x8d04b503, + 0x18156559, 0x590c164b, 0x1b221d65, 0x51790416, 0x0ac17205, 0x254b6559, + 0x020afe5f, 0x26425e4c, 0xfd872309, 0x7d1803fb, 0x24420977, 0x5f862608, + 0xfec48d04, 0x099146f2, 0x21093546, 0x33414d9e, 0x07134e11, 0xf0ff5425, + 0x83064804, 0x00c0272b, 0x00060100, 0x2b88689d, 0x1b2f0a28, 0x3e1d0ab1, + 0xd944b059, 0x232b8507, 0x01260204, 0x07242b83, 0x9b00a000, 0x88097543, + 0x0707422d, 0x05212d84, 0x222d88fc, 0x414e01a1, 0x2d88098d, 0x2607835c, + 0x04f9fd54, 0x859d0448, 0x0700272d, 0x6a01a201, 0x5d4792fe, 0x68042105, + 0xc1209f84, 0x7b209f85, 0x2d479f88, 0x42102008, 0xff270557, 0x02000091, + 0x8214066e, 0x054b4643, 0x17ffa422, 0x57051b46, 0x97200a13, 0x05212383, + 0x232388d2, 0x0010ff70, 0x46087d42, 0xff210ff7, 0x212d82bd, 0xf1830643, + 0xa0225185, 0xf18948ff, 0xb7562d88, 0xfe152607, 0x048d0152, 0x255b858d, + 0xa3000600, 0xc18200ec, 0xb7827c20, 0xfc058222, 0x01241585, 0xfba10006, + 0x88085d43, 0x07b54b41, 0xf0ff2424, 0xed843704, 0x3582c320, 0x9d000724, + 0x6f89f400, 0x2008a644, 0x25ef8513, 0xf9fd7600, 0x6f846804, 0x0000c428, + 0xa2010700, 0x33411201, 0x49032007, 0xc52005cb, 0x06234582, 0x410a7500, + 0x9b490833, 0x067f4708, 0x03214383, 0x82438494, 0x5543842b, 0x762605e1, + 0x94030000, 0xb5829004, 0x01201782, 0x95225b83, 0xe1558a03, 0x3e1d240c, + 0x41313059, 0x418b05a1, 0x01a10025, 0x8546fd72, 0x67042317, 0xa9471e06, + 0x01752208, 0x12b54685, 0x7620f987, 0x6720cb82, 0xc7208784, 0x7820cb86, + 0x2208ff41, 0x881f0667, 0x009e2245, 0x4445899d, 0x59471001, 0x82d22005, + 0x84c8202d, 0x707022f9, 0x069d4422, 0x9d471d20, 0x8604200c, 0x00072421, + 0x48a800a0, 0x1b45121b, 0x066f220b, 0x222d881d, 0x82fe00a5, 0x000c262d, + 0xb02f0bb0, 0x0881541f, 0x00007624, 0xe9843904, 0x7582cb20, 0x75000724, + 0x91451701, 0x2f042305, 0xab4119b0, 0x8439200a, 0x252382df, 0xa2010700, + 0xdf881801, 0xdf843920, 0x01251782, 0x2f9e0006, 0x0e9b551e, 0xf0ff3e24, + 0x5d84ef03, 0x5d86cc20, 0x5d854120, 0x51480920, 0x20238509, 0x83a7821f, + 0x00062323, 0xf141429d, 0x08b97608, 0x2607fb53, 0x0341fe3e, 0x859d04ef, + 0x07002a2b, 0x4f017900, 0xffff0000, 0x21438f00, 0x8984599e, 0x230a8754, + 0x04f9fd24, 0x8408434c, 0x842520c3, 0x822420c3, 0x841620ff, 0x82cd20c3, + 0x20c382a1, 0x116f4447, 0x07410d20, 0xfe242206, 0x82438b47, 0x0039227d, + 0x267d8206, 0x04f0ff67, 0x8214061e, 0x84ce2095, 0x57a42243, 0x0783461f, + 0x4208b348, 0x2b8407f7, 0x88d20521, 0x5070232b, 0xe9520022, 0x06094405, + 0x21840020, 0x86040621, 0x00072421, 0x418800a0, 0xa94809e5, 0x214f8c08, + 0x2d887c06, 0xea00a22f, 0x0c005200, 0x2f00b000, 0xb0dc15b0, 0x0985491a, + 0x1d063422, 0xa5222588, 0x0b42de00, 0x20258205, 0x05816b12, 0x00010029, + 0x0482fe67, 0x828d041e, 0xb2612419, 0x5f201f1b, 0x172408bb, 0x17b11b2f, + 0x48075546, 0x0d200c70, 0x0d281982, 0xb0593e17, 0xb0584500, 0x23079751, + 0x001204b2, 0xb0223b82, 0xcd72100d, 0x7112200b, 0x30260bd8, 0x06110131, + 0x4d640706, 0x2626220d, 0x05425227, 0x11373228, 0x7d011e04, 0x42527f77, + 0xcd403107, 0x7ef102f2, 0x0404e56c, 0x81fcfc8d, 0x5a5632bd, 0x37054052, + 0xd606495d, 0xfd0503bb, 0xd4687300, 0xffff0703, 0x00002800, 0x1f06e505, + 0xd021e782, 0x057b5100, 0xb5491920, 0x07734712, 0x8305e349, 0x82d2202d, + 0x0006232d, 0xfb412e9d, 0x08674108, 0x8407fb41, 0xea05212b, 0x2b855982, + 0x4c596a21, 0x2b8808a1, 0x26091d51, 0x03000041, 0x821e06f3, 0x84d3202d, + 0x01752287, 0x12c34130, 0x84073f44, 0xfc05212d, 0xa1222d88, 0x6d461701, + 0x08294609, 0x8407f54a, 0x83e3842d, 0x0006235b, 0x5546489e, 0x0c716f11, + 0x66410621, 0x003c058f, 0xbfad0006, 0xffffff00, 0x0400004a, 0x004106b0, + 0x64290026, 0x00070000, 0x0084fead, 0x53241783, 0x7c050000, 0x2c201784, + 0x8d201786, 0x562a1784, 0x03020000, 0x26004306, 0x17862d00, 0x0200902a, + 0xa7ffffff, 0x3205ecff, 0x33212f84, 0x20478514, 0x202f83e1, 0x210582fe, + 0x17843a05, 0x2f863d20, 0x17831b20, 0x82b2ff21, 0x84f12077, 0x86b92017, + 0x84ec202f, 0xff873617, 0x06da02f4, 0x0026029a, 0x010000c2, 0xffae0007, + 0x00ebff20, 0x0a79641c, 0x593e1b2c, 0xb0dc18b0, 0x18b0d010, 0x736cb010, + 0x00122a06, 0x05420500, 0x000602b0, 0x25458325, 0x00009400, 0x0f84a304, + 0x0f882620, 0x0f844c20, 0x0f842920, 0x1f825020, 0x0f848c20, 0x0f843e20, + 0x05212f82, 0x200f8418, 0x200f842c, 0x207b82a3, 0x200f849f, 0x201f8e2d, + 0x210f872f, 0x1f846a06, 0x1f883120, 0x0f841720, 0x0f843220, 0xecff6626, + 0xc4051e05, 0x33208f82, 0xd4207f88, 0x34201f84, 0x84098557, 0x8438200f, + 0x8207200f, 0x84d6208f, 0x843d200f, 0x21a5820f, 0x0f84e904, 0x0f833c20, + 0x3f6fff20, 0x2fc1532f, 0xebff5629, 0x41067904, 0x51002602, 0xad2c0535, + 0x00005001, 0xb0000900, 0x24b02f13, 0x2406f144, 0x04ecff60, 0x4a23840c, + 0xad220595, 0xbd591901, 0x07934508, 0x61fe7e24, 0x23840604, 0x22055949, + 0x5c2301ad, 0x1420089d, 0xa9264786, 0x6102f4ff, 0xe1412c06, 0x00062406, + 0x44eb0fad, 0xa94206f5, 0x82802007, 0x0608228d, 0x282182a2, 0x010000ca, + 0x1dae0006, 0x070142f3, 0x0842af18, 0xb0dc1e29, 0x1eb0d015, 0x4427b010, + 0x8e2b05d5, 0x6b040000, 0x06023a04, 0x4c008d00, 0xec24055d, 0x4e043d04, + 0x53200f82, 0x92240f84, 0x1f0460fe, 0x76201f84, 0x16240f84, 0xda030000, + 0x5a200f84, 0x1f200f84, 0xe8200f82, 0x5c200f84, 0xff210f83, 0x22a582cc, + 0x42b70592, 0x6a240887, 0xebff6fff, 0x18078750, 0x23085b74, 0x1db0dc14, + 0xb3847f85, 0x88bf0521, 0x6c6a22b3, 0x882d87f3, 0xdc1a23b3, 0x1b5c23b0, + 0x4106210a, 0x9d822d82, 0x00070125, 0x412201ad, 0x04220527, 0xe147b02f, + 0x21518407, 0x51863406, 0x0d222383, 0x2941f3ff, 0x0a037106, 0x062d0623, + 0x23238232, 0x010000cd, 0x02232382, 0x86f1ff2c, 0x66232023, 0x35720c3b, + 0x9b002728, 0x37040000, 0x53823d07, 0x5384b020, 0x82017522, 0x73091161, + 0x08200875, 0x2c067d4c, 0x04ecff4a, 0x00c4058a, 0xb2630027, 0x5f4e1811, + 0x2f09250a, 0x1f09b11b, 0x20060d46, 0x2e0c821d, 0x593e0f1d, 0x091d02b2, + 0xb2391211, 0x821d090e, 0x09b02106, 0x210c0d7f, 0x47181002, 0xb2210aee, + 0x24298422, 0xb2101db0, 0x0a706925, 0x26340124, 0x7a192724, 0xff226551, + 0x054400ff, 0x3085430e, 0xecff2d34, 0xb005e403, 0x2e000602, 0xffff0000, + 0x00009b00, 0x0f833005, 0x44e30121, 0x18260835, 0x26023607, 0x69412f00, + 0x576e2006, 0x09610937, 0x07154308, 0xebff3926, 0x2307dd04, 0xdd202d82, + 0xa0222d84, 0x9741d900, 0x2f0f2709, 0x1f0fb11b, 0xe371593e, 0x1f114508, + 0x04218b82, 0x209b8437, 0x142145b0, 0xab829420, 0x6d840d20, 0x6d85db20, + 0x891d0121, 0x0803586d, 0x82071147, 0x100f452d, 0x450b4f45, 0x7d820f0f, + 0x84140521, 0x45b5207d, 0x2f82141f, 0x05eb0427, 0x000602c4, 0x142f4527, + 0x270e1f45, 0xecff5a00, 0x4e04fb03, 0x45202f82, 0x53242f84, 0x0b04ecff, + 0x49200f84, 0x862a0f84, 0x12040000, 0x2602d905, 0xcd85ef00, 0xff970023, + 0x079749f3, 0x1b20cd84, 0x200ac375, 0x443d824f, 0x7c240b3b, 0x300460fe, + 0x54214d84, 0x203e8200, 0x231f8200, 0x4e04f503, 0x9ded7519, 0x00ffff2d, + 0x034bfe0c, 0x023a04d6, 0x445d0006, 0x002013e3, 0x332cc571, 0x00008500, + 0xf3054d03, 0xeb002602, 0x07010000, 0xc2007500, 0x61094341, 0x0820082d, + 0x26067544, 0x03ecff4b, 0x824e04ca, 0x8457207b, 0x827d207b, 0x05902233, + 0x200f82d5, 0x200f834d, 0x2e8d71ff, 0xfeb5ff25, 0x8485014b, 0x844e203f, + 0x008f264f, 0x05650400, 0x208d82f2, 0x825982f0, 0x4401238d, 0x6753f2ff, + 0x3e1b220c, 0x07416659, 0x21050941, 0x2d82e605, 0x2105fd5a, 0xfd5a4aa0, + 0x07454b11, 0x2005b35b, 0x08b35b36, 0x08024422, 0x67099543, 0xd95608a9, + 0x05b35b07, 0xb35b0020, 0x01442208, 0x12b35b6a, 0x5b8f2d87, 0xa7027522, + 0x0c255b89, 0x0cb11b2f, 0x8fb58a1f, 0x0275225b, 0x465b8909, 0x1f440883, + 0x205b8507, 0x22b78802, 0x82d3016a, 0x000c295b, 0xb02f01b0, 0x0db0dc16, + 0x84057946, 0xcc052153, 0x6a22af88, 0x53823501, 0x3f48258f, 0x5c362005, + 0x44220801, 0xa789e800, 0x2008fd43, 0x06eb410a, 0x240d8b71, 0x77440006, + 0x062f6d00, 0x2a07c74c, 0x01fc0352, 0x0300060b, 0x630b0006, 0x21200e03, + 0x0121ef82, 0x29a382d0, 0xffff3130, 0xf4036500, 0x27844002, 0x27820620, + 0x44182c20, 0x78180ab3, 0x791807ab, 0x092808c8, 0xd006b010, 0xb02f06b0, + 0x8f2a3d89, 0xc803f2ff, 0x2600b005, 0x3d820500, 0x0500072e, 0x00002502, + 0xb1ffffff, 0x73024bfe, 0x240acf66, 0xff3fff9e, 0x0e5360de, 0x0004332a, + 0x00066501, 0x6d010602, 0x2509e149, 0x26023607, 0x5f423100, 0x90022105, + 0x20090141, 0x073b7902, 0x01411120, 0x007c2406, 0x82790600, 0x0026223d, + 0x202d8651, 0x08f748a0, 0x2607834f, 0x056dfe12, 0x4bb00542, 0x0730067f, + 0x7a01a600, 0xffff0300, 0x71fe5a00, 0x4e04fb03, 0x45201782, 0xa624b584, + 0x0700ad00, 0x2333777a, 0x3d070d05, 0xaf454582, 0x01442205, 0x12af454a, + 0x7607a356, 0x44210f0f, 0x1b3d7600, 0x20053d45, 0x083d45f3, 0xc4004422, + 0x87123d45, 0x0044245b, 0x825c0500, 0x000632e7, 0xff0000b8, 0xfe4f00ff, + 0x047e0522, 0x0006023a, 0x340f84cc, 0x04000010, 0x02fc06f3, 0x00180126, + 0x00070100, 0x014904ab, 0x072b490e, 0x2008c746, 0x07af7b11, 0x82f1ff21, + 0x0518262f, 0x012602d0, 0x232f8519, 0xe2ffe503, 0x11282f87, 0x11b11b2f, + 0xb0593e1b, 0x32091961, 0x084bfe4f, 0x004e0464, 0x00530026, 0x00070000, + 0x848e045d, 0xfe662677, 0x055c094b, 0x201782c4, 0x20178533, 0x2dd78205, + 0x4900ffff, 0x7f043afe, 0x2602c305, 0x1783da00, 0x01b00125, 0x82a0ff92, + 0xfe4d2617, 0x04c4033b, 0x2017824d, 0x221786ee, 0x82a1ff39, 0xfe662317, + 0x277c043e, 0x222f820a, 0x84a4ffd6, 0x773e20e7, 0x17820ba9, 0x17844a20, + 0x220fdb4b, 0x825ffe20, 0x023a2427, 0x4cbc0006, 0x1620146b, 0x9b22b482, + 0x77822307, 0xef84d920, 0x4702a021, 0x0d200a79, 0x0d21ef82, 0x51ef821f, + 0x1e26078f, 0x5c060000, 0x2d82d905, 0x2d85ed20, 0x41870121, 0x5d63099b, + 0x482d8708, 0x0f7e0ed1, 0x741c2006, 0x8d7d51a3, 0x29bd7d08, 0xecff5a25, + 0x7905fb03, 0x755f265f, 0xb0053105, 0x81000602, 0xffff0000, 0xecff4800, + 0x50048406, 0xd5410f82, 0x00942505, 0x074c0400, 0x34533171, 0x05ebff51, + 0x02db061e, 0x00450126, 0x00070100, 0x01c2006a, 0x0ceb4b0f, 0x593e1f23, + 0x09bf7bb0, 0xd7825920, 0x4f04f822, 0x9c209982, 0x0f84a984, 0x02cd0524, + 0x0f820026, 0x00060125, 0x8c01696a, 0x8c1b203d, 0x050d423d, 0x0d420920, + 0x026a2208, 0x09397d15, 0x0d420d20, 0xdc1d2307, 0xdf4526b0, 0x050f4205, + 0x0f42bf20, 0x016a2308, 0x894cff7f, 0x080f4208, 0x49262f89, 0x7f04edff, + 0xfd421707, 0x22cd8405, 0x874b01a3, 0x08ed468f, 0x2009d77a, 0x22cd824d, + 0x43cc05c4, 0xbd830515, 0x53774e20, 0x82252008, 0x8325208d, 0xdc2f23bd, + 0xc77d38b0, 0x060d2209, 0x089544f1, 0xe5007022, 0x4609b96d, 0x39440847, + 0x05674407, 0x6744a720, 0x00062406, 0x47f75f70, 0xbb6107d1, 0x4a2b8708, + 0x0920059f, 0x6a215988, 0x0a174101, 0x11205988, 0x8508f552, 0x44bf205b, + 0x6a2208c3, 0x17418f00, 0x08014a09, 0x66252f89, 0x1e05ecff, 0x29a57d07, + 0xecff4f25, 0x79053d04, 0x5f20296b, 0x17265f82, 0x0602c405, 0xaf4e1601, + 0x1701210d, 0x1f840f84, 0x02060723, 0x271f8326, 0x6a000701, 0x3a011301, + 0x420c7f4e, 0x7f880d65, 0x01243f83, 0x736a0006, 0x49089741, 0x917b089b, + 0x6b002108, 0xf126ad82, 0x26021807, 0xc342e600, 0x01e32206, 0x245d874c, + 0xb11b2f13, 0x235d8313, 0x30b0dc27, 0x2405c741, 0x03ecff51, 0x20dd84e8, + 0x822f82fe, 0x8859205d, 0x083b415d, 0xb0dc2823, 0x262d8531, 0x04ebff39, + 0x4cf106dd, 0x702408a9, 0x4101a100, 0x260e1148, 0x034bfe0c, 0x49b405d6, + 0x70220891, 0x218e0412, 0x07214584, 0x22458809, 0x42d1006a, 0x274609f9, + 0x09a55d08, 0x852ded79, 0x883c205d, 0x01a5225d, 0x235d922f, 0x12b0dc16, + 0x5d83d385, 0xff05f622, 0x0724af86, 0xa000a500, 0x8409c948, 0x3e1b238d, + 0x2f89b059, 0x00008e24, 0xbd84ee04, 0x6141e020, 0x0f012105, 0x44185f89, + 0x192308bf, 0x8522b0dc, 0x005f265f, 0x05e00300, 0x205f82bf, 0x056141f8, + 0xb5436720, 0x08c96a08, 0x9b322d89, 0x58060000, 0x26000a07, 0x000be500, + 0x2d002700, 0x3582b904, 0x6a000726, 0x3e01c201, 0x2310bd43, 0x29b0dc20, + 0x8f266585, 0xc9050000, 0x3782bf05, 0xbd82fd20, 0x8c002724, 0x37864704, + 0x0d437420, 0x08696609, 0xb0dc1f23, 0x2a378528, 0x054bfe29, 0x02b00551, + 0x823c0026, 0x01073037, 0x00c303af, 0x00ffff00, 0x044bfe1f, 0x823a0456, + 0x855c2017, 0xc8022117, 0x2608cd42, 0x02000603, 0x84480006, 0x822d200f, + 0x84fd203f, 0x85dc203f, 0x6f042127, 0x21201784, 0x07201782, 0xf1203f84, + 0x03211785, 0x22178479, 0x4997fe12, 0xac220c2b, 0x2b490d05, 0x499b2006, + 0xac230c2b, 0x18004004, 0x2009d744, 0x08c746bb, 0x0505aa24, 0x7f583c01, + 0x07314406, 0xecff5a26, 0x8506fb03, 0x2408617b, 0x008f04aa, 0x06796506, + 0x220bb37b, 0x87b1074a, 0xb7012747, 0x2101bf00, 0x874a1700, 0x07914f05, + 0x090eb124, 0x4e18b0f4, 0x55820737, 0x06d40423, 0x2c55867c, 0x49b70106, + 0x000c00ec, 0xb02f17b0, 0x080f432c, 0x00001026, 0xae074205, 0xb6245588, + 0x2b01c400, 0x04275587, 0x04b11b2f, 0x84593e1f, 0xd0132855, 0xff003130, + 0x849affff, 0x887920ab, 0x4eb62255, 0x205586f6, 0x2055882a, 0x20558412, + 0x245588de, 0x01c300b5, 0x23258313, 0x0bb02f04, 0x8308b742, 0x0657229f, + 0x224988a9, 0x96de4db5, 0x88d62049, 0x82b42049, 0x9305209f, 0xfb032349, + 0x4988a106, 0xd04eb422, 0xfe254991, 0x07420597, 0x23498537, 0x9d002700, + 0x36239382, 0x41000700, 0x06210cbf, 0x25438501, 0x9d002600, 0x1d83004d, + 0x410cc541, 0xb3240927, 0x3001ef00, 0x0e208786, 0x41086d68, 0x1b4105c7, + 0x79b32209, 0x208786fb, 0x0877462d, 0x89051b41, 0xa4b82049, 0x97b82049, + 0x3e082149, 0x24081b41, 0x01ee00b2, 0x21939536, 0x1b410807, 0x78b22208, + 0x21939500, 0x49881808, 0xf100b124, 0x49863c01, 0xb5651420, 0x20dd8508, + 0x224988e2, 0x86067bb1, 0xdc332149, 0x072b4218, 0x97fe1225, 0x49074205, + 0x002506b5, 0x00a00027, 0x419382f6, 0x05210e65, 0x844385e6, 0x0080211f, + 0x260b6741, 0x049efe94, 0x82b0054c, 0x8629201f, 0x00cb2c17, 0x00ffff0a, + 0x0494fe53, 0x824e040b, 0x86492017, 0x518f2017, 0x4c22089d, 0x237ac207, + 0x04aa2b08, 0x004301ca, 0x06b00009, 0xb758b02f, 0xff532607, 0x060b04ec, + 0x253b8585, 0xaa000701, 0x5d438304, 0x10c57a05, 0x47883320, 0x8a00a424, + 0x47863e01, 0xfd771720, 0xf605210b, 0x06244786, 0x0143a400, 0x7606fd77, + 0x0f220bb1, 0x4587b807, 0x00b70125, 0x43280184, 0x072d074d, 0x07b11b2f, + 0xb1593e1f, 0xb0f4090f, 0x054d4315, 0x9b830020, 0x7c06c822, 0x01275387, + 0x00ec3db7, 0x82b0000c, 0x71202099, 0xff2707ad, 0x040000d5, 0x88b5074c, + 0x00b62455, 0x87320189, 0x82062055, 0x87062055, 0x06f94355, 0x848eff21, + 0x887920f1, 0x42b62255, 0x205586f6, 0x2155871e, 0x55829400, 0xe5079222, + 0xb5245588, 0x1a018800, 0x2306fb6d, 0x13b0dc0c, 0x83055d45, 0x064b229f, + 0x224988a9, 0x94de41b5, 0x074c2249, 0x204988dd, 0x209f82b4, 0x2249940c, + 0x88a1060b, 0x42b42249, 0x214991d0, 0xe9829efe, 0x49853e20, 0x00270023, + 0x2593829d, 0x0007003d, 0x054204ac, 0x0106210a, 0x00244385, 0x419d0026, + 0x42053b42, 0xa326050b, 0x11020000, 0xa776c207, 0x03aa2208, 0x050b4278, + 0xb02f0223, 0x06c34104, 0x01232982, 0x827e06fd, 0x008c2e23, 0x00070100, + 0xff6403aa, 0x000900ff, 0x24238ab0, 0x019afe94, 0x081b77a7, 0xac000726, + 0x06007803, 0x78222582, 0x1d779efe, 0x2217830a, 0x820a005c, 0xfe662617, + 0x051e0594, 0x4d5382c4, 0xac2305bd, 0x4e001d05, 0x9224055d, 0x4e043d04, + 0xed4d1782, 0x04ac2405, 0x7ffeff9d, 0x05230509, 0x73bb071e, 0xaa2408ad, + 0x3c011c05, 0x14208383, 0x2609e57e, 0x04ecff4f, 0x5785063d, 0xaa220885, + 0xb3429804, 0x2f042305, 0x51741bb0, 0x0761220a, 0x294787b1, 0xd600b701, + 0x0c002101, 0x4782b000, 0x754b2120, 0x22498308, 0x867c06dd, 0x01062449, + 0x43ec52b7, 0x1d2006d9, 0x2208e147, 0x82ecff27, 0x88ae2091, 0x00b62449, + 0x862b01db, 0x871f2049, 0xa3ff2149, 0x79209384, 0xb6224988, 0x4986f657, + 0x49881b20, 0x20059b4a, 0x224988de, 0x45da00b5, 0xdb8405f9, 0x8307094c, + 0x06602293, 0x224988a9, 0x96de56b5, 0x88d62049, 0x82b42049, 0x8f052093, + 0x41002093, 0xa1200527, 0xb4224988, 0x4991d057, 0x8294fe21, 0x853720dd, + 0x27002349, 0x93829d00, 0x4105f945, 0x06210aa7, 0x24438501, 0x9d002600, + 0x05554256, 0x2b05ad41, 0x05ecff58, 0x023307aa, 0x00970026, 0x75261783, + 0x3301d301, 0x7984ffff, 0x0006bb22, 0x98281782, 0x07010000, 0x58017500, + 0x2008735a, 0x06a14125, 0x44223b8f, 0x3b943401, 0xb9004422, 0x23203b88, + 0xb8203b8c, 0xaa247788, 0x39011605, 0x85207788, 0xaa227788, 0x19429b04, + 0x2f092205, 0x203b8db0, 0x243b8829, 0x01d600a4, 0x213b8734, 0x3b86f605, + 0xa4000625, 0x7300015b, 0x2e2005e3, 0xfe257587, 0x06aa0594, 0x2339882e, + 0x000605ac, 0x2405cb42, 0x04bb048b, 0x313985a8, 0xac000700, 0xf7ff9a04, + 0x7d00ffff, 0xbd0494fe, 0x1b72b005, 0x20178405, 0x262f84f2, 0x0394fe77, + 0x723a04f7, 0x17840503, 0x17844120, 0x20054b72, 0x252f85bb, 0xaa000701, + 0xfb42f304, 0x2f002105, 0x7208b579, 0xe1830595, 0x00005922, 0x91202384, + 0x0620e185, 0x47822389, 0x073d0623, 0x20478242, 0x24238499, 0x01d70175, + 0x0ed56142, 0x05234782, 0x82ec0528, 0x869a2023, 0xff572223, 0x065b53ec, + 0x4a181c20, 0x478c096f, 0x38014422, 0x99504788, 0x22478f07, 0x88b80044, + 0x8c1a2047, 0x88c72047, 0x05aa248f, 0x8648011a, 0x21478c8f, 0x8f887106, + 0x9a04aa24, 0x8f86f2ff, 0x3820478d, 0xa4224788, 0xc344da00, 0x5c042005, + 0x8f8509ed, 0x4786e220, 0xa4000624, 0x4586ed5a, 0x26077742, 0x068bfe7d, + 0x8501063d, 0x07003145, 0x1905ac00, 0xfffff7ff, 0x94fe7700, 0x93042805, + 0x17833985, 0x0045042d, 0x00ffff00, 0x04a4fe07, 0x55b005d6, 0x17840553, + 0x1000c622, 0x0c261782, 0xd6030ffe, 0x594c3a04, 0x22478405, 0x827bff46, + 0x00072617, 0x07d60400, 0x088355bb, 0xca04aa22, 0x2305c541, 0x09b02f01, + 0x200c7955, 0x08954c85, 0x5904aa22, 0x8205c541, 0x077b5523, 0x2c204785, + 0xa4244788, 0x37018a00, 0x20066b4d, 0x21478b14, 0x8d4df605, 0x19a42208, + 0x20218601, 0x3121831b, 0x4f000200, 0xb204ecff, 0x16000006, 0x8c002100, + 0x4d191fb2, 0x1024089d, 0x13b000d0, 0x0aa35618, 0x07f44018, 0x0c147f18, + 0x1b2f022e, 0x3e0f02b1, 0x132fb259, 0x0fb25d01, 0x16270483, 0x12111302, + 0x1816b039, 0x220c4d52, 0x82060c04, 0x0eb22114, 0xb02a0684, 0x16b0d00f, + 0xd011b010, 0xad7306b0, 0xdc56180c, 0x2301370e, 0x06272311, 0x11022223, + 0x32331234, 0x35233517, 0x15333533, 0x64180133, 0x3b0809ca, 0xdcafb204, + 0xbeb66d0c, 0xacc3e8eb, 0xf3fbfb6a, 0x7f90fcaf, 0x43459575, 0x04807695, + 0x7037fbc9, 0x01320184, 0x2f01fa07, 0x8daaf378, 0xa59dfc8d, 0xce0185b9, + 0xffffbb82, 0xaefe4f00, 0x263af384, 0x00004800, 0xde012700, 0x42028501, + 0x43000701, 0x6dff9900, 0xb2001200, 0xce821c2f, 0x011c1f25, 0x829fb271, + 0x31302109, 0x9b2a3382, 0x7e059afe, 0x2602b005, 0x3382e301, 0xb0010734, + 0x00002f04, 0x8f00ffff, 0xc2049afe, 0x26023a04, 0x1785f000, 0x84730321, + 0x82942017, 0x83db202f, 0x2c00212f, 0x04211785, 0x2017848c, 0x202f8286, + 0x202f84d5, 0x201785f3, 0x05d75203, 0x17822d20, 0x230aef77, 0x4d02b001, + 0x23242f84, 0xd0039afe, 0xf5202f84, 0x01212f85, 0x201784e6, 0x205f8229, + 0x0ab94d22, 0xd303b022, 0x1f201784, 0x27204782, 0x220ab94d, 0x84d802b0, + 0x828e2017, 0x84ad202f, 0x85e0202f, 0x5e042147, 0x5f201784, 0xa4222f82, + 0x9f4e3b04, 0x82002005, 0x550321d7, 0x2f821784, 0x8bee0421, 0xcf02212f, + 0x2f821784, 0x8be00321, 0xc601212f, 0x9b201784, 0x37204782, 0xb0202f84, + 0x01215f85, 0x20178407, 0x20bf8285, 0x208f844d, 0x211785eb, 0x1784ec00, + 0x9afe1624, 0x2f840508, 0x1785d920, 0x84b60621, 0xfe1e2417, 0x84b4069a, + 0x85ed202f, 0x65052117, 0x162a1784, 0xbc0543fe, 0x2602c405, 0x17853f01, + 0xffed022d, 0xffffffa9, 0x0446fecb, 0x824e048b, 0x85402017, 0xf5012617, + 0xffffacff, 0x05cd7c00, 0x06020024, 0x17824c00, 0xd0ff0236, 0xc1040000, + 0x1300b005, 0x6e001c00, 0x1e1d00b2, 0xb0391211, 0x07564918, 0x0cfa5f18, + 0x08887518, 0x0a101322, 0x13202483, 0x200cca42, 0x2d148502, 0x00b02f02, + 0xd00cb010, 0xb01013b0, 0x9418d00e, 0x0a200e63, 0x0b705a18, 0x0131302d, + 0x32211523, 0x14151616, 0x18210704, 0x08072455, 0x21110338, 0x34353632, + 0x6d022726, 0xa02a01e0, 0xebfe7cee, 0xc0d3fdef, 0xe0e0fdc0, 0x8f802901, + 0x47047c8c, 0x85ca6ec4, 0x0402f8cc, 0xbfbfaa47, 0x12fec7fd, 0x806e738b, + 0xc9400002, 0xff012cc9, 0x040000f0, 0x00b00537, 0x4f49000d, 0x08240589, + 0x08b11b2f, 0x44075c60, 0x0d27085c, 0x12110208, 0x410db039, 0xb0280b87, + 0x0db0d004, 0xd006b010, 0x0d948c18, 0x107a7918, 0xfcf68d3f, 0x9c03abab, + 0x02f660fd, 0x0261fd9f, 0x6702aa9f, 0x0065fecc, 0x00e2ff01, 0x044d0300, + 0x447b8e3a, 0x7bb607e5, 0x23112129, 0x33352311, 0x82152111, 0x7f023801, + 0xa3f2f8fe, 0xfec802a3, 0x0108012a, 0x012ffed1, 0xbf01aad1, 0x8200fbc4, + 0x00e3247d, 0x82440500, 0x001422f9, 0x42f99274, 0x5c180c8e, 0xc81808f7, + 0x0f2408b8, 0x0eb2593e, 0x20051341, 0x3a47180e, 0x07b2210b, 0x8e181485, + 0x07310d8e, 0xd00ab010, 0xb01004b0, 0x12b2d00c, 0x12110e01, 0x09244139, + 0x15333535, 0x15231533, 0x01210133, 0x57022101, 0xccccfcac, 0x18d5d5fc, + 0x2c0e8195, 0xc7aa3f04, 0x02f3aac7, 0xfd47fd64, 0x27bb8209, 0x040000ae, + 0x00000649, 0xc75bbb8d, 0x41bb8407, 0xb0200f46, 0x1021bb8d, 0x20858202, + 0x20bb8fb0, 0x5f7b1810, 0x20bba111, 0x2abb8511, 0xf26ff601, 0xc4f2e7e7, + 0x180169c4, 0x350cb095, 0x9baabb04, 0xe1fdaa9b, 0x11fe9e01, 0xff00b5fd, + 0xfe9400ff, 0x6d61057e, 0x00db3205, 0x00270000, 0x011d01a0, 0x0007013d, + 0xff800410, 0x0c3960c6, 0x0bfd5518, 0x7efe8625, 0x6005e404, 0x35830667, + 0xff970023, 0x213583f3, 0x358e8703, 0x830b6f60, 0x46e9206b, 0x63820903, + 0xc6ff8c22, 0x4d838382, 0x0346e320, 0x10002309, 0x17848603, 0x07212f82, + 0x202f8432, 0x829b8231, 0xd5052193, 0x8f241784, 0x41067efe, 0xf2202f84, + 0x04211785, 0x201784e4, 0x20cb822d, 0x097d53dc, 0x7f205f82, 0x21201784, + 0xe620ad82, 0x82097d53, 0x8289205f, 0x00012fa5, 0x04000007, 0x00b005d6, + 0xb256000e, 0xaa180f0a, 0x764309e9, 0x2f0b240c, 0x430bb11b, 0x062a1083, + 0x12110802, 0x2f06b039, 0x481805b2, 0x0123099f, 0x420ab2d0, 0x06230572, + 0x180eb010, 0x220af77c, 0x82012101, 0x03332c02, 0xcafed5c3, 0x0167fe7a, + 0x824f0119, 0xfe183601, 0x04028667, 0x0402fcfd, 0xfd0203aa, 0xfcb2024e, + 0x010000fe, 0x06375b00, 0x63209582, 0x49429591, 0x08bb5407, 0x58450024, + 0xa28202b0, 0x1fcbde18, 0xb223a588, 0x83000b0a, 0xd00d21ba, 0x0521a284, + 0x05a34323, 0x33012308, 0x01331313, 0xdc600333, 0xfea2cef3, 0xecf3fbbb, + 0xafbcfefb, 0x0160fe01, 0x9103aaa0, 0xff0201fd, 0x9d836ffc, 0x23069162, + 0x63001100, 0x4105a943, 0x0e200c1f, 0x0e208982, 0x200f2c41, 0x18a383b0, + 0x22081484, 0x83020b11, 0x4611207e, 0x04200c45, 0x07291485, 0x1011b0d0, + 0xb2d009b0, 0x230f840d, 0x23013130, 0x21053a41, 0xd7423523, 0x03333706, + 0x950187db, 0xc7fed9fe, 0xdafec6fe, 0x73819601, 0x240182fe, 0x01823201, + 0x83fe2439, 0xfd950279, 0xfd16026b, 0xaa9502ea, 0xf2fd7102, 0x8ffd0e02, + 0x66000100, 0xb38e06f3, 0x18074a41, 0x440c34c3, 0xb3890c5d, 0xb3930e20, + 0xb3891485, 0xb3850f84, 0x21030323, 0x08b38401, 0x21131359, 0x57033301, + 0xfe260195, 0xfed7d8f4, 0x8a2501f2, 0x01effe82, 0x01ceca0c, 0x8ceefe0e, + 0x29fed701, 0x8efe7201, 0x01aad701, 0x019cfeb9, 0xff47fe64, 0xff6000ff, + 0x040c04ec, 0x0006024d, 0xff0000be, 0x000200ff, 0x05310400, 0x002602b0, + 0x0000002a, 0xffde0107, 0x8269fe72, 0x02812317, 0xe318056d, 0x51200f5d, + 0x40222b82, 0x3b82c405, 0x20096f59, 0x590f8415, 0x3420056f, 0x58201f82, + 0x06224b82, 0x5b841800, 0x6b828120, 0x0f843a20, 0x0f841920, 0xfaff5d29, + 0xc4051204, 0x4e000600, 0x7d2005cf, 0x36201f82, 0x14210f84, 0x208b8314, + 0x220f826a, 0x184b07f0, 0x2408df49, 0x01bd0175, 0x06b36f4b, 0x654b2120, + 0xfe522606, 0x060c0456, 0xd5491800, 0x01752208, 0x0825603f, 0xad672720, + 0x0d461809, 0x0144220c, 0x0977604c, 0x87520620, 0x56b02006, 0x461807d3, + 0x44220f0d, 0x5182b300, 0x81421320, 0x08776805, 0x52181220, 0x21200c91, + 0x24082557, 0x017704ab, 0x0c417a33, 0x593e1f27, 0xb0dc0cb0, 0x05975210, + 0xecff0d26, 0xec05fb03, 0x24083157, 0xff0104ab, 0x202f87fe, 0x9b571817, + 0xa9581809, 0x00482607, 0x074c0400, 0x08df5328, 0x3c04ab22, 0x8809b35a, + 0xdc0d23bb, 0x5f8511b0, 0xecff0124, 0x5f840b04, 0x00004928, 0xab000701, + 0x5f89f503, 0x2008575a, 0x0735691f, 0x00f6fe25, 0x841e0200, 0x852d205f, + 0xea02212f, 0x93615f89, 0xdc052308, 0x5f8409b0, 0x82e2fe21, 0x050a222f, + 0x088752e4, 0xd602ab24, 0xbf87f6ff, 0x1b202f84, 0x2f88ef82, 0x57510020, + 0x52212005, 0xab220833, 0x1f418e04, 0x089d6309, 0xb0dc2023, 0x215f8424, + 0xbf821600, 0xbf843d20, 0x8f855320, 0x890a0421, 0x2f0424bf, 0x8304b11b, + 0x181c205f, 0x25086154, 0x04000032, 0x5f8307de, 0x2f863620, 0x7f412620, + 0x6a192012, 0xff210753, 0x20bf826e, 0x205f84b4, 0x212f8556, 0x5f896203, + 0x2008115d, 0x0847540f, 0x8f827120, 0x5f84bd20, 0x2f853920, 0x89650421, + 0x0890695f, 0xb0dc1223, 0x24bf8516, 0x03ecff0f, 0x505f84f7, 0xab220503, + 0x5f920304, 0xfe322f88, 0x050000ac, 0x00410602, 0x64cf0026, 0x00070000, + 0x634cfdad, 0xfe942b05, 0x05a3049e, 0x002602b0, 0x17830026, 0xb904ac32, + 0xffff0a00, 0x8bfe7c00, 0x00063204, 0x46002602, 0xcb221786, 0x1782f7ff, + 0xd2202f83, 0x28202f84, 0x94201786, 0x4f242f84, 0x030494fe, 0x48202f84, + 0xb4291786, 0xffff0000, 0xf9fd9400, 0x252f8a04, 0x4801a201, 0x178292fe, + 0x17824f20, 0x17822f8a, 0x17846820, 0x05215f82, 0x0a4f4718, 0x2605ac22, + 0x79245f84, 0xf8039efe, 0x4c205f84, 0xa1205f86, 0x94201784, 0x8769d782, + 0x00092311, 0x4c1804b0, 0x00270883, 0x0400007d, 0x823d0736, 0x004f2bcb, + 0x00070100, 0x016b0175, 0x238d003d, 0xdffe9422, 0x2f207786, 0xe9225f86, + 0xa7824b00, 0xcafe7d22, 0x0b094b18, 0x04ac0025, 0x41360079, 0x26200607, + 0x3020a784, 0x240c3741, 0x019efe78, 0x20a7848b, 0x21178550, 0xa7855c03, + 0x069efe23, 0x0af7476a, 0xd605ac22, 0x7c201784, 0x79221782, 0x9b824e04, + 0x2f855120, 0x84d90521, 0xfe942217, 0x074a189a, 0xac00250b, 0x06002805, + 0x79227782, 0x4a189efe, 0x8f820b07, 0x2f858d20, 0x04000025, 0x824207d4, + 0x86342047, 0x517220e3, 0x032005a7, 0x09935f18, 0x60fe7c26, 0xf7053004, + 0x54202382, 0x9d272386, 0x0900f7ff, 0x6c0cb000, 0x942209b9, 0x48189efe, + 0x5f820b81, 0x5f84ba20, 0x9efe7222, 0x0b814818, 0x03ac0023, 0x22178456, + 0x1894fe4a, 0x2a0c9947, 0x00d504ac, 0x00ffff00, 0x188bfe4b, 0x820b6947, + 0xff7c2247, 0x221782f7, 0x1897fe2d, 0x240cf346, 0x00c304ac, 0x22178203, + 0x1894fe08, 0x820b2347, 0x8414202f, 0x00122647, 0x071d0500, 0x20b38238, + 0x22b3843a, 0x51b000a4, 0x581805ef, 0x16260a2b, 0xda030000, 0x2382ed05, + 0x23825a20, 0xa4000624, 0x0151f818, 0x083d4506, 0x059efe25, 0x85b0051d, + 0x07002145, 0xef205d82, 0x1626bd84, 0xda039efe, 0x39853a04, 0x57201784, + 0x30241784, 0xe5069efe, 0x3b202f84, 0x20069541, 0x201784e6, 0x20478221, + 0x202f84cc, 0x2017865b, 0x2417844e, 0x049efe50, 0x202f848c, 0x2117853e, + 0x1784c104, 0x5f825220, 0x2f84c020, 0x17865e20, 0x17836320, 0xff1cfe33, + 0x056405ec, 0x002600d7, 0x00004633, 0xfd5a0107, 0x2aed84b5, 0x04000009, + 0x021e0594, 0x84ba0126, 0xffad282f, 0xffddfe76, 0x822affff, 0x05f127e1, + 0x01260021, 0x2f823cbe, 0xfead0025, 0x82e0fe64, 0x82372017, 0x05a4222f, + 0x2017821c, 0x221786c1, 0x82dbfe71, 0x00392417, 0x84b30100, 0x86c2202f, + 0x84732017, 0xff93262f, 0x057904f0, 0x212f821e, 0x47850ac8, 0x5f83cd20, + 0x82e8fe21, 0x84722047, 0x86d22017, 0x8422202f, 0x82a42077, 0x848e2017, + 0x86f32017, 0x83de202f, 0x84002017, 0x8d0423a7, 0xa7830602, 0x20066777, + 0x200f840a, 0x20c784bb, 0x20af8276, 0x200f84b5, 0x200f84be, 0x200f8241, + 0x500f84f3, 0x1f8205c1, 0x84680421, 0x84c1200f, 0x8285201f, 0x847720af, + 0x84c2200f, 0x201f890f, 0x210f87c4, 0x1f848f05, 0x20058950, 0x22c7824f, + 0x829d046f, 0x05b35e7f, 0x2c202f83, 0xc9201f84, 0x24202f84, 0x1620b782, + 0xcd200f84, 0x05200f84, 0x36200f82, 0xd2200f84, 0x15200f84, 0x4a200f82, + 0xd1200f84, 0x40180f83, 0x4f843001, 0x18284574, 0x202c1541, 0x272d8300, + 0x021e0697, 0x00ea0126, 0x2005ad44, 0x056b7723, 0xb02f0422, 0x2407a16b, + 0x03f0ff3e, 0x20ff84ef, 0x133f41cc, 0x2420cfb0, 0x64254f82, 0x06028d04, + 0x051b6001, 0x04218382, 0x20838468, 0x104d78c4, 0x91480f20, 0xff1f2a06, + 0x063904ec, 0x02260204, 0x23238201, 0x7aa00006, 0x7708bf74, 0x2f42102d, + 0x84972023, 0x42f3827f, 0x0320054f, 0x830b3f42, 0x836e208f, 0xfe01216b, + 0xa0228f84, 0x8775ba00, 0x7d0d2012, 0x2d4209db, 0x0f6d420c, 0x20133d42, + 0x207d8462, 0x087d42ef, 0x830b4d42, 0x0443262f, 0x0106029d, 0x145d42bc, + 0x370c4d42, 0x42000100, 0xe70339fe, 0x28009d04, 0x27b2a400, 0x12112a29, + 0x17b00039, 0x20056755, 0x07cf7c0a, 0x0cb0cc18, 0x0fa09318, 0x32821920, + 0x1927b223, 0x2e06820a, 0xb22f27b0, 0x7201275f, 0x01273fb2, 0x83cfb271, + 0x83ff2004, 0x820f2004, 0x6fb42f13, 0x02277f27, 0x27afb471, 0x5d0227bf, + 0x12828fb2, 0x83bfb221, 0x71242004, 0xb2230876, 0x18272410, 0x21085f5c, + 0x52851db2, 0xb5181920, 0x34230e55, 0x18222326, 0x2b093dae, 0x16160706, + 0x07061415, 0x26112311, 0x1cb89318, 0xf3acbb24, 0x9318b09b, 0x862918b6, + 0x41fe18ae, 0xac18c201, 0xba931887, 0x01003007, 0x9afe7600, 0x8d042c05, + 0xa8000f00, 0x181003b2, 0x220987b3, 0x181b2f0c, 0x1809068a, 0x200ce770, + 0x20198201, 0x07997801, 0x180c9856, 0x2208947d, 0x8309060a, 0x2f0a2fe2, + 0xbf0aafb4, 0xb25d020a, 0x71010a3f, 0x0483cfb2, 0x72220982, 0x0983ffb2, + 0x010a0f2e, 0x0a6fb472, 0x71020a7f, 0xef0adfb4, 0xb4232682, 0x822f0a1f, + 0x5fb22106, 0xb2211982, 0x4a8d1805, 0x4e0e200c, 0x47510859, 0x5ff41806, + 0x05333c09, 0xfdc4f32c, 0x02f3f3f4, 0xfec4f30c, 0x0166019a, 0x0425fedb, + 0x0111fe8d, 0x8228fcef, 0xfe4f2ae1, 0x04430443, 0x001e009d, 0x0c7b795e, + 0xc7820e20, 0x08829618, 0x0c820420, 0xd17f0420, 0x26c78707, 0xb2d006b0, + 0x83030e12, 0x180e20ca, 0x200ccd6e, 0x0b717903, 0x031eb223, 0x05df510e, + 0xa2410620, 0x27022305, 0xbe183435, 0x0c281448, 0xb5f3a9c6, 0xec7e01cf, + 0x1148be18, 0x1bd09f2d, 0xb90149fe, 0xdd1f0124, 0x18ffa94f, 0x180b4dbe, + 0x22093588, 0x45010602, 0x0a34052b, 0xa8053afe, 0x2602a304, 0x00001702, + 0xb0010700, 0xa0ffe602, 0x2505a343, 0xd2056e04, 0x93432602, 0x00702c06, + 0x00220082, 0x00b00009, 0x440ab02f, 0x23830b23, 0x21062344, 0x21844270, + 0x50180220, 0x502609f1, 0x4d050000, 0x6d828d04, 0x0000f128, 0x1200ffff, + 0x3d6455fe, 0x01a3240c, 0x82030082, 0xfe5a2217, 0x0c3d6459, 0xb500a324, + 0x17820700, 0x5cfe9422, 0x240c0f61, 0x004001a3, 0x2217820a, 0x6152fe53, + 0xa3220c0f, 0x5f840401, 0x9efe7826, 0x3a048b01, 0x2705574c, 0xac000700, + 0x0a005c03, 0x0f28d782, 0x0300ba00, 0x09040100, 0x5e200b82, 0x0b850382, + 0x1a000124, 0x17865e00, 0x0e000224, 0x0b867800, 0x178a0320, 0x0b8a0420, + 0x2c000524, 0x23868600, 0x17820620, 0x0b86b220, 0x40000724, 0x0b86cc00, + 0x0c000924, 0x0b860c01, 0x14000b24, 0x0b861801, 0x26000c24, 0x0b862c01, + 0x5c000d24, 0x0b865201, 0x54000e24, 0x0b86ae01, 0x0c001024, 0x0b860202, + 0x0b821120, 0x43000e3a, 0x70006f00, 0x72007900, 0x67006900, 0x74006800, + 0x32002000, 0x31003000, 0x20220182, 0x1d824700, 0x17826f20, 0x65006c22, + 0x49261782, 0x63006e00, 0x09822e00, 0x6c004122, 0x20220182, 0x35885200, + 0x15827320, 0x25825220, 0x03827320, 0x76007222, 0x64200582, 0x52202982, + 0x62203f82, 0x74200382, 0x20220382, 0x15844d00, 0x75006924, 0x39826d00, + 0x57826520, 0x45827520, 0x7b826120, 0x35845620, 0x4d827320, 0x63826f20, + 0x2e208183, 0x85858382, 0x8f823520, 0x95883b20, 0x39823420, 0x87006f21, + 0x8e2d2053, 0x20198953, 0x834b8220, 0x82612093, 0x82742039, 0x00612261, + 0x21638264, 0x6d83006d, 0x13826b20, 0x66006f22, 0xdf8b0582, 0xed8c2e20, + 0x6320198d, 0x6d24bf82, 0x68004300, 0x69244982, 0x74007300, 0x61205d82, + 0xe185a984, 0x17826520, 0x17827420, 0x4c20bd83, 0x63201b82, 0x6e206b82, + 0x65200f82, 0x20207582, 0x6e20ef82, 0x72207d84, 0x68208b84, 0x20241b82, + 0x70004100, 0x63208b82, 0x65205182, 0x338d1582, 0x11822c20, 0x20151141, + 0x20798268, 0x22398274, 0x822f003a, 0x00772101, 0x2e200183, 0x4b894782, + 0xa9822e20, 0x67007222, 0x6c201d82, 0x7320878c, 0x4c221182, 0xc3824900, + 0x4e00452e, 0x45005300, 0x32002d00, 0x30002e00, 0x410c4f41, 0x03210ba1, + 0x21008400, 0xbb826aff, 0x048e0984, 0x0200012c, 0x02000800, 0x0f00ffff, + 0x1b820100, 0x000a2008, 0x00ac005c, 0x4c464404, 0x631a0054, 0x006c7279, + 0x65726728, 0x6c36006b, 0x006e7461, 0x82040044, 0x82002023, 0x0002242d, + 0x8a040000, 0x0001220d, 0x220d8a05, 0x8a060002, 0x00032a0d, 0x63080007, + 0x00707370, 0x20058432, 0x20058438, 0x2605843e, 0x72656b44, 0x914a006e, + 0x205f8205, 0x22918401, 0x84030001, 0x8402200b, 0x21048205, 0x5b820100, + 0x0c000522, 0x01210185, 0x202586de, 0x20078208, 0x2285820a, 0x82480024, + 0x82de2009, 0x25ec09d5, 0x27002600, 0x29002800, 0x2b002a00, 0x2d002c00, + 0x2f002e00, 0x31003000, 0x33003200, 0x35003400, 0x37003600, 0x39003800, + 0x3b003a00, 0x3d003c00, 0x65003e00, 0x92006700, 0xb100b000, 0xb300b200, + 0xb500b400, 0xb700b600, 0xb900b800, 0xd200d100, 0xd400d300, 0xd600d500, + 0xd800d700, 0xda00d900, 0xdc00db00, 0xde00dd00, 0xe000df00, 0xe200e100, + 0xe400e300, 0xe600e500, 0xe800e700, 0x30012c01, 0x38013201, 0x3c013a01, + 0x3f013e01, 0x46014501, 0x85017f01, 0x8d018a01, 0x47024602, 0x4b024902, + 0x4d024c02, 0x4f024e02, 0x51025002, 0x53025202, 0x55025402, 0x57025602, + 0x59025802, 0x5b025a02, 0x5d025c02, 0x5f025e02, 0x61026002, 0x63026202, + 0x65026402, 0x84028202, 0x88028602, 0x8c028a02, 0x90028e02, 0x94029202, + 0x98029602, 0x9c029a02, 0xa0029e02, 0xa402a202, 0xa802a602, 0xac02aa02, + 0xb102ae02, 0xb502b302, 0xb902b702, 0xbd02bb02, 0xc102bf02, 0xc602c402, + 0xca02c802, 0xce02cc02, 0xd202d002, 0xd802d402, 0xdc02da02, 0xe002de02, + 0xe402e202, 0xe802e602, 0xec02ea02, 0xf002ee02, 0xf302f102, 0x5203f502, + 0x54035303, 0x56035503, 0x58035703, 0x5b035a03, 0x5d035c03, 0x5f035e03, + 0x61036003, 0x64036303, 0x66036503, 0x68036703, 0x79036903, 0x7b037a03, + 0x7d037c03, 0x7f037e03, 0x81038003, 0x83038203, 0x85038403, 0x87038603, + 0x89038803, 0x8b038a03, 0x8d038c03, 0xba038e03, 0xbe03bc03, 0xd903d303, + 0x4804df03, 0x4e044a04, 0x58045604, 0x69045d04, 0x00000200, 0x0a000200, + 0x0100ba3b, 0x04006c03, 0xb1010000, 0x9e36b206, 0xdc069e36, 0x40373207, + 0xca364c36, 0xd8378a3b, 0xde3a3807, 0x1e38de3a, 0xea358c3a, 0x35080983, + 0x56368a3b, 0xf40a720a, 0x1e383e38, 0x7836a436, 0x003b3239, 0x5e0b2a36, + 0xdc36b637, 0xa00bee37, 0xd40cca0c, 0x96399639, 0xdc36f837, 0xca0d1836, + 0x2c0e2438, 0x05829039, 0xdc364628, 0xca39880e, 0x55824037, 0x0f403608, + 0x10fc0f02, 0x12d811fa, 0x12243876, 0x1596397c, 0x1814173a, 0x18401826, + 0x1a4c1846, 0x1a4c1a46, 0x1bb41a82, 0x1ea81c32, 0x3a18205a, 0x224e21de, + 0x253239e0, 0x217f832e, 0x0583f636, 0xf8253308, 0xa0399227, 0x32297028, + 0x1e2ac029, 0x2839f82a, 0x9039822b, 0x762c4c2c, 0xdc36dc2d, 0xa0306230, + 0x9033d231, 0x5432dc36, 0x0433da32, 0x90335a33, 0x91824037, 0x2438a423, + 0x2da78233, 0x2839ca39, 0x8c3a8c3a, 0x9e362839, 0xf383e033, 0x359e3631, + 0x35783552, 0x358c3582, 0x35bc35aa, 0x83e035ce, 0x8a3b21fd, 0x38210183, + 0x203b823e, 0x23038940, 0xd837ca36, 0x89830185, 0x29850385, 0x1e212d84, + 0x23018438, 0xb637003b, 0xee21018c, 0x23018437, 0xf8379639, 0x38230187, + 0x82243824, 0x87b62057, 0xca362103, 0x3b210185, 0x205f828a, 0x23038fee, + 0x9639de3a, 0x91417189, 0xea352105, 0x19850183, 0x39231d83, 0x82963996, + 0x87f8203d, 0x18362103, 0x38210183, 0x8401843e, 0x299d8597, 0x003b7836, + 0x003b2438, 0x01832a36, 0xd8207f82, 0x8205db41, 0x364026b5, 0x36d8374c, + 0x2069842a, 0x2915858c, 0x3e385636, 0x3239003b, 0x0582de3a, 0xb582bf82, + 0xd837f824, 0x1942ca39, 0x8c3a2407, 0x8237f636, 0xca392237, 0x29478637, + 0xca365636, 0x32393e38, 0xf582b637, 0xdc36f82e, 0x90392438, 0x2839ee37, + 0x78362438, 0x7d830183, 0x83057741, 0x24ff84bb, 0x36ee37d8, 0x201f82a4, + 0x821b83ca, 0x39322415, 0x41de3a90, 0x1d82081d, 0xee214982, 0x83158239, + 0x823720db, 0xf6362153, 0x03862d82, 0x2b881783, 0x75824020, 0x538303a3, + 0xfb85039a, 0x4b413720, 0x0b574108, 0x38238385, 0x411e381e, 0x38210547, + 0x22b58424, 0x83de3a8c, 0x903925f5, 0x2839ca39, 0x39269383, 0x39a03996, + 0x47413aca, 0x3b002805, 0x0002008a, 0x8204008b, 0x00002201, 0x24018206, + 0x000b0001, 0x2213820c, 0x82130013, 0x00252813, 0x0005002a, 0x8236002c, + 0x00383215, 0x0016003f, 0x00460045, 0x0049001e, 0x0020004a, 0x2201824c, + 0x824f0022, 0x00232801, 0x00540051, 0x82560024, 0x00282201, 0x24018258, + 0x005a0029, 0x263d825d, 0x005f005f, 0x828a002e, 0x002f2201, 0x2a01829c, + 0x00b00030, 0x003100b4, 0x82b800b6, 0x00ba2655, 0x003900ba, 0x280182bc, + 0x00bf003a, 0x003b00c0, 0x220182c2, 0x82c4003d, 0x003e2801, 0x00cd00c6, + 0x82d1003f, 0x00472801, 0x00dd00d3, 0x82df0048, 0x00532401, 0x82e300e1, + 0x00e5266d, 0x005700ee, 0x0a0182f0, 0xf500618a, 0x6200f700, 0xfb00fa00, + 0xfd006500, 0x6700ff00, 0x04010201, 0x09016a00, 0x6d000901, 0x0c010c01, + 0x17016e00, 0x6f001901, 0x21012101, 0x2b017200, 0x73002d01, 0x30013001, + 0x32017600, 0x77003201, 0x49014901, 0x6c017800, 0x79006d01, 0x71016f01, + 0xba017b00, 0x7e00ba01, 0xbd01bd01, 0xc4017f00, 0x8000c501, 0xc801c801, + 0xca018200, 0x8300cb01, 0xcd01cd01, 0x28028500, 0x86002802, 0x2b022a02, + 0x46028700, 0x89004702, 0x49024902, 0x4b028b00, 0x8c006c02, 0x71026e02, + 0x7602ae00, 0xb2007b02, 0x88028002, 0x8a02b800, 0xc1008a02, 0x8c028c02, + 0x8e02c200, 0xc3008e02, 0x90029002, 0x9202c400, 0xc5009b02, 0xa602a402, + 0xa802cf00, 0xd200a802, 0xaa02aa02, 0xac02d300, 0xd400ac02, 0xae02ae02, + 0xb102d500, 0xd600b102, 0xb302b302, 0xb502d700, 0xd800b502, 0xb702b702, + 0xb902d900, 0xda00b902, 0xbb02bb02, 0xbd02db00, 0xdc00c902, 0xcb02cb02, + 0xcd02e900, 0xea00cd02, 0xcf02cf02, 0xda02eb00, 0xec00da02, 0xdc02dc02, + 0xde02ed00, 0xee00de02, 0xe002e002, 0xe202ef00, 0xf000e202, 0xe402e402, + 0xe602f100, 0xf200e602, 0xe802e802, 0xea02f300, 0xf400ea02, 0xec02ec02, + 0xee02f500, 0xf600f102, 0xf302f302, 0xf502fa00, 0xfb00f502, 0x57035203, + 0x5a03fc00, 0x02016903, 0x6c036c03, 0x70031201, 0x13017003, 0x72037203, + 0x76031401, 0x15017603, 0x7a037903, 0x7c031601, 0x18018503, 0x89038703, + 0x8b032201, 0x25019003, 0x93039203, 0x95032b01, 0x2d019803, 0x9f039e03, + 0xa1033101, 0x3301a103, 0xa303a303, 0xa5033401, 0x3501a803, 0xb003ab03, + 0xb2033901, 0x3f01b203, 0xb703b603, 0xbc034001, 0x4201bc03, 0xc703be03, + 0xca034301, 0x4d01cb03, 0xd003cd03, 0xd7034f01, 0x5301d803, 0xdc03dc03, + 0xde035501, 0x5601e403, 0xea03e903, 0xee035d01, 0x5f011604, 0x18041804, + 0x1a048801, 0x89012704, 0x2f042f04, 0x32049701, 0x98013204, 0x34043404, + 0x40049901, 0x9a014504, 0x48044804, 0x4a04a001, 0xa1014a04, 0x4c044c04, + 0x4e04a201, 0xa3014f04, 0x57045404, 0x5a04a501, 0xa9015a04, 0x5d045c04, + 0x5f04aa01, 0xac015f04, 0x63046304, 0x6504ad01, 0xae016504, 0x69046904, + 0xa904af01, 0xb001a904, 0x38000a00, 0xd100c4ff, 0xd5240382, 0x3201c4ff, + 0x3a240382, 0xda02c4ff, 0xdc200382, 0xde280382, 0x8d03c4ff, 0x4c04c4ff, + 0x153a1f82, 0x14003a00, 0x26003b00, 0x16003d00, 0x14001801, 0x16006502, + 0x2600ec02, 0x0782ee02, 0x1600f024, 0x03825703, 0x03826620, 0x03826920, + 0x26009f24, 0x0382a103, 0x0382a320, 0x0f82a520, 0x1400b628, 0x1600be03, + 0x03824004, 0x03824220, 0x03824420, 0x002d2782, 0xff130001, 0x00ce0008, + 0x00eefe10, 0x28038212, 0x0040ff25, 0x0030ff2e, 0x286b8238, 0x00deff45, + 0x00ebff47, 0x20038248, 0x20038249, 0x2003824b, 0x20038253, 0x2c038255, + 0x00e6ff56, 0x00eaff59, 0x00e8ff5a, 0x2003825d, 0x20138293, 0x20038298, + 0x2013829a, 0x204382b1, 0x200382b3, 0x200f82ba, 0x201b82bc, 0x200782c7, + 0x200382c8, 0x201b82ca, 0x205782d1, 0x240382d5, 0x01ebfff6, 0x24038202, + 0x0140ff0c, 0x24078217, 0x01e8ff19, 0x2007821d, 0x24038221, 0x01140032, + 0x20078239, 0x8207823a, 0x4c012173, 0x56200b82, 0x6e240382, 0x7201eefe, + 0x76200382, 0x77200382, 0xba280382, 0x4b02c0ff, 0x4c0240ff, 0x4d200382, + 0x4e200382, 0x4f200382, 0x50200382, 0x51200382, 0x66240382, 0x6702deff, + 0x68200382, 0x69200382, 0x6a200382, 0x6b200382, 0x6c200382, 0x6d240382, + 0x6e02ebff, 0x6f200382, 0x70200382, 0x71200382, 0x77200382, 0x78200382, + 0x79200382, 0x7a200382, 0x7b200382, 0x7c240382, 0x7d02eaff, 0x7e200382, + 0x7f200382, 0x80240382, 0x8102e8ff, 0x82200382, 0x83205f82, 0x84204782, + 0x85200782, 0x86200782, 0x87200782, 0x89200782, 0x8b203382, 0x8d200382, + 0x8f200382, 0x91200382, 0x93200382, 0x95200382, 0x97200382, 0x99200382, + 0x9b200382, 0x9d200382, 0x9f200382, 0xa1200382, 0xa3200382, 0xb1240382, + 0xc50230ff, 0xc7200782, 0xc9200382, 0xda240382, 0xdc021400, 0xde200382, + 0xe1200382, 0xe3207782, 0xe5200382, 0xe7200382, 0xe9200382, 0xeb200382, + 0xef280382, 0x5203e8ff, 0x5a0340ff, 0x6a270382, 0x6e03ebff, 0x8203eaff, + 0x720321cb, 0x75201782, 0x76200b82, 0x77201382, 0x7e230782, 0x820330ff, + 0x8d0329af, 0x8f031400, 0x9003deff, 0x92201782, 0x94200382, 0x95200382, + 0x97202b82, 0x9e200782, 0xa6200782, 0xae200382, 0xaf204b82, 0xb2202382, + 0xb7201382, 0xb8200f82, 0xbd200782, 0xbf200382, 0xc4200b82, 0xc5201b82, + 0xc6201b82, 0xc7200782, 0xcb200782, 0xcd201782, 0xce200382, 0xd8200382, + 0xda200382, 0xdc200382, 0xe0200382, 0xe2202b82, 0xe4200382, 0xeb200382, + 0xee200f82, 0xef202f82, 0xf0202f82, 0xf1200782, 0xf2200782, 0xf3200782, + 0xf4200782, 0xf5200782, 0xf6200782, 0xf7200782, 0xf8200782, 0xf9200782, + 0xfa200782, 0xfb200782, 0xfc200782, 0xfd200782, 0xfe200782, 0xff280782, + 0x0004deff, 0x010440ff, 0x02200782, 0x03200782, 0x04200782, 0x05200782, + 0x07240782, 0x0904ebff, 0x0b200382, 0x0d200382, 0x0f200382, 0x11200382, + 0x13200382, 0x15200382, 0x1b200382, 0x1d200382, 0x1f200382, 0x21200382, + 0x23200382, 0x25200382, 0x27200382, 0x29200382, 0x2b200382, 0x2d200382, + 0x2f200382, 0x31200382, 0x33240382, 0x3504eaff, 0x37200382, 0x39200382, + 0x3b200382, 0x3d200382, 0x3f200382, 0x41240382, 0x4304e8ff, 0x45200382, + 0x4c360382, 0x20001400, 0xdfff3800, 0xe4ff3a00, 0xecff3b00, 0xddff3d00, + 0x0f82d100, 0xdfffd528, 0xe4ff1801, 0x07823201, 0x03823a20, 0x0e00ba2c, + 0xddff6502, 0xdfffda02, 0x0382dc02, 0x0382de20, 0xecffec24, 0x1382ee02, + 0xddfff024, 0x03825703, 0x03826620, 0x03826920, 0xdfff8d28, 0xecff9f03, + 0x0382a103, 0x0382a320, 0x1382a520, 0xe4ffb628, 0xddffbe03, 0x03824004, + 0x03824220, 0x03824420, 0xdfff4c23, 0x212f8204, 0x81821a00, 0x8182ce20, + 0x7d82ed20, 0x7d82d020, 0xd500ce24, 0x7d82ceff, 0x7d82ed20, 0x3a01ce24, + 0x7982ceff, 0x7982d020, 0x7982ce20, 0xde02ce22, 0xee260f82, 0xf002d0ff, + 0x7582d0ff, 0x6603d022, 0x69200782, 0x8d240382, 0xa503ceff, 0xb6220782, + 0x6982edff, 0x6982d020, 0x4204d026, 0x4404d0ff, 0x4c220382, 0x6982ceff, + 0x1000d02c, 0xeeff2e00, 0xeeff3900, 0x03826102, 0x03826220, 0x03826320, + 0x03826420, 0x0382b120, 0x0382e020, 0x0382e220, 0x0382e420, 0x0382e620, + 0x0382e820, 0xeeffea28, 0xeeff7e03, 0x03823204, 0x3b823420, 0x06004a22, + 0x0b204582, 0x0d2c0382, 0x41001400, 0x47001200, 0x4800e8ff, 0x49200382, + 0x4b200382, 0x55200382, 0x61240382, 0x93001300, 0x98200782, 0xba200382, + 0xc7200382, 0xc8200382, 0xf6240382, 0x0201e8ff, 0x1d200382, 0x21200382, + 0x39200382, 0x33820382, 0x824c0121, 0x82562007, 0x006c2403, 0x826d0110, + 0x826f2003, 0x82702003, 0x00712803, 0xff6d0210, 0x826e02e8, 0x826f2003, + 0x82702003, 0x82712003, 0x82892003, 0x828b2003, 0x828d2003, 0x828f2003, + 0x82912003, 0x216f8203, 0x07829502, 0x03829720, 0x03829920, 0x03829b20, + 0x03829d20, 0x03829f20, 0x0382a120, 0xe8ffa324, 0x03826a03, 0x03829020, + 0x03829420, 0x03829720, 0x1000a724, 0x0382a803, 0x0382ab20, 0x0f82b220, + 0x0382b820, 0x0382bd20, 0x0382cb20, 0x0382cd20, 0x0382ce20, 0x0382da20, + 0xe8ffeb24, 0x03820704, 0x03820920, 0x03820b20, 0x03820d20, 0x03820f20, + 0x03821120, 0x03821320, 0x03821520, 0x03822920, 0x03822b20, 0x03822d20, + 0xeb823120, 0xf5000230, 0x6d01d6ff, 0x3d0098ff, 0xecff4700, 0x03824800, + 0x03824920, 0x03824b20, 0x03825520, 0x03829320, 0x03829820, 0x0382ba20, + 0x0382c720, 0x0382c820, 0xecfff624, 0x03820201, 0x03821d20, 0x03822120, + 0x03823920, 0x01212f82, 0x2407824c, 0x02ecff56, 0x2003826d, 0x2003826e, + 0x2003826f, 0x20038270, 0x20038271, 0x20038289, 0x2003828b, 0x2003828d, + 0x2003828f, 0x82038291, 0x9502215b, 0x97200782, 0x99200382, 0x9b200382, + 0x9d200382, 0x9f200382, 0xa1200382, 0xa3240382, 0x6a03ecff, 0x90200382, + 0x94200382, 0x97200382, 0xb2200382, 0xb8200382, 0xbd200382, 0xcb200382, + 0xcd200382, 0xce200382, 0xda200382, 0xeb220382, 0xff82ecff, 0x0904ec22, + 0x0b200782, 0x0d200382, 0x0f200382, 0x11200382, 0x13200382, 0x15200382, + 0x29200382, 0x2b200382, 0x2d200382, 0x31200382, 0x1826cb82, 0xe2ff5300, + 0x03821701, 0x18006d28, 0xe2ff7702, 0x03827802, 0x03827920, 0x03827a20, + 0x03827b20, 0x0382c520, 0x0382c720, 0xe2ffc924, 0x03827003, 0x03827620, + 0x03829220, 0x0382d820, 0xe2ffdc24, 0x03821b04, 0x03821d20, 0x03821f20, + 0x03822120, 0x03822320, 0x03822520, 0x03822720, 0xe2ff2f2e, 0x10000600, + 0x120084ff, 0x6e0184ff, 0x72200382, 0x76200382, 0x77200382, 0x10221382, + 0x81822e00, 0xe9823920, 0x03826120, 0x03826220, 0x03826320, 0x03826420, + 0x0382b120, 0x0382e020, 0x0382e220, 0x0382e420, 0x0382e620, 0x0382e820, + 0xe582ea20, 0xb9827e20, 0x03823220, 0x3b823420, 0x06001e26, 0x0b00f2ff, + 0x5a240382, 0x5d00f3ff, 0xbc200382, 0xf52c0382, 0x1901f5ff, 0x6c01f3ff, + 0x6d01f2ff, 0x6f200382, 0x70200382, 0x71280382, 0x8002f2ff, 0x8102f3ff, + 0xef240382, 0x7203f3ff, 0x95200382, 0x9e200382, 0xa6200382, 0xa7240382, + 0xa803f2ff, 0xab200382, 0xb7200382, 0xbf200f82, 0xe0200382, 0xe2200382, + 0xe4240382, 0x4104f3ff, 0x43200382, 0x45200382, 0x3e226382, 0x05822700, + 0x03822b20, 0x03823320, 0x03823520, 0x03828320, 0x03829220, 0x03829720, + 0x0382b220, 0x0d00c324, 0x8582d200, 0x03820720, 0x03821620, 0x03821a20, + 0x03821c20, 0x03821e20, 0x03822020, 0x03823820, 0x89825520, 0x03822820, + 0x03822920, 0x02214b82, 0x2007822c, 0x20038252, 0x8203825c, 0x5e0221cd, + 0x5f200782, 0x60200382, 0x88200382, 0x8a200382, 0x8c200382, 0x8e200382, + 0x9c200382, 0xb9820382, 0x82a00221, 0x82a22007, 0x82c42003, 0x82c62003, + 0x82c82003, 0x82f92003, 0x825620b1, 0x82632003, 0x82892003, 0x21338203, + 0x0782b903, 0x0382bc20, 0x0382d720, 0x0382d920, 0xc982db20, 0x03821a20, + 0x03821c20, 0x03821e20, 0x03822020, 0x03822220, 0x03822420, 0x03822620, + 0x03822820, 0x03822a20, 0x03822c20, 0x03822e20, 0x03823020, 0xd782a920, + 0xf9823f20, 0x2b00e626, 0x3300e6ff, 0x35200382, 0x83200382, 0x92200382, + 0x97200382, 0xb2200382, 0xb7260382, 0xc300c2ff, 0xfd821000, 0x0701e626, + 0x1601e6ff, 0x1a200382, 0x1c200382, 0x1e200382, 0x20200382, 0x38200382, + 0x55240382, 0x2802e6ff, 0x29200382, 0x4f820382, 0xe622fd82, 0x0b825202, + 0x03825c20, 0x03825d20, 0x03825e20, 0x03825f20, 0x03826020, 0x03828820, + 0x03828a20, 0x03828c20, 0x03828e20, 0x03829c20, 0x03829e20, 0x0382a020, + 0x0382a220, 0x0382c420, 0x0382c620, 0x0382c820, 0xe6fff924, 0x03825603, + 0x03826320, 0x03828920, 0xfd823382, 0xbc03e622, 0xd7200b82, 0xd9200382, + 0xdb240382, 0x1a04e6ff, 0x1c200382, 0x1e200382, 0x20200382, 0x22200382, + 0x24200382, 0x26200382, 0x28200382, 0x2a200382, 0x2c200382, 0x2e200382, + 0x30200382, 0xa9200382, 0x372edb82, 0xe4ff2500, 0xd2ff3c00, 0xd3ff3d00, + 0x0b82b100, 0x0382b320, 0xe2ffc32c, 0xd2ffd900, 0xe4ff0c01, 0x03824b02, + 0x03824c20, 0x03824d20, 0x03824e20, 0x03824f20, 0x03825020, 0x03825120, + 0xd3ff6524, 0x07828202, 0x03828420, 0x03828620, 0x0f82ee20, 0xd3fff028, + 0xe4ff5203, 0x07825703, 0x07825a20, 0x07826620, 0xd2ff6724, 0x07826903, + 0x0f828220, 0x0b828e20, 0x0b82a520, 0x0b82ae20, 0x0782be20, 0x0f82c120, + 0x0b82c420, 0x0382c620, 0x0b82cf20, 0x0382e920, 0x0b82ee20, 0x0382f020, + 0x0382f220, 0x0382f420, 0x0382f620, 0x0382f820, 0x0382fa20, 0x0382fc20, + 0xe4fffe24, 0x03820004, 0x03820220, 0x03820420, 0xd3ff4024, 0x03824204, + 0x03824420, 0xd2ff4e24, 0x03825604, 0x00276f82, 0xff100027, 0x82120046, + 0xff252203, 0x22dd82cd, 0x82b300cd, 0xffc62207, 0x26d982f2, 0xff6e01cd, + 0x82720146, 0x82762003, 0xff772203, 0x26e98246, 0xff4c02cd, 0x824d02cd, + 0x824e2003, 0x824f2003, 0x82502003, 0x82512003, 0x82822003, 0x82842003, + 0xff862203, 0x22dd82cd, 0x825a03cd, 0x82822007, 0x82ae2003, 0x82c42003, + 0x82c62003, 0x82ee2003, 0x82f02003, 0x82f22003, 0x82f42003, 0x82f62003, + 0x82f82003, 0x82fa2003, 0x82fc2003, 0xfffe2403, 0x820004cd, 0x82022003, + 0x82042003, 0x00012c87, 0x000e00c3, 0xff4700af, 0x824800dc, 0x82492003, + 0x824b2003, 0xff512403, 0x825200c1, 0xff532403, 0x825400d6, 0x82552007, + 0xff592813, 0xff5a00dd, 0x825d00e1, 0x82932003, 0x8298200f, 0x829a2003, + 0x82ba2013, 0x82bc2007, 0xffbe2413, 0x82c000e6, 0xffc1302b, 0xffc200eb, + 0xffc400e9, 0xffc500f0, 0x82c700e7, 0x82c8201f, 0xffc92403, 0x82ca00e3, + 0xffcb2c2f, 0xffcc00ce, 0xffcd00d4, 0x82eb00db, 0x82ef202f, 0x82f02003, + 0x82f22003, 0x82f32003, 0x82f42003, 0x82f62003, 0x82f7202f, 0x82f92007, + 0x82fa2003, 0x82fd2003, 0xffff2803, 0xff0201c1, 0x820401dc, 0xff172807, + 0xff1901d6, 0x821d01e1, 0x8221200f, 0x82352003, 0x82392013, 0x82442007, + 0x82492007, 0x824b2003, 0x824c200b, 0xff562403, 0x826d02dc, 0x826e2003, + 0x826f2003, 0x82702003, 0x82712003, 0xff762803, 0xff7702c1, 0x827802d6, + 0x82792003, 0x827a2003, 0x827b2003, 0xff7c2403, 0x827d02dd, 0x827e2003, + 0x827f2003, 0xff802403, 0x828102e1, 0x82892003, 0x828b2033, 0x828d2003, + 0x828f2003, 0x82912003, 0x82932003, 0x82952003, 0x82972003, 0x82992003, + 0x829b2003, 0x829d2003, 0x829f2003, 0x82a12003, 0x82a32003, 0x82be2003, + 0x82c02067, 0x82c22003, 0x82c32003, 0x82c52003, 0x82c72063, 0x82c92003, + 0x82e12003, 0x82e3205f, 0x82e52003, 0x82e72003, 0x82e92003, 0x82eb2003, + 0xffef3403, 0xff6a03e1, 0xff6c03dc, 0xff6e03c1, 0xff7003dd, 0x827203d6, + 0x82752013, 0x8276200b, 0x8277200b, 0x82902007, 0x8291201f, 0x8292201f, + 0x8293200f, 0x82942007, 0x8295200f, 0x82972023, 0x82982007, 0x829d200f, + 0x829e2003, 0x82a6200f, 0x82ad2003, 0x82b2200b, 0x82b32017, 0x82b72007, + 0x82b8200f, 0x82bd200b, 0x82bf2003, 0x82cb200b, 0x82cd2007, 0x82ce2003, + 0x82d42003, 0x82d6201f, 0x82d82003, 0x82da2053, 0x82dc200f, 0x82e02007, + 0x82e22023, 0x82e42003, 0x82e82003, 0xffeb241b, 0x820704dc, 0x82092003, + 0x820b2003, 0x820d2003, 0x820f2003, 0x82112003, 0x82132003, 0x82152003, + 0xff1b2403, 0x821d04d6, 0x821f2003, 0x82212003, 0x82232003, 0x82252003, + 0x82272003, 0x82292003, 0x822b201f, 0x822d2003, 0x822f2003, 0x8231200f, + 0xff332407, 0x823504dd, 0x82372003, 0x82392003, 0x823b2003, 0x823d2003, + 0x823f2003, 0xff412403, 0x824304e1, 0x82452003, 0xff492403, 0x824b04c1, + 0x82552003, 0x82622003, 0x82642003, 0xff662a03, 0x007600c1, 0x00daff06, + 0x2403820b, 0x00f0ff47, 0x20038248, 0x20038249, 0x2003824b, 0x28038255, + 0x00efff59, 0x00dcff5a, 0x2003825d, 0x200f8293, 0x20038298, 0x2013829a, + 0x200782ba, 0x2c1382bc, 0x00ecffc1, 0x000f00c3, 0x00eaffc5, 0x201382c7, + 0x240382c8, 0x00ceffc9, 0x282382ca, 0x00e7ffcb, 0x01f0fff6, 0x24038202, + 0x01dcff19, 0x2007821d, 0x20038221, 0x82038239, 0x4c01215f, 0x56200782, + 0x6c240382, 0x6d01daff, 0x6f200382, 0x70200382, 0x71280382, 0x6d02daff, + 0x6e02f0ff, 0x6f200382, 0x70200382, 0x71200382, 0x7c240382, 0x7d02efff, + 0x7e200382, 0x7f200382, 0x80240382, 0x8102dcff, 0x89200382, 0x8b201b82, + 0x8d200382, 0x8f200382, 0x91200382, 0xab820382, 0x82950221, 0x82972007, + 0x82992003, 0x829b2003, 0x829d2003, 0x829f2003, 0x82a12003, 0x82a32003, + 0x82e12003, 0x82e32043, 0x82e52003, 0x82e72003, 0x82e92003, 0x82eb2003, + 0xffef2c03, 0xff6a03dc, 0xff6e03f0, 0x827203ef, 0x8275200b, 0x82772007, + 0x82902003, 0x82942013, 0x82952003, 0x82972013, 0x829e2007, 0x82a62007, + 0xffa72403, 0x82a803da, 0x82ab2003, 0x82b22003, 0x82b72017, 0x82b82013, + 0x82bd2007, 0x82bf2003, 0x82cb200b, 0x82cd2007, 0x82ce2003, 0x82da2003, + 0x82e02003, 0x82e22013, 0x82e42003, 0xffeb2403, 0x820704f0, 0x82092003, + 0x820b2003, 0x820d2003, 0x820f2003, 0x82112003, 0x82132003, 0x82152003, + 0x82292003, 0x822b2003, 0x822d2003, 0x82312003, 0xff332403, 0x823504ef, + 0x82372003, 0x82392003, 0x823b2003, 0x823d2003, 0x823f2003, 0xff412403, + 0x824304dc, 0xff452a03, 0x004400dc, 0x000c0010, 0x24038212, 0x00e7ff47, + 0x20038248, 0x20038249, 0x2003824b, 0x20038255, 0x20038293, 0x20038298, + 0x240382ba, 0x000f00c3, 0x200782c7, 0x240382c8, 0x01e7fff6, 0x20038202, + 0x2003821d, 0x20038221, 0x82038239, 0x4c012133, 0x56200782, 0x6e240382, + 0x72010c00, 0x76200382, 0x77280382, 0x6d020c00, 0x6e02e7ff, 0x6f200382, + 0x70200382, 0x71200382, 0x89200382, 0x8b200382, 0x8d200382, 0x8f200382, + 0x91200382, 0x6f820382, 0x82950221, 0x82972007, 0x82992003, 0x829b2003, + 0x829d2003, 0x829f2003, 0x82a12003, 0xffa32403, 0x826a03e7, 0x82902003, + 0x82942003, 0x82972003, 0x82b22003, 0x82b82003, 0x82bd2003, 0x82cb2003, + 0x82cd2003, 0x82ce2003, 0x82da2003, 0xffeb2403, 0x820704e7, 0x82092003, + 0x820b2003, 0x820d2003, 0x820f2003, 0x82112003, 0x82132003, 0x82152003, + 0x82292003, 0x822b2003, 0x822d2003, 0x82312003, 0x00063adb, 0x00eaffc9, + 0x00eeffec, 0x00d5fff5, 0x01edfffd, 0x01ecff33, 0x00ecff58, 0x20118201, + 0x2a0582c0, 0x002000c9, 0x0006007e, 0x820b000c, 0x0ba34c03, 0x0f824a20, + 0xe8ff4b24, 0x41825300, 0x07825520, 0x21825a20, 0x03825d20, 0x200baf4c, + 0x240f82bc, 0x0090ffc3, 0x200782c5, 0x202382c7, 0x200382c8, 0x203782c9, + 0x06bf4cf6, 0xeaff1727, 0x0b001901, 0x19c74c01, 0x6d010c26, 0x6f010c00, + 0x70200382, 0x71200382, 0xba280382, 0xbc01bfff, 0xc001eeff, 0xc820a982, + 0xca20b182, 0xcc2e0782, 0xcd01f5ff, 0xcf010e00, 0xd2010d00, 0xeb4c0d00, + 0xff772414, 0x827802ea, 0x82792003, 0x827a2003, 0x827b2003, 0x00802403, + 0x8281020b, 0x36074d03, 0x82c50221, 0x82c72043, 0x82c92003, 0x00ef2c03, + 0xff6a030b, 0xff7003e8, 0x827203ea, 0x8276200b, 0x82902007, 0x8292200f, + 0x82942007, 0x82952007, 0x82972013, 0x829e2007, 0x82a62007, 0x00a72403, + 0x82a8030c, 0x82ab2003, 0x82b22003, 0x82b72017, 0x07374d13, 0x0b82bf20, + 0x200b3b4d, 0x204382d8, 0x202382da, 0x200782dc, 0x201b82e0, 0x200382e2, + 0x4d0382e4, 0x1b24234f, 0x1d04eaff, 0x1f200382, 0x21200382, 0x23200382, + 0x25200382, 0x27200382, 0x6b4d0382, 0x822f200b, 0xff31280f, 0x004104e8, + 0x8243040b, 0x00453003, 0x0001000b, 0x00e2fff5, 0xff5c000d, 0x825e00ed, + 0x82ed2003, 0xfff52803, 0xfff202c0, 0x82f402ed, 0xfff62403, 0x829603ed, + 0x82c22003, 0x82d02003, 0xffea2403, 0x824f04ed, 0x82572003, 0x820c2027, + 0x82f22035, 0x00f22435, 0x82f2ffed, 0x82f22031, 0x02f22431, 0x82f2fff6, + 0x03f22231, 0x200782c2, 0x220382d0, 0x82f2ffea, 0x04f22a31, 0x00f2ff57, + 0xff5a001f, 0x203584f4, 0x2407825d, 0x00f3ff5e, 0x820782bc, 0x1901253d, + 0x8002f4ff, 0x81200382, 0xef200382, 0xf2220382, 0x4d82f3ff, 0x4d82f320, + 0x7203f326, 0x9503f4ff, 0x96200382, 0x9e204d82, 0xa6200782, 0xb7200382, + 0xbf200382, 0x65870382, 0x0b82e020, 0x0382e220, 0x0382e420, 0x7182ea20, + 0xf4ff4124, 0x03824304, 0x03824520, 0x0f824f20, 0x5d267d83, 0xcaff0600, + 0x03820b00, 0xd2ff3828, 0xd4ff3a00, 0x7d823c00, 0xd3ff3d22, 0xe6209582, + 0xef249582, 0xe6ff5d00, 0xe6229182, 0x1f82d100, 0x0382d520, 0x1f82d920, + 0xe982dd20, 0xe1ffe024, 0x2f82e500, 0xefffed32, 0xc9fff500, 0xd1fffd00, + 0xe5ff0801, 0xd4ff1801, 0xe62eb982, 0xe3ff1f01, 0xd2ff3201, 0xc4ff3301, + 0x07823a01, 0xe1ff3c24, 0x1b824d01, 0xf5ff4e34, 0xe7ff4f01, 0x64ff5701, + 0xc9ff5801, 0xcaff6c01, 0x03826d01, 0x03826f20, 0x03827020, 0xcaff7126, + 0xd3ff6502, 0xe62af982, 0xe6ff8102, 0xd2ffda02, 0x0382dc02, 0x0382de20, + 0x1782ee20, 0x1382ef20, 0xd3fff024, 0x03825703, 0x2205934a, 0x826903f4, + 0xff722c0b, 0xff8103e6, 0xff8d03ed, 0x828e03d2, 0x829520f1, 0xff96240f, + 0x829e03ef, 0x82a52007, 0x82a6201f, 0xffa72407, 0x82a803ca, 0x82ab2003, + 0xffb62403, 0x82b703d4, 0x82be2013, 0x82bf201b, 0x82c12007, 0x82c22033, + 0x82cf202f, 0x82d02007, 0x82df2007, 0x82e0204b, 0x82e12017, 0x82e22007, + 0x82e32007, 0x82e42007, 0xffe52407, 0x82e903e1, 0xffea2c23, 0xff4004ef, + 0xff4104d3, 0x824204e6, 0x82432007, 0x82442007, 0x82452007, 0xff4c2807, + 0xff4e04d2, 0x824f04f4, 0xff502423, 0x825204e1, 0x82562003, 0x8257200f, + 0x27ab820f, 0x06006c00, 0x0b00c0ff, 0x38340382, 0x3a009dff, 0x3c00c7ff, + 0x3d00f0ff, 0x5100abff, 0x5200d2ff, 0x54200382, 0xc0200382, 0xd1200382, + 0xd3241f82, 0xd500f5ff, 0xd9200782, 0xdc202382, 0xdd2c0b82, 0xe000eaff, + 0xe500e5ff, 0xeb00c1ff, 0xef202382, 0xf0200382, 0xf2200382, 0xf3200382, + 0xf4200382, 0xf5240382, 0xf700cdff, 0xf9200782, 0xfa200382, 0xfd200382, + 0xff240382, 0x0401d2ff, 0x182c0382, 0x3201c7ff, 0x33019dff, 0x3501ccff, + 0x3a200f82, 0x3c280b82, 0x3f01e5ff, 0x4401dfff, 0x49200f82, 0x4d300382, + 0x4f01ceff, 0x5101eaff, 0x5701f5ff, 0x58019eff, 0x6c240f82, 0x6d01c0ff, + 0x6f200382, 0x70200382, 0x712c0382, 0x6502c0ff, 0x7602abff, 0xbe02d2ff, + 0xc0200382, 0xc2200382, 0xc3200382, 0xda240382, 0xdc029dff, 0xde200382, + 0xee200382, 0xf0242382, 0x5703abff, 0x66200382, 0x67240382, 0x6903f0ff, + 0x6c2c0782, 0x8103d2ff, 0x8d03eaff, 0x8e039dff, 0x91201382, 0x93200f82, + 0x98200382, 0x9d200382, 0xa5200382, 0xa7242382, 0xa803c0ff, 0xab200382, + 0xad200382, 0xb3201382, 0xb6240382, 0xbe03c7ff, 0xc1201b82, 0xcf203382, + 0xd4200382, 0xd6201382, 0xdf200382, 0xe1204b82, 0xe3200382, 0xe5240382, + 0xe803e5ff, 0xe9201382, 0xec281f82, 0x4004f5ff, 0x4204abff, 0x44200382, + 0xdf820382, 0xff4b0431, 0xff4c04d2, 0xff4e049d, 0xff5004f0, 0x825204e5, + 0x82552003, 0x82562013, 0x8262200f, 0x82642007, 0x82662003, 0x82672003, + 0x27ab823b, 0x06006f00, 0x0b00b1ff, 0x38340382, 0x3a009eff, 0x3c00c5ff, + 0x3d00f2ff, 0x5100a8ff, 0x5200cfff, 0x54200382, 0x5c240382, 0xc000efff, + 0xd1200782, 0xd5202382, 0xd9200382, 0xdd232382, 0x4300ecff, 0xc222052b, + 0x1b82eb00, 0x2382ed20, 0x0782ef20, 0x0382f020, 0x0382f220, 0x0382f320, + 0x0382f420, 0xc6fff524, 0x0782f700, 0x0382f920, 0x0382fa20, 0x0382fd20, + 0xcfffff24, 0x03820401, 0xc5ff182c, 0x9eff3201, 0xc0ff3301, 0x0f823501, + 0x0b823a20, 0xe1ff3c22, 0x2206b141, 0x824901cf, 0xff4d3413, 0xff4f01cd, + 0xff5701e8, 0xff58019f, 0xff6c01c6, 0x826d01b1, 0x826f2003, 0x82702003, + 0xff712c03, 0xff6502b1, 0xff7602a8, 0x82be02cf, 0x82c02003, 0x82c22003, + 0x82c32003, 0xffda2403, 0x82dc029e, 0x82de2003, 0x82ee2003, 0xfff02423, + 0x825703a8, 0x82662003, 0xff672403, 0x826903f2, 0xff6c2c07, 0xff8103cf, + 0xff8d03ec, 0x828e039e, 0x82912013, 0x8293200f, 0xff962403, 0x829803ef, + 0x829d2007, 0x82a52003, 0xffa72427, 0x82a803b1, 0x82ab2003, 0x82ad2003, + 0x82b32013, 0xffb62403, 0x82be03c5, 0x82c1201b, 0x05634337, 0xd003f222, + 0xd4203782, 0xd6201b82, 0xdf200382, 0xe1205782, 0xe3200382, 0xe5240382, + 0xe803e1ff, 0xe9201382, 0x63432b82, 0x04a82605, 0x04a8ff42, 0x82038244, + 0x4b042be7, 0x4c04cfff, 0x4e049eff, 0x5f43f2ff, 0x8255200c, 0x82562017, + 0xff572413, 0x826204ef, 0x8264200b, 0x82662003, 0x2bbb8203, 0x38004d00, + 0x5100beff, 0x5200e1ff, 0x54200382, 0x5a240382, 0x5d00efff, 0xbc200382, + 0xc0200382, 0xd1200f82, 0xd5201f82, 0xe5240382, 0xeb00c9ff, 0xef200f82, + 0xf0200382, 0xf2200382, 0xf3200382, 0xf4200382, 0xf5240382, 0xf700dfff, + 0xf9200782, 0xfa200382, 0xfd200382, 0xff240382, 0x0401e1ff, 0x08340382, + 0x1901edff, 0x1f01efff, 0x3201ebff, 0x3301beff, 0x3501dfff, 0x3a201782, + 0x3f240b82, 0x4401e9ff, 0x49200b82, 0x4e300382, 0x5801f5ff, 0x7602e0ff, + 0x8002e1ff, 0x8102efff, 0xbe200382, 0xc0200b82, 0xc2200382, 0xc3200382, + 0xda240382, 0xdc02beff, 0xde200382, 0xef280382, 0x6c03efff, 0x7203e1ff, + 0x8d240782, 0x9103beff, 0x93200b82, 0x95200382, 0x98200f82, 0x9d200782, + 0x9e200382, 0xa6200b82, 0xad200382, 0xb3200b82, 0xb7200382, 0xbf200b82, + 0xd4200382, 0xd6200b82, 0xe0200382, 0xe2200b82, 0xe4200382, 0xe8280382, + 0x4104e1ff, 0x4304efff, 0x45200382, 0x93820382, 0x824b0421, 0xff4c2413, + 0x825504be, 0x82622007, 0x82642003, 0x82662003, 0x006428db, 0x00e6ff38, + 0x42e7ff3a, 0xe72606eb, 0xd6ff5100, 0x03825200, 0x03825420, 0xf1ff5c24, + 0x0782c000, 0x2382d120, 0x0382d520, 0x2605eb42, 0xffe000ee, 0x82e500e8, + 0x82eb200f, 0x82ed201b, 0x82ef2023, 0x82f02007, 0x82f22003, 0x82f32003, + 0x82f42003, 0xfff52403, 0x82f700d0, 0x82f92007, 0x82fa2003, 0x82fd2003, + 0xffff2403, 0x820401d6, 0xff182c03, 0xff3201e7, 0xff3301e6, 0x823501ce, + 0x823a200f, 0xff3c240b, 0x824401e8, 0x8249200b, 0x824d2003, 0xff4f241f, + 0x825701ed, 0xff582c17, 0xff6502d0, 0xff7602e7, 0x82be02d6, 0x82c02003, + 0x82c22003, 0x82c32003, 0xffda2403, 0x82dc02e6, 0x82de2003, 0x82ee2003, + 0xfff02423, 0x825703e7, 0x82662003, 0x05d34203, 0x6c03e72c, 0x8103d6ff, + 0x8d03eeff, 0xd342e6ff, 0x03d62206, 0x24138293, 0x03f1ff96, 0x20078298, + 0x2003829d, 0x202f82a5, 0x200782ad, 0x200382b3, 0x200b82b6, 0x420382be, + 0xf12605c7, 0xf2ffcf03, 0x2b82d003, 0x1b82d420, 0x0382d620, 0x4b82df20, + 0x0382e120, 0x0382e320, 0xe8ffe524, 0x1382e803, 0x2605c742, 0xff4004f1, + 0x824204e7, 0x82442003, 0x27c78203, 0xd6ff4b04, 0xe6ff4c04, 0x2606c742, + 0xff5004f1, 0x825204e8, 0x82552003, 0x05c74217, 0x6204f122, 0x64200b82, + 0x66200382, 0x692e0382, 0x9300e7ff, 0x10002500, 0xe8ff2700, 0x03822b00, + 0x03823320, 0x03823520, 0xe0ff3824, 0x03823a00, 0xdfff3d24, 0x0f828300, + 0x03829220, 0x03829720, 0x2b82b120, 0x0782b220, 0x0782b320, 0x1f82d120, + 0x0b82d220, 0x0b82d320, 0x0b82d520, 0x1400d824, 0x0b82dc00, 0x26059944, + 0x00ec00e0, 0x82f10013, 0xfff82c0f, 0x000301e0, 0xff070110, 0x820c01e8, + 0x82162007, 0x82182007, 0x821a2013, 0x821c2007, 0x821e2003, 0x82202003, + 0x82322003, 0x82382013, 0x823a2007, 0xff3c2407, 0x823d01e1, 0x82402007, + 0xff452c07, 0xff4d01e9, 0xff4f01df, 0x825101de, 0x8255203f, 0x82572023, + 0xff59280f, 0xff2802f2, 0x822902e8, 0x21bb8203, 0x07822c02, 0x10004b24, + 0x03824c02, 0x03824d20, 0x03824e20, 0x03824f20, 0x03825020, 0x02213782, + 0x201f8252, 0x2003825c, 0x2003825d, 0x2003825e, 0x2003825f, 0x24038260, + 0x02dfff65, 0x20238282, 0x20038284, 0x20038286, 0x20138288, 0x2003828a, + 0x2003828c, 0x2003828e, 0x2003829c, 0x2003829e, 0x200382a0, 0x200382a2, + 0x200382c4, 0x200382c6, 0x240382c8, 0x02e0ffda, 0x200382dc, 0x200382de, + 0x204782ee, 0x280382f0, 0x03e8fff9, 0x03100052, 0x82078256, 0x5a0321a7, + 0x63200b82, 0x66240b82, 0x6903dfff, 0x6b820382, 0x82890321, 0x255f820f, + 0xe0ff8d03, 0x1382a503, 0x2382ae20, 0x0b82b620, 0x1782b920, 0x0382bc20, + 0x1382be20, 0x1382c420, 0x0382c620, 0x0f82d720, 0x0382d920, 0x0382db20, + 0xe1ffe524, 0x2782e603, 0x1782ec20, 0x0382ed20, 0x0382ee20, 0x0382f020, + 0x0382f220, 0x0382f420, 0x0382f620, 0x0382f820, 0x0382fa20, 0x0382fc20, + 0x1000fe24, 0x03820004, 0x03820220, 0x03820420, 0xe8ff1a24, 0x03821c04, + 0x03821e20, 0x03822020, 0x03822220, 0x03822420, 0x03822620, 0x03822820, + 0x03822a20, 0x03822c20, 0x03822e20, 0x03823020, 0xdfff4024, 0x03824204, + 0x03824420, 0xe0ff4c28, 0xe1ff5004, 0x07825104, 0x07825220, 0x07825320, + 0x53826720, 0x03826820, 0x0431d782, 0x00e8ffa9, 0xff1b0032, 0xff3800f2, + 0xff3a00f1, 0x06f749f4, 0xd100f022, 0x71480f82, 0x00f12205, 0x481782d9, + 0xf32a0571, 0xf1ffe500, 0xf4ff1801, 0x07823201, 0x03823a20, 0xf2ff4d24, + 0x03824f01, 0x2a052148, 0xff6502f2, 0xffda02f0, 0x82dc02f1, 0x82de2003, + 0x82ee2003, 0xfff0240f, 0x825703f0, 0x82662003, 0xff672403, 0x826903f4, + 0xff812807, 0xff8d03f3, 0x828e03f1, 0x82a5200f, 0x82b6200f, 0x82be2007, + 0x82c12007, 0x82cf2007, 0x82df2003, 0x82e1201f, 0x82e32003, 0x82e92003, + 0x05bd470f, 0xd982f020, 0x4404f02e, 0x4c04f0ff, 0x4e04f1ff, 0x5604f4ff, + 0x67230382, 0x8204f5ff, 0x66002553, 0x0f002500, 0xe620c982, 0xe62ac982, + 0x0e003c00, 0xe6ff3d00, 0x1382b100, 0x0382b320, 0x0b82d120, 0x1382d320, + 0x0782d520, 0x1300d824, 0x0b82d900, 0x0382dc20, 0x0b00dd22, 0x2a064749, + 0xffe600e6, 0x00ec00f4, 0x82f10012, 0xfff5302f, 0xfff800e7, 0xfffd00e8, + 0x000301e7, 0x820c010f, 0xff182203, 0x069544e6, 0x3a01e722, 0x3c280b82, + 0x3d01e5ff, 0x4d01e8ff, 0x4f200b82, 0x51220382, 0x91440e00, 0x02e72606, + 0x020f004b, 0x2003824c, 0x2003824d, 0x2003824e, 0x2003824f, 0x20038250, + 0x24038251, 0x02e6ff65, 0x20078282, 0x20038284, 0x44038286, 0xe62a0da5, + 0xe6fff002, 0x0f005203, 0x07825703, 0x07825a20, 0x07826620, 0x0e006724, + 0x07826903, 0x0b008123, 0x213b8203, 0x0b828d03, 0x13828e20, 0x0782a520, + 0x2382ae20, 0x0782b620, 0x0382be20, 0x1382c120, 0x0f82c420, 0x0382c620, + 0x0b82cf20, 0x2f82df20, 0x0382e120, 0x0382e320, 0xe5ffe528, 0xe8ffe603, + 0x1782e903, 0x0382ec20, 0x2382ed20, 0x0382ee20, 0x0382f020, 0x0382f220, + 0x0382f420, 0x0382f620, 0x0382f820, 0x0382fa20, 0x0382fc20, 0x0f00fe24, + 0x03820004, 0x03820220, 0x03820420, 0xe6ff4024, 0x03824204, 0x03824420, + 0x03824c20, 0x0e004e2c, 0xe5ff5004, 0xe8ff5104, 0x07825204, 0x07825320, + 0x13825620, 0x0421af82, 0x822f8268, 0x370027b3, 0xbfff0600, 0x03820b00, + 0x9fff382c, 0xc9ff3a00, 0xadff3d00, 0x0b82d100, 0x0382d520, 0x3a051b49, + 0xffe500e6, 0xfff500c4, 0xfffd00cd, 0xff1801d5, 0xff3201c9, 0xff33019f, + 0x823a01cc, 0xff3c3c07, 0xff3f01e6, 0xff4d01df, 0xff4f01d1, 0xff5701ec, + 0xff5801a1, 0xff6c01cf, 0x826d01bf, 0x826f2003, 0x82702003, 0xff712c03, + 0xff6502bf, 0xffda02ad, 0x82dc029f, 0x82de2003, 0x82ee2003, 0xfff0240f, + 0x825703ad, 0x82662003, 0x82692003, 0xff812803, 0xff8d03ec, 0x82a5039f, + 0xffa7240b, 0x82a803bf, 0x82ab2003, 0xffb62403, 0x82be03c9, 0x0d8b4813, + 0x4004e624, 0xf582adff, 0x4404ad22, 0x4c220782, 0xf1829fff, 0xed82e620, + 0x8204e621, 0x3000294b, 0xe3ff3800, 0xe5ff3c00, 0xe420d582, 0xe322d582, + 0x0b82d300, 0x1382d520, 0xe2ffd824, 0x0b82d900, 0x0382dc20, 0xe9ffdd28, + 0xeafff100, 0x03820301, 0xe3ff3222, 0xe328d582, 0xe5ff5101, 0xe4ff5701, + 0xe420b182, 0xe320b182, 0xe326b182, 0xe3ffde02, 0x1382ee02, 0xe4fff023, + 0x211b8203, 0x07826603, 0xe5ff6724, 0x07826903, 0xe9ff8122, 0xe322b582, + 0x0f828e03, 0x0f82a520, 0x0382be20, 0x0b82c120, 0x0382cf20, 0x1b82df20, + 0x0382e120, 0x0382e320, 0x0f82e920, 0x0382ec20, 0xeaffed22, 0xe424b982, + 0xe4ff4204, 0xe42ab982, 0xe3ff4c04, 0xe5ff4e04, 0x03825604, 0x04215382, + 0x821f8268, 0x23002157, 0xe220c182, 0xbd83c182, 0xbd82e220, 0xd500e422, + 0xd822b982, 0xbd82e1ff, 0xdc00e425, 0x8300e4ff, 0x82ec20bd, 0xfff12207, + 0x24c182eb, 0xff3201eb, 0x20c182e2, 0x83c182e2, 0x02e224b9, 0x82e2ffdc, + 0x03e222b9, 0x20a58867, 0x22a582e2, 0x82c103e4, 0x82cf200f, 0x219d8d03, + 0x4b8203e4, 0xffed0323, 0x209182eb, 0x209182e2, 0x219182e4, 0x3b8204e4, + 0xeb229182, 0x8d821700, 0x3d00eb28, 0xd100f3ff, 0x8982ebff, 0xeb206d83, + 0xeb286d82, 0xf3ff6502, 0xebffda02, 0xeb206d82, 0xeb226d82, 0x0f82ee02, + 0xf3fff024, 0x03825703, 0x03826620, 0x03826920, 0xebff8d24, 0x0782a503, + 0xf3ffbe22, 0xf320fb82, 0xf320fb82, 0xf320fb82, 0xeb216982, 0x271f8204, + 0x51003600, 0x5200efff, 0x54200382, 0x5c240382, 0xc000f0ff, 0xeb200782, + 0xec240382, 0xed00eeff, 0xef200f82, 0xf0200b82, 0xf2200382, 0xf3200382, + 0xf4200382, 0xf5200382, 0xf7201b82, 0xf9200782, 0xfa200382, 0xfd200382, + 0xff240382, 0x0401efff, 0x08280382, 0x1f01f4ff, 0x3301f1ff, 0x35200b82, + 0x44200382, 0x49200382, 0x58240382, 0x7602efff, 0xbe200382, 0xc0200382, + 0xc2200382, 0xc3240382, 0x6c03efff, 0x91200382, 0x93200382, 0x96240382, + 0x9803f0ff, 0x9d200782, 0xad200382, 0xb3200382, 0xc2200382, 0xd0201382, + 0xd4200382, 0xd6200b82, 0xe8200382, 0xea230382, 0x8204f0ff, 0x4b042553, + 0x4f04efff, 0x55200b82, 0x57200782, 0x62200782, 0x64200782, 0x66200382, + 0x22208f82, 0x260a6f5c, 0xff5d00f5, 0x82bc00f5, 0xfff52403, 0x82fd00f4, + 0xff0824a1, 0x821901f5, 0x82332003, 0x82582003, 0x157f5c03, 0x8102f52a, + 0xef02f5ff, 0x7203f5ff, 0x95200382, 0x9e200382, 0xa6200382, 0x7f5c0382, + 0x03f5220d, 0x201382bf, 0x200382e0, 0x240382e2, 0x04f5ffe4, 0x20038241, + 0x20038243, 0x26738245, 0xff510032, 0x825200ee, 0x82542003, 0x82c02003, + 0x82eb2003, 0x00ec2403, 0x82ef0014, 0x82f02007, 0x82f22003, 0x82f32003, + 0x82f42003, 0xfff52403, 0x82f700ed, 0x82f82007, 0x82f92007, 0x82fa2007, + 0xfffb2203, 0x26b582d0, 0xffff00ee, 0x820401ee, 0xff332403, 0x823501ed, + 0x823d2007, 0x82442007, 0x82492007, 0xff582803, 0xff7602ed, 0x82be02ee, + 0x82c02003, 0x82c22003, 0xffc32403, 0x826c03ee, 0x82912003, 0x82932003, + 0x82982003, 0x829d2003, 0x82ad2003, 0x82b32003, 0x82d42003, 0x82d62003, + 0xffe62703, 0xffe803ed, 0x478204ee, 0x824b0421, 0xff512407, 0x825304ed, + 0x82552003, 0x8262200b, 0x82642003, 0x82662003, 0x000a2287, 0x24cf8206, + 0x01f5ff0b, 0x2003826c, 0x2003826d, 0x2003826f, 0x24038270, 0x03f5ff71, + 0x200382a7, 0x200382a8, 0x212382ab, 0x33570059, 0xff53280f, 0xff5500c7, + 0x829300f0, 0x82982003, 0x82ba2003, 0x57c72003, 0xf6210617, 0x050b57ff, + 0xc7ff1726, 0xebff1b01, 0x20180f57, 0x241b82bc, 0x01e9ffc0, 0x220782c8, + 0x57ebffca, 0x7724140b, 0x7802c7ff, 0x79200382, 0x7a200382, 0x7b200382, + 0x07570382, 0x82c52037, 0x82c7203b, 0xffc92803, 0xff6a03c7, 0x827003f0, + 0x82762007, 0x82902003, 0x8292200b, 0x82942007, 0x82972007, 0x82b22003, + 0x07d75603, 0x200bd356, 0x202382d8, 0x201b82da, 0x560782dc, 0x1b2423cf, + 0x1d04c7ff, 0x1f200382, 0x21200382, 0x23200382, 0x25200382, 0x27200382, + 0xeb560382, 0x822f200b, 0xff312a0f, 0x00a100f0, 0x000d0006, 0x2003820b, + 0x240d8245, 0x00c0ff47, 0x20038248, 0x20038249, 0x2013824a, 0x2407824b, + 0x00e2ff53, 0x55078255, 0xc0220993, 0x0f829800, 0x0382ba20, 0x3982bc20, + 0xd6ffc624, 0x0b82c700, 0x0382c820, 0xd5ffcb30, 0xc8ffec00, 0xd7fff100, + 0xc0fff600, 0x03820201, 0xd7ff0330, 0xe2ff1701, 0x0b001901, 0xecff1b01, + 0x13821d01, 0x0c001f24, 0x07822101, 0x03823920, 0x01216382, 0x2007824c, + 0x201f824e, 0x20038250, 0x240b8256, 0x010d006c, 0x2003826d, 0x2003826f, + 0x20038270, 0x55038271, 0x662423ab, 0x6702f0ff, 0x68200382, 0x69200382, + 0x6a200382, 0x6b200382, 0x6c200382, 0x6d240382, 0x6e02c0ff, 0x6f200382, + 0x70200382, 0x71200382, 0x01610382, 0x07c75513, 0x33828320, 0x03828520, + 0x03828720, 0x2b828920, 0x03828b20, 0x03828d20, 0x03828f20, 0x03829120, + 0x03829320, 0x03829520, 0x03829720, 0x03829920, 0x03829b20, 0x03829d20, + 0x03829f20, 0x0382a120, 0x0382a320, 0x200a4d61, 0x05d35502, 0x7003c024, + 0xd355e2ff, 0x03e22a06, 0x03f0ff8f, 0x03c0ff90, 0x20138292, 0x55078294, + 0xc02105d7, 0x09d75503, 0xa8030d26, 0xab030d00, 0xaf200382, 0xb2202b82, + 0xdb552382, 0x03c02205, 0x240b82bd, 0x030b00bf, 0x201782c5, 0x200382c7, + 0x200f82cb, 0x200382cd, 0x200382ce, 0x204f82d8, 0x200782da, 0x550782dc, + 0xc0260de3, 0xd7ffed03, 0x2f82ef03, 0x0382f120, 0x0382f320, 0x0382f520, + 0x0382f720, 0x0382f920, 0x0382fb20, 0x0382fd20, 0xf0ffff24, 0x03820104, + 0x03820320, 0x03820520, 0xc0ff0724, 0x03820904, 0x03820b20, 0x03820d20, + 0x03820f20, 0x03821120, 0x03821320, 0x03821520, 0x201b1562, 0x201f8229, + 0x2003822b, 0x2403822d, 0x04e2ff2f, 0x56078231, 0x042e0a17, 0x00d7ff68, + 0x00ec000f, 0x00f10014, 0x8d820010, 0xfff80024, 0x858200f0, 0x00000131, + 0x00030116, 0xff330110, 0xff3d01e6, 0x825801dc, 0x82e62099, 0x00ed2403, + 0x82510410, 0x82532095, 0x82682003, 0x004c2633, 0x00eeff47, 0x20038248, + 0x20038249, 0x2003824b, 0x20038255, 0x20038293, 0x20038298, 0x200382ba, + 0x200382c7, 0x220382c8, 0x821200ec, 0x820e2065, 0x00e32265, 0x260f82f6, + 0x00e3fff8, 0x82b8fffb, 0x01e3246d, 0x82eeff02, 0x010e226d, 0x2007821d, + 0x24038221, 0x01baff33, 0x23078239, 0x01d9ff3d, 0x01215382, 0x200b824c, + 0x28038256, 0x02e3ff58, 0x02eeff6d, 0x2003826e, 0x2003826f, 0x20038270, + 0x20038271, 0x20038289, 0x2003828b, 0x2003828d, 0x2003828f, 0x82038291, + 0x95022183, 0x97200782, 0x99200382, 0x9b200382, 0x9d200382, 0x9f200382, + 0xa1200382, 0xa3240382, 0x6a03eeff, 0x90200382, 0x94200382, 0x97200382, + 0xb2200382, 0xb8200382, 0xbd200382, 0xcb200382, 0xcd200382, 0xce200382, + 0xda200382, 0xe6240382, 0xeb03e3ff, 0xed280782, 0x07040e00, 0x0904eeff, + 0x0b200382, 0x0d200382, 0x0f200382, 0x11200382, 0x13200382, 0x15200382, + 0x29200382, 0x2b200382, 0x2d200382, 0x31200382, 0x51240382, 0x5304e3ff, + 0x682a0382, 0x20000e00, 0xc0ff5a00, 0x03825d00, 0x0382bc20, 0x80fff53c, + 0xeefff800, 0xf0fffd00, 0xdbff0801, 0xc0ff1901, 0xdcff1f01, 0x47ff3301, + 0xf1823d01, 0x07004e30, 0xf4ff5001, 0x7fff5801, 0xc0ff8002, 0x03828102, + 0xc0ffef24, 0x03827203, 0x03829520, 0x03829e20, 0x0382a620, 0x0382b720, + 0x0382bf20, 0x0382e020, 0x0382e220, 0x0382e420, 0x7982e620, 0xc0ff4124, + 0x03824304, 0x03824520, 0x0f825120, 0x6b825320, 0x9f572120, 0x82f02006, + 0x00f43085, 0x00f4ffbc, 0x00efffec, 0x00f0ffed, 0x82f3fff1, 0x01ee2489, + 0x57f3ff03, 0x9f570fab, 0x03f0210a, 0x25119f57, 0xffd003f0, 0x9f5703f0, + 0x03f0250d, 0x04f3ffed, 0x260da357, 0xff5704f0, 0x826804f0, 0x000a2a67, + 0x00d6ff06, 0x01d6ff0b, 0x2003826c, 0x2003826d, 0x2003826f, 0x24038270, + 0x03d6ff71, 0x200382a7, 0x200382a8, 0x242382ab, 0xff5c0015, 0x289f82e0, + 0xfff500e0, 0xfff80076, 0x08a382c2, 0x0801d322, 0x1f01d9ff, 0x3301dbff, + 0x3d011eff, 0x4e01edff, 0x5001f0ff, 0x5801f2ff, 0x960356ff, 0xc203e0ff, + 0xd0200382, 0xe6280382, 0xea03c2ff, 0x4f04e0ff, 0x51240382, 0x5304c2ff, + 0x57200382, 0x0d204f82, 0x64204d82, 0xd2204d82, 0xd9204d82, 0xe6244d9c, + 0x5104d2ff, 0x53240382, 0x0900d2ff, 0x6a203582, 0xc6203182, 0x0020319b, + 0xd720db83, 0xd720db82, 0xd726db82, 0xd7ff6d01, 0x03826f01, 0x03827020, + 0xd7ff7122, 0xd722db82, 0x0782a803, 0xd7ffab2a, 0x47005c00, 0x480098ff, + 0x49200382, 0x4b200382, 0x53240382, 0x550070ff, 0x57280782, 0x5b0018ff, + 0x93000b00, 0x98200b82, 0xba200382, 0xc7200382, 0xc8200382, 0xf6240382, + 0x020198ff, 0x17240382, 0x1d0170ff, 0x21200782, 0x39200382, 0x3f820382, + 0x824c0121, 0xff562407, 0x826d0298, 0x826e2003, 0x826f2003, 0x82702003, + 0x82712003, 0xff772403, 0x82780270, 0x82792003, 0x827a2003, 0x827b2003, + 0x82892003, 0x828b2017, 0x828d2003, 0x828f2003, 0x82912003, 0x21738203, + 0x07829502, 0x03829720, 0x03829920, 0x03829b20, 0x03829d20, 0x03829f20, + 0x0382a120, 0x0382a320, 0x3b82c520, 0x0382c720, 0x0382c920, 0x18ffd124, + 0x0382d302, 0x0382d520, 0x0382d720, 0x18ffd92c, 0x98ff6a03, 0x70ff7003, + 0x03827603, 0x0b829020, 0x07829220, 0x07829420, 0x03829720, 0x1f829920, + 0x0782b220, 0x0382b820, 0x0382bd20, 0x0382cb20, 0x0382cd20, 0x0382ce20, + 0x2782d820, 0x0782da20, 0x0782dc20, 0x98ffeb24, 0x03820704, 0x03820920, + 0x03820b20, 0x03820d20, 0x03820f20, 0x03821120, 0x03821320, 0x03821520, + 0x70ff1b24, 0x03821d04, 0x03821f20, 0x03822120, 0x03822320, 0x03822520, + 0x03822720, 0x1f822920, 0x03822b20, 0x03822d20, 0x0f822f20, 0x98ff312a, + 0xbc010900, 0xc001f2ff, 0xc8200382, 0xca200382, 0xcd340382, 0xce01c0ff, + 0xcf01ecff, 0xd001c7ff, 0xd201d8ff, 0x0200bfff, 0xee200d82, 0xf5200d82, + 0xaf480982, 0x07002d06, 0xefffc801, 0xf0ffca01, 0xbbffcd01, 0xb7203186, + 0xd5202382, 0xb4223182, 0x15820400, 0x3582ee20, 0xd101f122, 0xd2224b82, + 0x1184eaff, 0x1182e920, 0x2382eb20, 0x2382f120, 0x1184e520, 0x2384f220, + 0xf5ffd022, 0xee201182, 0xeb5c5d82, 0x0b002906, 0xccff5b00, 0x1300ba01, + 0xf3209f82, 0xf1209f82, 0xf2206d82, 0xf2206d82, 0xbd235782, 0x83ffce01, + 0x82b8205b, 0x82d72049, 0x00b73437, 0x004a0004, 0x00580014, 0x005b0032, + 0x006d0111, 0x82080010, 0x00e5283f, 0x00cbffb7, 0x82e4ffcc, 0x820d2047, + 0x82ed2047, 0x82eb2047, 0x82ec2047, 0x82ec2047, 0x0010266b, 0xff57010b, + 0x082b82e6, 0x0e005830, 0xd7fe8100, 0x98ffc300, 0xc7ffc600, 0x12ffd800, + 0x52ffec00, 0xcfff4a01, 0x80ffba01, 0x0d000900, 0x41000f00, 0x56000c00, + 0x6100ebff, 0x15820e00, 0x5182cb20, 0x5182e920, 0x5182e720, 0x5182e720, + 0x0100e722, 0x0b207d82, 0x14202b84, 0x11202b82, 0xe2202b82, 0x13202b82, + 0xb4202b82, 0xd9202b82, 0xd9202b82, 0xd9202b82, 0xd9202b82, 0x0d20b182, + 0x412b7982, 0x6100f4ff, 0x4001efff, 0x5e00edff, 0xd6200bb5, 0x200cb55e, + 0x288f8212, 0x00e500ae, 0xffea0012, 0x3e9782e0, 0xffee00ad, 0xfffc00d6, + 0xff0001df, 0xff0601d2, 0xff1b01e0, 0xff2b01ce, 0xff2d01dd, 0x823101e2, + 0x8237200f, 0xff3d2203, 0x205782e9, 0x22c382da, 0x825401bd, 0x00573e2b, + 0x001d0011, 0x00afff23, 0x00efff58, 0x00dfff5b, 0x00eeff99, 0x00e5ffb7, + 0x00d1ffb8, 0x2e1d82c3, 0x00c8ffc9, 0x001300d8, 0x00c5ffe5, 0x82cafff5, + 0x01d03083, 0x0181ff33, 0x0165ff3c, 0x0185ff3d, 0x8266ff3f, 0x01dd3451, + 0x01f2ff45, 0x01b1ff4d, 0x01caff4f, 0x01a9ff57, 0x82c8ff58, 0x82f520db, + 0x01f52edb, 0x01c7ffcd, 0x01f1ffce, 0x01cdffcf, 0x249182d0, 0x00c4ffd2, + 0x474d8208, 0x08200547, 0x1f221982, 0x5582f3ff, 0x4e01f122, 0x50200782, + 0x58260382, 0x0500f1ff, 0x8b824a00, 0xeaff5b22, 0xf0203782, 0xed263782, + 0xf0ffd201, 0x37820200, 0x6d01f526, 0x0900c0ff, 0x2006d15f, 0x241182b8, + 0xff0801e2, 0x06954df0, 0x4582eb20, 0x7f82f520, 0x2582ec20, 0x0100903a, + 0xebffba01, 0x4a000600, 0xc5000d00, 0xc6000b00, 0xc900eaff, 0xec000c00, + 0x1b209f82, 0x3a226582, 0x8d820400, 0xbfff5622, 0x2408fd82, 0xff6d00d1, + 0xff7c006c, 0xff81006e, 0xff860043, 0xff8900ac, 0xffb700a1, 0xffbe00b8, + 0xffc2007e, 0xffc5007b, 0x2041829b, 0x22798279, 0x82cb00b2, 0xffcc3613, + 0xffcd007d, 0xffd8007c, 0x00e500af, 0xffe9000f, 0xffea00e4, 0x245d82a0, + 0xffee0074, 0x22998280, 0x82fc00b2, 0xfffd3223, 0xfffe00b2, 0xff000180, + 0x00010179, 0xff060128, 0x32b1827d, 0xff1b017f, 0xff1f0166, 0xff2b01da, + 0xff2d0181, 0x82310198, 0xff333a17, 0xff3701b3, 0xff3d01a0, 0xff3f017c, + 0xff40019a, 0xff45016c, 0xff4a01e6, 0x34d9826b, 0xff500192, 0xff5401ad, + 0x0057017b, 0xff58010f, 0xff590191, 0x26e382f2, 0xffbc01af, 0x82c001b9, + 0x82c82003, 0x82ca2003, 0xffcc2803, 0xffcd01bc, 0x82d001f1, 0xffd12403, + 0x820200ed, 0x82682095, 0x00ee2871, 0xffb70017, 0x82c100d4, 0x05e14113, + 0xcb82e020, 0xcc00e724, 0xcb82e5ff, 0xd800ee24, 0xc7821200, 0xbb82e920, + 0x3301d724, 0x8782d7ff, 0x8782d320, 0x8782d620, 0x8782c520, 0x4d01e728, + 0x4f010d00, 0x7b820c00, 0x7b84d620, 0x42ffbc21, 0xe9220bf1, 0x63820100, + 0x6d82f120, 0xd6fff52c, 0x88ff6d01, 0xe5000a00, 0x4d82c3ff, 0xfd00cf24, + 0x5182d4ff, 0x3c01ce24, 0xdd51e7ff, 0x82a0200e, 0x00d13e4d, 0xff560030, + 0xff5b007e, 0xfe6d009d, 0xfe7c00f1, 0xfe8100f4, 0xff8600ab, 0xff89005e, + 0x34b3824b, 0xffbe0072, 0xffc2000f, 0xffc5000a, 0xffc60041, 0xffc90007, + 0x20bb8268, 0x20bb820f, 0x28bb820e, 0xffd8000c, 0x00e50063, 0x2cbf8205, + 0xffea00bd, 0xfeec0049, 0xffee00fe, 0x247d8213, 0xfffc0068, 0x0881820e, + 0xfe006826, 0x000113ff, 0x010107ff, 0x06013000, 0x08010eff, 0x1b0111ff, + 0x1f01e7fe, 0x2b01acff, 0x2d0115ff, 0x31013cff, 0x34081782, 0x016aff33, + 0x0149ff37, 0x010cff3d, 0x013fff3f, 0x01f1fe40, 0x01c0ff45, 0x01effe4a, + 0x0131ff4e, 0x015fff50, 0x010aff54, 0x01050057, 0x0130ff58, 0x00d5ff59, + 0x24bd8214, 0xffb700c1, 0x209982c5, 0x208582b4, 0x207982d7, 0x207582b9, + 0x2c6582e9, 0xff1b01b2, 0xff1f01d2, 0xff3301c8, 0x205582a0, 0x204d82c5, + 0x204982e4, 0x204982cc, 0x204182cc, 0x284182cb, 0xffbc01ef, 0xffc001e8, + 0x083f44e6, 0xd800082c, 0xec001500, 0x3c011500, 0x3582e4ff, 0x8b82e520, + 0x4d01e434, 0x4f01e3ff, 0x5701e2ff, 0x2200e4ff, 0xe2ff0a00, 0x7b820d00, + 0xcfff0e30, 0x12004100, 0xeaff4a00, 0xd8ff5600, 0x07825800, 0x13006136, + 0xaeff6d00, 0xcdff7c00, 0xa0ff8100, 0xc1ff8600, 0xc0ff8900, 0xd022a382, + 0x1f82bb00, 0xc6ffbe24, 0x3d82bf00, 0xe9ffc12e, 0xd6ffc200, 0xe8ffc500, + 0xbaffc600, 0xe934bf82, 0xcbffcb00, 0xdaffcc00, 0xc7ffcd00, 0xd3ff7501, + 0xabffba01, 0xcd209f82, 0xcb209f82, 0xcb2a9f82, 0xcbffca01, 0xf3ffcd01, + 0x0382d001, 0xefffd132, 0x81000900, 0xb400dfff, 0xb600f3ff, 0xc300f0ff, + 0xd8205d82, 0xe5220f82, 0xa782e0ff, 0x3d82e020, 0x01ed2508, 0x00f5ffd1, + 0x008a0702, 0x0a000004, 0x0036125e, 0x001d0021, 0xffdbff00, 0xffceff88, + 0xffecffc5, 0x00a4ffa5, 0xfe2100aa, 0x8c2caae3, 0x88ff212a, 0xff230e85, + 0x82f4ffd0, 0x82eb2081, 0xffef3281, 0xffd9ffb3, 0xfff5ff6a, 0x000c00ce, + 0x00c9ff11, 0x85bd8212, 0x21059a26, 0x3f82e5ff, 0x0382e820, 0x248dc920, + 0x8df3ff21, 0x200d910f, 0x21bdaaff, 0x3f8bebff, 0x00abff25, 0x82eaff00, + 0x85d52003, 0xe1ff2115, 0x00270785, 0xff86ff00, 0x87e9ffea, 0x2407870d, + 0x0000edff, 0x820382ff, 0x8214200f, 0x23028403, 0xe6ffefff, 0x04990884, + 0x1a8b1220, 0xff21ad87, 0x201586e4, 0x20098211, 0x82fd8311, 0x8211200f, + 0x83028a03, 0xae0e8a9b, 0x8397830a, 0x25d58957, 0xe9ff0000, 0x4687d8ff, + 0x88a3ff21, 0x875c2009, 0xe0fe2309, 0x0b871300, 0xff000031, 0xff33ffc0, + 0xff32ffe8, 0xffe9fea3, 0x8985fff2, 0x25099319, 0xf5ff4eff, 0x3582f3ff, + 0x2011b141, 0x2015820f, 0x2003826f, 0x253783a7, 0xcdff6cfe, 0x0d82dcff, + 0x0d834820, 0xff250383, 0xff58ff88, 0x260182a7, 0xffb4ff30, 0x821000e4, + 0x00103613, 0xff10000f, 0xffaeffbf, 0x00cbffc4, 0xff7eff00, 0xfe00007c, + 0x281982fe, 0xfff0fe00, 0xfff0ff28, 0x290b83b3, 0xd2ffb5ff, 0x0000d4ff, + 0x778dd2ff, 0xffe4ff23, 0x871f83f5, 0x29ff2103, 0xff210983, 0x85058363, + 0xd5ff2703, 0xe1ffdfff, 0x1d410000, 0x850e2006, 0x08df4115, 0x00220e87, + 0x0a8371ff, 0x83c4ff21, 0x25038905, 0x0000e6ff, 0x0382ebff, 0x1384e720, + 0xff213d84, 0x204b84eb, 0x22118211, 0x82d1ff11, 0x21028405, 0x068464ff, + 0xff230484, 0x82c1ff6a, 0x82d820d3, 0xffc63203, 0xff1100e3, 0x001200a0, + 0xff120011, 0xffecffd9, 0x842284e2, 0x19ff2904, 0x00000d00, 0xa0ff68ff, + 0x8542e782, 0x200f8305, 0x831382eb, 0x0a6f4203, 0x42edff21, 0x37840639, + 0xff210491, 0x871391ef, 0xf1ff2111, 0x07930987, 0x211b5543, 0x3b85f5ff, + 0x8ff2ff21, 0x41178339, 0x218f0d79, 0x4f910f9b, 0x07442d89, 0xb0ff211d, + 0x09ad2989, 0x99a8ff21, 0xf1ff232f, 0x1d83f0ff, 0x09830585, 0xff210387, + 0x260982eb, 0xff000010, 0x82edffe2, 0x82dc2005, 0x43028d0d, 0x53200df3, + 0x00211c8d, 0x2033820f, 0x41d183f1, 0xff211983, 0x213383d7, 0x058359ff, + 0xff23038f, 0x430000ec, 0x1d8f09c7, 0xc9830f9b, 0x319bcd91, 0xff251b83, + 0xff5fff33, 0x26018255, 0xff6bff66, 0x820700bd, 0x00073713, 0xff070005, + 0xff61ff7e, 0x0092ff86, 0xff0fff00, 0xfe00000c, 0x00820036, 0x821efe21, + 0xffd1220f, 0x2005826a, 0x8a0e82c0, 0x9fff2102, 0xc8201382, 0xad200382, + 0xff211487, 0x200983e7, 0x0d9545ff, 0x1384c920, 0xafffa526, 0xaeffbdff, + 0xd2230382, 0x4100e9ff, 0x0786074f, 0x00caff25, 0x82bbff00, 0xfe002217, + 0x202d8477, 0x89058339, 0xecff2403, 0x82ff0000, 0x8b118903, 0x153b4109, + 0x8b79ff21, 0x210b8d23, 0x0f87b5ff, 0x820f1743, 0x000224bb, 0x82060078, + 0x00002201, 0x2201820b, 0x82100001, 0x82022001, 0x001232b1, 0x00250003, + 0x00040029, 0x0034002c, 0x00380009, 0x2615823e, 0x00470045, 0x82490019, + 0x001c2201, 0x2801824c, 0x0051001d, 0x001e0054, 0x22018256, 0x825a0022, + 0x00232801, 0x005e005c, 0x828a0024, 0x00272801, 0x00b300b0, 0x82bc0028, + 0x002c2201, 0x220182c0, 0x82c6002d, 0x002e2801, 0x00d400d3, 0x82d6002f, + 0x00312201, 0x280182d9, 0x00db0032, 0x003300dd, 0x220182df, 0x82e10036, + 0x00372201, 0x220182e3, 0x82e50038, 0x00392201, 0x220182eb, 0x82ed003a, + 0x003b2201, 0x220182f6, 0x82fb003c, 0x3d1c0a01, 0xfe00fd00, 0x03013e00, + 0x40000401, 0x09010901, 0x0c014200, 0x43000c01, 0x19011701, 0x2b014400, + 0x47002d01, 0x30013001, 0x32014a00, 0x4b003201, 0x49014901, 0x6c014c00, + 0x4d007201, 0x77017601, 0x28025400, 0x56002802, 0x2b022a02, 0x46025700, + 0x59004702, 0x49024902, 0x4b025b00, 0x5c007102, 0x7b027602, 0x80028300, + 0x89009002, 0x9b029202, 0xa4029a00, 0xa400a602, 0xa802a802, 0xaa02a700, + 0xa800aa02, 0xac02ac02, 0xae02a900, 0xaa00ae02, 0xb102b102, 0xb302ab00, + 0xac00b302, 0xb502b502, 0xb702ad00, 0xae00b702, 0xb902b902, 0xbb02af00, + 0xb000bb02, 0xc902bd02, 0xcb02b100, 0xbe00cb02, 0xcd02cd02, 0xcf02bf00, + 0xc000cf02, 0xda02da02, 0xdc02c100, 0xc200dc02, 0xde02de02, 0xe002c300, + 0xc400e002, 0xe202e202, 0xe402c500, 0xc600e402, 0xe602e602, 0xe802c700, + 0xc800e802, 0xea02ea02, 0xec02c900, 0xca00ec02, 0xf602ee02, 0x5203cb00, + 0xd4005703, 0x69035a03, 0x6c03da00, 0xea006c03, 0x70037003, 0x7203eb00, + 0xec007203, 0x76037603, 0x7903ed00, 0xee007a03, 0x85037c03, 0x8703f000, + 0xfa008903, 0x90038b03, 0x9203fd00, 0x03019803, 0x9f039e03, 0xa1030a01, + 0x0c01a103, 0xa303a303, 0xa5030d01, 0x0e01a803, 0xb003ab03, 0xb2031201, + 0x1801b203, 0xb703b603, 0xbc031901, 0x1b01c703, 0xcb03ca03, 0xcd032701, + 0x2901d003, 0xd803d703, 0xdc032d01, 0x2f01dc03, 0xe403de03, 0xe9033001, + 0x3701ea03, 0x1604ee03, 0x18043901, 0x62011804, 0x27041a04, 0x2f046301, + 0x71012f04, 0x32043204, 0x34047201, 0x73013404, 0x45044004, 0x48047401, + 0x7a014804, 0x4a044a04, 0x4c047b01, 0x7c014c04, 0x4f044e04, 0x54047d01, + 0x7f015704, 0x5a045a04, 0x5c048301, 0x84015d04, 0x5f045f04, 0x63048601, + 0x87016304, 0x65046504, 0x69048801, 0x89016904, 0xa904a904, 0x02008a01, + 0x10004e01, 0x01220182, 0x01821200, 0x25000122, 0x02220182, 0x01822600, + 0x27000322, 0x04220182, 0x01822800, 0x29000522, 0x06280182, 0x2d002c00, + 0x2e000700, 0x08220182, 0x01822f00, 0x30000922, 0x0a240182, 0x32003100, + 0x33261782, 0x05003300, 0x01823400, 0x38000b22, 0x0c220182, 0x01823900, + 0x3a000822, 0x0d220182, 0x01823b00, 0x3c000e22, 0x0f220182, 0x01823d00, + 0x3e001022, 0x11220182, 0x01824500, 0x46001222, 0x13220182, 0x01824700, + 0x49001422, 0x15220182, 0x01824c00, 0x51001628, 0x16005200, 0x01825300, + 0x54001722, 0x13220182, 0x01825600, 0x5a001822, 0x19220182, 0x01825c00, + 0x5d001a22, 0x19220182, 0x01825e00, 0x8a001b22, 0x13220182, 0x0182b000, + 0xb1001c22, 0x02220182, 0x0182b200, 0xb3000522, 0x02220182, 0x0182bc00, + 0xc0001922, 0x16220182, 0x0182c600, 0xd3001328, 0x1d00d400, 0x0182d600, + 0xd9000722, 0x0f240182, 0xdc00db00, 0xdd26cb82, 0x1e00dd00, 0x0182df00, + 0xe1000722, 0x07220182, 0x0182e300, 0xe5001d22, 0x1d220182, 0x0182eb00, + 0xed001f22, 0x1a220182, 0x0182f600, 0xfb001322, 0x20220182, 0x0182fd00, + 0xfe002022, 0x132a0182, 0x04010301, 0x09012000, 0x05820901, 0x010c3208, + 0x0102000c, 0x00170117, 0x01180117, 0x010d0018, 0x00190119, 0x012b0119, + 0x0113002b, 0x002c012c, 0x012d011c, 0x011f002d, 0x00300130, 0x01320109, + 0x22058232, 0x82490149, 0x016e2811, 0x0101006e, 0x82720172, 0x01763405, + 0x02010077, 0x00280228, 0x022a0204, 0x0205002b, 0x82470246, 0x02492e05, + 0x020c0049, 0x0051024b, 0x02520202, 0x2e1d8252, 0x00560253, 0x02570206, + 0x0207005b, 0x8260025c, 0x61320823, 0x08006402, 0x65026502, 0x66021000, + 0x12006c02, 0x6d026d02, 0x6e021400, 0x15007102, 0x76027602, 0x77021600, + 0x17007b02, 0x81028002, 0x82021900, 0x4d828202, 0x83028322, 0x84222982, + 0x0b828402, 0x85028522, 0x86220b82, 0x0b828602, 0x87028722, 0x88220b82, + 0x6b828802, 0x89028922, 0x8a224782, 0x0b828a02, 0x8b028b22, 0x8c220b82, + 0x0b828c02, 0x8d028d22, 0x8e220b82, 0x0b828e02, 0x8f028f22, 0x90220b82, + 0x89829002, 0x92029222, 0x93229b82, 0x77829302, 0x94029422, 0x95220b82, + 0x0b829502, 0x96029622, 0x97220b82, 0x0b829702, 0x98029822, 0x99220b82, + 0x0b829902, 0x9a029a22, 0x9b220b82, 0x0b829b02, 0xa402a422, 0xa522d182, + 0xad82a502, 0xa602a622, 0xa8220b82, 0x0582a802, 0xaa02aa22, 0xac220582, + 0x0582ac02, 0xae02ae22, 0xb1220582, 0xef82b102, 0xb302b32e, 0xb5020900, + 0x0a00b502, 0xb702b702, 0xb9220582, 0x0582b902, 0xbb02bb22, 0xbd220582, + 0x2982bd02, 0xbe02be22, 0xbf224d82, 0x0b82bf02, 0xc002c022, 0xc1220b82, + 0x0b82c102, 0xc302c222, 0xc4220b82, 0xb382c402, 0xc502c528, 0xc6021700, + 0x0b82c602, 0xc702c722, 0xc8220b82, 0x0b82c802, 0xc902c922, 0xcb280b82, + 0x1800cb02, 0xcd02cd02, 0xcf220582, 0x0582cf02, 0xda02da28, 0xdc020c00, + 0x0582dc02, 0xde02de22, 0xe0220582, 0x8f82e002, 0xe202e222, 0xe4220582, + 0x0582e402, 0xe602e622, 0xe8220582, 0x0582e802, 0xea02ea22, 0xec340582, + 0x0e00ec02, 0xee02ee02, 0xef021000, 0x1900ef02, 0xf002f002, 0xf12e0b82, + 0x1100f102, 0xf202f202, 0xf3021b00, 0x0b82f302, 0xf402f422, 0xf5220b82, + 0x0b82f502, 0x02f62608, 0x031b00f6, 0x00520352, 0x03530302, 0x03060053, + 0x00550354, 0x03560307, 0x03050056, 0x00570357, 0x035a0310, 0x281d825a, + 0x005b035b, 0x035c0303, 0x2823825c, 0x005d035d, 0x035e0311, 0x2829825f, + 0x00600360, 0x03610309, 0x220b8262, 0x82630363, 0x03642e35, 0x030b0064, + 0x00650365, 0x0366030c, 0x28418266, 0x00670367, 0x0368030f, 0x22238268, + 0x82690369, 0x036c3411, 0x0316006c, 0x00700370, 0x03720317, 0x03190072, + 0x82760376, 0x0379220b, 0x285f8279, 0x007a037a, 0x037c031c, 0x282f827d, + 0x007e037e, 0x037f0308, 0x28658280, 0x00810381, 0x0382031e, 0x288f8282, + 0x00830383, 0x03840303, 0x22298284, 0x82850385, 0x03872235, 0x222f8288, + 0x82890389, 0x038b2283, 0x2883828b, 0x008c038c, 0x038d0304, 0x2289828d, + 0x828e038e, 0x038f2e83, 0x0312008f, 0x00900390, 0x03920315, 0x2e718292, + 0x00930393, 0x03940313, 0x03140094, 0x82950395, 0x03962889, 0x031a0096, + 0x82970397, 0x03982823, 0x031f0098, 0x829e039e, 0x039f2817, 0x030e009f, + 0x82a103a1, 0x03a32205, 0x220582a3, 0x82a503a5, 0x03a622cb, 0x221d82a6, + 0x82ac03ac, 0x03ad227d, 0x22d782ad, 0x82ae03ae, 0x03af22a1, 0x226b82af, + 0x82b003b0, 0x03b2229b, 0x284d82b2, 0x00b603b6, 0x03b7030d, 0x222f82b7, + 0x82bc03bc, 0x03bd229b, 0x227782bd, 0x82be03be, 0x03bf2247, 0x221782bf, + 0x82c003c0, 0x03c12247, 0x22ad82c1, 0x82c203c2, 0x03c32289, 0x221182c3, + 0x82c403c4, 0x03c52253, 0x225382c5, 0x82c603c6, 0x03c7220b, 0x220b82c7, + 0x82ca03ca, 0x03cb225f, 0x225f82cb, 0x82ce03cd, 0x03cf2205, 0x223b82cf, + 0x82d003d0, 0x03d7283b, 0x030500d7, 0x82d803d8, 0x03dc22e9, 0x220582dc, + 0x82de03de, 0x03df28ef, 0x031e00df, 0x82e003e0, 0x03e12271, 0x220b82e1, + 0x82e203e2, 0x03e3220b, 0x220b82e3, 0x82e403e4, 0x03e9220b, 0x224782e9, + 0x82ea03ea, 0x03ee2247, 0x227182ee, 0x82ef03ef, 0x03f02271, 0x220b82f0, + 0x82f103f1, 0x03f2220b, 0x220b82f2, 0x82f303f3, 0x03f4220b, 0x220b82f4, + 0x82f503f5, 0x03f6220b, 0x220b82f6, 0x82f703f7, 0x03f8220b, 0x220b82f8, + 0x82f903f9, 0x03fa220b, 0x220b82fa, 0x82fb03fb, 0x03fc220b, 0x220b82fc, + 0x82fd03fd, 0x03fe220b, 0x2e0b82fe, 0x00ff03ff, 0x04000412, 0x04020000, + 0x82010401, 0x0402220b, 0x220b8202, 0x82030403, 0x0404220b, 0x220b8204, + 0x82050405, 0x04062e0b, 0x04060006, 0x00070407, 0x04080415, 0x220b8208, + 0x82090409, 0x040a220b, 0x220b820a, 0x820b040b, 0x040c220b, 0x220b820c, + 0x820d040d, 0x040e220b, 0x220b820e, 0x820f040f, 0x0410220b, 0x220b8210, + 0x82110411, 0x0412220b, 0x220b8212, 0x82130413, 0x0414220b, 0x220b8214, + 0x82150415, 0x0416280b, 0x04070016, 0x82180418, 0x041a2e05, 0x0405001a, + 0x001b041b, 0x041c0417, 0x220b821c, 0x821d041d, 0x041e220b, 0x220b821e, + 0x821f041f, 0x0420220b, 0x220b8220, 0x82210421, 0x0422220b, 0x220b8222, + 0x82230423, 0x0424220b, 0x220b8224, 0x82250425, 0x0426220b, 0x220b8226, + 0x82270427, 0x042f220b, 0x2805822f, 0x00320432, 0x04340408, 0x2e058234, + 0x00400440, 0x04410410, 0x04190041, 0x82420442, 0x0443220b, 0x220b8243, + 0x82440444, 0x0445220b, 0x280b8245, 0x00480448, 0x044a0409, 0x0895824a, + 0x4c044c20, 0x4e040c00, 0x0f004e04, 0x4f044f04, 0x54041a00, 0x1c005404, + 0x55045504, 0x56041f00, 0x17825604, 0x57045722, 0x5a2e1782, 0x16005a04, + 0x5c045c04, 0x5d041d00, 0x23825d04, 0x5f045f22, 0x63224782, 0x47826304, + 0x65046522, 0x69220582, 0x65826904, 0xa904a92a, 0x02000500, 0x06006d01, + 0x01200182, 0x220aab4a, 0x82110016, 0x00192201, 0x21018212, 0xe9470016, + 0x00272605, 0x00080027, 0x2201822b, 0x822e0008, 0x001a2201, 0x22018233, + 0x82350008, 0x00082201, 0x22018237, 0x8238001b, 0x00092201, 0x22018239, + 0x823a000a, 0x000b2201, 0x2201823b, 0x823c000c, 0x00172201, 0x2201823d, + 0x823e000d, 0x00182201, 0x28018245, 0x00470003, 0x00040049, 0x2401824b, + 0x00510004, 0x228d8252, 0x82530053, 0x0054228b, 0x220b8254, 0x82550055, + 0x0057261d, 0x00070057, 0x22018259, 0x825a000e, 0x000f2201, 0x2201825c, + 0x825d001c, 0x000f2201, 0x2201825e, 0x82830010, 0x00082201, 0x22018292, + 0x82930008, 0x00042201, 0x22018297, 0x82980008, 0x00042201, 0x2101829a, + 0xe347000e, 0x47082009, 0xba2206e3, 0x5f82ba00, 0xbc00bc26, 0xc0000f00, + 0x05240182, 0xc800c700, 0xca261182, 0x0e00ca00, 0x0182d100, 0xd2000922, + 0x08220182, 0x0182d300, 0xd5001122, 0x09220182, 0x0182d900, 0xdc001722, + 0x11220182, 0x0182dd00, 0xe0001522, 0x12220182, 0x0182eb00, 0xed000522, + 0x1c240182, 0xf000ef00, 0xf128bf82, 0x1300f100, 0xf400f200, 0xf6220b82, + 0x5982f600, 0xf700f722, 0xf8280b82, 0x1400f800, 0xfa00f900, 0xfd220b82, + 0x0582fd00, 0xff00ff34, 0x02010500, 0x04000201, 0x03010301, 0x04011300, + 0x11820401, 0x0701072e, 0x0c010800, 0x02000c01, 0x16011601, 0x17340b82, + 0x06001701, 0x18011801, 0x19010b00, 0x0f001901, 0x1a011a01, 0x1c221782, + 0x05821c01, 0x1d011d22, 0x1e224182, 0x0b821e01, 0x20012022, 0x21220582, + 0x11822101, 0x22052548, 0x82350135, 0x01382253, 0x22178238, 0x82390139, + 0x013a2817, 0x0109003a, 0x82440144, 0x01492217, 0x22058249, 0x824c014b, + 0x01512817, 0x01110051, 0x82550155, 0x01562229, 0x34118256, 0x006a0169, + 0x016c0119, 0x0101006d, 0x006e016e, 0x016f0116, 0x220b8271, 0x82720172, + 0x01762e0b, 0x02160077, 0x00290228, 0x022b0208, 0x2405822c, 0x00450245, + 0x0a674819, 0x5c020824, 0x17826002, 0x02612e08, 0x020a0064, 0x00650265, + 0x0266020d, 0x0203006c, 0x0071026d, 0x02760204, 0x02050076, 0x007b0277, + 0x027c0206, 0x020e007f, 0x00810280, 0x0a5b480f, 0x48020321, 0x0321095b, + 0x095b4802, 0x88020324, 0x59828802, 0x89028922, 0x8a224782, 0x0b828a02, + 0x8b028b22, 0x8c220b82, 0x0b828c02, 0x8d028d22, 0x8e220b82, 0x0b828e02, + 0x8f028f22, 0x91220b82, 0x05829102, 0x93029322, 0x95220582, 0x05829502, + 0x97029722, 0x99220582, 0x05829902, 0x9b029b22, 0x9c220582, 0x2f829c02, + 0x9d029d22, 0x9e220b82, 0x0b829e02, 0x9f029f22, 0xa0220b82, 0x0b82a002, + 0xa102a122, 0xa2220b82, 0x0b82a202, 0xa302a322, 0xb1280b82, 0x1a00b102, + 0xbe02be02, 0xc022c582, 0x0582c002, 0xc302c222, 0xc4220582, 0x2382c402, + 0xc502c522, 0xc622d782, 0x0b82c602, 0xc702c722, 0xc8220b82, 0x0b82c802, + 0xc902c922, 0xd02e0b82, 0x1b00d002, 0xd102d102, 0xd2020700, 0x0b82d202, + 0xd302d322, 0xd4220b82, 0x0b82d402, 0xd502d522, 0xd6220b82, 0x0b82d602, + 0xd702d722, 0xd8220b82, 0x0b82d802, 0xd902d922, 0xda280b82, 0x0900da02, + 0xdc02dc02, 0xde220582, 0x0582de02, 0xe002e02e, 0xe1020a00, 0x0e00e102, + 0xe202e202, 0xe3220b82, 0x0b82e302, 0xe402e422, 0xe5220b82, 0x0b82e502, + 0xe602e622, 0xe7220b82, 0x0b82e702, 0xe802e822, 0xe9220b82, 0x0b82e902, + 0xea02ea22, 0xeb220b82, 0x0b82eb02, 0xec02ec34, 0xee020c00, 0x0d00ee02, + 0xef02ef02, 0xf0020f00, 0x0b82f002, 0xf102f12e, 0xf2021800, 0x1000f202, + 0xf302f302, 0xf4220b82, 0x0b82f402, 0xf502f522, 0xf6220b82, 0x0b82f602, + 0xf902f924, 0x67480800, 0x03562206, 0x240b8256, 0x00570357, 0x065b480d, + 0x5d035d28, 0x63031800, 0x17826303, 0x66036622, 0x67281782, 0x17006703, + 0x69036903, 0x20080b82, 0x006a036a, 0x036c0304, 0x0305006c, 0x006e036e, + 0x0370030e, 0x03060070, 0x00720372, 0x0375030f, 0x22118275, 0x82760376, + 0x03772211, 0x2a0b8277, 0x007e037e, 0x0381031a, 0x48150081, 0x8922062b, + 0x59828903, 0x8c038c22, 0x8d280582, 0x09008d03, 0x8e038e03, 0x8f285f82, + 0x03008f03, 0x90039003, 0x91225f82, 0x5f829103, 0x92039222, 0x93224782, + 0x0b829303, 0x94039422, 0x95221782, 0x65829503, 0x96039628, 0x97031c00, + 0x11829703, 0x98039822, 0x99281d82, 0x07009903, 0x9d039d03, 0x9e220b82, + 0x23829e03, 0x9f039f28, 0xa1030c00, 0x0582a103, 0xa303a322, 0xa5220582, + 0xbf82a503, 0xa603a622, 0xa7281d82, 0x0100a803, 0xab03ab03, 0xad220582, + 0x3582ad03, 0x24092548, 0x03b20303, 0x225982b2, 0x82b303b3, 0x03b62817, + 0x030b00b6, 0x82b703b7, 0x03b82235, 0x221782b8, 0x82b903b9, 0x03bc22b9, + 0x220582bc, 0x82bd03bd, 0x03be2211, 0x225982be, 0x82bf03bf, 0x03c12223, + 0x22cb82c1, 0x82c203c2, 0x092548a1, 0x48030321, 0x03240925, 0xcb03cb03, + 0xcd223582, 0x0582ce03, 0xcf03cf22, 0xd0222f82, 0x2f82d003, 0xd403d422, + 0xd6227182, 0x0582d603, 0xd703d722, 0xd8285f82, 0x0600d803, 0xd903d903, + 0xda220b82, 0x2f82da03, 0xdb03db22, 0xdc220b82, 0x1782dc03, 0xdf03df28, + 0xe0031500, 0x7782e003, 0xe103e122, 0xe2220b82, 0x0b82e203, 0xe303e322, + 0xe4220b82, 0x0b82e403, 0xe503e52e, 0xe6031200, 0x1400e603, 0xe803e803, + 0xe9225982, 0x7182e903, 0xea03ea22, 0xeb227182, 0x5382eb03, 0xec03ec2b, + 0xed031100, 0x1300ed03, 0x095b4803, 0x48030321, 0x0321095b, 0x095b4803, + 0x48030321, 0x0321095b, 0x095b4803, 0x48030321, 0x0321095b, 0x095b4803, + 0x48030321, 0x0321095b, 0x095b4803, 0x5b480320, 0x0403210a, 0x21095b48, + 0x5b480403, 0x04032a09, 0x00070407, 0x04090404, 0x22058209, 0x820b040b, + 0x040d2205, 0x2205820d, 0x820f040f, 0x04112205, 0x22058211, 0x82130413, + 0x04152205, 0x2e058215, 0x001a041a, 0x041b0408, 0x0406001b, 0x821c041c, + 0x041d220b, 0x220b821d, 0x821e041e, 0x041f220b, 0x220b821f, 0x82200420, + 0x0421220b, 0x220b8221, 0x82220422, 0x0423220b, 0x220b8223, 0x82240424, + 0x0425220b, 0x220b8225, 0x82260426, 0x0427220b, 0x220b8227, 0x82280428, + 0x0429220b, 0x225f8229, 0x822a042a, 0x042b220b, 0x220b822b, 0x822c042c, + 0x042d220b, 0x220b822d, 0x822e042e, 0x042f220b, 0x222f822f, 0x82300430, + 0x0431220b, 0x2e178231, 0x00320432, 0x0433040a, 0x040e0033, 0x82340434, + 0x0435220b, 0x220b8235, 0x82370437, 0x04392205, 0x22058239, 0x823b043b, + 0x043d2205, 0x2205823d, 0x823f043f, 0x04402e05, 0x040d0040, 0x00410441, + 0x0442040f, 0x220b8242, 0x82430443, 0x0444220b, 0x220b8244, 0x82450445, + 0x0449280b, 0x04050049, 0x824b044b, 0x4c200805, 0x09004c04, 0x4e044e04, + 0x4f041700, 0x1c004f04, 0x50045004, 0x51041200, 0x14005104, 0x52045204, + 0x53220b82, 0x0b825304, 0x55045522, 0x56222f82, 0x29825604, 0x57045722, + 0x62222982, 0x11826204, 0x64046422, 0x66220582, 0x05826604, 0x6704672e, + 0x68041100, 0x13006804, 0x69046904, 0x6f347182, 0x19006f04, 0xa904a904, + 0x01000800, 0x0a000000, 0x10080602, 0x0c0b5918, 0x7267482e, 0x76006b65, + 0x6e74616c, 0x0400a400, 0x00242382, 0x1200ffff, 0x20080782, 0x0014000a, + 0x0028001e, 0x00410034, 0x0055004b, 0x0069005f, 0x007d0073, 0x00910087, + 0x00a5009b, 0x082d8aaf, 0x0b000122, 0x1f001500, 0x35002900, 0x4c004200, + 0x60005600, 0x74006a00, 0x88007e00, 0x9c009200, 0xb000a600, 0x22082d8a, + 0x000c0002, 0x00200016, 0x0036002a, 0x004d0043, 0x00610057, 0x0075006b, + 0x0089007f, 0x009d0093, 0x82b100a7, 0x06250877, 0x20455a41, 0x52435400, + 0x7e002054, 0x204c4f4d, 0x414ea800, 0xd4002056, 0x204d4f52, 0x55540001, + 0x2c012052, 0x08ad8300, 0x03001326, 0x17000d00, 0x2b002100, 0x37003200, + 0x4e004400, 0x62005800, 0x76006c00, 0x8a008000, 0x9e009400, 0xb200a800, + 0x12202b84, 0x20088782, 0x0018000e, 0x002c0022, 0x00450038, 0x0059004f, + 0x006d0063, 0x00810077, 0x0095008b, 0x00a9009f, 0x082986b3, 0x0f000522, + 0x23001900, 0x39002d00, 0x50004600, 0x64005a00, 0x78006e00, 0x8c008200, + 0xa0009600, 0xb400aa00, 0x26082984, 0x00060013, 0x001a0010, 0x002e0024, + 0x003e003a, 0x00510047, 0x0065005b, 0x0079006f, 0x008d0083, 0x00a10097, + 0x86b500ab, 0x0724082b, 0x1b001100, 0x2f002500, 0x3f003b00, 0x52004800, + 0x66005c00, 0x7a007000, 0x8e008400, 0xa2009800, 0xb600ac00, 0x24082b86, + 0x00120008, 0x0026001c, 0x003c0030, 0x00490040, 0x005d0053, 0x00710067, + 0x0085007b, 0x0099008f, 0x00ad00a3, 0x082b86b7, 0x1300092c, 0x27001d00, + 0x33003100, 0x4a003d00, 0x5e005400, 0x72006800, 0x86007c00, 0x9a009000, + 0xae00a400, 0xb900b800, 0x63733263, 0x05845804, 0x05845e20, 0x05846420, + 0x05a46a20, 0x706d6325, 0xb4637004, 0x6c642505, 0x78046769, 0x7e200584, + 0x84200584, 0x8a200584, 0x6e2505a4, 0x90046d6f, 0x20058364, 0x20058496, + 0x2005849c, 0x2505a3a2, 0x63617266, 0x05b5a804, 0x6122b282, 0x0584b204, + 0x6e6cba26, 0xc0046d75, 0xc6200584, 0xcc200584, 0xd2200584, 0x6f2505a4, + 0xd8046c63, 0x2005836c, 0x200584de, 0x224c82e4, 0x84ea0472, 0x84f02005, + 0x84f62005, 0xa3fc2005, 0x826f2005, 0x02052124, 0x08200584, 0x0e200584, + 0x14200584, 0x702005a3, 0x1a203b83, 0x20200584, 0x26200584, 0x2c200584, + 0x732505a3, 0x0570636d, 0x20058432, 0x20058438, 0x2005843e, 0x2505a444, + 0x05313073, 0x0583734a, 0x05845020, 0x05845620, 0x05a65c20, 0x62053222, + 0x32222982, 0x05846805, 0x05846e20, 0x05a67420, 0x7a053322, 0x33222982, + 0x05848005, 0x05848620, 0x05a68c20, 0x92053422, 0x34222982, 0x05849805, + 0x05849e20, 0x05a6a420, 0xaa053522, 0x35222982, 0x0584b005, 0x0584b620, + 0x05a6bc20, 0xc2053622, 0x36222982, 0x0584c805, 0x0584ce20, 0x05a6d420, + 0xda053722, 0x37222982, 0x0584e005, 0x0584e620, 0x05a3ec20, 0x756e7425, + 0x84f2056d, 0x84f82005, 0x83fe2005, 0x04062105, 0x002205a3, 0x5e180000, + 0x022417db, 0x09000800, 0x0e201f84, 0x10200584, 0x0f200584, 0x0d200584, + 0x43200584, 0x45200584, 0x44200584, 0x42200584, 0x03260582, 0x40003f00, + 0x09824100, 0x11000224, 0x17841200, 0x3c200585, 0x3e200b84, 0x3d200584, + 0x3b200584, 0x0a200584, 0x0c200584, 0x0b200584, 0x47200584, 0x49200584, + 0x48200584, 0x46200584, 0x30200584, 0x32200584, 0x31200584, 0x2f200584, + 0x38200584, 0x3a200584, 0x39200584, 0x37200584, 0x05200584, 0x07200584, + 0x06200584, 0x04200584, 0x14200584, 0x16200584, 0x15200584, 0x13200584, + 0x18200584, 0x1a200584, 0x19200584, 0x17200584, 0x1c200584, 0x1e200584, + 0x1d200584, 0x1b200584, 0x20200584, 0x22200584, 0x21200584, 0x1f200584, + 0x24200584, 0x26200584, 0x25200584, 0x23200584, 0x28200584, 0x2a200584, + 0x29200584, 0x27200584, 0x2c200584, 0x2e200584, 0x2d200584, 0x2b200584, + 0x34200584, 0x36200584, 0x35200584, 0x33240584, 0x98004b00, 0x04210185, + 0x25018526, 0xc0071407, 0x0182500e, 0x880e6622, 0xbe240186, 0x120fe40e, + 0x26210186, 0x2101850f, 0x01850f3a, 0x850f4e21, 0x0f602101, 0x7a210185, + 0x2101850f, 0x01850fbc, 0x850fda21, 0x0ff82101, 0x10210184, 0x2101862a, + 0x0185105c, 0xa2108e26, 0xcc10da10, 0xda200186, 0x03820b82, 0x00061123, + 0x089f8401, 0x0200086f, 0xdf00c401, 0xba01e701, 0xbc01bb01, 0xbe01bd01, + 0xc001bf01, 0xc201c101, 0xc401c301, 0xc601c501, 0xc801c701, 0xca01c901, + 0xcc01cb01, 0xce01cd01, 0xd001cf01, 0xd201d101, 0xe801d301, 0x4302e901, + 0xea013b02, 0xec01eb01, 0xee01ed01, 0xf001ef01, 0xf201f101, 0xf401f301, + 0xf601f501, 0xf801f701, 0xfa01f901, 0xfc01fb01, 0xfe01fd01, 0x096e8202, + 0x02dc0455, 0x02030202, 0x02050204, 0x02070206, 0x02090208, 0x020b020a, + 0x020f022f, 0x02110210, 0x02150214, 0x02170216, 0x02190218, 0x021c021b, + 0x021d021e, 0x02fc02fb, 0x02fe02fd, 0x030003ff, 0x03020301, 0x03040303, + 0x03060305, 0x03080307, 0x030a0309, 0x030c030b, 0x030e030d, 0x0310030f, + 0x03120311, 0x03140313, 0x03160315, 0x03180317, 0x031a0319, 0x031c031b, + 0x031e031d, 0x0320031f, 0x03220321, 0x03240323, 0x03260325, 0x03280327, + 0x032a0329, 0x032c032b, 0x032e032d, 0x0330032f, 0x03320331, 0x03340333, + 0x03360335, 0x03380337, 0x033a0339, 0x033c033b, 0x033e033d, 0x0340033f, + 0x03420341, 0x03450343, 0x03460344, 0x03480347, 0x034a0349, 0x034c034b, + 0x034e034d, 0x0350034f, 0x04aa0451, 0x04ac04ab, 0x04ae04ad, 0x04b004af, + 0x04b204b1, 0x04b404b3, 0x04b604b5, 0x04b804b7, 0x04ba04b9, 0x04bc04bb, + 0x04be04bd, 0x04c004bf, 0x04c204c1, 0x04c404c3, 0x04ff01c5, 0x04c704c6, + 0x04c904c8, 0x04cb04ca, 0x04cd04cc, 0x04cf04ce, 0x04d104d0, 0x04d304d2, + 0x04d504d4, 0x04d804d7, 0x041a02da, 0x040e02db, 0x021302d6, 0x02d9040d, + 0x0012020c, 0x18df0001, 0x223ab562, 0x10920085, 0x8001b762, 0x22098d43, + 0x43b70074, 0x022b338b, 0x022f03fc, 0x04fa013b, 0x43ca04c9, 0x012b076d, + 0x040002ff, 0x04ce04cd, 0x43d304d0, 0xa5431575, 0x0c81430b, 0x19021722, + 0x20387143, 0x2c73434e, 0x433b7143, 0xc82e056f, 0xcc04cb04, 0xd104cf04, + 0x0102d204, 0x5343d404, 0xc604230b, 0x3743c704, 0x18022105, 0x20063943, + 0x0a3b43fb, 0x3d431620, 0xb7820906, 0x46004500, 0x48004700, 0x4a004900, + 0x4c004b00, 0x4e004d00, 0x50004f00, 0x52005100, 0x54005300, 0x56005500, + 0x58005700, 0x5a005900, 0x5c005b00, 0x5e005d00, 0x8c008700, 0xe9009300, + 0xeb00ea00, 0xed00ec00, 0xef00ee00, 0xf100f000, 0xf300f200, 0xf500f400, + 0xf700f600, 0xf900f800, 0xfb00fa00, 0xfd00fc00, 0xff00fe00, 0x01010001, + 0x03010201, 0x05010401, 0x2d010601, 0x33013101, 0x3b013901, 0x40013d01, + 0x4a024701, 0x67026602, 0x69026802, 0x6b026a02, 0x6d026c02, 0x6f026e02, + 0x71027002, 0x73027202, 0x75027402, 0x77027602, 0x79027802, 0x7b027a02, + 0x7d027c02, 0x7f027e02, 0x81028002, 0x85028302, 0x89028702, 0x8d028b02, + 0x91028f02, 0x95029302, 0x99029702, 0x9d029b02, 0xa1029f02, 0xa502a302, + 0xa902a702, 0xad02ab02, 0xb402b202, 0xb802b602, 0xbc02ba02, 0xc002be02, + 0xc502c202, 0xc902c702, 0xcd02cb02, 0xd102cf02, 0xd502d302, 0xdb02d902, + 0xdf02dd02, 0xe302e102, 0xe702e502, 0xeb02e902, 0xef02ed02, 0xf402f202, + 0x8f03f602, 0x91039003, 0x93039203, 0x95039403, 0x97039603, 0x99039803, + 0x9b039a03, 0x9d039c03, 0xbb039e03, 0xbf03bd03, 0xd403cd03, 0xe003da03, + 0x49044604, 0x4f044b04, 0x59045704, 0x5e045a04, 0x06006a04, 0x06000000, + 0x2a001200, 0x5a004200, 0x8a007200, 0x11820300, 0x11820120, 0x90000124, + 0x0b820100, 0x05824a20, 0x4d000122, 0x7820178a, 0x4e20178a, 0x6020178a, + 0x02211789, 0x20178aad, 0x21178948, 0x178a9a03, 0x178a3020, 0x178a9c20, + 0x17891820, 0x00190423, 0x220d8202, 0x82ab00a7, 0x82042089, 0x00012803, + 0x06010008, 0x8236001e, 0x05df4dab, 0x00ca7208, 0x010e01fc, 0x014a0118, + 0x017e0164, 0x01ba0190, 0x02f601ec, 0x02320218, 0x02760244, 0x02a20288, + 0x03de02cc, 0x031a0310, 0x03360324, 0x03720368, 0x0386037c, 0x03ba03a0, + 0x04f603cc, 0x04320428, 0x046e0454, 0x04b20480, 0x05de04c4, 0x051a0508, + 0x052e0524, 0x05420538, 0x0596056c, 0x06ea05c0, 0x00060014, 0x0014000e, + 0x0020001a, 0x022c0026, 0x2293824b, 0x824c02a7, 0x02a82205, 0x2205824e, + 0x82f003a9, 0x04aa2205, 0x2205827a, 0x82ee03ab, 0x00ac2605, 0x04040001, + 0x21098787, 0x09828802, 0x0382a820, 0x0c000624, 0x07828904, 0x8b04ac26, + 0xa2010200, 0x5320578e, 0x54205784, 0xa8220582, 0x05820a04, 0x0804a922, + 0x7c205784, 0xab220582, 0x4d840604, 0x33820220, 0x76040c22, 0xa2207b84, + 0x69834384, 0x1b848d20, 0x5720a58d, 0x58204d84, 0xa6202984, 0x16204d84, + 0x7e204d84, 0x18204d84, 0x03223184, 0xd9830800, 0x848f0421, 0x82912073, + 0x02ac2205, 0x865584b3, 0xb5022119, 0x93201984, 0xb7201984, 0x81841984, + 0x84ac0321, 0x84952017, 0x00052c45, 0x0012000c, 0x001e0018, 0x84780424, + 0x84bd2075, 0x845b2075, 0x84972075, 0x92bf203b, 0x845c20ef, 0x845d202b, + 0x845f202b, 0x841c202b, 0x848020a1, 0x411a20a1, 0x99200847, 0xa82c0982, + 0x0a000400, 0x16001000, 0xca021c00, 0x82207b84, 0x9b202584, 0xcc205d84, + 0xd020b38c, 0x9d201f84, 0xd6201984, 0x0421b389, 0x2011849f, 0x208992da, + 0x20898461, 0x20898462, 0x208984e0, 0x20898434, 0x20638484, 0x0a794132, + 0x1d84a120, 0x3d41a320, 0x8303200b, 0x03a72257, 0x207584a1, 0x0f1141a5, + 0x11830320, 0x6502a722, 0x44201d84, 0x42203d84, 0x40205b84, 0x02215589, + 0x201d84f1, 0x12c541a7, 0x99846620, 0x99846720, 0x05826920, 0x8303a921, + 0x04aa222b, 0x220b827b, 0x41ef03ab, 0x88200823, 0x20086b42, 0x0a6b4289, + 0x0b828a20, 0x8c04ac22, 0x6e20f192, 0x6f205784, 0x0b207784, 0x09209584, + 0x7d209584, 0x0720f184, 0x77205788, 0x01244d84, 0x8e040400, 0x19201388, + 0x200c3b42, 0x20438490, 0x22058292, 0x41b402ac, 0xb6200c87, 0x94201984, + 0xb8201984, 0x21098741, 0x1784ad03, 0x29419620, 0x7904210f, 0xbe209384, + 0x7620eb84, 0x98209384, 0xc0203b84, 0x9783bf92, 0x7802a722, 0x7a202b84, + 0x1d202b84, 0x8120bf84, 0x1b20bf84, 0x9a20ab88, 0x200e3b42, 0x207b84cb, + 0x20258483, 0x205d849c, 0x20b38ccd, 0x201f84d1, 0x2019849e, 0x21b389d7, + 0x1184a004, 0x8992db20, 0xb5847c20, 0x89847d20, 0x8984e120, 0x89843520, + 0x63848520, 0xe5413320, 0xa2042109, 0xa4201d84, 0x200c3b42, 0x220d82a0, + 0x84a203a7, 0x41a62075, 0x03200f11, 0xa7221183, 0x1d848002, 0x3d844520, + 0x5b844320, 0x55894120, 0x84f20221, 0x41a8201d, 0xf72008ff, 0x0124f184, + 0xf9020400, 0xf8200988, 0xfa200988, 0xb1430984, 0x7202210a, 0x7320bf84, + 0xa720bf84, 0x17206384, 0x7f206384, 0xab210582, 0x21298a00, 0x11822a04, + 0x2804a722, 0x2e206f84, 0x2c202984, 0x30202984, 0x0421b78f, 0x2029842b, + 0x20298429, 0x2029842f, 0x2029842d, 0x20299031, 0x20298438, 0x20298436, + 0x2029843c, 0x2029843a, 0x2029903e, 0x20298439, 0x20298437, 0x2029843d, + 0x2029843b, 0x08eb413f, 0xdb848620, 0x1100022c, 0x29002500, 0x2b000000, + 0xbf822d00, 0x002f3008, 0x00080034, 0x003b0036, 0x003d000e, 0x0014003e, + 0x00490045, 0x004b0016, 0x001b004d, 0x0054004f, 0x0056001e, 0x0024005b, + 0x005e005d, 0x8281002a, 0x002c2201, 0x22018283, 0x8286002d, 0x002e2201, + 0x22018289, 0x828c002f, 0x00302801, 0x009a0097, 0x82cf0031, 0x00352101, + 0x2207294a, 0x82060001, 0x00012679, 0x02d40202, 0x201588d5, 0x286f8202, + 0x04dd0404, 0x04df04de, 0x291582e0, 0x02860204, 0x02980287, 0xc7460099, + 0x26002108, 0x0a223782, 0x19461c00, 0xa3012105, 0x4a220782, 0x0582a801, + 0x01005826, 0xa9010400, 0x02240986, 0x57004a00, 0x4420358a, 0x14203584, + 0xa4202384, 0x4d200b82, 0xa6200984, 0x5b890984, 0x258a1e20, 0x0b82a520, + 0x25845020, 0x0986a720, 0x6f825382, 0x0121c18a, 0x221f8295, 0x884b0001, + 0x21d582bf, 0x13842701, 0x138cba20, 0x1384ac20, 0x13883620, 0xbf830220, + 0x01e30123, 0x26118ae4, 0x0102000a, 0x82e601e5, 0x00022411, 0x8a4f002f, + 0x001e3a19, 0x0228020c, 0x0229022a, 0x022c022b, 0x0220021f, 0x02ae0121, + 0x02240223, 0x2a258225, 0x0027000c, 0x002b0028, 0x4a350033, 0x4b210605, + 0x05f34900, 0x2908954b, 0x03000c00, 0x27022602, 0x2f822702, 0x49000326, + 0xae014b00, 0x66325f8a, 0x3d020800, 0x2e022d02, 0x31023002, 0x3a023902, + 0x1d8a3c02, 0x08001632, 0x15001b00, 0x17001600, 0x19001800, 0x14001d00, + 0x08301d82, 0x2202ad01, 0x71047004, 0x73047204, 0x75047404, 0x0421318d, + 0x231d8975, 0x7404ad01, 0x08201d82, 0x45893782, 0x47821b20, 0x63839f89, + 0x63841b8d, 0x0221938d, 0x0c53413d, 0x0d826920, 0x13000128, 0x00000600, + 0xa3820100, 0x05820320, 0x03821220, 0x0f845220, 0x4a00002a, 0x02000200, + 0x7c017c01, 0xd4221e82, 0x7952dd01, 0x82082008, 0x01282209, 0x384b88c0, + 0x001a0002, 0x0032020a, 0x0073007a, 0x02330274, 0x02350234, 0x02370236, + 0x203f8238, 0x51b38201, 0x44820581, 0x24086382, 0x00260002, 0x01d40110, + 0x01d601d5, 0x01d801d7, 0x01da01d9, 0x01dc01db, 0x024002dd, 0x0241023e, + 0x043f0242, 0x205982e1, 0x24eb8c10, 0x001b001a, 0x2aef821c, 0x024e004d, + 0x039a03ad, 0x0519049c, 0x4bd158fa, 0x00000034, +}; diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_App.cpp b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_App.cpp new file mode 100644 index 00000000..5f44b202 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_App.cpp @@ -0,0 +1,417 @@ +#include "NetImguiServer_App.h" + +#include "Fonts/Roboto_Medium.cpp" +#include "NetImguiServer_Config.h" +#include "NetImguiServer_Network.h" +#include "NetImguiServer_RemoteClient.h" +#include "NetImguiServer_UI.h" + +namespace NetImguiServer { +namespace App { + +constexpr uint32_t kClientCountMax = + 32; //! @sammyfreg todo: support unlimited client count +ImVector + gServerTextures; // List of ALL server created textures (used by server and + // clients) +ServerTexture* gServerTextureEmpty = + nullptr; // Empty texture used when no valid texture found +bool gLoadedConfigOnce = false; + +void UpdateServerTextures(); + +bool Startup(const char* CmdLine) { + //--------------------------------------------------------------------------------------------- + // Load Settings savefile and parse for auto connect commandline option + //--------------------------------------------------------------------------------------------- + if (!gLoadedConfigOnce) { + NetImguiServer::Config::Client::LoadAll(); + gLoadedConfigOnce = true; + } + AddTransientClientConfigFromString(CmdLine); + + //--------------------------------------------------------------------------------------------- + // Perform application initialization: + //--------------------------------------------------------------------------------------------- + if (RemoteClient::Client::Startup(kClientCountMax) && + NetImguiServer::Network::Startup() && NetImguiServer::UI::Startup()) { + NetImgui::Internal::CmdTexture cmdTexture; + uint32_t EmptyData[4 * 4] = { + 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, + 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, + 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF}; + cmdTexture.mTextureClientID = 0; + cmdTexture.mFormat = ImTextureFormat::ImTextureFormat_RGBA32; + cmdTexture.mWidth = cmdTexture.mHeight = 4; + cmdTexture.mpTextureData.SetPtr((uint8_t*)EmptyData); + gServerTextureEmpty = CreateTexture(cmdTexture, sizeof(EmptyData)); + + LoadFonts(); + ImGui::GetIO().IniFilename = + nullptr; // Disable server ImGui ini settings (not really needed, and + // avoid imgui.ini filename conflicts) + ImGui::GetIO().LogFilename = nullptr; + return HAL_Startup(CmdLine); + } + return false; +} + +void Shutdown() { + // Mark all texture resources as wanting deletion + for (ServerTexture* texServer : gServerTextures) { + if (texServer && texServer->IsValid()) { + if (!texServer->mIsCustom) { + texServer->mTexData.SetStatus(ImTextureStatus_WantDestroy); + texServer->mTexData.UnusedFrames = 1; + } else { +#if TEXTURE_CUSTOM_SAMPLE + if (texServer && texServer->mIsCustom) { + 0 // TODO + } +#endif + } + } + } + + // Allow Dear ImGui to delete the textures + ImGui::NewFrame(); + ImGui::Render(); + HAL_RenderDrawData(ImGui::GetDrawData()); + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + + // Finish removing them from Dear ImGui user textures and delete objects + UpdateServerTextures(); + + // Update Dear ImGui texture list (so it doesn't have deleted items in it) + ImGui::NewFrame(); + ImGui::Render(); + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + + // Remove deleted textures from clients + for (uint32_t i(0); i < RemoteClient::Client::GetCountMax(); ++i) { + RemoteClient::Client& client = RemoteClient::Client::Get(i); + client.mTextureTable.clear(); + } + + NetImguiServer::Network::Shutdown(); + NetImguiServer::UI::Shutdown(); + NetImguiServer::Config::Client::Clear(); + RemoteClient::Client::Shutdown(); + HAL_Shutdown(); +} + +//================================================================================================= +// INIT CLIENT CONFIG FROM STRING +// Take a commandline string, and create a ClientConfig from it. +// Simple format of (Hostname);(HostPort) +bool AddTransientClientConfigFromString(const char* string) +//================================================================================================= +{ + NetImguiServer::Config::Client cmdlineClient; + const char* zEntryStart = string; + const char* zEntryCur = string; + int paramIndex = 0; + cmdlineClient.mConfigType = + NetImguiServer::Config::Client::eConfigType::Transient; + NetImgui::Internal::StringCopy(cmdlineClient.mClientName, "Commandline"); + + while (*zEntryCur != 0) { + zEntryCur++; + // Skip commandline preamble holding path to executable + if (*zEntryCur == ' ' && *(zEntryCur + 1) != 0) { + zEntryStart = zEntryCur + 1; + } + if ((*zEntryCur == ';' || *zEntryCur == 0)) { + if (paramIndex == 0) + NetImgui::Internal::StringCopy(cmdlineClient.mHostName, zEntryStart, + zEntryCur - zEntryStart); + else if (paramIndex == 1) + cmdlineClient.mHostPort = static_cast(atoi(zEntryStart)); + + cmdlineClient.mConnectAuto = + paramIndex >= + 1; // Mark valid for connexion as soon as we have a HostAddress + zEntryStart = zEntryCur + 1; + paramIndex++; + } + } + + if (cmdlineClient.mConnectAuto) { + NetImguiServer::Config::Client::SetConfig(cmdlineClient); + return true; + } + + return false; +} + +//================================================================================================= +// DRAW CLIENT BACKGROUND +// Create a separate Dear ImGui drawing context, to generate a commandlist that +// will fill the RenderTarget with a specific background picture +void DrawClientBackground(RemoteClient::Client& client) +//================================================================================================= +{ + NetImgui::Internal::CmdBackground* pBGUpdate = + client.mPendingBackgroundIn.Release(); + if (pBGUpdate) { + client.mBGSettings = *pBGUpdate; + client.mBGNeedUpdate = true; + netImguiDeleteSafe(pBGUpdate); + } + + if (client.mpBGContext == nullptr) { + client.mpBGContext = ImGui::CreateContext(ImGui::GetIO().Fonts); + client.mpBGContext->IO.DeltaTime = 1 / 30.f; + client.mpBGContext->IO.IniFilename = + nullptr; // Disable server ImGui ini settings (not really needed, and + // avoid imgui.ini filename conflicts) + client.mpBGContext->IO.LogFilename = nullptr; + client.mpBGContext->IO.BackendFlags |= + ImGuiBackendFlags_RendererHasTextures; + } + + // Detect when the main font textures was updated, + // in which case we need to re-generate the BG DrawData + const ImVector& MainTextures = + ImGui::GetPlatformIO().Textures; + NetImgui::Internal::ScopedImguiContext scopedCtx(client.mpBGContext); + const ImVector& BGTextures = ImGui::GetPlatformIO().Textures; + for (ImTextureData* texData : BGTextures) { + client.mBGNeedUpdate |= MainTextures.contains(texData) == false; + } + + // Update the BG DrawData + // Note: Maybe we should try rendering it directly in client windows every + // frame instead, to keep things simpler + if (client.mBGNeedUpdate) { + ImGui::GetIO().DisplaySize = ImVec2(client.mAreaSizeX, client.mAreaSizeY); + ImGui::NewFrame(); + ImGui::SetNextWindowPos(ImVec2(0, 0)); + ImGui::SetNextWindowSize(ImVec2(client.mAreaSizeX, client.mAreaSizeY)); + ImGui::Begin("Background", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs | + ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoBackground | + ImGuiWindowFlags_NoSavedSettings); + // Look for the desired texture (and use default if not found) + auto texIt = client.mTextureTable.find(client.mBGSettings.mTextureId); + const ServerTexture* pTexture = texIt == client.mTextureTable.end() + ? UI::GetBackgroundTexture() + : texIt->second; + UI::DrawCenteredBackground(pTexture, + ImVec4(client.mBGSettings.mTextureTint[0], + client.mBGSettings.mTextureTint[1], + client.mBGSettings.mTextureTint[2], + client.mBGSettings.mTextureTint[3])); + ImGui::End(); + ImGui::Render(); + client.mBGNeedUpdate = false; + } +} + +//================================================================================================= +void UpdateServerTextures() +//================================================================================================= +{ + for (int i(gServerTextures.size() - 1); i >= 0; --i) { + if (gServerTextures[i]) { + ServerTexture& ServerTex = *gServerTextures[i]; + + // Release un-needed pixel data once it has been processed by backend + if (ServerTex.mIsUpdatable == false && + ServerTex.mTexData.Pixels != nullptr && + ServerTex.mTexData.Status == ImTextureStatus_OK) { + ServerTex.mTexData.DestroyPixels(); + } + + // Backend deleted the texture, remove it from our list + else if (ServerTex.mTexData.Status == ImTextureStatus_Destroyed) { + ImGui::UnregisterUserTexture(&ServerTex.mTexData); + delete gServerTextures[i]; + gServerTextures[i] = nullptr; + } + + // Send deletion request to backend + else if (ServerTex.mTexData.WantDestroyNextFrame) { + const RemoteClient::Client* Client = + ServerTex.mOwnerClientIndex >= 0 + ? &RemoteClient::Client::Get(ServerTex.mOwnerClientIndex) + : nullptr; + if (!Client || !Client->mpImguiDrawData || + Client->mpImguiDrawData->mFrameIndex > ServerTex.mLastFrameUsed) { + if (ServerTex.mTexData.UnusedFrames++ > 0) { + ServerTex.mTexData.Status = ImTextureStatus_WantDestroy; + } + } + } + } + + // Remove release textures (null) from our list + if (gServerTextures[i] == nullptr) { + ImSwap(gServerTextures[i], gServerTextures[gServerTextures.Size - 1]); + gServerTextures.pop_back(); + } + } +} + +//================================================================================================= +// Default texture creation behavior, relying on Dear ImGui backend to do +// the heavy lifting of texture creation and management +bool CreateTexture_Default(ServerTexture& serverTexture, + const NetImgui::Internal::CmdTexture& cmdTexture, + uint32_t customDataSize) +//================================================================================================= +{ + if (!serverTexture.mIsCustom && cmdTexture.mpTextureData.Get() != nullptr) { + serverTexture.mIsUpdatable = cmdTexture.mUpdatable; + serverTexture.mTexData.Create(ImTextureFormat::ImTextureFormat_RGBA32, + cmdTexture.mWidth, cmdTexture.mHeight); + if (cmdTexture.mFormat == ImTextureFormat::ImTextureFormat_RGBA32) { + memcpy(serverTexture.mTexData.Pixels, cmdTexture.mpTextureData.Get(), + customDataSize); + } else if (cmdTexture.mFormat == ImTextureFormat::ImTextureFormat_Alpha8) { + const uint8_t* pSrcCur = cmdTexture.mpTextureData.Get(); + uint32_t* pDestCur = + reinterpret_cast(serverTexture.mTexData.GetPixels()); + uint32_t* pDestEnd = &pDestCur[cmdTexture.mHeight * cmdTexture.mWidth]; + while (pDestCur < pDestEnd) { + *pDestCur++ = 0x00FFFFFF | (uint64_t(*pSrcCur++) << 24); + } + } else { + IM_ASSERT_USER_ERROR(0, "Unsupported format"); + } + + serverTexture.mTexData.Status = ImTextureStatus_WantCreate; + serverTexture.mTexData.UseColors = + cmdTexture.mFormat == ImTextureFormat::ImTextureFormat_RGBA32; + ImGui::RegisterUserTexture(&serverTexture.mTexData); + return true; + } + return false; +} + +//================================================================================================= +ServerTexture* CreateTexture(const NetImgui::Internal::CmdTexture& cmdTexture, + uint32_t textureDataSize) +//================================================================================================= +{ + ServerTexture* serverTex(new ServerTexture); + if (serverTex) { + serverTex->mIsCustom = + cmdTexture.mFormat == NetImgui::eTexFormat::kTexFmtCustom; + serverTex->mClientTexID = cmdTexture.mTextureClientID; + serverTex->mIsUpdatable = false; + if (CreateTexture_Custom(*serverTex, cmdTexture, textureDataSize) || + CreateTexture_Default(*serverTex, cmdTexture, textureDataSize)) { + gServerTextures.push_back(serverTex); + } else { + delete serverTex; + serverTex = NULL; + } + } + return serverTex; +} + +//================================================================================================= +// Initialize all needed fonts by the NetImguiServer application +void LoadFonts() +//================================================================================================= +{ + ImFontConfig fontConfig; + ImFontAtlas* pFontAtlas = ImGui::GetIO().Fonts; + + // Add Fonts here... + // Using a different default font (provided with Dear ImGui) + NetImgui::Internal::StringCopy(fontConfig.Name, "Roboto Medium"); + if (!pFontAtlas->AddFontFromMemoryCompressedTTF(Roboto_Medium_compressed_data, + Roboto_Medium_compressed_size, + 0.f, &fontConfig)) { + pFontAtlas->AddFontDefault(&fontConfig); + } +} + +//================================================================================================= +void UpdateWindowPlacement(int x, int y, int w, int h, bool isMaximized) +//================================================================================================= +{ + NetImguiServer::Config::Server::sWindowPlacement[0] = x; + NetImguiServer::Config::Server::sWindowPlacement[1] = y; + NetImguiServer::Config::Server::sWindowPlacement[2] = w; + NetImguiServer::Config::Server::sWindowPlacement[3] = h; + NetImguiServer::Config::Server::sWindowMaximized = isMaximized; + NetImguiServer::Config::Client::SaveAll(); +} + +//================================================================================================= +WindowPlacement GetWindowPlacement() +//================================================================================================= +{ + if (!gLoadedConfigOnce) { + NetImguiServer::Config::Client::LoadAll(); + gLoadedConfigOnce = true; + } + + WindowPlacement wp; + wp.x = NetImguiServer::Config::Server::sWindowPlacement[0]; + wp.y = NetImguiServer::Config::Server::sWindowPlacement[1]; + wp.w = ImMax(100, NetImguiServer::Config::Server::sWindowPlacement[2]); + wp.h = ImMax(100, NetImguiServer::Config::Server::sWindowPlacement[3]); + wp.isMaximized = NetImguiServer::Config::Server::sWindowMaximized; + return wp; +} +//================================================================================================= +// UPDATE REMOTE CONTENT +// Create a render target for each connected remote client once, and update it +// every frame with the last drawing commands received from it. This Render +// Target will then be used normally as the background image of each client +// window renderered by this Server +void UpdateClientDraw() +//================================================================================================= +{ + for (uint32_t i(0); i < RemoteClient::Client::GetCountMax(); ++i) { + RemoteClient::Client& client = RemoteClient::Client::Get(i); + if (client.mbIsConnected) { + if (client.mbIsReleased) { + client.Uninitialize(); + } else { + client.ProcessPendingTextureCmds(); + if (client.mbIsVisible) { + // Update the RenderTarget destination of each client, of size was + // updated + if (client.mAreaSizeX > 0 && client.mAreaSizeY > 0 && + (!client.mpHAL_AreaRT || + client.mAreaRTSizeX != client.mAreaSizeX || + client.mAreaRTSizeY != client.mAreaSizeY)) { + if (HAL_CreateRenderTarget(client.mAreaSizeX, client.mAreaSizeY, + client.mpHAL_AreaRT, + client.mHAL_AreaTexture)) { + client.mAreaRTSizeX = client.mAreaSizeX; + client.mAreaRTSizeY = client.mAreaSizeY; + client.mLastUpdateTime = + std::chrono::steady_clock::now() - + std::chrono::hours(1); // Will redraw the client + client.mBGNeedUpdate = true; + } + } + + // Render the remote results + ImDrawData* pDrawData = + client.GetImguiDrawData(gServerTextureEmpty->mTexData.GetTexID()); + if (pDrawData) { + DrawClientBackground(client); + HAL_RenderDrawData(client, pDrawData); + } + } + } + } + } + + UpdateServerTextures(); +} +} // namespace App +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_App.h b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_App.h new file mode 100644 index 00000000..cb767b87 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_App.h @@ -0,0 +1,144 @@ +// Google modifications: +// - Added #ifndef guards around HAL_API_PLATFORM_* defines so they can be +// overridden from BUILD-level defines (-D flags). +#pragma once + +#include +#include + +//============================================================================================= +// SELECT RENDERING/OS API HERE +//============================================================================================= +#ifndef HAL_API_PLATFORM_WIN32_DX11 +#define HAL_API_PLATFORM_WIN32_DX11 1 +#endif +#ifndef HAL_API_PLATFORM_GLFW_GL3 +#define HAL_API_PLATFORM_GLFW_GL3 0 // Note: Currently doesn't work on VS2026 +#endif +#ifndef HAL_API_PLATFORM_SOKOL +#define HAL_API_PLATFORM_SOKOL \ + 0 // Sokol Lib needs to be updated to latest Dear ImGui 1.92 support for this + // to work +#endif +#define HAL_API_RENDERTARGET_INVERT_Y \ + (HAL_API_PLATFORM_GLFW_GL3 || \ + HAL_API_PLATFORM_SOKOL) // Invert client render target Y axis (since OpenGL + // start texture UV from BottomLeft instead of + // DirectX TopLeft) +//============================================================================================= + +// Forward declare +namespace NetImguiServer { +namespace RemoteClient { +struct Client; +} +} // namespace NetImguiServer +namespace NetImgui { +namespace Internal { +struct CmdTexture; +} +} // namespace NetImgui + +namespace NetImguiServer { +namespace App { +struct WindowPlacement { + int x = 0; + int y = 0; + int w = 0; + int h = 0; + bool isMaximized = false; +}; + +//============================================================================================= +// Code specific to 'NetImgui Server' application and needed inside platform +// specific code +//============================================================================================= +// Additional initialisation needed by 'NetImGui Server' and not part of default +// ImGui sample code +bool Startup(const char* CmdLine); +// Prepare for shutdown of application +void Shutdown(); +// Receive rendering request of each Remote client and output it to their own +// RenderTarget +void UpdateClientDraw(); +// Save server window placement (to restore it on next start) +void UpdateWindowPlacement(int x, int y, int w, int h, bool isMaximized); +// Get last server window placement +WindowPlacement GetWindowPlacement(); +// Add a new remote client config to our list (to attempt connexion) +bool AddTransientClientConfigFromString(const char* string); +// Initialize the font atlas used by the Serve +void LoadFonts(); + +// Descriptor of each textures by Server. Format always RGBA8 +struct ServerTexture { + inline ServerTexture() { + mTexData.Status = ImTextureStatus_Destroyed; + mTexData.RefCount = 1; + } + inline bool IsValid() const { + return mTexData.Status != ImTextureStatus_WantCreate && + mTexData.Status != ImTextureStatus_Destroyed; + } + inline void MarkForDelete() { + mTexData.WantDestroyNextFrame = true; + mTexData.UnusedFrames = 0; + } + ImTextureData mTexData; // Struct used by backend for texture support + ImTextureID mClientTexID; // Client UserID associated with this texture + uint64_t mCustomData = 0u; // Memory available to custom command + uint64_t mLastFrameUsed = 0u; // Last draw frame this texture was used + // (needed for resources release) + int32_t mOwnerClientIndex = -1; // Client that created this texture (if any) + uint8_t mIsCustom = 0u; // Format handled by custom version of NetImguiServer + // modified by library user + uint8_t mIsUpdatable = 0u; // True when textures can be updated (font) + uint8_t mPadding[6] = {}; +}; + +//============================================================================================= +// Handling of texture data +//============================================================================================= +ServerTexture* CreateTexture(const NetImgui::Internal::CmdTexture& cmdTexture, + uint32_t customDataSize); + +// Library users can implement their own texture format (on client/server). +// Useful for vidoe streaming, new format, etc. +bool CreateTexture_Custom(ServerTexture& serverTexture, + const NetImgui::Internal::CmdTexture& cmdTexture, + uint32_t customDataSize); +bool DestroyTexture_Custom(ServerTexture& serverTexture, + const NetImgui::Internal::CmdTexture& cmdTexture, + uint32_t customDataSize); + +//============================================================================================= +// Note (H)ardware (A)bstraction (L)ayer +// When porting the 'NetImgui Server' application to other +//platform, theses are the few functions needed to be supported by each specific +//API that are not already supported by de 'Dear ImGui' provided backends +//============================================================================================= +// Additional initialisation that are platform specific +bool HAL_Startup(const char* CmdLine); +// Prepare for shutdown of application, with platform specific code +void HAL_Shutdown(); +// Receive a platform specific socket, and return us with info on the connection +bool HAL_GetSocketInfo(NetImgui::Internal::Network::SocketInfo* pClientSocket, + char* pOutHostname, size_t HostNameLen, int& outPort); +// Provide the current user setting folder (used to save the shared config file) +const char* HAL_GetUserSettingFolder(); +// Return true when new content should be retrieved from Clipboard (avoid +// constantly reading/converting content) +bool HAL_GetClipboardUpdated(); +// Receive a ImDrawData drawlist and render it to backbuffer +void HAL_RenderDrawData(ImDrawData* pDrawData); +// Receive a ImDrawData drawlist and request Dear ImGui's backend to output it +// into a texture +void HAL_RenderDrawData(RemoteClient::Client& client, ImDrawData* pDrawData); +// Allocate a RenderTarget that each client will use to output their ImGui +// drawing into. +bool HAL_CreateRenderTarget(uint16_t Width, uint16_t Height, void*& pOutRT, + ImTextureData& OutTexture); +// Free a RenderTarget resource +void HAL_DestroyRenderTarget(void*& pOutRT, ImTextureData& OutTexture); +} // namespace App +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Config.cpp b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Config.cpp new file mode 100644 index 00000000..c61b1b73 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Config.cpp @@ -0,0 +1,441 @@ +// Google modifications: +// - Updated nlohmann/json include path for Google third_party layout. +#include "NetImguiServer_Config.h" + +#include + +#include +#include +#include + +#include "NetImguiServer_RemoteClient.h" + +namespace NetImguiServer { +namespace Config { + +static ImVector gConfigList; +static std::mutex gConfigLock; +static Client::RuntimeID gRuntimeID = static_cast(1); + +static constexpr char kConfigField_ServerPort[] = "ServerPort"; +static constexpr char kConfigField_ServerRefreshActive[] = "RefreshFPSActive"; +static constexpr char kConfigField_ServerRefreshInactive[] = + "RefreshFPSInactive"; +static constexpr char kConfigField_ServerDPIScaleRatio[] = "DPIScaleRatio"; +static constexpr char kConfigField_ServerCompressionEnable[] = + "CompressionEnable"; +static constexpr char kConfigField_ServerFontSize[] = "ServerFontSize"; +static constexpr char kConfigField_ServerWindowPlacementX[] = + "ServerWindowPlacementX"; +static constexpr char kConfigField_ServerWindowPlacementY[] = + "ServerWindowPlacementY"; +static constexpr char kConfigField_ServerWindowPlacementW[] = + "ServerWindowPlacementW"; +static constexpr char kConfigField_ServerWindowPlacementH[] = + "ServerWindowPlacementH"; +static constexpr char kConfigField_ServerWindowMaximized[] = + "ServerWindowMaximized"; + +static constexpr char kConfigField_Note[] = "Note"; +static constexpr char kConfigField_Version[] = "Version"; +static constexpr char kConfigField_Configs[] = "Configs"; +static constexpr char kConfigField_Name[] = "Name"; +static constexpr char kConfigField_Hostname[] = "Hostname"; +static constexpr char kConfigField_Hostport[] = "HostPort"; +static constexpr char kConfigField_AutoConnect[] = "Auto"; +static constexpr char kConfigField_BlockTakeover[] = "BlockTakeover"; +static constexpr char kConfigField_DPIScaleEnabled[] = "DPIScaleEnabled"; + +uint32_t Server::sPort = NetImgui::kDefaultServerPort; +float Server::sRefreshFPSActive = 30.f; +float Server::sRefreshFPSInactive = 30.f; +float Server::sDPIScaleRatio = 1.f; +bool Server::sCompressionEnable = true; +float Server::sFontSize = 16.f; +int Server::sWindowPlacement[4] = {100, 100, 1280, 1024}; +bool Server::sWindowMaximized = false; + +//================================================================================================= +// The user config is created when the main config file is readonly +// Allows having a distributed config file that cannot be touched by users +static const char* GetConfigFilename(Client::eConfigType configFileType) +//================================================================================================= +{ + if (configFileType == Client::eConfigType::Local) { + return "netImgui.cfg"; + } else if (configFileType == Client::eConfigType::Local2nd) { + return "netImgui_2.cfg"; + } else { + static char sUserSettingFile[1024]; + const char* userSettingFolder = + NetImguiServer::App::HAL_GetUserSettingFolder(); + NetImgui::Internal::StringFormat( + sUserSettingFile, + (userSettingFolder ? "%s\\netImgui.cfg" : "netImgui_2.cfg"), + userSettingFolder); + return sUserSettingFile; + } +} + +//================================================================================================= +// Find entry index with same configId. (-1 if not found) +// Note: 'gConfigLock' should have already locked before calling this +static int FindClientIndex(uint32_t configID) +//================================================================================================= +{ + if (configID != Client::kInvalidRuntimeID) { + for (int i(0); i < gConfigList.size(); ++i) { + if (gConfigList[i] && gConfigList[i]->mRuntimeID == configID) return i; + } + } + return -1; +} + +//================================================================================================= +template +TType GetPropertyValue(const nlohmann::json& config, const char* zPropertyName, + const TType& valueDefault) +//================================================================================================= +{ + const auto& valueNode = config.find(zPropertyName); + return valueNode != config.end() ? valueNode->get() : valueDefault; +} + +//================================================================================================= +Client::Client() + //================================================================================================= + : mHostPort(NetImgui::kDefaultClientPort), + mRuntimeID(kInvalidRuntimeID), + mConfigType(NetImguiServer::Config::Client::eConfigType::Pending), + mDPIScaleEnabled(true), + mBlockTakeover(false), + mReadOnly(false), + mConnectAuto(false), + mConnectRequest(false), + mConnectForce(false), + mConnectStatus(eStatus::Disconnected) { + NetImgui::Internal::StringCopy(mClientName, "New Client"); + NetImgui::Internal::StringCopy(mHostName, "localhost"); +} + +//================================================================================================= +void Client::SetConfig(const Client& config) +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + + // Only allow 1 transient connection to keep things clean + for (int i = 0; config.IsTransient() && i < gConfigList.size(); ++i) { + if (gConfigList[i] && gConfigList[i]->IsTransient()) { + NetImgui::Internal::netImguiDelete(gConfigList[i]); + gConfigList.erase(&gConfigList[i]); + } + } + + int index = FindClientIndex(config.mRuntimeID); + // Config not found, add it to our list + if (index == -1) { + index = gConfigList.size(); + gConfigList.push_back( + NetImgui::Internal::netImguiNew()); + } + + // Update the entry + *gConfigList[index] = config; + gConfigList[index]->mRuntimeID = + (config.mRuntimeID == kInvalidRuntimeID ? gRuntimeID++ + : config.mRuntimeID); +} + +//================================================================================================= +void Client::DelConfig(uint32_t configID) +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + int index = FindClientIndex(configID); + if (index != -1) { + NetImgui::Internal::netImguiDelete(gConfigList[index]); + gConfigList.erase(&gConfigList[index]); + } +} + +//================================================================================================= +bool Client::GetConfigByID(uint32_t configID, Client& config) +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + int index = FindClientIndex(configID); + if (index != -1) { + config = *gConfigList[index]; + return true; + } + return false; +} + +//================================================================================================= +bool Client::GetConfigByIndex(uint32_t index, Client& config) +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + if (index < static_cast(gConfigList.size())) { + config = *gConfigList[index]; + return true; + } + return false; +} + +//================================================================================================= +uint32_t Client::GetConfigCount() +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + return gConfigList.size(); +} + +//================================================================================================= +bool Client::GetProperty_BlockTakeover(uint32_t configID) +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + int index = FindClientIndex(configID); + if (index != -1) { + return gConfigList[index]->mBlockTakeover; + } + return false; +} + +//================================================================================================= +void Client::SetProperty_Status(uint32_t configID, eStatus Status) +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + int index = FindClientIndex(configID); + if (index != -1) { + gConfigList[index]->mConnectStatus = Status; + } +} + +//================================================================================================= +void Client::SetProperty_ConnectAuto(uint32_t configID, bool value) +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + int index = FindClientIndex(configID); + if (index != -1) { + gConfigList[index]->mConnectAuto = value; + } +} + +//================================================================================================= +void Client::SetProperty_ConnectRequest(uint32_t configID, bool value, + bool force) +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + int index = FindClientIndex(configID); + if (index != -1) { + gConfigList[index]->mConnectRequest = value && !force; + gConfigList[index]->mConnectForce = value && force; + gConfigList[index]->mConnectLastTime = std::chrono::steady_clock::now(); + } +} + +//================================================================================================= +bool Client::ShouldSave(eConfigType fileConfigType) const +//================================================================================================= +{ + return mConfigType == fileConfigType || mConfigType == eConfigType::Pending; +} + +//================================================================================================= +void Client::SaveAll() +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + std::ofstream localFile(GetConfigFilename(eConfigType::Local)); + bool localIsWritable = localFile.is_open(); + localFile.close(); + + std::ifstream local2ndFileExist(GetConfigFilename(eConfigType::Local2nd)); + bool local2ndExist = local2ndFileExist.is_open(); + bool local2ndIsWritable = false; + local2ndFileExist.close(); + + // Try saving into default config file + SaveConfigFile(eConfigType::Local, localIsWritable); + // And then in 2nd workingdir user file when 1st one is read only + if (!localIsWritable || local2ndExist) { + std::ofstream local2ndFile(GetConfigFilename(eConfigType::Local2nd)); + SaveConfigFile(eConfigType::Local2nd, + !localIsWritable && local2ndIsWritable); + } + + // Finally saved the shared config into user folder + SaveConfigFile(eConfigType::Shared, !localIsWritable && !local2ndIsWritable); +} + +//================================================================================================= +void Client::SaveConfigFile(eConfigType configFileType, + bool writeServerSettings) +//================================================================================================= +{ + nlohmann::json configRoot; + configRoot[kConfigField_Version] = eVersion::_Latest; + configRoot[kConfigField_Note] = + configFileType == eConfigType::Local + ? "NetImgui Server's list of Clients (Using JSON format) Local File." + : configFileType == eConfigType::Local + ? "NetImgui Server's list of Clients (Using JSON format) 2nd Local " + "File." + : "NetImgui Server's list of Clients (Using JSON format) Shared " + "File."; + if (writeServerSettings) { + configRoot[kConfigField_ServerPort] = Server::sPort; + configRoot[kConfigField_ServerRefreshActive] = Server::sRefreshFPSActive; + configRoot[kConfigField_ServerRefreshInactive] = + Server::sRefreshFPSInactive; + configRoot[kConfigField_ServerDPIScaleRatio] = Server::sDPIScaleRatio; + configRoot[kConfigField_ServerCompressionEnable] = + Server::sCompressionEnable; + configRoot[kConfigField_ServerFontSize] = Server::sFontSize; + configRoot[kConfigField_ServerWindowPlacementX] = + Server::sWindowPlacement[0]; + configRoot[kConfigField_ServerWindowPlacementY] = + Server::sWindowPlacement[1]; + configRoot[kConfigField_ServerWindowPlacementW] = + Server::sWindowPlacement[2]; + configRoot[kConfigField_ServerWindowPlacementH] = + Server::sWindowPlacement[3]; + configRoot[kConfigField_ServerWindowMaximized] = Server::sWindowMaximized; + } + + int clientToSaveCount(0); + for (int i(0); i < gConfigList.size(); ++i) { + Client* pConfig = gConfigList[i]; + if (pConfig && pConfig->ShouldSave(configFileType)) { + auto& config = configRoot[kConfigField_Configs][clientToSaveCount++] = + nullptr; + config[kConfigField_Name] = pConfig->mClientName; + config[kConfigField_Hostname] = pConfig->mHostName; + config[kConfigField_Hostport] = pConfig->mHostPort; + config[kConfigField_AutoConnect] = pConfig->mConnectAuto; + config[kConfigField_BlockTakeover] = pConfig->mBlockTakeover; + config[kConfigField_DPIScaleEnabled] = pConfig->mDPIScaleEnabled; + } + } + + std::ofstream outputFile(GetConfigFilename(configFileType)); + if (outputFile.is_open()) { + outputFile << configRoot.dump(4); + for (int i(0); clientToSaveCount > 0 && i < gConfigList.size(); ++i) { + Client* pConfig = gConfigList[i]; + if (pConfig && pConfig->ShouldSave(configFileType)) { + pConfig->mReadOnly = false; + pConfig->mConfigType = configFileType; + } + } + } +} + +//================================================================================================= +void Client::LoadAll() +//================================================================================================= +{ + Clear(); + std::lock_guard guard(gConfigLock); + LoadConfigFile(eConfigType::Local); + LoadConfigFile(eConfigType::Local2nd); + LoadConfigFile(eConfigType::Shared); +} + +//================================================================================================= +void Client::LoadConfigFile(eConfigType configFileType) +//================================================================================================= +{ + nlohmann::json configRoot; + const char* filename = GetConfigFilename(configFileType); + std::ifstream inputFile(filename); + if (!inputFile.is_open() || inputFile.eof()) return; + + configRoot = nlohmann::json::parse(inputFile, nullptr, false); + inputFile.close(); + + std::ofstream outputFile(filename, std::ios_base::app); + bool isWritable = outputFile.is_open() && !outputFile.eof(); + outputFile.close(); + + uint32_t configVersion = + GetPropertyValue(configRoot, kConfigField_Version, 0u); + Server::sPort = GetPropertyValue(configRoot, kConfigField_ServerPort, + NetImgui::kDefaultServerPort); + Server::sRefreshFPSActive = GetPropertyValue( + configRoot, kConfigField_ServerRefreshActive, Server::sRefreshFPSActive); + Server::sRefreshFPSInactive = + GetPropertyValue(configRoot, kConfigField_ServerRefreshInactive, + Server::sRefreshFPSInactive); + Server::sDPIScaleRatio = GetPropertyValue( + configRoot, kConfigField_ServerDPIScaleRatio, Server::sDPIScaleRatio); + Server::sCompressionEnable = + GetPropertyValue(configRoot, kConfigField_ServerCompressionEnable, + Server::sCompressionEnable); + Server::sFontSize = GetPropertyValue(configRoot, kConfigField_ServerFontSize, + Server::sFontSize); + Server::sWindowPlacement[0] = + GetPropertyValue(configRoot, kConfigField_ServerWindowPlacementX, + Server::sWindowPlacement[0]); + Server::sWindowPlacement[1] = + GetPropertyValue(configRoot, kConfigField_ServerWindowPlacementY, + Server::sWindowPlacement[1]); + Server::sWindowPlacement[2] = + GetPropertyValue(configRoot, kConfigField_ServerWindowPlacementW, + Server::sWindowPlacement[2]); + Server::sWindowPlacement[3] = + GetPropertyValue(configRoot, kConfigField_ServerWindowPlacementH, + Server::sWindowPlacement[3]); + Server::sWindowMaximized = GetPropertyValue( + configRoot, kConfigField_ServerWindowMaximized, Server::sWindowMaximized); + + if (configVersion >= static_cast(eVersion::Initial)) { + for (const auto& config : configRoot[kConfigField_Configs]) { + gConfigList.push_back( + NetImgui::Internal::netImguiNew()); + Client* pConfig = gConfigList.back(); + pConfig->mRuntimeID = gRuntimeID++; + + if (config.find(kConfigField_Name) != config.end()) + NetImgui::Internal::StringCopy( + pConfig->mClientName, + config[kConfigField_Name].get().c_str()); + + if (config.find(kConfigField_Hostname) != config.end()) + NetImgui::Internal::StringCopy( + pConfig->mHostName, + config[kConfigField_Hostname].get().c_str()); + + pConfig->mHostPort = + GetPropertyValue(config, kConfigField_Hostport, pConfig->mHostPort); + pConfig->mConnectAuto = GetPropertyValue(config, kConfigField_AutoConnect, + pConfig->mConnectAuto); + pConfig->mDPIScaleEnabled = GetPropertyValue( + config, kConfigField_DPIScaleEnabled, pConfig->mDPIScaleEnabled); + pConfig->mBlockTakeover = GetPropertyValue( + config, kConfigField_BlockTakeover, pConfig->mBlockTakeover); + pConfig->mConfigType = configFileType; + pConfig->mReadOnly = !isWritable; + } + } +} + +//================================================================================================= +void Client::Clear() +//================================================================================================= +{ + std::lock_guard guard(gConfigLock); + while (gConfigList.size()) { + NetImgui::Internal::netImguiDelete(gConfigList.back()); + gConfigList.pop_back(); + } +} + +} // namespace Config +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Config.h b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Config.h new file mode 100644 index 00000000..30dee020 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Config.h @@ -0,0 +1,160 @@ +// Google modifications: +// - Added #include for std::chrono::steady_clock::time_point + +#pragma once + +#include +#include + +namespace NetImguiServer { +namespace Config { + +//================================================================================================= +// Client Configs are used by this server to reach remote netImgui Clients. +// +// Note:For multihreading safety, we are always working with copies of the +// original data. +// +// Note:It is also possible for a remote netImgui client to connect to Server +// directly, +// in which case they don't need to have an associated config. +//================================================================================================= +class Client { + public: + using RuntimeID = uint32_t; + using TimeStamp = std::chrono::steady_clock::time_point; + static constexpr RuntimeID kInvalidRuntimeID = static_cast(0); + + enum class eVersion : uint32_t { + Initial = 1, // First version save file deployed + Refresh = 2, // Added refresh rate support + DPIScale = 3, // Added DPI scaling + BlockTakeOver = 4, // Added Takeover Block + WindowPlacement = 5, // Added saving of main window location and size + _Count, + _Latest = _Count - 1 + }; + enum class eConfigType : uint8_t { + Pending, // New config, will try saving it in the local config + Local, // Config fetched from local config file, in the current working + // directory + Local2nd, // Config fetched from a second local config file, in the current + // working directory. Used when 'Local' file is read only + Shared, // Config fetched from the shared user folder + Transient, // Config created from connection request (command line, OS + // pipes), cannot be saved + }; + enum class eStatus : uint8_t { + Disconnected, // No connection detected on client + Connecting, // This server is connecting to client + Connected, // This server is connect to client + Available, // Client already taken, but this server can take over + ErrorBusy, // Client already taken + ErrorVer, // Server/Client network api mismatch + }; + + // Config settings + char mClientName[128]; //!< Client display name + char mHostName[128]; //!< Client IP or remote host address to attempt + //!< connection at + uint32_t mHostPort; //!< Client Port to attempt connection at + RuntimeID mRuntimeID; //!< Unique RuntimeID used to find this Config + eConfigType mConfigType; //!< Type of the configuration + bool mDPIScaleEnabled; //!< Enable support of Font DPI scaling requests by + //!< Server + bool mBlockTakeover; //!< If another NetImguiServer is allowed to forcefully + //!< disconnect this client to connect to it + bool mReadOnly; //!< Config comes from read only file, can't be modified + bool mConnectAuto; //!< Try automatically connecting to client + + // Transient values used while running + mutable bool + mConnectRequest; //!< Attempt connecting to Client, after user request + mutable bool mConnectForce; //!< Attempt connecting to Client, after user + //!< request, even if already connected + mutable eStatus mConnectStatus; //!< Connection status of associated client + mutable TimeStamp mConnectLastTime; //!< Last connection attempt time (avoid + //!< quickly retrying same client) + + // Access methods + public: + Client(); + + inline bool IsReadOnly() const { return mReadOnly; }; + inline bool IsTransient() const { + return mConfigType == eConfigType::Transient; + }; + inline bool IsConnected() const { + return mConnectStatus == eStatus::Connected; + } + inline bool IsConnecting() const { + return mConnectStatus == eStatus::Connecting || mConnectRequest || + mConnectForce; + } + inline bool IsConnectReady() const { + bool bAvailable = mConnectStatus != eStatus::Connected && + mConnectStatus != eStatus::Connecting; + return bAvailable && (mConnectRequest || mConnectForce); + } + inline bool IsAutoConnectReady() const { + bool bAvailable = mConnectStatus != eStatus::Connected && + mConnectStatus != eStatus::Connecting; + auto elapsedTime = std::chrono::steady_clock::now() - mConnectLastTime; + int durationSec = static_cast( + std::chrono::duration_cast(elapsedTime).count()); + bool elapseOk = + durationSec > (mConnectStatus == eStatus::Disconnected ? 5 : 30); + return bAvailable && mConnectAuto && elapseOk; + } + + // Add/Edit/Remove config + static void SetConfig( + const Client& config); //!< Add or replace a client configuration info + static void DelConfig(uint32_t configID); //!< Remove a client configuration + static bool GetConfigByID( + uint32_t configID, + Client& outConfig); //!< Find client configuration with this id (return + //!< true if found) + static bool GetConfigByIndex( + uint32_t index, + Client& outConfig); //!< Find client configuration at the x position + static uint32_t GetConfigCount(); + + // Set property value directly (without having to copy entire structure) + static bool GetProperty_BlockTakeover(uint32_t configID); + static void SetProperty_Status(uint32_t configID, eStatus Status); + static void SetProperty_ConnectAuto(uint32_t configID, bool value); + static void SetProperty_ConnectRequest(uint32_t configID, bool value, + bool force); + + // Client Config list management + static void SaveAll(); + static void LoadAll(); + static void Clear(); + + protected: + static void SaveConfigFile(eConfigType fileConfigType, + bool writeServerSettings); + static void LoadConfigFile(eConfigType fileConfigType); + inline bool ShouldSave(eConfigType fileConfigType) const; +}; + +struct Server { + static uint32_t sPort; //!< Port that Server should use for connection. + //!< (Note: not really a 'Client' setting, but easier + //!< to just bundle the value here for the moment) + static float sRefreshFPSActive; //!< Refresh rate of active Window + static float sRefreshFPSInactive; //!< Refresh rate of inactive Window + static float + sDPIScaleRatio; //!< Ratio of DPI scale applied to Font size (helps with + //!< high resolution monitor, default 1.0) + static bool sCompressionEnable; //!< Ask the clients to compress their data + //!< before transmission + static float sFontSize; //!< Font size used for Server UI + static int sWindowPlacement[4]; //!< Main window position and size + //!< (x,y,width,height) + static bool sWindowMaximized; +}; + +} // namespace Config +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Network.cpp b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Network.cpp new file mode 100644 index 00000000..5828433f --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Network.cpp @@ -0,0 +1,577 @@ +#include "NetImguiServer_Network.h" + +#include +#include + +#include + +#include "NetImguiServer_App.h" +#include "NetImguiServer_Config.h" +#include "NetImguiServer_RemoteClient.h" +#include "Private/NetImgui_WarningDisableStd.h" + +using namespace NetImgui::Internal; + +namespace NetImguiServer { +namespace Network { +using atomic_SocketInfo = std::atomic<::Network::SocketInfo*>; +static bool gbShutdown(false); // Set to true when NetImguiServer exiting +static atomic_SocketInfo gListenSocket( + nullptr); // Need global access to kill socket on shutdown +static std::atomic_uint32_t gActiveClientThreadCount( + 0); // How many active client connection currently running +static std::atomic_bool gActiveThreadConnectOut( + false); // True while Server is still trying to connect to new clients +static std::atomic_bool gActiveThreadConnectIn( + false); // True while Server is still trying to receive connection from new + // clients +static std::atomic_uint64_t gStatsDataSent(0); +static std::atomic_uint64_t gStatsDataRcvd(0); + +//================================================================================================= +// (IN) COMMAND TEXTURE +//================================================================================================= +void Communications_Incoming_CmdTexture(RemoteClient::Client& Client) { + auto pCmdTexture = reinterpret_cast( + Client.mPendingRcv.pCommand); + Client.mPendingRcv.bAutoFree = false; // Taking ownership of the data + pCmdTexture->mpTextureData.ToPointer(); + + // For debug tracking + uint32_t idx = + Client.mTextureHistoryIndex % IM_ARRAYSIZE(Client.mTextureHistory); + Client.mTextureHistory[idx].UpdateId = Client.mTextureHistoryIndex++; + Client.mTextureHistory[idx].Frame = Client.mLastDrawFrameIndex; + Client.mTextureHistory[idx].ClientId = pCmdTexture->mTextureClientID; + Client.mTextureHistory[idx].Format = pCmdTexture->mFormat; + Client.mTextureHistory[idx].isCreate = + pCmdTexture->mStatus == CmdTexture::eType::Create; + Client.mTextureHistory[idx].isDestroy = + pCmdTexture->mStatus == CmdTexture::eType::Destroy; + Client.mTextureHistory[idx].isUpdate = + pCmdTexture->mStatus == CmdTexture::eType::Update; + Client.mTextureHistory[idx].isDearImguiManaged = + pCmdTexture->mIsDearImGuiManaged != 0; + Client.mTextureHistory[idx].x = pCmdTexture->mOffsetX; + Client.mTextureHistory[idx].y = pCmdTexture->mOffsetY; + Client.mTextureHistory[idx].w = pCmdTexture->mWidth; + Client.mTextureHistory[idx].h = pCmdTexture->mHeight; + Client.ReceiveTexture(pCmdTexture); +} + +//================================================================================================= +// (IN) COMMAND BACKGROUND +//================================================================================================= +void Communications_Incoming_CmdBackground(RemoteClient::Client& Client) { + auto pCmdBackground = reinterpret_cast( + Client.mPendingRcv.pCommand); + Client.mPendingRcv.bAutoFree = false; // Taking ownership of the data + Client.mPendingBackgroundIn.Assign(pCmdBackground); +} + +//================================================================================================= +// (IN) COMMAND DRAW FRAME +//================================================================================================= +void Communications_Incoming_CmdDrawFrame(RemoteClient::Client& Client) { + auto pCmdDraw = reinterpret_cast( + Client.mPendingRcv.pCommand); + Client.mPendingRcv.bAutoFree = false; // Taking ownership of the data + pCmdDraw->ToPointers(); + Client.ReceiveDrawFrame(pCmdDraw); +} + +//================================================================================================= +// (IN) COMMAND CLIPBOARD +//================================================================================================= +void Communications_Incoming_CmdClipboard(RemoteClient::Client& Client) { + auto pCmdClipboard = reinterpret_cast( + Client.mPendingRcv.pCommand); + Client.mPendingRcv.bAutoFree = false; // Taking ownership of the data + pCmdClipboard->ToPointers(); + Client.mPendingClipboardIn.Assign(pCmdClipboard); +} + +//================================================================================================= +// Receive every commands sent by remote client and process them +//================================================================================================= +void Communications_Incoming(RemoteClient::Client& Client) { + if (::Network::DataReceivePending(Client.mpSocket)) { + //----------------------------------------------------------------------------------------- + // 1. Ready to receive new command, starts the process by reading Header + //----------------------------------------------------------------------------------------- + if (Client.mPendingRcv.IsReady()) { + Client.mCmdPendingRead = NetImgui::Internal::CmdPendingRead(); + Client.mPendingRcv.pCommand = &Client.mCmdPendingRead; + Client.mPendingRcv.bAutoFree = false; + } + + //----------------------------------------------------------------------------------------- + // 2. Read incoming command from server + //----------------------------------------------------------------------------------------- + if (Client.mPendingRcv.IsPending()) { + ::Network::DataReceive(Client.mpSocket, Client.mPendingRcv); + + // Detected a new command bigger than header, allocate memory for it + if (Client.mPendingRcv.pCommand->mSize > + sizeof(NetImgui::Internal::CmdPendingRead) && + Client.mPendingRcv.pCommand == &Client.mCmdPendingRead) { + CmdPendingRead* pCmdHeader = + reinterpret_cast( + netImguiSizedNew(Client.mPendingRcv.pCommand->mSize)); + *pCmdHeader = Client.mCmdPendingRead; + Client.mPendingRcv.pCommand = pCmdHeader; + Client.mPendingRcv.bAutoFree = true; + } + } + + //----------------------------------------------------------------------------------------- + // 3. Command fully received from Server, process it + //----------------------------------------------------------------------------------------- + if (Client.mPendingRcv.IsDone()) { + if (!Client.mPendingRcv.IsError()) { + Client.mStatsDataRcvd += Client.mPendingRcv.pCommand->mSize; + Client.mLastIncomingComTime = std::chrono::steady_clock::now(); + switch (Client.mPendingRcv.pCommand->mType) { + case NetImgui::Internal::CmdHeader::eCommands::Texture: + Communications_Incoming_CmdTexture(Client); + break; + case NetImgui::Internal::CmdHeader::eCommands::Background: + Communications_Incoming_CmdBackground(Client); + break; + case NetImgui::Internal::CmdHeader::eCommands::DrawFrame: + Communications_Incoming_CmdDrawFrame(Client); + break; + case NetImgui::Internal::CmdHeader::eCommands::Clipboard: + Communications_Incoming_CmdClipboard(Client); + break; + // Commands not received in main loop, by Server + case NetImgui::Internal::CmdHeader::eCommands::Version: + case NetImgui::Internal::CmdHeader::eCommands::Input: + case NetImgui::Internal::CmdHeader::eCommands::Count: + break; + } + } + + // Reset pending read + if (Client.mPendingRcv.IsError()) { + Client.mbDisconnectPending = true; + } + if (Client.mPendingRcv.bAutoFree) { + netImguiDeleteSafe(Client.mPendingRcv.pCommand); + } + Client.mPendingRcv = PendingCom(); + } + } + // Prevent high CPU usage when waiting for new data + else { + // std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::microseconds(250)); + } +} + +//================================================================================================= +// Send the updates to RemoteClient +// Ends with a Ping Command (signal a end of commands) +//================================================================================================= +void Communications_Outgoing(RemoteClient::Client& Client) { + //--------------------------------------------------------------------------------------------- + // Try finishing sending a pending command to Server + //--------------------------------------------------------------------------------------------- + if (Client.mPendingSend.IsPending()) { + ::Network::DataSend(Client.mpSocket, Client.mPendingSend); + + // Free allocated memory for command + if (Client.mPendingSend.IsDone()) { + if (Client.mPendingSend.IsError()) { + Client.mbDisconnectPending = true; + } + Client.mStatsDataSent += Client.mPendingSend.pCommand->mSize; + if (Client.mPendingSend.bAutoFree) { + netImguiDeleteSafe(Client.mPendingSend.pCommand); + } + Client.mPendingSend = PendingCom(); + } + } + + if (Client.mPendingSend.IsReady()) { + NetImgui::Internal::CmdClipboard* pClipboardCmd = + Client.TakePendingClipboard(); + if (pClipboardCmd) { + pClipboardCmd->ToOffsets(); + Client.mPendingSend.pCommand = pClipboardCmd; + Client.mPendingSend.bAutoFree = true; + } + } + + if (Client.mPendingSend.IsReady()) { + NetImgui::Internal::CmdInput* pInputCmd = Client.TakePendingInput(); + Client.mPendingSend.pCommand = pInputCmd; + Client.mPendingSend.bAutoFree = true; + } +} + +//================================================================================================= +// Update communications stats of a client, after a frame +//================================================================================================= +void Communications_UpdateClientStats(RemoteClient::Client& Client) { + // Update data transfer stats + auto elapsedTime = std::chrono::steady_clock::now() - Client.mStatsTime; + if (std::chrono::duration_cast(elapsedTime) + .count() >= 250) { + constexpr uint64_t kHysteresis = 10; // out of 100 + uint64_t newDataRcvd = Client.mStatsDataRcvd - Client.mStatsDataRcvdPrev; + uint64_t newDataSent = Client.mStatsDataSent - Client.mStatsDataSentPrev; + uint64_t tmMicrosS = + std::chrono::duration_cast(elapsedTime) + .count(); + uint32_t newDataRcvdBps = + static_cast(newDataRcvd * 1000000u / tmMicrosS); + uint32_t newDataSentBps = + static_cast(newDataSent * 1000000u / tmMicrosS); + Client.mStatsRcvdBps = (Client.mStatsRcvdBps * (100u - kHysteresis) + + newDataRcvdBps * kHysteresis) / + 100u; + Client.mStatsSentBps = (Client.mStatsSentBps * (100u - kHysteresis) + + newDataSentBps * kHysteresis) / + 100u; + gStatsDataRcvd += newDataRcvd; + gStatsDataSent += newDataSent; + + Client.mStatsTime = std::chrono::steady_clock::now(); + Client.mStatsDataRcvdPrev = Client.mStatsDataRcvd; + Client.mStatsDataSentPrev = Client.mStatsDataSent; + } +} + +//================================================================================================= +// Keep sending/receiving commands to Remote Client, until disconnection occurs +//================================================================================================= +void Communications_ClientExchangeLoop(RemoteClient::Client* pClient) { + gActiveClientThreadCount++; + + NetImguiServer::Config::Client::SetProperty_Status( + pClient->mClientConfigID, + NetImguiServer::Config::Client::eStatus::Connected); + pClient->mbDisconnectPending = false; + pClient->mbIsConnected = true; + while (!gbShutdown && !pClient->mbDisconnectPending) { + Communications_Outgoing(*pClient); + Communications_Incoming(*pClient); + Communications_UpdateClientStats(*pClient); + } + NetImguiServer::Config::Client::SetProperty_Status( + pClient->mClientConfigID, + NetImguiServer::Config::Client::eStatus::Disconnected); + NetImgui::Internal::Network::Disconnect(pClient->mpSocket); + pClient->Release(); + gActiveClientThreadCount--; +} + +//================================================================================================= +// Establish connection with Remote Client +// Makes sure that Server/Client are compatible +//================================================================================================= +bool Communications_InitializeClient( + NetImgui::Internal::Network::SocketInfo* pClientSocket, + RemoteClient::Client* pClient, bool ConnectForce) { + NetImgui::Internal::CmdVersion cmdVersionSend, cmdVersionRcv; + NetImgui::Internal::PendingCom PendingRcv, PendingSend; + + //--------------------------------------------------------------------- + // Handshake confirming connection validity + //--------------------------------------------------------------------- + NetImgui::Internal::StringCopy(cmdVersionSend.mClientName, "Server"); + const bool ConnectExclusive = + NetImguiServer::Config::Client::GetProperty_BlockTakeover( + pClient->mClientConfigID); + cmdVersionSend.mFlags |= + ConnectExclusive + ? static_cast( + NetImgui::Internal::CmdVersion::eFlags::ConnectExclusive) + : 0; + cmdVersionSend.mFlags |= + ConnectForce ? static_cast( + NetImgui::Internal::CmdVersion::eFlags::ConnectForce) + : 0; + PendingSend.pCommand = reinterpret_cast(&cmdVersionSend); + while (!gbShutdown && !PendingSend.IsDone()) { + ::Network::DataSend(pClientSocket, PendingSend); + } + + if (!PendingSend.IsError()) { + PendingRcv.pCommand = reinterpret_cast(&cmdVersionRcv); + while (!PendingRcv.IsDone() && + cmdVersionRcv.mType == CmdHeader::eCommands::Version) { + while (!gbShutdown && !::Network::DataReceivePending(pClientSocket)) { + std::this_thread::yield(); // Idle until we receive the remote data + } + ::Network::DataReceive(pClientSocket, PendingRcv); + } + + if (!gbShutdown && !PendingRcv.IsError()) { + //--------------------------------------------------------------------- + // Connection accepted, initialize client + //--------------------------------------------------------------------- + if (cmdVersionRcv.mType != + NetImgui::Internal::CmdHeader::eCommands::Version || + cmdVersionRcv.mVersion != + NetImgui::Internal::CmdVersion::eVersion::_current) { + NetImguiServer::Config::Client::SetProperty_Status( + pClient->mClientConfigID, + NetImguiServer::Config::Client::eStatus::ErrorVer); + return false; + } else if (cmdVersionRcv.mFlags & + static_cast( + NetImgui::Internal::CmdVersion::eFlags::IsConnected)) { + bool bAvailable = + (cmdVersionRcv.mFlags & + static_cast( + NetImgui::Internal::CmdVersion::eFlags::IsUnavailable)) == 0; + NetImguiServer::Config::Client::SetProperty_Status( + pClient->mClientConfigID, + bAvailable ? NetImguiServer::Config::Client::eStatus::Available + : NetImguiServer::Config::Client::eStatus::ErrorBusy); + return false; + } + + pClient->Initialize(); + pClient->mInfoImguiVerID = cmdVersionRcv.mImguiVerID; + pClient->mInfoNetImguiVerID = cmdVersionRcv.mNetImguiVerID; + pClient->mPendingRcv = PendingCom(); + pClient->mPendingSend = PendingCom(); + NetImgui::Internal::StringCopy(pClient->mInfoName, + cmdVersionRcv.mClientName); + NetImgui::Internal::StringCopy(pClient->mInfoImguiVerName, + cmdVersionRcv.mImguiVerName); + NetImgui::Internal::StringCopy(pClient->mInfoNetImguiVerName, + cmdVersionRcv.mNetImguiVerName); + + NetImguiServer::Config::Client clientConfig; + if (NetImguiServer::Config::Client::GetConfigByID( + pClient->mClientConfigID, clientConfig)) { + NetImgui::Internal::StringFormat( + pClient->mWindowID, "%s (%s)##%i", pClient->mInfoName, + clientConfig.mClientName, + static_cast(pClient->mClientIndex)); // Using ClientIndex as a + // window unique ID + } else { + NetImgui::Internal::StringFormat( + pClient->mWindowID, "%s##%i", pClient->mInfoName, + static_cast(pClient->mClientIndex)); // Using ClientIndex as a + // window unique ID + } + return true; + } + } + + NetImguiServer::Config::Client::SetProperty_Status( + pClient->mClientConfigID, + NetImguiServer::Config::Client::eStatus::Disconnected); + return false; +} + +//================================================================================================= +// New connection Init request. +// Start new communication thread if handshake sucessfull +//================================================================================================= +void NetworkConnectionNew( + NetImgui::Internal::Network::SocketInfo* pClientSocket, + RemoteClient::Client* pNewClient, bool ConnectForce) { + const char* zErrorMsg(nullptr); + if (pNewClient == nullptr) { + zErrorMsg = "Too many connection on server already"; + } else { + NetImguiServer::Config::Client::SetProperty_Status( + pNewClient->mClientConfigID, + NetImguiServer::Config::Client::eStatus::Connecting); + if (zErrorMsg == nullptr && !gbShutdown && + Communications_InitializeClient(pClientSocket, pNewClient, + ConnectForce) == false) { + zErrorMsg = "Initialization failed. Wrong communication version?"; + } + } + + if (zErrorMsg == nullptr && !gbShutdown) { + pNewClient->mpSocket = pClientSocket; + std::thread(Communications_ClientExchangeLoop, pNewClient).detach(); + } else { + NetImgui::Internal::Network::Disconnect(pClientSocket); + if (!gbShutdown) { + if (pNewClient) { + pNewClient->mbIsFree = true; + printf("Error connecting to client '%s:%i' (%s)\n", + pNewClient->mConnectHost, pNewClient->mConnectPort, zErrorMsg); + } else { + printf("Error connecting to client (%s)\n", zErrorMsg); + } + } + } +} + +//================================================================================================= +// Thread waiting on new Client Connection request +//================================================================================================= +void NetworkConnectRequest_Receive() { + uint32_t serverPort(0); + + gActiveThreadConnectIn = true; + while (!gbShutdown) { + // Open (and update when needed) listening socket + if (gListenSocket == nullptr || + serverPort != NetImguiServer::Config::Server::sPort) { + serverPort = NetImguiServer::Config::Server::sPort; + gListenSocket = NetImgui::Internal::Network::ListenStart(serverPort); + if (gListenSocket.load() == nullptr) { + printf("Failed to start connection listen on port : %i", serverPort); + std::this_thread::sleep_for(std::chrono::milliseconds( + 500)); // Reduce Server listening socket open attempt frequency + } + } + + // Detect connection request from Clients + if (gListenSocket.load() != nullptr) { + NetImgui::Internal::Network::SocketInfo* pClientSocket = + NetImgui::Internal::Network::ListenConnect(gListenSocket.load()); + if (pClientSocket) { + uint32_t freeIndex = RemoteClient::Client::GetFreeIndex(); + if (freeIndex != RemoteClient::Client::kInvalidClient) { + RemoteClient::Client& newClient = + RemoteClient::Client::Get(freeIndex); + newClient.mClientConfigID = + NetImguiServer::Config::Client::kInvalidRuntimeID; + newClient.mClientIndex = freeIndex; + NetImguiServer::App::HAL_GetSocketInfo( + pClientSocket, newClient.mConnectHost, + sizeof(newClient.mConnectHost), newClient.mConnectPort); + NetworkConnectionNew(pClientSocket, &newClient, false); + } else { + NetImgui::Internal::Network::Disconnect(pClientSocket); + } + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(16)); + } + NetImgui::Internal::Network::SocketInfo* socketDisconnect = + gListenSocket.exchange(nullptr); + NetImgui::Internal::Network::Disconnect(socketDisconnect); + gActiveThreadConnectIn = false; +} + +//================================================================================================= +// Thread trying to reach out new Clients with a connection +//================================================================================================= +void NetworkConnectRequest_Send() { + uint64_t loopIndex(0); + NetImguiServer::Config::Client clientConfig; + gActiveThreadConnectOut = true; + while (!gbShutdown) { + uint32_t clientConfigID(NetImguiServer::Config::Client::kInvalidRuntimeID); + NetImgui::Internal::Network::SocketInfo* pClientSocket = nullptr; + + // Find next client configuration to attempt connection to + bool ConnectForce = false; + uint64_t configCount = + static_cast(NetImguiServer::Config::Client::GetConfigCount()); + uint32_t configIdx = + configCount ? static_cast(loopIndex++ % configCount) : 0; + if (NetImguiServer::Config::Client::GetConfigByIndex(configIdx, + clientConfig)) { + ConnectForce = clientConfig.mConnectForce; + if ((clientConfig.IsConnectReady() || + clientConfig.IsAutoConnectReady()) && + clientConfig.mHostPort != NetImguiServer::Config::Server::sPort) { + NetImguiServer::Config::Client::SetProperty_ConnectRequest( + clientConfig.mRuntimeID, false, + false); // Reset the Connection request, we are processing it + NetImguiServer::Config::Client::SetProperty_Status( + clientConfig.mRuntimeID, + NetImguiServer::Config::Client::eStatus::Disconnected); + clientConfigID = + clientConfig.mRuntimeID; // Keep track of ClientConfig we are + // attempting to connect to + pClientSocket = NetImgui::Internal::Network::Connect( + clientConfig.mHostName, clientConfig.mHostPort); + } + } + + // Connection successful, find an available client slot + if (pClientSocket) { + uint32_t freeIndex = RemoteClient::Client::GetFreeIndex(); + if (freeIndex != RemoteClient::Client::kInvalidClient) { + RemoteClient::Client& newClient = RemoteClient::Client::Get(freeIndex); + if (NetImguiServer::Config::Client::GetConfigByID(clientConfigID, + clientConfig)) { + NetImgui::Internal::StringCopy(newClient.mInfoName, + clientConfig.mClientName); + newClient.mConnectPort = clientConfig.mHostPort; + newClient.mClientConfigID = clientConfigID; + newClient.mClientIndex = freeIndex; + } + NetImguiServer::App::HAL_GetSocketInfo( + pClientSocket, newClient.mConnectHost, + sizeof(newClient.mConnectHost), newClient.mConnectPort); + NetworkConnectionNew(pClientSocket, &newClient, ConnectForce); + } else { + NetImgui::Internal::Network::Disconnect(pClientSocket); + NetImguiServer::Config::Client::SetProperty_Status( + clientConfigID, + NetImguiServer::Config::Client::eStatus::Disconnected); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds( + 500)); // There's already a wait time in Connect attempt, so no need to + // sleep for too long here + } + gActiveThreadConnectOut = false; +} + +//================================================================================================= +// Initialize Networking and start listening thread +//================================================================================================= +bool Startup() { + // Relying on shared network implementation for Winsock Init + if (!NetImgui::Internal::Network::Startup()) { + return false; + } + + gbShutdown = false; + gActiveClientThreadCount = 0; + std::thread(NetworkConnectRequest_Receive).detach(); + std::thread(NetworkConnectRequest_Send).detach(); + return true; +} + +//================================================================================================= +// Send signal to terminate all communications and wait until all client have +// been released +//================================================================================================= +void Shutdown() { + gbShutdown = true; + NetImgui::Internal::Network::SocketInfo* socketDisconnect = + gListenSocket.exchange(nullptr); + NetImgui::Internal::Network::Disconnect(socketDisconnect); + while (gActiveClientThreadCount > 0 || gActiveThreadConnectIn || + gActiveThreadConnectOut) { + std::this_thread::yield(); + } + + NetImgui::Internal::Network::Shutdown(); +} + +//================================================================================================= +// True when we are listening for client's connection requests +//================================================================================================= +bool IsWaitingForConnection() { return gListenSocket.load() != nullptr; } + +//================================================================================================= +// Total amount of data sent to clients since start +//================================================================================================= +uint64_t GetStatsDataSent() { return gStatsDataSent; } + +//================================================================================================= +// Total amount of data received from clients since start +//================================================================================================= +uint64_t GetStatsDataRcvd() { return gStatsDataRcvd; } + +} // namespace Network +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Network.h b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Network.h new file mode 100644 index 00000000..96fe2815 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_Network.h @@ -0,0 +1,28 @@ +// Google modifications: +// - Added #include for uint32_t (not implicitly available in +// Google). +#pragma once + +#include + +namespace NetImguiServer { +namespace Network { +// Initialize application's networking +bool Startup(); + +// Shutdown application's networking +void Shutdown(); + +// True if this application is actively waiting for clients to reach it +// Note: False when unable to open listen socket (probably because port number +// alreay in use) +bool IsWaitingForConnection(); + +// Total amount of data sent to clients since start +uint64_t GetStatsDataSent(); + +// Total amount of data received from clients since start +uint64_t GetStatsDataRcvd(); + +} // namespace Network +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_RemoteClient.cpp b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_RemoteClient.cpp new file mode 100644 index 00000000..7c471181 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_RemoteClient.cpp @@ -0,0 +1,664 @@ +#include "NetImguiServer_RemoteClient.h" + +#include + +#include + +#include "NetImguiServer_App.h" +#include "NetImguiServer_Config.h" +#include "NetImguiServer_UI.h" + +namespace NetImguiServer { +namespace RemoteClient { + +static Client* gpClients = + nullptr; // Table of all potentially connected clients to this server +static uint32_t gClientCountMax = 0; + +NetImguiImDrawData::NetImguiImDrawData() : mCommandList(nullptr) { + CmdListsCount = 1; // All draws collapsed in same CmdList + CmdLists.push_back(&mCommandList); +} + +Client::Client() + : mPendingTextureReadIndex(0), + mPendingTextureWriteIndex(0), + mbIsFree(true), + mbCompressionSkipOncePending(false), + mbDisconnectPending(false), + mClientConfigID(NetImguiServer::Config::Client::kInvalidRuntimeID) {} + +Client::~Client() { Uninitialize(); } + +void Client::ReceiveDrawFrame(NetImgui::Internal::CmdDrawFrame* pFrameData) { + if (pFrameData->mCompressed) { + if (mpFrameDrawPrev != nullptr && + (mpFrameDrawPrev->mFrameIndex + 1) == pFrameData->mFrameIndex) { + NetImgui::Internal::CmdDrawFrame* pUncompressedFrame = + NetImgui::Internal::DecompressCmdDrawFrame(mpFrameDrawPrev, + pFrameData); + netImguiDeleteSafe(pFrameData); + pFrameData = pUncompressedFrame; + } + // Missing previous frame data + // ignore this drawframe and request a new uncompressed one to be able to + // resume display + else { + mbCompressionSkipOncePending = true; + netImguiDeleteSafe(pFrameData); + } + } + + netImguiDeleteSafe(mpFrameDrawPrev); + if (pFrameData) { + // Convert DrawFrame command to Dear Imgui DrawData, + // and make it available for main thread to use in rendering + ProcessCmdDrawFrame(pFrameData); + + // Update framerate + constexpr float kHysteresis = 0.025f; // Between 0 to 1.0 + auto elapsedTime = std::chrono::steady_clock::now() - mLastDrawFrame; + float elapsedMs = + static_cast( + std::chrono::duration_cast(elapsedTime) + .count()) / + 1000.f; + mStatsDrawElapsedMs = + mStatsDrawElapsedMs * (1.f - kHysteresis) + elapsedMs * kHysteresis; + mLastDrawFrame = std::chrono::steady_clock::now(); + } +} + +void Client::ReceiveTexture(NetImgui::Internal::CmdTexture* pTextureCmd) { + if (pTextureCmd) { + // Wait for a free spot in the ring buffer + while (mPendingTextureWriteIndex - mPendingTextureReadIndex >= + IM_ARRAYSIZE(mpPendingTextures)) { + std::this_thread::yield(); + } + + uint64_t writeIndex = + mPendingTextureWriteIndex % IM_ARRAYSIZE(mpPendingTextures); + mpPendingTextures[writeIndex] = pTextureCmd; + mPendingTextureWriteIndex = mPendingTextureWriteIndex + 1; + } +} + +//================================================================================================= +// Process pending texture commands received from Client +//================================================================================================= +void Client::ProcessPendingTextureCmds() { + while (mPendingTextureReadIndex != mPendingTextureWriteIndex) { + uint64_t readIndex = + mPendingTextureReadIndex % IM_ARRAYSIZE(mpPendingTextures); + NetImgui::Internal::CmdTexture* pTextureCmd = mpPendingTextures[readIndex]; + auto texIt = mTextureTable.find(pTextureCmd->mTextureClientID); + NetImguiServer::App::ServerTexture* serverTex = + texIt != mTextureTable.end() ? texIt->second : nullptr; + + bool isCreate = + pTextureCmd->mStatus == NetImgui::Internal::CmdTexture::eType::Create && + pTextureCmd->mFormat != NetImgui::eTexFormat::kTexFmt_Invalid; + bool isUpdate = + pTextureCmd->mStatus == NetImgui::Internal::CmdTexture::eType::Update && + pTextureCmd->mFormat != NetImgui::eTexFormat::kTexFmtCustom; + uint32_t texDataSize = + pTextureCmd->mSize - sizeof(NetImgui::Internal::CmdTexture); + + // Delete a texture on request or when creating new one with same + // ClientTextureID + if (!isUpdate && serverTex) { + serverTex->MarkForDelete(); + mTextureTable.erase(texIt); + } + + // Add a texture + if (isCreate) { + serverTex = NetImguiServer::App::CreateTexture(*pTextureCmd, texDataSize); + if (serverTex) { + serverTex->mOwnerClientIndex = static_cast(mClientIndex); + mTextureTable.insert({pTextureCmd->mTextureClientID, serverTex}); + } + } + // Update a Texture + else if (isUpdate && serverTex && + serverTex->mTexData.Status != + ImTextureStatus::ImTextureStatus_WantDestroy && + serverTex->mTexData.Status != + ImTextureStatus::ImTextureStatus_Destroyed) { + auto TexFormat = static_cast(pTextureCmd->mFormat); + if (serverTex->mTexData.Width < + (int)(pTextureCmd->mWidth + pTextureCmd->mOffsetX) || + serverTex->mTexData.Height < + (int)(pTextureCmd->mHeight + pTextureCmd->mOffsetY)) { + // Update bigger than texture should not happen, but left here as a + // precaution to avoid memory corruption. Could happen if there's an + // error with client/server re-using a texture ID somehow + } else { + size_t SrcLineBytes = NetImgui::GetTexture_BytePerLine( + TexFormat, static_cast(pTextureCmd->mWidth)); + size_t DstLineBytes = NetImgui::GetTexture_BytePerLine( + TexFormat, static_cast(serverTex->mTexData.Width)); + size_t OffsetBytes = + (pTextureCmd->mOffsetY * DstLineBytes) + + NetImgui::GetTexture_BytePerLine(TexFormat, pTextureCmd->mOffsetX); + const uint8_t* pDataSrc = pTextureCmd->mpTextureData.Get(); + uint8_t* pDataDst = + reinterpret_cast(serverTex->mTexData.GetPixels()); + for (uint64_t y(0); y < pTextureCmd->mHeight; ++y) { + memcpy(&pDataDst[OffsetBytes + (y * DstLineBytes)], + &pDataSrc[y * SrcLineBytes], SrcLineBytes); + } + + // No need to queue if status is _WantCreate + if (serverTex->mTexData.Status != ImTextureStatus_WantCreate) { + // Following code mostly copied from + // ImFontAtlasTextureBlockQueueUpload + ImTextureData* tex = &serverTex->mTexData; + ImTextureRect req = {(unsigned short)pTextureCmd->mOffsetX, + (unsigned short)pTextureCmd->mOffsetY, + (unsigned short)pTextureCmd->mWidth, + (unsigned short)pTextureCmd->mHeight}; + int new_x1 = ImMax(tex->UpdateRect.w == 0 + ? 0 + : tex->UpdateRect.x + tex->UpdateRect.w, + req.x + req.w); + int new_y1 = ImMax(tex->UpdateRect.h == 0 + ? 0 + : tex->UpdateRect.y + tex->UpdateRect.h, + req.y + req.h); + tex->UpdateRect.x = ImMin(tex->UpdateRect.x, req.x); + tex->UpdateRect.y = ImMin(tex->UpdateRect.y, req.y); + tex->UpdateRect.w = (unsigned short)(new_x1 - tex->UpdateRect.x); + tex->UpdateRect.h = (unsigned short)(new_y1 - tex->UpdateRect.y); + tex->UsedRect.x = ImMin(tex->UsedRect.x, req.x); + tex->UsedRect.y = ImMin(tex->UsedRect.y, req.y); + tex->UsedRect.w = + (unsigned short)(ImMax(tex->UsedRect.x + tex->UsedRect.w, + req.x + req.w) - + tex->UsedRect.x); + tex->UsedRect.h = + (unsigned short)(ImMax(tex->UsedRect.y + tex->UsedRect.h, + req.y + req.h) - + tex->UsedRect.y); + tex->Status = ImTextureStatus_WantUpdates; + tex->Updates.push_back(req); + } + } + } + NetImgui::Internal::netImguiDeleteSafe(pTextureCmd); + mPendingTextureReadIndex = mPendingTextureReadIndex + 1; + } +} + +void Client::Initialize() { + mConnectedTime = std::chrono::steady_clock::now(); + mLastUpdateTime = std::chrono::steady_clock::now() - std::chrono::hours(1); + mLastDrawFrame = std::chrono::steady_clock::now(); + mLastIncomingComTime = std::chrono::steady_clock::now(); + mLastDrawFrameIndex = 0; + mStatsIndex = 0; + mStatsRcvdBps = 0; + mStatsSentBps = 0; + mStatsDrawElapsedMs = 0.f; + mStatsDataRcvd = 0; + mStatsDataSent = 0; + mStatsDataRcvdPrev = 0; + mStatsDataSentPrev = 0; + mbIsReleased = false; + mStatsTime = std::chrono::steady_clock::now(); + mBGSettings = + NetImgui::Internal::CmdBackground(); // Assign background default value, + // until we receive first update + // from client + mPendingRcv = NetImgui::Internal::PendingCom(); + mPendingSend = NetImgui::Internal::PendingCom(); + NetImgui::Internal::netImguiDeleteSafe(mpImguiDrawData); + NetImgui::Internal::netImguiDeleteSafe(mpFrameDrawPrev); +} + +void Client::Uninitialize() { + NetImguiServer::App::HAL_DestroyRenderTarget(mpHAL_AreaRT, mHAL_AreaTexture); + + for (auto serverTexIt : mTextureTable) { + if (serverTexIt.second) { + serverTexIt.second->MarkForDelete(); + } + } + mTextureTable.clear(); + + mPendingImguiDrawDataIn.Free(); + mPendingBackgroundIn.Free(); + mPendingInputOut.Free(); + mPendingClipboardOut.Free(); + + NetImgui::Internal::netImguiDeleteSafe(mpImguiDrawData); + NetImgui::Internal::netImguiDeleteSafe(mpFrameDrawPrev); + if (mpBGContext) { + ImGui::DestroyContext(mpBGContext); + mpBGContext = nullptr; + } + + mInfoName[0] = 0; + mClientIndex = 0; + mClientConfigID = NetImguiServer::Config::Client::kInvalidRuntimeID; + mbCompressionSkipOncePending = false; + mbDisconnectPending = false; + mbIsConnected = false; + mbIsFree = true; + mBGNeedUpdate = true; +} + +// Used on communication thread to let main thread know this client resources +// should be deleted +void Client::Release() { mbIsReleased = true; } + +bool Client::Startup(uint32_t clientCountMax) { + gClientCountMax = clientCountMax; + gpClients = new Client[clientCountMax]; + return gpClients != nullptr; +} + +void Client::Shutdown() { + gClientCountMax = 0; + if (gpClients) { + delete[] gpClients; + gpClients = nullptr; + } +} + +uint32_t Client::GetCountMax() { return gClientCountMax; } + +Client& Client::Get(uint32_t index) { + bool bValid = gpClients && index < gClientCountMax; + static Client sInvalidClient; + assert(bValid); + return bValid ? gpClients[index] : sInvalidClient; +} + +uint32_t Client::GetFreeIndex() { + for (uint32_t i(0); i < gClientCountMax; ++i) { + if (gpClients[i].mbIsFree.exchange(false) == true) return i; + } + return kInvalidClient; +} + +//================================================================================================= +// Get the current Dear Imgui drawdata to use for this client rendering content +//================================================================================================= +NetImguiImDrawData* Client::GetImguiDrawData(ImTextureID EmtpyTextureID) { + // DrawData's textures should now have been created, safe to use it + if (mpPendingDrawData) { + NetImgui::Internal::netImguiDeleteSafe(mpImguiDrawData); + mpImguiDrawData = mpPendingDrawData; + mLastDrawFrameIndex = mpImguiDrawData->mFrameIndex; + mpPendingDrawData = nullptr; + } + + // Check if a new frame has been added. If yes, then take ownership of it. + NetImguiImDrawData* pPendingDrawData = mPendingImguiDrawDataIn.Release(); + if (pPendingDrawData) { + bool bHasPendingTextureUpdate(false); + + // When a new drawdata is available, need to convert the textureid from + // NetImgui Id to the backend renderer format (texture view pointer). Done + // here (in main thread) instead of when first received on the (com thread), + // since 'mvTextures' can only be safely accessed on (main thread). + for (int i(0); i < pPendingDrawData->CmdListsCount; ++i) { + ImDrawList* pCmdList = pPendingDrawData->CmdLists[i]; + for (int drawIdx(0), drawCount(pCmdList->CmdBuffer.size()); + drawIdx < drawCount; ++drawIdx) { + uint64_t clientTexUserID = pCmdList->CmdBuffer[drawIdx].TexRef._TexID; + auto texIt = mTextureTable.find(clientTexUserID); + ImTextureRef serverTexRef = EmtpyTextureID; + if (texIt != mTextureTable.end() && texIt->second) { + ImTextureData* texData = &texIt->second->mTexData; + serverTexRef = texData->GetTexRef(); + texIt->second->mLastFrameUsed = + pPendingDrawData->mFrameIndex; // Needed to know when it is safe + // to release the texture resource + bHasPendingTextureUpdate |= + texData->Status != ImTextureStatus::ImTextureStatus_OK; + } + pCmdList->CmdBuffer[drawIdx].TexRef = serverTexRef; + } + } + + // DrawData contains textures with pending updates, + // wait 1 frame to display it + if (bHasPendingTextureUpdate) { + mpPendingDrawData = pPendingDrawData; + } + // New valid DrawData, use it for display + else { + NetImgui::Internal::netImguiDeleteSafe(mpImguiDrawData); + mpImguiDrawData = pPendingDrawData; + mLastDrawFrameIndex = mpImguiDrawData->mFrameIndex; + } + } + + return mpImguiDrawData; +} + +//================================================================================================= +// Create a new Dear Imgui DrawData ready to be submitted for rendering +//================================================================================================= +void Client::ProcessCmdDrawFrame( + NetImgui::Internal::CmdDrawFrame* pCmdDrawFrame) { + constexpr float kPosRangeMin = + static_cast(NetImgui::Internal::ImguiVert::kPosRange_Min); + constexpr float kPosRangeMax = + static_cast(NetImgui::Internal::ImguiVert::kPosRange_Max); + constexpr float kUVRangeMin = + static_cast(NetImgui::Internal::ImguiVert::kUvRange_Min); + constexpr float kUVRangeMax = + static_cast(NetImgui::Internal::ImguiVert::kUvRange_Max); + + if (!pCmdDrawFrame) { + return; + } + mMouseCursor = static_cast(pCmdDrawFrame->mMouseCursor); + + NetImguiImDrawData* pDrawData = + NetImgui::Internal::netImguiNew(); + pDrawData->mFrameIndex = pCmdDrawFrame->mFrameIndex; + pDrawData->Valid = true; + pDrawData->TotalVtxCount = + static_cast(pCmdDrawFrame->mTotalVerticeCount); + pDrawData->TotalIdxCount = static_cast(pCmdDrawFrame->mTotalIndiceCount); + pDrawData->DisplayPos.x = pCmdDrawFrame->mDisplayArea[0]; + pDrawData->DisplayPos.y = pCmdDrawFrame->mDisplayArea[1]; + pDrawData->DisplaySize.x = + pCmdDrawFrame->mDisplayArea[2] - pCmdDrawFrame->mDisplayArea[0]; + pDrawData->DisplaySize.y = + pCmdDrawFrame->mDisplayArea[3] - pCmdDrawFrame->mDisplayArea[1]; + pDrawData->FramebufferScale = + ImVec2(1, 1); //! @sammyfreg Currently untested, so force set to 1 + pDrawData->OwnerViewport = nullptr; + + ImDrawList* pCmdList = pDrawData->CmdLists[0]; + pCmdList->IdxBuffer.resize(pCmdDrawFrame->mTotalIndiceCount); + pCmdList->VtxBuffer.resize(pCmdDrawFrame->mTotalVerticeCount); + pCmdList->CmdBuffer.resize(pCmdDrawFrame->mTotalDrawCount); + pCmdList->Flags = + ImDrawListFlags_AllowVtxOffset | ImDrawListFlags_AntiAliasedLines | + ImDrawListFlags_AntiAliasedFill | ImDrawListFlags_AntiAliasedLinesUseTex; + + if (pCmdDrawFrame->mTotalDrawCount != 0) { + uint32_t indexOffset(0), vertexOffset(0); + ImDrawIdx* pIndexDst = &pCmdList->IdxBuffer[0]; + ImDrawVert* pVertexDst = &pCmdList->VtxBuffer[0]; + ImDrawCmd* pCommandDst = &pCmdList->CmdBuffer[0]; + + for (uint32_t i(0); i < pCmdDrawFrame->mDrawGroupCount; ++i) { + const NetImgui::Internal::ImguiDrawGroup& drawGroup = + pCmdDrawFrame->mpDrawGroups[i]; + + // Copy/Convert Indices from network command to Dear ImGui indices format + const uint16_t* pIndices = + reinterpret_cast(drawGroup.mpIndices.Get()); + if (drawGroup.mBytePerIndex == sizeof(ImDrawIdx)) { + memcpy(pIndexDst, pIndices, drawGroup.mIndiceCount * sizeof(ImDrawIdx)); + } else { + for (uint32_t indexIdx(0); indexIdx < drawGroup.mIndiceCount; + ++indexIdx) { + pIndexDst[indexIdx] = static_cast(pIndices[indexIdx]); + } + } + + // Convert the Vertices from network command to Dear Imgui Format + const NetImgui::Internal::ImguiVert* pVertexSrc = + drawGroup.mpVertices.Get(); + for (uint32_t vtxIdx(0); vtxIdx < drawGroup.mVerticeCount; ++vtxIdx) { + pVertexDst[vtxIdx].pos.x = + (static_cast(pVertexSrc[vtxIdx].mPos[0]) * + (kPosRangeMax - kPosRangeMin)) / + static_cast(0xFFFF) + + kPosRangeMin + drawGroup.mReferenceCoord[0]; + pVertexDst[vtxIdx].pos.y = + (static_cast(pVertexSrc[vtxIdx].mPos[1]) * + (kPosRangeMax - kPosRangeMin)) / + static_cast(0xFFFF) + + kPosRangeMin + drawGroup.mReferenceCoord[1]; + pVertexDst[vtxIdx].uv.x = + (static_cast(pVertexSrc[vtxIdx].mUV[0]) * + (kUVRangeMax - kUVRangeMin)) / + static_cast(0xFFFF) + + kUVRangeMin; + pVertexDst[vtxIdx].uv.y = + (static_cast(pVertexSrc[vtxIdx].mUV[1]) * + (kUVRangeMax - kUVRangeMin)) / + static_cast(0xFFFF) + + kUVRangeMin; + pVertexDst[vtxIdx].col = pVertexSrc[vtxIdx].mColor; + } + + // Convert the Draws from network command to Dear Imgui Format + const NetImgui::Internal::ImguiDraw* pDrawSrc = drawGroup.mpDraws.Get(); + for (uint32_t drawIdx(0); drawIdx < drawGroup.mDrawCount; ++drawIdx) { + pCommandDst[drawIdx].ClipRect.x = pDrawSrc[drawIdx].mClipRect[0]; + pCommandDst[drawIdx].ClipRect.y = pDrawSrc[drawIdx].mClipRect[1]; + pCommandDst[drawIdx].ClipRect.z = pDrawSrc[drawIdx].mClipRect[2]; + pCommandDst[drawIdx].ClipRect.w = pDrawSrc[drawIdx].mClipRect[3]; + pCommandDst[drawIdx].VtxOffset = + pDrawSrc[drawIdx].mVtxOffset + vertexOffset; + pCommandDst[drawIdx].IdxOffset = + pDrawSrc[drawIdx].mIdxOffset + indexOffset; + pCommandDst[drawIdx].ElemCount = pDrawSrc[drawIdx].mIdxCount; + pCommandDst[drawIdx].UserCallback = nullptr; + pCommandDst[drawIdx].UserCallbackData = nullptr; + pCommandDst[drawIdx].TexRef._TexID = + NetImgui::Internal::ConvertFromClientTexID( + pDrawSrc[drawIdx].mClientTexId); + } + + pIndexDst += drawGroup.mIndiceCount; + pVertexDst += drawGroup.mVerticeCount; + pCommandDst += drawGroup.mDrawCount; + indexOffset += drawGroup.mIndiceCount; + vertexOffset += drawGroup.mVerticeCount; + } + } + mpFrameDrawPrev = pCmdDrawFrame; + mPendingImguiDrawDataIn.Assign(pDrawData); +} + +//================================================================================================= +// Note: Caller must take ownership of item and delete the object +//================================================================================================= +NetImgui::Internal::CmdInput* Client::TakePendingInput() { + return mPendingInputOut.Release(); +} + +NetImgui::Internal::CmdClipboard* Client::TakePendingClipboard() { + return mPendingClipboardOut.Release(); +} + +//================================================================================================= +// Capture current received Dear ImGui input, and forward it to the active +// client Note: Even if a client is not focused, we are still sending it the +// mouse position, +// so it can update its UI. +// Note: Sending an input command, will trigger a redraw on the client, +// which we receive on the server afterward +//================================================================================================= +void Client::CaptureImguiInput() { + // Capture input from Dear ImGui (when this Client is in focus) + const ImGuiIO& io = ImGui::GetIO(); + if (mbIsVisible) { + if (ImGui::IsWindowFocused()) { + const size_t initialSize = mPendingInputChars.size(); + const size_t addedChar = io.InputQueueCharacters.size(); + if (addedChar) { + mPendingInputChars.resize(initialSize + addedChar); + memcpy(&mPendingInputChars[initialSize], io.InputQueueCharacters.Data, + addedChar * sizeof(ImWchar)); + } + + mMouseWheelPos[0] += io.MouseWheel; + mMouseWheelPos[1] += io.MouseWheelH; + } + + // Update persistent mouse status + if (ImGui::IsMousePosValid(&io.MousePos)) { + mMousePos[0] = io.MousePos.x - ImGui::GetCursorScreenPos().x; + mMousePos[1] = io.MousePos.y - ImGui::GetCursorScreenPos().y; + } + } + + // This method is tied to the Server VSync setting, which might not match our + // client desired refresh setting When client refresh drops too much, take + // into consideration the lenght of the Server frame, to evaluate if we should + // update or not + bool wasActive = mbIsActive; + mbIsActive = ImGui::IsWindowFocused(); + float clientFPS = !mbIsVisible ? 0.f + : !mbIsActive + ? NetImguiServer::Config::Server::sRefreshFPSInactive + : NetImguiServer::Config::Server::sRefreshFPSActive; + float elapsedMs = + static_cast(std::chrono::duration_cast( + std::chrono::steady_clock::now() - mLastUpdateTime) + .count()) / + 1000.f; + bool bRefresh = (wasActive != mbIsActive) || elapsedMs > 1000.f / 60.f; + + if (!bRefresh) { + return; + } + + // Try to re-acquire unsent input command, or create a new one if none pending + NetImgui::Internal::CmdInput* pNewInput = TakePendingInput(); + pNewInput = + pNewInput + ? pNewInput + : NetImgui::Internal::netImguiNew(); + + // Create new Input command to send to client + NetImguiServer::Config::Client config; + NetImguiServer::Config::Client::GetConfigByID(mClientConfigID, config); + pNewInput->mScreenSize[0] = + static_cast(ImGui::GetContentRegionAvail().x); + pNewInput->mScreenSize[1] = + static_cast(ImGui::GetContentRegionAvail().y); + pNewInput->mMousePos[0] = static_cast(mMousePos[0]); + pNewInput->mMousePos[1] = static_cast(mMousePos[1]); + pNewInput->mMouseWheelVert = mMouseWheelPos[0]; + pNewInput->mMouseWheelHoriz = mMouseWheelPos[1]; + pNewInput->mCompressionUse = + NetImguiServer::Config::Server::sCompressionEnable; + pNewInput->mCompressionSkip = mbCompressionSkipOncePending; + pNewInput->mFontDPIScaling = 1.f; + pNewInput->mDesiredFps = clientFPS; + + if (config.mDPIScaleEnabled) { + float scale = ImGui::GetMainViewport()->DpiScale; + scale = scale > 1.f ? scale : 1.f; + pNewInput->mFontDPIScaling = + 1.f + (scale - 1.f) * NetImguiServer::Config::Server::sDPIScaleRatio; + } + + mbCompressionSkipOncePending = false; + + if ((mbIsVisible && mbIsActive) && ImGui::IsWindowFocused()) { + // Mouse Buttons Inputs + // If Dear ImGui Update this enum, must also adjust our enum copy + static_assert( + static_cast(NetImgui::Internal::CmdInput::NetImguiMouseButton:: + ImGuiMouseButton_COUNT) == + static_cast(ImGuiMouseButton_::ImGuiMouseButton_COUNT), + "Update the NetImgui enum to match the updated Dear ImGui enum"); + pNewInput->mMouseDownMask = 0; + pNewInput->mMouseDownMask |= + ImGui::IsMouseDown(ImGuiMouseButton_::ImGuiMouseButton_Left) + ? 1 << NetImgui::Internal::CmdInput::ImGuiMouseButton_Left + : 0; + pNewInput->mMouseDownMask |= + ImGui::IsMouseDown(ImGuiMouseButton_::ImGuiMouseButton_Right) + ? 1 << NetImgui::Internal::CmdInput::ImGuiMouseButton_Right + : 0; + pNewInput->mMouseDownMask |= + ImGui::IsMouseDown(ImGuiMouseButton_::ImGuiMouseButton_Middle) + ? 1 << NetImgui::Internal::CmdInput::ImGuiMouseButton_Middle + : 0; + pNewInput->mMouseDownMask |= + ImGui::IsMouseDown(3) + ? 1 << NetImgui::Internal::CmdInput::ImGuiMouseButton_Extra1 + : 0; + pNewInput->mMouseDownMask |= + ImGui::IsMouseDown(4) + ? 1 << NetImgui::Internal::CmdInput::ImGuiMouseButton_Extra2 + : 0; + +// Keyboard / Gamepads Inputs +// If Dear ImGui Update their enum, must also adjust our enum copy, +// so adding a few check to detect a change +#define EnumKeynameTest(KEYNAME) \ + static_cast(NetImgui::Internal::CmdInput::NetImguiKeys::KEYNAME) == \ + static_cast(ImGuiKey::KEYNAME - ImGuiKey::ImGuiKey_NamedKey_BEGIN), \ + "Update the NetImgui enum to match the updated Dear ImGui enum" + static_assert( + NetImgui::Internal::CmdInput::NetImguiKeys::ImGuiKey_COUNT == + (ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN), + "Update the NetImgui enum to match the updated Dear ImGui enum"); + static_assert(EnumKeynameTest(ImGuiKey_Tab)); + static_assert(EnumKeynameTest(ImGuiKey_Escape)); + static_assert(EnumKeynameTest(ImGuiKey_RightSuper)); + static_assert(EnumKeynameTest(ImGuiKey_Apostrophe)); + static_assert(EnumKeynameTest(ImGuiKey_Keypad0)); + static_assert(EnumKeynameTest(ImGuiKey_CapsLock)); + static_assert(EnumKeynameTest(ImGuiKey_GamepadStart)); + static_assert(EnumKeynameTest(ImGuiKey_GamepadLStickUp)); + static_assert(EnumKeynameTest(ImGuiKey_ReservedForModCtrl)); + static_assert(EnumKeynameTest(ImGuiKey_ReservedForModShift)); + static_assert(EnumKeynameTest(ImGuiKey_ReservedForModAlt)); + static_assert(EnumKeynameTest(ImGuiKey_ReservedForModSuper)); + static_assert(EnumKeynameTest(ImGuiKey_GamepadStart)); + static_assert(EnumKeynameTest(ImGuiKey_GamepadR3)); + static_assert(EnumKeynameTest(ImGuiKey_GamepadLStickUp)); + static_assert(EnumKeynameTest(ImGuiKey_GamepadRStickRight)); + + // Save every keydown status to out bitmask + uint64_t valueMask(0); + for (uint32_t i(0); i < ImGuiKey::ImGuiKey_NamedKey_COUNT; ++i) { + valueMask |= + ImGui::IsKeyDown(static_cast(ImGuiKey_NamedKey_BEGIN + i)) + ? 0x0000000000000001ull << (i % 64) + : 0; + if (((i % 64) == 63) || i == (ImGuiKey::ImGuiKey_NamedKey_COUNT - 1)) { + pNewInput->mInputDownMask[i / 64] = valueMask; + valueMask = 0; + } + } + // Save analog keys (gamepad) + for (uint32_t i(0); i < NetImgui::Internal::CmdInput::kAnalog_Count; ++i) { + pNewInput->mInputAnalog[i] = + ImGui::GetIO() + .KeysData[NetImgui::Internal::CmdInput::kAnalog_First + i] + .AnalogValue; + } + } + + // Copy waiting characters inputs + size_t addedKeyCount = + std::min(NetImgui::Internal::ArrayCount(pNewInput->mKeyChars) - + pNewInput->mKeyCharCount, + mPendingInputChars.size()); + if (addedKeyCount) { + memcpy(&pNewInput->mKeyChars[pNewInput->mKeyCharCount], + &mPendingInputChars[0], addedKeyCount * sizeof(ImWchar)); + pNewInput->mKeyCharCount += static_cast(addedKeyCount); + size_t charRemainCount = mPendingInputChars.size() - addedKeyCount; + if (charRemainCount > 0) { + memcpy(&mPendingInputChars[0], &mPendingInputChars[addedKeyCount], + mPendingInputChars.size() - addedKeyCount); + } + mPendingInputChars.resize(charRemainCount); + } + + mPendingInputOut.Assign(pNewInput); + mLastUpdateTime = std::chrono::steady_clock::now(); +} + +} // namespace RemoteClient +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_RemoteClient.h b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_RemoteClient.h new file mode 100644 index 00000000..a18e6732 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_RemoteClient.h @@ -0,0 +1,199 @@ +#pragma once + +#include + +#include +#include +#include + +#include "NetImguiServer_App.h" + +namespace NetImguiServer { +namespace RemoteClient { + +//================================================================================================= +// ImDrawData wrapper +// +// Allocate a single ImDrawList and assign it to itself. +// +// This child class leave the original ImDrawData behavior intact, but add the +// proper memory freeing of the ImDrawList member. +//================================================================================================= +struct NetImguiImDrawData : ImDrawData { + NetImguiImDrawData(); + ImDrawList mCommandList; + uint64_t mFrameIndex = 0; +}; + +//================================================================================================= +// All info needed by the server to communicate with a remote client, and render +// its content +//================================================================================================= +struct Client { + static constexpr uint32_t kInvalidClient = static_cast(-1); + using ExchPtrInput = + NetImgui::Internal::ExchangePtr; + using ExchPtrClipboard = + NetImgui::Internal::ExchangePtr; + using ExchPtrBackground = + NetImgui::Internal::ExchangePtr; + using ExchPtrImguiDraw = NetImgui::Internal::ExchangePtr; + using TextureTable = std::unordered_map; + struct TexUpdateInfo { + uint64_t ClientId; + uint64_t Frame; + uint32_t UpdateId; + uint32_t Format; + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; + uint32_t isCreate : 1; + uint32_t isDestroy : 1; + uint32_t isUpdate : 1; + uint32_t isDearImguiManaged : 1; + }; + Client(); + ~Client(); + Client(const Client&) = delete; + Client(const Client&&) = delete; + void operator=(const Client&) = delete; + void Initialize(); + void Uninitialize(); + void Release(); + bool IsValid() const; + + void ReceiveTexture(NetImgui::Internal::CmdTexture*); + void ReceiveDrawFrame(NetImgui::Internal::CmdDrawFrame*); + void ProcessCmdDrawFrame(NetImgui::Internal::CmdDrawFrame* pCmdDrawFrame); + NetImguiImDrawData* GetImguiDrawData( + ImTextureID EmtpyTextureID); // Get current active Imgui draw data + + void CaptureImguiInput(); + NetImgui::Internal::CmdInput* TakePendingInput(); + NetImgui::Internal::CmdClipboard* TakePendingClipboard(); + void ProcessPendingTextureCmds(); + + static bool Startup(uint32_t clientCountMax); + static void Shutdown(); + static uint32_t GetCountMax(); + static uint32_t GetFreeIndex(); + static Client& Get(uint32_t index); + + void* mpHAL_AreaRT = nullptr; + ImTextureData mHAL_AreaTexture; + uint16_t mAreaRTSizeX = 0; //!< Currently allocated RenderTarget size + uint16_t mAreaRTSizeY = 0; //!< Currently allocated RenderTarget size + uint16_t mAreaSizeX = 0; //!< Available area size available to remote client + uint16_t mAreaSizeY = 0; //!< Available area size available to remote client + char mInfoName[128] = {}; + char mWindowID[128 + 16] = {}; + char mInfoImguiVerName[16] = {}; + char mInfoNetImguiVerName[16] = {}; + uint32_t mInfoImguiVerID = 0; + uint32_t mInfoNetImguiVerID = 0; + char mConnectHost[64] = {}; //!< Connected Hostname of this remote client + int mConnectPort = 0; //!< Connected Port of this remote client + + NetImguiImDrawData* mpImguiDrawData = + nullptr; //!< Current Imgui Data that this client is the owner of + NetImguiImDrawData* mpPendingDrawData = + nullptr; //!< Pending Imgui Data that has to have 1 frame display delay, + //!< to avoid issue with textures with pending updates + NetImgui::Internal::CmdDrawFrame* mpFrameDrawPrev = + nullptr; //!< Last valid DrawDrame (used by com thread, to uncompress + //!< data) + TextureTable mTextureTable; //!< Table matching client TextureUserID to + //!< textures allocated on Server for it + ExchPtrImguiDraw + mPendingImguiDrawDataIn; //!< Pending received Imgui DrawData, waiting to + //!< be taken ownership of + ExchPtrBackground mPendingBackgroundIn; //!< Background settings received and + //!< waiting to update client setting + ExchPtrClipboard mPendingClipboardIn; //!< Clipboard received from Client and + //!< waiting to be processed on Server + ExchPtrInput + mPendingInputOut; //!< Input command waiting to be sent out to client + ExchPtrClipboard mPendingClipboardOut; //!< Clipboard command waiting to be + //!< sent out to client + std::vector + mPendingInputChars; //!< Captured Imgui characters input waiting to be + //!< added to new InputCmd + NetImgui::Internal::CmdTexture* mpPendingTextures[1024] = + {}; //!< Textures commands waiting to be processed in main update loop + std::atomic_uint64_t mPendingTextureReadIndex; + std::atomic_uint64_t mPendingTextureWriteIndex; + bool mbIsVisible = false; //!< If currently shown + bool mbIsActive = false; //!< Is the current active window (will receive + //!< input, only one is true at a time) + bool mbIsReleased = false; //!< If released in com thread and main thread + //!< should delete resources + bool mbIsConnected = + false; //!< If connected to a remote client. Set to false in Unitialize, + //!< after mIsRelease is set to unload resources + std::atomic_bool + mbIsFree; //!< If available to use for a new connected client + std::atomic_bool + mbCompressionSkipOncePending; //!< When we detect invalid previous + //!< DrawFrame command, cancel compression + //!< for 1 frame, to get good data + std::atomic_bool mbDisconnectPending; //!< Terminate Client/Server coms + std::chrono::steady_clock::time_point + mConnectedTime; //!< When the connection was established with this remote + //!< client + std::chrono::steady_clock::time_point + mLastUpdateTime; //!< When the client last send a content refresh request + std::chrono::steady_clock::time_point + mLastDrawFrame; //!< When we last receive a new drawframe commant + std::chrono::steady_clock::time_point + mLastIncomingComTime; //!< When we last received a valid command from + //!< client (to detect timeout) + uint32_t mClientConfigID = + 0; //!< ID of ClientConfig that connected (if connection came from our + //!< list of ClientConfigs) + uint32_t mClientIndex = 0; //!< Entry idx into table of connected clients + uint64_t mStatsDataRcvd = + 0; //!< Current amount of Bytes received since connected + uint64_t mStatsDataSent = + 0; //!< Current amount of Bytes sent to client since connected + uint64_t mStatsDataRcvdPrev = + 0; //!< Last amount of Bytes received since connected + uint64_t mStatsDataSentPrev = + 0; //!< Last amount of Bytes sent to client since connected + std::chrono::steady_clock::time_point + mStatsTime; //!< Time when info was collected (with history of last x + //!< values) + uint32_t mStatsRcvdBps = 0; //!< Average Bytes received per second + uint32_t mStatsSentBps = 0; //!< Average Bytes sent per second + float mStatsDrawElapsedMs = + 0.f; //!< Average milliseconds between 2 draw requests + uint32_t mStatsIndex = 0; + float mMousePos[2] = {0, 0}; + float mMouseWheelPos[2] = {0, 0}; + ImGuiMouseCursor mMouseCursor = + ImGuiMouseCursor_None; // Last mosue cursor remote client requested + ImGuiContext* mpBGContext = + nullptr; // Special Imgui Context used to render the background (only + // updated when needed) + bool mBGNeedUpdate = true; // Let engine know that we should regenerate the + // background draw commands + NetImgui::Internal::Network::SocketInfo* mpSocket = + nullptr; //!< Socket used for communications + NetImgui::Internal::CmdBackground + mBGSettings; //!< Settings for client background drawing settings + NetImgui::Internal::CmdPendingRead + mCmdPendingRead; //!< Used to get info on the next incoming command from + //!< Client + NetImgui::Internal::PendingCom + mPendingRcv; //!< Data being currently received from Client + NetImgui::Internal::PendingCom + mPendingSend; //!< Data being currently sent to Client + TexUpdateInfo mTextureHistory[256] = + {}; //!< Keeps track of texture changes (for debug info) + uint32_t mTextureHistoryIndex = 0; + uint64_t mLastDrawFrameIndex = + 0; //!< Last frame index of valid drawdata drawn +}; + +} // namespace RemoteClient +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_UI.cpp b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_UI.cpp new file mode 100644 index 00000000..a8b81e75 --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_UI.cpp @@ -0,0 +1,1178 @@ +// Google modifications: +// - Updated stb_image include path for Google third_party layout. +#include "NetImguiServer_UI.h" + +#include +#include +#include + +#include + +#include "NetImguiServer_App.h" +#include "NetImguiServer_Config.h" +#include "NetImguiServer_Network.h" +#include "NetImguiServer_RemoteClient.h" + +#define STB_IMAGE_IMPLEMENTATION +#include "third_party/stblib/stb_image.h" +#undef STB_IMAGE_IMPLEMENTATION + +namespace NetImguiServer { +namespace UI { + +constexpr uint32_t kClientRemoteInvalid = 0xFFFFFFFF; +constexpr char kNetImguiURL[] = "https://github.com/sammyfreg/netImgui"; +const char* kDataSizeUnits[] = {"B", "KB", "MB", "GB"}; +static const ImVec4 kColorBGClear = ImVec4( + 0.8f, 0.8f, 0.8f, 1.f); // Background color of the main Server window +static const ImVec4 kColorBGTint = ImVec4( + 1.f, 1.f, 1.f, 1.f); // Tint applied to the main server window bg logo +static const ImVec4 kColorTitle = + ImVec4(0.3f, 1.0f, 0.3f, 1.f); // Various Server title content color +static const ImVec4 kColorContent = + ImVec4(0.7f, 0.75f, 0.7f, 1.f); // Various Server text content color +static ImGuiID gMainDockID = 0; +static float gDisplayFPS = 30.f; +static auto gLastUIUpdate = std::chrono::steady_clock::now(); +static App::ServerTexture* gpBackgroundTexture; + +static uint32_t gPopup_ConfirmDisconnect_ClientIdx = kClientRemoteInvalid; +static uint32_t gPopup_ConfirmDelete_ConfigIdx = + NetImguiServer::Config::Client::kInvalidRuntimeID; +static bool gPopup_AboutNetImgui_Show = false; +static bool gPopup_ServerConfig_Show = false; +static NetImguiServer::Config::Client* gPopup_ClientConfig_pConfig = nullptr; + +//================================================================================================= +// Convert a memory size to a displayable value +//================================================================================================= +uint8_t ConvertDataAmount(uint64_t& dataSize) { + uint8_t outUnitIdx = 0; + for (size_t i(0); i < IM_ARRAYSIZE(kDataSizeUnits); ++i) { + outUnitIdx += dataSize >= 1024 * 100 ? 1 : 0; + dataSize /= outUnitIdx > i ? 1024 : 1; + } + return outUnitIdx; +} + +const App::ServerTexture* GetBackgroundTexture() { return gpBackgroundTexture; } + +//================================================================================================= +// Fill current window with our main background picture +//================================================================================================= +void DrawCenteredBackground(const App::ServerTexture* Texture, + const ImVec4& Tint) { + if (Texture && Texture->IsValid()) { + const ImVec2 savedPos = ImGui::GetCursorPos(); + const ImVec2 areaSize = ImGui::GetContentRegionAvail(); + const float ratioH = + static_cast(Texture->mTexData.Width) / areaSize.x; + const float ratioV = + static_cast(Texture->mTexData.Height) / areaSize.y; + float bgSizeX = ratioH > ratioV + ? areaSize.x + : areaSize.y * + static_cast(Texture->mTexData.Width) / + static_cast(Texture->mTexData.Height); + float bgSizeY = ratioH < ratioV + ? areaSize.y + : areaSize.x * + static_cast(Texture->mTexData.Height) / + static_cast(Texture->mTexData.Width); + float uvOffsetX = (areaSize.x - bgSizeX) / 2.f; + float uvOffsetY = (areaSize.y - bgSizeY) / 2.f; + ImTextureRef texRef = + const_cast(Texture->mTexData) + .GetTexRef(); // Note: method does not modify object, but wasn't + // marked 'const' + ImGui::SetCursorPos(ImVec2(savedPos.x + uvOffsetX, savedPos.y + uvOffsetY)); + ImGui::ImageWithBg(texRef, ImVec2(bgSizeX, bgSizeY), ImVec2(0, 0), + ImVec2(1, 1), ImVec4(0, 0, 0, 0), Tint); + ImGui::SetCursorPos(savedPos); + } +} + +//================================================================================================= +// If last Imgui item is hovered, display info on the provided remote client +//================================================================================================= +void ClientInfoTooltip(const RemoteClient::Client& Client) { + if (ImGui::IsItemHovered()) { + NetImguiServer::Config::Client config; + float width = ImGui::CalcTextSize("Config ").x; + auto elapsedTime = std::chrono::steady_clock::now() - Client.mConnectedTime; + int tmSec = static_cast( + std::chrono::duration_cast(elapsedTime).count() % + 60); + int tmMin = static_cast( + std::chrono::duration_cast(elapsedTime).count() % + 60); + int tmHour = static_cast( + std::chrono::duration_cast(elapsedTime).count()); + bool validConfig = NetImguiServer::Config::Client::GetConfigByID( + Client.mClientConfigID, config); + + uint64_t rxData(Client.mStatsDataRcvdPrev); + uint64_t txData(Client.mStatsDataSentPrev); + uint8_t txUnitIdx = ConvertDataAmount(txData); + uint8_t rxUnitIdx = ConvertDataAmount(rxData); + + ImGui::BeginTooltip(); + ImGui::TextUnformatted("Name"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %s", Client.mInfoName); + ImGui::TextUnformatted("Config"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %s", + validConfig ? config.mClientName : "None"); + ImGui::TextUnformatted("Host"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %s", Client.mConnectHost); + ImGui::TextUnformatted("Port"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %i", Client.mConnectPort); + ImGui::TextUnformatted("ImGui"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %s", Client.mInfoImguiVerName); + ImGui::TextUnformatted("Time"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %03ih%02i:%02i", tmHour, tmMin, tmSec); + ImGui::TextUnformatted("Fps"); + ImGui::SameLine(width); + ImGui::TextColored( + kColorContent, ": %04.1f", + Client.mbIsVisible ? 1000.f / Client.mStatsDrawElapsedMs : 0.f); + ImGui::TextUnformatted("Data"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": (Rx) %7i KB/s \t(Tx) %7i KB/s", + Client.mStatsRcvdBps / 1024, + Client.mStatsSentBps / 1024); + ImGui::NewLine(); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": (Rx) %7i %s \t(Tx) %7i %s", + static_cast(rxData), kDataSizeUnits[rxUnitIdx], + static_cast(txData), kDataSizeUnits[txUnitIdx]); + ImGui::EndTooltip(); + } +} + +//================================================================================================= +// When a Remote Client request is made, first makes sure to confirm with user +//================================================================================================= +void Popup_ConfirmDisconnect() { + bool pendingDisconnectOpen(gPopup_ConfirmDisconnect_ClientIdx != + kClientRemoteInvalid); + if (pendingDisconnectOpen) { + RemoteClient::Client& client = + RemoteClient::Client::Get(gPopup_ConfirmDisconnect_ClientIdx); + bool wantExit = ImGui::IsKeyPressed(ImGuiKey_Escape); + static ImVec2 sPopupSize = ImVec2(250.f, 200.f); + + ImGuiWindowClass windowClass; + windowClass.ViewportFlagsOverrideSet = ImGuiViewportFlags_TopMost; + ImGui::SetNextWindowClass(&windowClass); + + ImGuiViewport* pViewport = ImGui::GetWindowViewport(); + ImVec2 popupPos = pViewport->Pos; + popupPos.x += pViewport->Size.x / 2.f - sPopupSize.x / 2.f; + popupPos.y += pViewport->Size.y / 2.f - sPopupSize.y / 2.f; + ImGui::SetNextWindowPos(popupPos, ImGuiCond_Appearing); + + ImGui::OpenPopup("Confirmation##DEL"); + if (ImGui::BeginPopupModal("Confirmation##DEL", &pendingDisconnectOpen, + ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::NewLine(); + ImGui::TextUnformatted( + "Are you certain you want to disconnect\nfrom this client " + "configuration ?"); + ImGui::SetNextItemWidth(-1.0f); + + if (ImGui::BeginListBox( + "##", ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 2.f))) { + ImGui::TextUnformatted(client.mInfoName); + ImGui::EndListBox(); + } + + ImGui::NewLine(); + ImGui::Separator(); + if (ImGui::Button("Cancel", + ImVec2(ImGui::GetContentRegionAvail().x / 2.f, 0)) || + wantExit) { + pendingDisconnectOpen = false; + } + ImGui::SetItemDefaultFocus(); + + ImGui::SameLine(); + if (ImGui::Button("Yes", ImVec2(ImGui::GetContentRegionAvail().x, 0)) && + gPopup_ConfirmDisconnect_ClientIdx != kClientRemoteInvalid) { + client.mbDisconnectPending = true; + pendingDisconnectOpen = false; + } + sPopupSize = ImGui::GetWindowSize(); + ImGui::EndPopup(); + } + } + + if (!pendingDisconnectOpen) { + gPopup_ConfirmDisconnect_ClientIdx = kClientRemoteInvalid; + } +} + +//================================================================================================= +// Display information about NetImgui Server application +//================================================================================================= +void Popup_AboutNetImgui() { + if (gPopup_AboutNetImgui_Show) { + static ImVec2 sPopupSize = ImVec2(250.f, 200.f); + ImGuiWindowClass windowClass; + windowClass.ViewportFlagsOverrideSet = ImGuiViewportFlags_TopMost; + ImGui::SetNextWindowClass(&windowClass); + + ImGuiViewport* pViewport = ImGui::GetWindowViewport(); + ImVec2 popupPos = pViewport->Pos; + popupPos.x += pViewport->Size.x / 2.f - sPopupSize.x / 2.f; + popupPos.y += pViewport->Size.y / 2.f - sPopupSize.y / 2.f; + ImGui::SetNextWindowPos(popupPos, ImGuiCond_Appearing); + ImGui::OpenPopup("About NetImgui..."); + if (ImGui::BeginPopupModal("About NetImgui...", &gPopup_AboutNetImgui_Show, + ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::NewLine(); + ImGui::Text("Version : %s", NETIMGUI_VERSION); + ImGui::NewLine(); + ImGui::Text("For more informations : "); + + ImGui::TextColored(ImColor(0.5f, 0.5f, 1.f, 1.f), kNetImguiURL); + + ImGui::NewLine(); + ImGui::TextUnformatted( + "Note: Commandline can be used to connect to a Client."); + ImGui::TextColored(kColorContent, "Syntax : (HostName);(HostPort)"); + ImGui::TextColored(kColorContent, + "Example: netImgui_Server.exe 127.0.0.1;8889"); + ImGui::NewLine(); + ImGui::Separator(); + + bool wantExit = ImGui::IsKeyPressed(ImGuiKey_Escape); + wantExit |= ImGui::IsKeyPressed(ImGuiKey_Enter); + if (ImGui::Button("Close", ImVec2(ImGui::GetContentRegionAvail().x, 0)) || + wantExit) + gPopup_AboutNetImgui_Show = false; + sPopupSize = ImGui::GetWindowSize(); + ImGui::EndPopup(); + } + } +} + +//================================================================================================= +// Edit the Server configuration +//================================================================================================= +void Popup_ServerConfig() { + static int sEditPort = -1; + static float sEditRefreshFPSActive = 0; + static float sEditRefreshFPSInactive = 0; + static bool sEditCompressionEnable = true; + static int sEditServerFontSize = 0; + static float sSavedDPIScalePourcentage = 0.f; + if (gPopup_ServerConfig_Show) { + if (sEditPort == -1) { + sEditPort = static_cast(NetImguiServer::Config::Server::sPort); + sEditRefreshFPSActive = NetImguiServer::Config::Server::sRefreshFPSActive; + sEditRefreshFPSInactive = + NetImguiServer::Config::Server::sRefreshFPSInactive; + sEditCompressionEnable = + NetImguiServer::Config::Server::sCompressionEnable; + sEditServerFontSize = (int)NetImguiServer::Config::Server::sFontSize; + sSavedDPIScalePourcentage = + NetImguiServer::Config::Server::sDPIScaleRatio; + } + + static ImVec2 sPopupSize = ImVec2(250.f, 200.f); + ImGuiWindowClass windowClass; + windowClass.ViewportFlagsOverrideSet = ImGuiViewportFlags_TopMost; + ImGui::SetNextWindowClass(&windowClass); + + ImGuiViewport* pViewport = ImGui::GetWindowViewport(); + ImVec2 popupPos = pViewport->Pos; + popupPos.x += pViewport->Size.x / 2.f - sPopupSize.x / 2.f; + popupPos.y += pViewport->Size.y / 2.f - sPopupSize.y / 2.f; + ImGui::SetNextWindowPos(popupPos, ImGuiCond_Appearing); + ImGui::OpenPopup("Server Configuration"); + if (ImGui::BeginPopupModal("Server Configuration", + &gPopup_ServerConfig_Show, + ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::NewLine(); + + // --- Port --- + ImGui::TextUnformatted("Port waiting for connection requests"); + if (ImGui::InputInt("Port", &sEditPort, 1, 100, 0)) { + sEditPort = std::min(0xFFFF, std::max(1, sEditPort)); + } + ImGui::SameLine(); + if (ImGui::Button("Default")) { + sEditPort = NetImgui::kDefaultServerPort; + } + + // --- Refresh --- + ImGui::SliderFloat("Active Window", &sEditRefreshFPSActive, 0.f, 60.f, + "%2.f Fps"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "How often we refresh content of *visible* and *focused* " + "clients.\nNote: Lowering this will reduce network traffic."); + } + + ImGui::SliderFloat("Inactive Window", &sEditRefreshFPSInactive, 0.f, 60.f, + "%2.f Fps"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "How often we refresh content of *visible* and *unfocused* " + "clients.\nNote: Lowering this will reduce network traffic."); + } + + // --- Font Size --- + ImGui::SliderInt("Server UI Font size", &sEditServerFontSize, 8, 32, + "%2i pts"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Font size for Server UI elements. This does not control the size " + "of text of remote client content."); + } + + // --- DPI Scale --- + constexpr float kStepSize = 5.f; + float scalePourcentage = + NetImguiServer::Config::Server::sDPIScaleRatio * 100.f; + ImGui::SliderFloat("DPI Scale Factor", &scalePourcentage, 0.f, 200.f, + "%4.f %%"); + scalePourcentage = round(scalePourcentage / kStepSize) * kStepSize; + NetImguiServer::Config::Server::sDPIScaleRatio = scalePourcentage / 100.f; + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Amount of Font scaling applied on high resolution " + "monitors.\n(Helps with tiny text)"); + } + + // --- Data Compression --- + ImGui::Checkbox("Use Compression", &sEditCompressionEnable); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Enable data compression between Client/Server communications.\n" + "Greatly reduce bandwidth for a small CPU overhead on the client.\n" + "Note: This setting can be overridden on client side."); + } + + // --- Save/Cancel --- + ImGui::NewLine(); + ImGui::Separator(); + bool wantExit = ImGui::IsKeyPressed(ImGuiKey_Escape); + gPopup_ServerConfig_Show &= + !ImGui::Button("Cancel", + ImVec2(ImGui::GetContentRegionAvail().x / 2.f, 0)) && + !wantExit; + ImGui::SetItemDefaultFocus(); + ImGui::SameLine(); + // Save settings + if (ImGui::Button("Save", ImVec2(ImGui::GetContentRegionAvail().x, 0))) { + NetImguiServer::Config::Server::sPort = + static_cast(sEditPort); + NetImguiServer::Config::Server::sRefreshFPSActive = + sEditRefreshFPSActive; + NetImguiServer::Config::Server::sRefreshFPSInactive = + sEditRefreshFPSInactive; + NetImguiServer::Config::Server::sCompressionEnable = + sEditCompressionEnable; + NetImguiServer::Config::Server::sFontSize = (float)sEditServerFontSize; + NetImguiServer::Config::Client::SaveAll(); + gPopup_ServerConfig_Show = false; + } + // Restore settings + else if (!gPopup_ServerConfig_Show) { + NetImguiServer::Config::Server::sDPIScaleRatio = + sSavedDPIScalePourcentage; + } + + sPopupSize = ImGui::GetWindowSize(); + ImGui::EndPopup(); + } + } + + if (!gPopup_ServerConfig_Show) { + sEditPort = -1; + } +} + +//================================================================================================= +// Edit a new or existing client settings +//================================================================================================= +void Popup_ClientConfigEdit() { + bool bOpenEdit(gPopup_ClientConfig_pConfig != nullptr); + if (bOpenEdit) { + static ImVec2 sPopupSize = ImVec2(250.f, 200.f); + static bool sAnyItemWasActive = + false; // Keep track if any item was in 'edit' mode the previous frame + bool bSkipEscapeKey = false; // Ignore 'Esc key' when it was used to revert + // field change/stop editing a field + + ImGuiWindowClass windowClass; + windowClass.ViewportFlagsOverrideSet = ImGuiViewportFlags_TopMost; + ImGui::SetNextWindowClass(&windowClass); + ImGuiViewport* pViewport = ImGui::GetWindowViewport(); + ImVec2 popupPos = + ImVec2(pViewport->Pos.x + pViewport->Size.x / 2.f - sPopupSize.x / 2.f, + pViewport->Pos.y + pViewport->Size.y / 2.f - sPopupSize.y / 2.f); + ImGui::SetNextWindowPos(popupPos, ImGuiCond_Appearing); + ImGui::OpenPopup("Edit Client Info"); + if (ImGui::BeginPopupModal("Edit Client Info", &bOpenEdit, + ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::NewLine(); + // --- Name --- + ImGui::InputText("Display Name", gPopup_ClientConfig_pConfig->mClientName, + sizeof(gPopup_ClientConfig_pConfig->mClientName)); + + // --- IP Address --- + ImGui::InputText("Host Name", gPopup_ClientConfig_pConfig->mHostName, + sizeof(gPopup_ClientConfig_pConfig->mHostName)); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("IP address or name of the host to reach"); + } + + // --- Port --- + int port = static_cast(gPopup_ClientConfig_pConfig->mHostPort); + if (ImGui::InputInt("Host Port", &port, 1, 100, + ImGuiInputTextFlags_None)) { + gPopup_ClientConfig_pConfig->mHostPort = + std::min(0xFFFF, std::max(1, port)); + } + ImGui::SameLine(); + if (ImGui::Button("Default")) { + gPopup_ClientConfig_pConfig->mHostPort = NetImgui::kDefaultClientPort; + } + + // --- Auto --- + ImGui::Checkbox("Auto Connect", + &gPopup_ClientConfig_pConfig->mConnectAuto); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Server automatically detect when this client is available and " + "connect to it."); + } + + // --- DPI Scale --- + ImGui::Checkbox("DPI Scale", + &gPopup_ClientConfig_pConfig->mDPIScaleEnabled); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Text content will be scaled up on high resolution monitors for " + "increased readability."); + } + + // --- Takeover Config --- + ImGui::Checkbox("Block Takeover", + &gPopup_ClientConfig_pConfig->mBlockTakeover); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Enabled this if you want to prevent other NetImguiServers to " + "forcefully disconnect this client and take over the connection."); + } + + // --- Shared Config --- + if (NetImguiServer::App::HAL_GetUserSettingFolder() != nullptr) { + bool isShared = gPopup_ClientConfig_pConfig->mConfigType == + NetImguiServer::Config::Client::eConfigType::Shared; + if (ImGui::Checkbox("Shared Config", &isShared)) { + gPopup_ClientConfig_pConfig->mConfigType = + isShared ? NetImguiServer::Config::Client::eConfigType::Shared + : NetImguiServer::Config::Client::eConfigType::Pending; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Client's settings are saved in 'Working Directory' by " + "default.\nEnabling this option saves their settings in the " + "'User Directory', making it available no matter which folder " + "the Server Application is launched from."); + } + } + + // --- Save/Cancel --- + ImGui::NewLine(); + ImGui::Separator(); + bOpenEdit &= !ImGui::Button( + "Cancel", ImVec2(ImGui::GetContentRegionAvail().x / 2.f, 0)); + ImGui::SetItemDefaultFocus(); + ImGui::SameLine(); + if (ImGui::Button("Save", ImVec2(ImGui::GetContentRegionAvail().x, 0))) { + NetImguiServer::Config::Client::SetConfig(*gPopup_ClientConfig_pConfig); + NetImguiServer::Config::Client::SaveAll(); + bOpenEdit = false; + } + + bSkipEscapeKey = sAnyItemWasActive != ImGui::IsAnyItemActive(); + sAnyItemWasActive = ImGui::IsAnyItemActive(); + sPopupSize = ImGui::GetWindowSize(); + ImGui::EndPopup(); + } + + bool wantExit = !bSkipEscapeKey && ImGui::IsKeyPressed(ImGuiKey_Escape); + bOpenEdit &= !wantExit; + } + + if (!bOpenEdit) { + NetImgui::Internal::netImguiDeleteSafe(gPopup_ClientConfig_pConfig); + } +} + +//================================================================================================= +// Client Config Delete Confirmation +//================================================================================================= +void Popup_ClientConfigDelete() { + NetImguiServer::Config::Client config; + bool bOpenDelConfirm(NetImguiServer::Config::Client::GetConfigByID( + gPopup_ConfirmDelete_ConfigIdx, config)); + if (bOpenDelConfirm) { + static ImVec2 sPopupSize = ImVec2(250.f, 200.f); + ImGuiWindowClass windowClass; + windowClass.ViewportFlagsOverrideSet = ImGuiViewportFlags_TopMost; + ImGui::SetNextWindowClass(&windowClass); + + ImGuiViewport* pViewport = ImGui::GetWindowViewport(); + ImVec2 popupPos = pViewport->Pos; + popupPos.x += pViewport->Size.x / 2.f - sPopupSize.x / 2.f; + popupPos.y += pViewport->Size.y / 2.f - sPopupSize.y / 2.f; + ImGui::SetNextWindowPos(popupPos, ImGuiCond_Appearing); + ImGui::OpenPopup("Confirmation##DEL"); + if (ImGui::BeginPopupModal("Confirmation##DEL", &bOpenDelConfirm, + ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::NewLine(); + ImGui::TextUnformatted( + "Are you certain you want to remove\nthis client configuration ?"); + ImGui::SetNextItemWidth(-1.0f); + if (ImGui::BeginListBox( + "##", ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 2.f))) { + ImGui::TextUnformatted(config.mClientName); + ImGui::EndListBox(); + } + + ImGui::NewLine(); + ImGui::Separator(); + bOpenDelConfirm &= !ImGui::Button( + "Cancel", ImVec2(ImGui::GetContentRegionAvail().x / 2.f, 0)); + ImGui::SetItemDefaultFocus(); + + ImGui::SameLine(); + if (ImGui::Button("Yes", ImVec2(ImGui::GetContentRegionAvail().x, 0))) { + NetImguiServer::Config::Client::DelConfig( + gPopup_ConfirmDelete_ConfigIdx); + NetImguiServer::Config::Client::SaveAll(); + bOpenDelConfirm = false; + } + sPopupSize = ImGui::GetWindowSize(); + ImGui::EndPopup(); + } + + bool wantExit = ImGui::IsKeyPressed(ImGuiKey_Escape); + bOpenDelConfirm &= !wantExit; + if (!bOpenDelConfirm) { + gPopup_ConfirmDelete_ConfigIdx = + NetImguiServer::Config::Client::kInvalidRuntimeID; + } + } +} + +//================================================================================================= +// Setuping the docking of our application +//================================================================================================= +void DrawImguiContent_SetupDocking() { + if (gMainDockID == 0) { + gMainDockID = ImGui::GetID("MainDockID"); + } + + // We are using the ImGuiWindowFlags_NoDocking flag to make the parent window + // not dockable into, + // because it would be confusing to have two docking targets within each + // others. + ImGuiViewport* viewport = ImGui::GetMainViewport(); + ImGuiWindowFlags window_flags = + ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground; + window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; + window_flags |= + ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; + ImGui::SetNextWindowPos(viewport->WorkPos); + ImGui::SetNextWindowSize(viewport->WorkSize); + ImGui::SetNextWindowViewport(viewport->ID); + + // Important: note that we proceed even if Begin() returns false (aka window + // is collapsed). + // This is because we want to keep our DockSpace() active. If a DockSpace() is + // inactive, all active windows docked into it will lose their parent and + // become undocked. We cannot preserve the docking relationship between an + // active window and an inactive docking, otherwise any change of + // dockspace/settings would lead to windows being stuck in limbo and never + // being visible. + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.f, 4.f)); + ImGui::Begin("DockSpace", nullptr, window_flags); + ImGui::PopStyleVar(3); + DrawCenteredBackground(gpBackgroundTexture, kColorBGTint); + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DockingEnable) { + ImGui::DockSpace(gMainDockID, ImVec2(0.0f, 0.0f), + ImGuiDockNodeFlags_PassthruCentralNode); + } + + ImGui::End(); +} + +//================================================================================================= +// Display the dockable window of each connected client we can interact with +//================================================================================================= +void DrawImguiContent_Clients() { + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.f, 0.f)); + + //--------------------------------------------------------------------------------------------- + // Display each connected client window + //--------------------------------------------------------------------------------------------- + bool hasConnection(false), hasClipboardSet(false); + for (uint32_t i(0); i < RemoteClient::Client::GetCountMax(); ++i) { + RemoteClient::Client& client = RemoteClient::Client::Get(i); + if (client.mbIsConnected) { + ImGui::PushID(i); + ImGui::SetNextWindowBgAlpha(1.0); + ImGui::SetNextWindowDockID(gMainDockID, ImGuiCond_Once); + bool bOpened = true; + hasConnection = true; + client.mbIsVisible = ImGui::Begin( + client.mWindowID, &bOpened, + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f)); + ClientInfoTooltip(client); + ImGui::PopStyleVar(1); + + // Capture input to forward to remote client, and update drawing area size + ImVec2 areaSize = ImGui::GetContentRegionAvail(); + client.mAreaSizeX = static_cast(std::max( + 8.f, areaSize.x)); // Prevents issue with render target of size 0 + client.mAreaSizeY = + static_cast(std::max(8.f, areaSize.y)); + client.CaptureImguiInput(); + + if (client.mbIsVisible) { + // Display remote client drawing results + if (client.mHAL_AreaTexture.Status == + ImTextureStatus::ImTextureStatus_OK && + areaSize.x > 0 && areaSize.y > 0) { + // Add fake button to discard mouse input (prevent window moving when + // draging inside client area) + ImVec2 savedPos = ImGui::GetCursorPos(); + ImGui::InvisibleButton("canvas", areaSize, + ImGuiButtonFlags_MouseButtonLeft | + ImGuiButtonFlags_MouseButtonRight | + ImGuiButtonFlags_MouseButtonMiddle); + ImGui::SetCursorPos(savedPos); + + // Display Client Context + ImTextureRef clientFrameTexRef; + clientFrameTexRef._TexData = &client.mHAL_AreaTexture; + ImGui::Image(clientFrameTexRef, areaSize, + ImVec2(0, HAL_API_RENDERTARGET_INVERT_Y ? 1 : 0), + ImVec2(1, HAL_API_RENDERTARGET_INVERT_Y ? 0 : 1)); + + if (ImGui::IsItemHovered()) { + ImGui::SetMouseCursor(client.mMouseCursor); + } + } + } + ImGui::End(); + if (!bOpened && client.mbIsConnected) { + gPopup_ConfirmDisconnect_ClientIdx = i; + } + ImGui::PopID(); + + // Clipboard Received from Client + NetImgui::Internal::CmdClipboard* pClientIncomingClipboard = + client.mPendingClipboardIn.Release(); + if (pClientIncomingClipboard) { + ImGui::SetClipboardText(pClientIncomingClipboard->mContentUTF8.Get()); + netImguiDeleteSafe(pClientIncomingClipboard); + hasClipboardSet = true; + } + } + } + + //--------------------------------------------------------------------------------------------- + // Retrieve Server Clipboard content and Update Clients Clipboard + //--------------------------------------------------------------------------------------------- + if (hasConnection) { + // Fetch OS clipboard (when supported by Dear ImGui backend) + static ImVector sSavedServerClipboard; + if (sSavedServerClipboard.empty()) { + sSavedServerClipboard.push_back(static_cast(0)); + } + bool clipboardContentUpdated(false); + if (NetImguiServer::App::HAL_GetClipboardUpdated() || hasClipboardSet) { + const char* serverClipboard = ImGui::GetClipboardText(); + serverClipboard = serverClipboard ? serverClipboard : ""; + clipboardContentUpdated = + strncmp(&sSavedServerClipboard[0], serverClipboard, + sSavedServerClipboard.size()) != 0; + if (clipboardContentUpdated) { + sSavedServerClipboard.resize(0); + while (*serverClipboard != 0) { + sSavedServerClipboard.push_back(*serverClipboard++); + } + sSavedServerClipboard.push_back(0); + } + } + // Forward Server Clipboard content to Clients + for (uint32_t i(0); i < RemoteClient::Client::GetCountMax(); ++i) { + RemoteClient::Client& client = RemoteClient::Client::Get(i); + const bool bFirstTimeDisplay = client.mpHAL_AreaRT == nullptr; + if (client.mbIsConnected && + (clipboardContentUpdated || bFirstTimeDisplay)) { + NetImgui::Internal::CmdClipboard* pClipboard = + NetImgui::Internal::CmdClipboard::Create(&sSavedServerClipboard[0]); + client.mPendingClipboardOut.Assign(pClipboard); + } + } + } + + //--------------------------------------------------------------------------------------------- + // Display some instruction when no connection detected + //--------------------------------------------------------------------------------------------- + if (!hasConnection) { + ImGui::SetNextWindowBgAlpha(1.0); + ImGui::SetNextWindowDockID(gMainDockID, ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(24.f, 24.f)); + if (ImGui::Begin("Information", nullptr, 0)) { + DrawCenteredBackground(gpBackgroundTexture, ImVec4(1.f, 1.f, 1.f, 0.15f)); + + ImGui::TextColored(kColorTitle, "%s", "Purpose:"); + ImGui::PushStyleColor(ImGuiCol_Text, kColorContent); + ImGui::TextWrapped( + "This 'NetImgui Server' application allows connection to clients " + "running with the 'NetImGui Library."); + ImGui::PopStyleColor(); + ImGui::NewLine(); + + ImGui::TextColored(kColorTitle, "%s", "Instructions:"); + ImGui::PushStyleColor(ImGuiCol_Text, kColorContent); + ImGui::TextWrapped( + "There are 2 ways of establishing a connection between this Server " + "and a Client."); + ImGui::TextWrapped( + " (A) The client can connect directly to this server, using " + "'NetImgui::ConnectToApp(...)' on port %i", + NetImguiServer::Config::Server::sPort); + ImGui::TextWrapped( + " (B) The client can wait for a Server connection using " + "'NetImgui::ConnectFrom(...)' and adding the Client configuration on " + "the Server."); + ImGui::PopStyleColor(); + ImGui::NewLine(); + + ImGui::TextColored(kColorTitle, "%s", "Note:"); + ImGui::PushStyleColor(ImGuiCol_Text, kColorContent); + ImGui::TextWrapped( + "'Multiple clients can be connected to this server. Each client " + "window can be undocked and moved around independently."); + ImGui::PopStyleColor(); + } + ImGui::End(); + ImGui::PopStyleVar(); + } + + ImGui::PopStyleVar(3); +} + +//================================================================================================= +// Main Menu client table entry detail (1 line in clients table) +//================================================================================================= +void DrawImguiContent_MainMenu_Clients_Entry( + RemoteClient::Client* pClient, + NetImguiServer::Config::Client* pClientConfig) { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + + // Name / Status + auto ConfigStatus = + pClientConfig ? pClientConfig->mConnectStatus + : NetImguiServer::Config::Client::eStatus::Disconnected; + ImVec4 StatusColor = + pClient && pClient->mbIsConnected ? ImVec4(0.7f, 1.f, 0.25f, 1.f) + : ConfigStatus == NetImguiServer::Config::Client::eStatus::ErrorVer + ? ImVec4(1.f, 0.7f, 0.25f, 1.f) + : ConfigStatus == NetImguiServer::Config::Client::eStatus::ErrorBusy + ? ImVec4(1.f, 0.7f, 0.25f, 1.f) + : ConfigStatus == NetImguiServer::Config::Client::eStatus::Available + ? ImVec4(1.f, 0.9f, 0.1f, 1.f) + : ImVec4(0.0f, 0.0f, 0.0f, 0.f); + ImGui::PushStyleColor(ImGuiCol_CheckMark, StatusColor); + ImGui::BeginDisabled(pClientConfig && pClientConfig->IsReadOnly()); + ImGui::RadioButton("##Connected", true); + ImGui::PopStyleColor(); + if (pClient && pClient->mbIsConnected) { + bool selected(false); + ImGui::SameLine(); + if (ImGui::Selectable( + pClient->mInfoName, &selected, ImGuiSelectableFlags_NoAutoClosePopups /* | ImGuiSelectableFlags_SpanAllColumns*/)) { + ImGui::SetWindowCollapsed(pClient->mWindowID, false); + ImGui::SetWindowFocus(pClient->mWindowID); + } + ClientInfoTooltip(*pClient); + } + + ImGui::SameLine(); + ImGui::Text("(%s)", pClientConfig ? pClientConfig->mClientName : "No Config"); + ImGui::TableNextColumn(); + + // Hostname info IP/Port + ImGui::Text("%s : %i", + pClientConfig ? pClientConfig->mHostName + : pClient ? pClient->mConnectHost + : "", + pClientConfig ? pClientConfig->mHostPort + : pClient ? pClient->mConnectPort + : 0); + if (ImGui::IsItemHovered() && pClient) { + ImGui::SetTooltip("Communications assigned port: %i", + pClient->mConnectPort); + } + ImGui::TableNextColumn(); + + // Config: AutoConnect + if (pClientConfig) { + if (ImGui::Checkbox("##auto", &pClientConfig->mConnectAuto)) { + NetImguiServer::Config::Client::SetProperty_ConnectAuto( + pClientConfig->mRuntimeID, pClientConfig->mConnectAuto); + NetImguiServer::Config::Client::SaveAll(); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Toggle auto connection attempt on this client"); + } + + ImGui::TableNextColumn(); + + if (ImGui::Button(" - ")) { + gPopup_ConfirmDelete_ConfigIdx = pClientConfig->mRuntimeID; + } + ImGui::SameLine(); + if (ImGui::Button(" ... ") && + !gPopup_ClientConfig_pConfig) // Only 1 config edit at a time, + // otherwise need to handle properly to + // avoid mem leak + { + gPopup_ClientConfig_pConfig = + NetImgui::Internal::netImguiNew( + *pClientConfig); + } + ImGui::TableNextColumn(); + } else { + ImGui::TableNextColumn(); + ImGui::TableNextColumn(); + } + ImGui::EndDisabled(); + + // Config: Connection + float kButtonWidth = + ImGui::GetFont() + ->CalcTextSizeA(ImGui::GetFontSize(), 500.f, 0.f, " Disconnect ") + .x; + if (pClient && !pClient->mbDisconnectPending && + ImGui::Button("Disconnect", ImVec2(kButtonWidth, 0))) { + gPopup_ConfirmDisconnect_ClientIdx = pClient->mClientIndex; + } else if (pClientConfig) { + if (pClientConfig->IsConnecting()) { + ImGui::SetNextItemWidth(kButtonWidth); + ImGui::TextUnformatted("(Connecting)"); + } else if (pClientConfig->IsTransient()) { + ImGui::SetNextItemWidth(kButtonWidth); + ImGui::TextUnformatted("(Request)"); + } else if (!pClientConfig->IsConnected() && + !pClientConfig->mConnectRequest && + !pClientConfig->mConnectForce) { + if (ConfigStatus == + NetImguiServer::Config::Client::eStatus::Disconnected) { + if (ImGui::Button("Connect", ImVec2(kButtonWidth, 0))) { + NetImguiServer::Config::Client::SetProperty_ConnectRequest( + pClientConfig->mRuntimeID, true, false); + } + } else if (ConfigStatus == + NetImguiServer::Config::Client::eStatus::Available) { + if (ImGui::Button("Takeover", ImVec2(kButtonWidth, 0))) { + NetImguiServer::Config::Client::SetProperty_ConnectRequest( + pClientConfig->mRuntimeID, true, true); + } + ImGui::SetItemTooltip( + "Client already connected to another NetImguiServer, disconnect it " + "and force connect this Server"); + } else if (ConfigStatus == + NetImguiServer::Config::Client::eStatus::ErrorBusy) { + ImGui::SetNextItemWidth(kButtonWidth); + ImGui::TextUnformatted("(In Use)"); + ImGui::SetItemTooltip( + "Client already connected to another NetImguiServer and doesn't " + "allow taking over the connection"); + } else if (ConfigStatus == + NetImguiServer::Config::Client::eStatus::ErrorVer) { + ImGui::SetNextItemWidth(kButtonWidth); + ImGui::TextUnformatted("(Version)"); + ImGui::SetItemTooltip( + "Client is using a different network protocol than this " + "NetImguiServer. Update the client code to match the Server."); + } + } + } +} + +//================================================================================================= +// MainMenu Entry : Client +// Display the list of connected and unconnected clients +//================================================================================================= +void DrawImguiContent_MainMenu_Clients() { + int connectedClient(0); + constexpr ImGuiTableFlags flags = + ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable | + ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2(4.f, 4.f)); + if (ImGui::BeginTable("##TableClient", 5, flags)) { + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("HostName (IP)", + ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("Auto", ImGuiTableColumnFlags_WidthFixed | + ImGuiTableColumnFlags_NoResize); + ImGui::TableSetupColumn("###Config", ImGuiTableColumnFlags_WidthFixed | + ImGuiTableColumnFlags_NoResize | + ImGuiTableColumnFlags_NoResize | + ImGuiTableColumnFlags_NoReorder); + ImGui::TableSetupColumn( + "###Connection", + ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize | + ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder); + ImGui::TableHeadersRow(); + + // First, display all connected clients without a config + ImGui::PushID("Connected"); + for (uint32_t i(0); i < RemoteClient::Client::GetCountMax(); ++i) { + RemoteClient::Client& client = RemoteClient::Client::Get(i); + if (client.mbIsConnected && + client.mClientConfigID == + NetImguiServer::Config::Client::kInvalidRuntimeID) { + ImGui::PushID(i); + DrawImguiContent_MainMenu_Clients_Entry(&client, nullptr); + ImGui::PopID(); + ++connectedClient; + } + } + ImGui::PopID(); + + // Next, display all connected clients with a config + NetImguiServer::Config::Client clientConfig; + ImGui::PushID("ConfigConnected"); + for (uint32_t i(0); i < RemoteClient::Client::GetCountMax(); ++i) { + RemoteClient::Client& client = RemoteClient::Client::Get(i); + if (client.mbIsConnected && NetImguiServer::Config::Client::GetConfigByID( + client.mClientConfigID, clientConfig)) { + ImGui::PushID(i); + DrawImguiContent_MainMenu_Clients_Entry(&client, &clientConfig); + ImGui::PopID(); + ++connectedClient; + } + } + ImGui::PopID(); + + // Finally, display unconnected client configs + ImGui::PushID("ConfigUnconnected"); + for (int i = 0; + NetImguiServer::Config::Client::GetConfigByIndex(i, clientConfig); + ++i) { + if (!clientConfig.IsConnected()) { + ImGui::PushID(i); + DrawImguiContent_MainMenu_Clients_Entry(nullptr, &clientConfig); + ImGui::PopID(); + } + } + ImGui::PopID(); + + // Info about Server waiting on connection + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.f, 0.35f, 0.35f, 1.f)); + ImGui::RadioButton("##ServerPortStatus", + !NetImguiServer::Network::IsWaitingForConnection()); + ImGui::PopStyleColor(); + ImGui::SameLine(); + if (NetImguiServer::Network::IsWaitingForConnection()) { + ImGui::Text("Waiting for clients on port: %i", + static_cast(NetImguiServer::Config::Server::sPort)); + } else { + ImGui::Text("Unable to accept clients on port: %i", + static_cast(NetImguiServer::Config::Server::sPort)); + } + } + ImGui::EndTable(); + } + ImGui::PopStyleVar(2); + + // Button to create new client configs + { + ImGui::NewLine(); + if (ImGui::Button("Add Client Config") && !gPopup_ClientConfig_pConfig) { + gPopup_ClientConfig_pConfig = + NetImgui::Internal::netImguiNew(); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Clients configurations let this 'NetImgui Server' attempt " + "connection to waiting clients (Server -> Client).\n" + "Clients without configuration can also connect directly to this " + "server on port : %i (Server <- Client).", + static_cast(NetImguiServer::Config::Server::sPort)); + } + + ImGui::SameLine(0.f, 16.f); + ImGui::TextUnformatted("Note:"); + ImGui::SameLine(); + ImGui::TextColored(ImVec4(0.75f, 0.75f, 0.75f, 1.f), + "%i connected client(s)", connectedClient); + if (connectedClient == 0 && ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Make sure your remote client either:" + "\n -Attempts connection to this server on port (%i)" + "\n -Waits connection from the server (after being added to client " + "configs list)", + NetImguiServer::Config::Server::sPort); + } + } +} + +//================================================================================================= +// Display some relevenant stats in the MainMenu bar +//================================================================================================= +void DrawImguiContent_MainMenu_Stats() { + uint32_t txKBs(0), rxKBs(0), connected(0); + for (uint32_t i(0); i < RemoteClient::Client::GetCountMax(); ++i) { + RemoteClient::Client& client = RemoteClient::Client::Get(i); + txKBs += client.mbIsConnected ? client.mStatsSentBps / 1024 : 0; + rxKBs += client.mbIsConnected ? client.mStatsRcvdBps / 1024 : 0; + connected += client.mbIsConnected ? 1 : 0; + } + + float textWidth = ImGui::CalcTextSize("(Rx)0000KB/s (Tx) 0000KB/s").x; + ImGui::SameLine(0.f, ImGui::GetContentRegionAvail().x - textWidth); + ImGui::TextColored(kColorContent, "(Rx) %4iKB/s (Tx) %4iKB/s", rxKBs, txKBs); + if (ImGui::IsItemHovered()) { + uint64_t txData(NetImguiServer::Network::GetStatsDataSent()); + uint64_t rxData(NetImguiServer::Network::GetStatsDataRcvd()); + uint8_t txUnitIdx = ConvertDataAmount(txData); + uint8_t rxUnitIdx = ConvertDataAmount(rxData); + ImGui::BeginTooltip(); + { + float width = ImGui::CalcTextSize("Data Received ").x; + ImGui::TextUnformatted("Connections"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %i", connected); + ImGui::TextUnformatted("Data Received"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %i %s", static_cast(rxData), + kDataSizeUnits[rxUnitIdx]); + ImGui::TextUnformatted("Data Sent"); + ImGui::SameLine(width); + ImGui::TextColored(kColorContent, ": %i %s", static_cast(txData), + kDataSizeUnits[txUnitIdx]); + } + ImGui::EndTooltip(); + } +} + +//================================================================================================= +// Generate the entries for the main menubar +//================================================================================================= +void DrawImguiContent_MainMenu() { + if (ImGui::BeginMainMenuBar()) { + ImGui::SetNextWindowSize( + ImVec2(ImGui::GetContentRegionAvail().x, + 0)); // Will let Menu popup content fill the screen width + if (ImGui::BeginMenu("Clients")) { + DrawImguiContent_MainMenu_Clients(); + ImGui::EndMenu(); + } + + gPopup_ServerConfig_Show ^= ImGui::MenuItem("Settings"); + gPopup_AboutNetImgui_Show ^= ImGui::MenuItem("About"); + DrawImguiContent_MainMenu_Stats(); + ImGui::EndMainMenuBar(); + } +} + +//================================================================================================= +// Main entry point for rendering all of our NetImguiServer UI +//================================================================================================= +ImVec4 DrawImguiContent() { + constexpr float kHysteresis = 0.05f; + float elapsedMicroS = + static_cast(std::chrono::duration_cast( + std::chrono::steady_clock::now() - gLastUIUpdate) + .count()); + gLastUIUpdate = std::chrono::steady_clock::now(); + gDisplayFPS = gDisplayFPS * (1.f - kHysteresis) + + (1000000.f / elapsedMicroS) * kHysteresis; + + ImGui::PushFont(nullptr, NetImguiServer::Config::Server::sFontSize); + Popup_ServerConfig(); + Popup_ClientConfigEdit(); + Popup_ClientConfigDelete(); + Popup_ConfirmDisconnect(); + Popup_AboutNetImgui(); + + DrawImguiContent_MainMenu(); + DrawImguiContent_SetupDocking(); + DrawImguiContent_Clients(); + // ImGui::ShowDemoWindow(); + ImGui::PopFont(); + + return kColorBGClear; +} + +//================================================================================================= +// Startup : Initialize resources used by out server UI +//================================================================================================= +bool Startup() { + int Width(0), Height(0), Channel(0); + stbi_uc* pBGPixels = + stbi_load("Background.png", &Width, &Height, &Channel, 0); + if (pBGPixels) { + // @Sammyfreg TODO : Support multiple format for Background + NetImgui::Internal::CmdTexture cmdTexture; + constexpr NetImgui::eTexFormat format = NetImgui::eTexFormat::kTexFmtRGBA8; + const uint32_t textureBytes = + NetImgui::GetTexture_BytePerImage(format, Width, Height); + cmdTexture.mTextureClientID = 0; + cmdTexture.mFormat = format; + cmdTexture.mWidth = static_cast(Width); + cmdTexture.mHeight = static_cast(Height); + cmdTexture.mpTextureData.SetPtr((uint8_t*)pBGPixels); + gpBackgroundTexture = App::CreateTexture(cmdTexture, textureBytes); + stbi_image_free(pBGPixels); + } + + ImGui::GetStyle().WindowMenuButtonPosition = ImGuiDir_Right; + ImGui::GetStyle().TabBorderSize = 1.f; + return true; +} + +//================================================================================================= +// Shutdown : Free resources +//================================================================================================= +void Shutdown() {} + +//================================================================================================= +// Return the current average FPS of UI refreshed (tied to GPU VSync setting of +// backend) +//================================================================================================= +float GetDisplayFPS() { return gDisplayFPS; } + +} // namespace UI +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_UI.h b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_UI.h new file mode 100644 index 00000000..6ee156bb --- /dev/null +++ b/python/mujoco/experimental/netimgui/Code/ServerApp/Source/NetImguiServer_UI.h @@ -0,0 +1,26 @@ +// Google modifications: +// - Added #include for uint32_t (not implicitly available in Google) + +#pragma once + +#include +#include + +namespace NetImguiServer { +namespace App { +struct ServerTexture; +} +} // namespace NetImguiServer + +namespace NetImguiServer { +namespace UI { +constexpr uint32_t kWindowDPIDefault = 96; +bool Startup(); +void Shutdown(); +ImVec4 DrawImguiContent(); +void DrawCenteredBackground(const App::ServerTexture* Texture, + const ImVec4& tint = ImVec4(1.f, 1.f, 1.f, 1.f)); +float GetDisplayFPS(); +const App::ServerTexture* GetBackgroundTexture(); +} // namespace UI +} // namespace NetImguiServer diff --git a/python/mujoco/experimental/netimgui/LICENSE b/python/mujoco/experimental/netimgui/LICENSE new file mode 100644 index 00000000..3974d916 --- /dev/null +++ b/python/mujoco/experimental/netimgui/LICENSE @@ -0,0 +1,240 @@ +MIT License + +Copyright (c) 2021 Sammy Fatnassi (Github: @Sammyfreg) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +============= +Code in the google subdirectory is licensed under the Apache License: + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + Copyright 2026 DeepMind Technologies Limited + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/python/mujoco/experimental/netimgui/google/NetImgui_NetworkWASM.cpp b/python/mujoco/experimental/netimgui/google/NetImgui_NetworkWASM.cpp new file mode 100644 index 00000000..db831cff --- /dev/null +++ b/python/mujoco/experimental/netimgui/google/NetImgui_NetworkWASM.cpp @@ -0,0 +1,324 @@ +// Copyright 2026 DeepMind Technologies Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// WASM networking backend for NetImgui. +// +// Implements the NetImgui::Internal::Network interface using Emscripten +// WebSockets. This file is compiled only under the Emscripten toolchain and +// provides the browser-side transport layer for netimgui draw data. +#include "NetImgui_Shared.h" + +#ifndef __EMSCRIPTEN__ +#error "This file must be compiled with emscripten." +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include "NetImgui_CmdPackets.h" +#include "google/logging.h" +#include "google/network_status.h" + +namespace NetImgui { +namespace Internal { +namespace Network { + +struct SocketInfo { + EMSCRIPTEN_WEBSOCKET_T mSocket = 0; + std::atomic mConnected{false}; + std::atomic mError{false}; + std::atomic mClosed{false}; + std::atomic mCloseCode{0}; + + std::vector mBuffer; + std::mutex mBufferMutex; + int mSendSizeMax = + 1024 * 1024; // Interface compatibility with other backends +}; + +// --- WebSocket event callbacks --- + +static EM_BOOL OnWebSocketOpen(int /*event_type*/, + const EmscriptenWebSocketOpenEvent* /*event*/, + void* user_data) { + auto* socket = static_cast(user_data); + if (socket) { + socket->mConnected = true; + } + return EM_TRUE; +} + +static EM_BOOL OnWebSocketMessage(int /*event_type*/, + const EmscriptenWebSocketMessageEvent* event, + void* user_data) { + auto* socket = static_cast(user_data); + if (socket && !event->isText) { + std::lock_guard lock(socket->mBufferMutex); + size_t old_size = socket->mBuffer.size(); + socket->mBuffer.insert(socket->mBuffer.end(), event->data, + event->data + event->numBytes); + static int msg_count = 0; + ++msg_count; + VLOG(1, "onmessage #%d: %d bytes, buffer: %zu -> %zu", msg_count, + event->numBytes, old_size, socket->mBuffer.size()); + } else if (socket && event->isText) { + VLOG(1, "onmessage: TEXT frame (%d bytes), IGNORED", event->numBytes); + } + return EM_TRUE; +} + +static EM_BOOL OnWebSocketClose(int /*event_type*/, + const EmscriptenWebSocketCloseEvent* event, + void* user_data) { + auto* socket = static_cast(user_data); + if (socket) { + socket->mClosed = true; + socket->mCloseCode = event->code; + } + return EM_TRUE; +} + +static EM_BOOL OnWebSocketError(int /*event_type*/, + const EmscriptenWebSocketErrorEvent* /*event*/, + void* user_data) { + auto* socket = static_cast(user_data); + if (socket) { + socket->mError = true; + } + return EM_TRUE; +} + +// --- Network interface implementation --- + +bool Startup() { return emscripten_websocket_is_supported(); } + +void Shutdown() {} + +SocketInfo* Connect(const char* server_host, uint32_t /*server_port*/) { + if (!emscripten_websocket_is_supported()) return nullptr; + + SocketInfo* socket_info = netImguiNew(); + + EmscriptenWebSocketCreateAttributes attr; + emscripten_websocket_init_create_attributes(&attr); + + // The web viewer always passes a complete WebSocket URL (e.g. + // "ws://host:8080/ui", built from the page origin by WsUrl), so it is used + // verbatim and server_port is ignored — a browser reaches the viewer's + // paths on the page's own shared port, not a dedicated NetImgui port. + const std::string url(server_host); + attr.url = url.c_str(); + attr.createOnMainThread = EM_TRUE; + LOG(Info, "Connecting WebSocket to: %s", url.c_str()); + + socket_info->mSocket = emscripten_websocket_new(&attr); + if (socket_info->mSocket <= 0) { + netImguiDelete(socket_info); + return nullptr; + } + + emscripten_websocket_set_onopen_callback(socket_info->mSocket, socket_info, + OnWebSocketOpen); + emscripten_websocket_set_onmessage_callback(socket_info->mSocket, socket_info, + OnWebSocketMessage); + emscripten_websocket_set_onclose_callback(socket_info->mSocket, socket_info, + OnWebSocketClose); + emscripten_websocket_set_onerror_callback(socket_info->mSocket, socket_info, + OnWebSocketError); + + return socket_info; +} + +// Abandoned sockets are not freed immediately: with -pthread, websocket +// events are queued across threads, so an already-queued close/error event +// can still dereference the SocketInfo after emscripten_websocket_delete(). +// When the freed block was recycled for the next socket, such a late event +// stamped a stale mClosed flag onto a healthy connection, which the +// reconnect logic then tore down — a self-sustaining reconnect loop. Keep +// abandoned sockets in a small ring and free them several disconnects +// later, when any queued events are long gone. +static SocketInfo* s_socket_graveyard[8] = {}; +static int s_socket_graveyard_idx = 0; + +void Disconnect(SocketInfo* client_socket) { + if (!client_socket) return; + client_socket->mClosed = true; + // Detach this socket from future events; queued events may already hold + // the pointer (the graveyard above covers those). + emscripten_websocket_set_onopen_callback(client_socket->mSocket, nullptr, + OnWebSocketOpen); + emscripten_websocket_set_onmessage_callback(client_socket->mSocket, nullptr, + OnWebSocketMessage); + emscripten_websocket_set_onclose_callback(client_socket->mSocket, nullptr, + OnWebSocketClose); + emscripten_websocket_set_onerror_callback(client_socket->mSocket, nullptr, + OnWebSocketError); + emscripten_websocket_close(client_socket->mSocket, 1000, + "Normal Disconnection"); + emscripten_websocket_delete(client_socket->mSocket); + { + // Release the receive buffer now; only the flags must stay valid. + std::lock_guard lock(client_socket->mBufferMutex); + client_socket->mBuffer.clear(); + client_socket->mBuffer.shrink_to_fit(); + } + if (s_socket_graveyard[s_socket_graveyard_idx]) { + netImguiDelete(s_socket_graveyard[s_socket_graveyard_idx]); + } + s_socket_graveyard[s_socket_graveyard_idx] = client_socket; + s_socket_graveyard_idx = (s_socket_graveyard_idx + 1) % 8; +} + +bool DataReceivePending(SocketInfo* client_socket) { + if (!client_socket) return false; + + if (client_socket->mError || client_socket->mClosed) { + // Connection is dead — flush any buffered data so we stop processing + // stale commands that arrived before the close. + std::lock_guard lock(client_socket->mBufferMutex); + if (!client_socket->mBuffer.empty()) { + LOG(Warning, "Connection closed/error. Discarding %zu buffered bytes.", + client_socket->mBuffer.size()); + client_socket->mBuffer.clear(); + } + return false; + } + + std::lock_guard lock(client_socket->mBufferMutex); + return !client_socket->mBuffer.empty(); +} + +void DataReceive(SocketInfo* client_socket, PendingCom& pending_rcv) { + if (!client_socket || !pending_rcv.pCommand) { + pending_rcv.bError = true; + return; + } + + if (!client_socket->mConnected) { + pending_rcv.bError = false; // Not ready yet, caller will retry. + return; + } + + // The size field comes off the wire; a value smaller than what has already + // been read (e.g. a command header claiming < 8 bytes, from a corrupted or + // desynced stream) would underflow the subtraction below into a huge + // size_t and memcpy past the destination command buffer. + if (pending_rcv.pCommand->mSize < pending_rcv.SizeCurrent) { + LOG(Error, "DataReceive: wire size %u < %zu bytes already read; stream " + "is corrupt", + pending_rcv.pCommand->mSize, + static_cast(pending_rcv.SizeCurrent)); + pending_rcv.bError = true; + return; + } + + size_t bytes_to_read = pending_rcv.pCommand->mSize - pending_rcv.SizeCurrent; + if (bytes_to_read == 0) return; + + std::lock_guard lock(client_socket->mBufferMutex); + + VLOG(1, "DataReceive: want=%zu, have=%zu, cmd_size=%u, progress=%zu", + bytes_to_read, client_socket->mBuffer.size(), + pending_rcv.pCommand->mSize, pending_rcv.SizeCurrent); + + if (client_socket->mBuffer.empty()) { + if (client_socket->mError || client_socket->mClosed) { + pending_rcv.bError = true; + } + return; + } + + size_t bytes_to_consume = + std::min(bytes_to_read, client_socket->mBuffer.size()); + if (bytes_to_consume > 0) { + memcpy(reinterpret_cast(pending_rcv.pCommand) + + pending_rcv.SizeCurrent, + client_socket->mBuffer.data(), bytes_to_consume); + client_socket->mBuffer.erase( + client_socket->mBuffer.begin(), + client_socket->mBuffer.begin() + bytes_to_consume); + pending_rcv.SizeCurrent += bytes_to_consume; + pending_rcv.bError = false; + } +} + +void DataSend(SocketInfo* client_socket, PendingCom& pending_send) { + if (!client_socket || client_socket->mClosed || client_socket->mError || + !pending_send.pCommand) { + pending_send.bError = true; + return; + } + + if (!client_socket->mConnected) { + pending_send.bError = false; // Not ready yet, caller will retry. + return; + } + + size_t bytes_remaining = + pending_send.pCommand->mSize - pending_send.SizeCurrent; + if (bytes_remaining == 0) return; + + EMSCRIPTEN_RESULT result = emscripten_websocket_send_binary( + client_socket->mSocket, + reinterpret_cast(pending_send.pCommand) + + pending_send.SizeCurrent, + bytes_remaining); + + if (result == EMSCRIPTEN_RESULT_SUCCESS) { + pending_send.SizeCurrent += bytes_remaining; + pending_send.bError = false; + } else { + pending_send.bError = true; + } +} + +SocketInfo* ListenStart(uint32_t /*listen_port*/) { + return nullptr; // Browsers cannot open listening ports. +} + +SocketInfo* ListenConnect(SocketInfo* /*listen_socket*/) { return nullptr; } + +int GetCloseCode(SocketInfo* client_socket) { + return client_socket ? client_socket->mCloseCode.load() : 0; +} + +ReadyState GetReadyState(SocketInfo* client_socket) { + if (!client_socket) return ReadyState::kDisconnected; + if (client_socket->mError) return ReadyState::kError; + if (client_socket->mClosed) return ReadyState::kClosed; + + uint16_t ready_state = 0; + emscripten_websocket_get_ready_state(client_socket->mSocket, &ready_state); + switch (ready_state) { + case 0: + return ReadyState::kConnecting; + case 1: + return ReadyState::kOpen; + case 2: + return ReadyState::kClosing; + case 3: + return ReadyState::kClosed; + } + return ReadyState::kError; +} + +} // namespace Network +} // namespace Internal +} // namespace NetImgui diff --git a/python/mujoco/experimental/netimgui/google/logging.h b/python/mujoco/experimental/netimgui/google/logging.h new file mode 100644 index 00000000..4d307756 --- /dev/null +++ b/python/mujoco/experimental/netimgui/google/logging.h @@ -0,0 +1,100 @@ +// Copyright 2026 DeepMind Technologies Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef THIRD_PARTY_NETIMGUI_GOOGLE_LOGGING_H_ +#define THIRD_PARTY_NETIMGUI_GOOGLE_LOGGING_H_ + +#include + +#include +#include +#include +#include + +#if defined(__EMSCRIPTEN__) +#include +#endif + +namespace NetImgui { + +enum class LogSeverity { kInfo, kWarning, kError }; + +// Set to 1 or higher to enable VLOG messages at runtime. +constexpr int kLogVerbosity = 0; + +__attribute__((format(printf, 4, 5))) inline void NetImGuiLog( + LogSeverity severity, const char* file, int line, const char* fmt, ...) { + char buf[1024]; + const char* basename = strrchr(file, '/'); + basename = basename ? basename + 1 : file; + + auto now_tp = std::chrono::system_clock::now(); + time_t now = std::chrono::system_clock::to_time_t(now_tp); + auto now_usec = std::chrono::duration_cast( + now_tp.time_since_epoch()) + .count() % + 1000000; + struct tm tm_info; + localtime_r(&now, &tm_info); + + const char severity_char = severity == LogSeverity::kError ? 'E' + : severity == LogSeverity::kWarning ? 'W' + : 'I'; + + int prefix_len = snprintf( + buf, sizeof(buf), "%c%02d%02d %02d:%02d:%02d.%06d %s:%d] ", severity_char, + tm_info.tm_mon + 1, tm_info.tm_mday, tm_info.tm_hour, tm_info.tm_min, + tm_info.tm_sec, static_cast(now_usec), basename, line); + if (prefix_len < 0 || prefix_len >= static_cast(sizeof(buf))) { + prefix_len = 0; // overwrite prefix on error or truncation + } + + va_list args; + va_start(args, fmt); + vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, fmt, args); + va_end(args); + + if (severity == LogSeverity::kInfo) { +#if defined(__EMSCRIPTEN__) + emscripten_out(buf); +#else + fputs(buf, stdout); + fputc('\n', stdout); + fflush(stdout); +#endif + } else { +#if defined(__EMSCRIPTEN__) + emscripten_err(buf); +#else + fputs(buf, stderr); + fputc('\n', stderr); + fflush(stderr); +#endif + } +} + +} // namespace NetImgui + +#define LOG(severity, fmt, ...) \ + ::NetImgui::NetImGuiLog(::NetImgui::LogSeverity::k##severity, __FILE__, \ + __LINE__, fmt, ##__VA_ARGS__) + +#define VLOG(level, fmt, ...) \ + do { \ + if (::NetImgui::kLogVerbosity >= (level)) \ + ::NetImgui::NetImGuiLog(::NetImgui::LogSeverity::kInfo, __FILE__, \ + __LINE__, fmt, ##__VA_ARGS__); \ + } while (0) + +#endif // THIRD_PARTY_NETIMGUI_GOOGLE_LOGGING_H_ diff --git a/python/mujoco/experimental/netimgui/google/network_status.h b/python/mujoco/experimental/netimgui/google/network_status.h new file mode 100644 index 00000000..ce801f1c --- /dev/null +++ b/python/mujoco/experimental/netimgui/google/network_status.h @@ -0,0 +1,75 @@ +// Copyright 2026 DeepMind Technologies Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Connection-state query for the WASM WebSocket network backend. +// +// Stock NetImgui has no such query and does not need one: its Connect() +// implementations block until the connection is established, so a non-null +// SocketInfo is always usable and later failures surface as DataSend / +// DataReceive errors inside the client thread. In the browser, +// emscripten_websocket_new() returns a socket handle immediately while the +// connection completes (or fails) asynchronously, and no client state +// machine is watching it. Callers poll this state to hold back traffic +// until the socket is actually open and to detect closure for reconnecting. + +#ifndef THIRD_PARTY_NETIMGUI_GOOGLE_NETWORK_STATUS_H_ +#define THIRD_PARTY_NETIMGUI_GOOGLE_NETWORK_STATUS_H_ + +namespace NetImgui { +namespace Internal { +namespace Network { + +struct SocketInfo; + +enum class ReadyState { + kDisconnected, // Null socket. + kConnecting, + kOpen, + kClosing, + kClosed, + kError, +}; + +// Implemented in NetImgui_NetworkWASM.cpp (Emscripten builds only). +ReadyState GetReadyState(SocketInfo* client_socket); + +// The WebSocket close code once the socket has closed, else 0. Lets callers +// distinguish a deliberate server-side rejection (e.g. 4001 = driver slot +// taken) from an ordinary drop. Implemented in NetImgui_NetworkWASM.cpp. +int GetCloseCode(SocketInfo* client_socket); + +// Human-readable state name, for status overlays and logs. +inline const char* ReadyStateName(ReadyState state) { + switch (state) { + case ReadyState::kDisconnected: + return "Disconnected"; + case ReadyState::kConnecting: + return "Connecting"; + case ReadyState::kOpen: + return "Open"; + case ReadyState::kClosing: + return "Closing"; + case ReadyState::kClosed: + return "Closed"; + case ReadyState::kError: + return "Error"; + } + return "Unknown"; +} + +} // namespace Network +} // namespace Internal +} // namespace NetImgui + +#endif // THIRD_PARTY_NETIMGUI_GOOGLE_NETWORK_STATUS_H_