diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..029eeff --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,460 @@ +# This file is automatically generated from cmake.toml - DO NOT EDIT +# See https://github.com/build-cpp/cmkr for more information + +cmake_minimum_required(VERSION 3.15) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build") +endif() + +# Regenerate CMakeLists.txt automatically in the root project +set(CMKR_ROOT_PROJECT OFF) +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(CMKR_ROOT_PROJECT ON) + + # Bootstrap cmkr + include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT) + if(CMKR_INCLUDE_RESULT) + cmkr() + endif() + + # Enable folder support + set_property(GLOBAL PROPERTY USE_FOLDERS ON) +endif() + +# Create a configure-time dependency on cmake.toml to improve IDE support +if(CMKR_ROOT_PROJECT) + configure_file(cmake.toml cmake.toml COPYONLY) +endif() + +project(automatamp) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") + +if ("${CMAKE_BUILD_TYPE}" MATCHES "Release") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MT") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT") + + # Statically compile runtime + string(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "/MD" "/MT" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + string(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REGEX REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") + message(NOTICE "Building in Release mode") +endif() + +# Target spdlog +set(CMKR_TARGET spdlog) +set(spdlog_SOURCES "") + +list(APPEND spdlog_SOURCES + "dependencies/submodules/spdlog/src/async.cpp" + "dependencies/submodules/spdlog/src/cfg.cpp" + "dependencies/submodules/spdlog/src/color_sinks.cpp" + "dependencies/submodules/spdlog/src/file_sinks.cpp" + "dependencies/submodules/spdlog/src/fmt.cpp" + "dependencies/submodules/spdlog/src/spdlog.cpp" + "dependencies/submodules/spdlog/src/stdout_sinks.cpp" +) + +list(APPEND spdlog_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${spdlog_SOURCES}) +add_library(spdlog STATIC) + +if(spdlog_SOURCES) + target_sources(spdlog PRIVATE ${spdlog_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${spdlog_SOURCES}) + +target_compile_definitions(spdlog PUBLIC + SPDLOG_COMPILED_LIB +) + +target_include_directories(spdlog PUBLIC + "dependencies/submodules/spdlog/include" +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + +# Target glm_static +set(CMKR_TARGET glm_static) +set(glm_static_SOURCES "") + +list(APPEND glm_static_SOURCES + "dependencies/submodules/glm/glm/detail/glm.cpp" +) + +list(APPEND glm_static_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${glm_static_SOURCES}) +add_library(glm_static STATIC) + +if(glm_static_SOURCES) + target_sources(glm_static PRIVATE ${glm_static_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${glm_static_SOURCES}) + +target_include_directories(glm_static PUBLIC + "dependencies/submodules/glm" +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + +# Target enet +set(CMKR_TARGET enet) +set(enet_SOURCES "") + +list(APPEND enet_SOURCES + "dependencies/submodules/enet/callbacks.c" + "dependencies/submodules/enet/compress.c" + "dependencies/submodules/enet/host.c" + "dependencies/submodules/enet/list.c" + "dependencies/submodules/enet/packet.c" + "dependencies/submodules/enet/peer.c" + "dependencies/submodules/enet/protocol.c" + "dependencies/submodules/enet/unix.c" + "dependencies/submodules/enet/win32.c" +) + +list(APPEND enet_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${enet_SOURCES}) +add_library(enet STATIC) + +if(enet_SOURCES) + target_sources(enet PRIVATE ${enet_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${enet_SOURCES}) + +target_include_directories(enet PUBLIC + "dependencies/submodules/enet/include" +) + +target_link_libraries(enet PUBLIC + ws2_32 + winmm +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + +# Target imgui +set(CMKR_TARGET imgui) +set(imgui_SOURCES "") + +list(APPEND imgui_SOURCES + "dependencies/submodules/imgui/imgui.cpp" + "dependencies/submodules/imgui/imgui_demo.cpp" + "dependencies/submodules/imgui/imgui_draw.cpp" + "dependencies/submodules/imgui/imgui_tables.cpp" + "dependencies/submodules/imgui/imgui_widgets.cpp" +) + +list(APPEND imgui_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${imgui_SOURCES}) +add_library(imgui STATIC) + +if(imgui_SOURCES) + target_sources(imgui PRIVATE ${imgui_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${imgui_SOURCES}) + +target_compile_definitions(imgui PUBLIC + "IMGUI_USER_CONFIG=\"${CMAKE_SOURCE_DIR}/src/automata-imgui/automata_imconfig.hpp\"" +) + +target_include_directories(imgui PUBLIC + "dependencies/submodules/imgui" + "src/automata-imgui" +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + +# Target utility +set(CMKR_TARGET utility) +set(utility_SOURCES "") + +list(APPEND utility_SOURCES + "shared/utility/Address.cpp" + "shared/utility/Config.cpp" + "shared/utility/Crc32.cpp" + "shared/utility/FunctionHook.cpp" + "shared/utility/Memory.cpp" + "shared/utility/Module.cpp" + "shared/utility/Patch.cpp" + "shared/utility/Pattern.cpp" + "shared/utility/PointerHook.cpp" + "shared/utility/Registry.cpp" + "shared/utility/Scan.cpp" + "shared/utility/String.cpp" + "shared/utility/Thread.cpp" + "shared/utility/VehHook.cpp" + "shared/utility/VtableHook.cpp" + "shared/utility/Address.hpp" + "shared/utility/Config.hpp" + "shared/utility/Crc32.hpp" + "shared/utility/FunctionHook.hpp" + "shared/utility/Memory.hpp" + "shared/utility/Module.hpp" + "shared/utility/Patch.hpp" + "shared/utility/Pattern.hpp" + "shared/utility/PointerHook.hpp" + "shared/utility/Registry.hpp" + "shared/utility/Scan.hpp" + "shared/utility/String.hpp" + "shared/utility/Thread.hpp" + "shared/utility/VehHook.hpp" + "shared/utility/VtableHook.hpp" +) + +list(APPEND utility_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${utility_SOURCES}) +add_library(utility STATIC) + +if(utility_SOURCES) + target_sources(utility PRIVATE ${utility_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${utility_SOURCES}) + +target_compile_features(utility PUBLIC + cxx_std_20 +) + +target_compile_options(utility PUBLIC + "/EHa" +) + +target_link_libraries(utility PUBLIC + spdlog + minhook +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + +# Target minhook +set(CMKR_TARGET minhook) +set(minhook_SOURCES "") + +list(APPEND minhook_SOURCES + "dependencies/submodules/minhook/src/buffer.c" + "dependencies/submodules/minhook/src/hde/hde32.c" + "dependencies/submodules/minhook/src/hde/hde64.c" + "dependencies/submodules/minhook/src/hook.c" + "dependencies/submodules/minhook/src/trampoline.c" +) + +list(APPEND minhook_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${minhook_SOURCES}) +add_library(minhook STATIC) + +if(minhook_SOURCES) + target_sources(minhook PRIVATE ${minhook_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${minhook_SOURCES}) + +target_include_directories(minhook PUBLIC + "dependencies/submodules/minhook/include" + "dependencies/submodules/minhook/src/hde" +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + +# Target sdk +set(CMKR_TARGET sdk) +set(sdk_SOURCES "") + +list(APPEND sdk_SOURCES + "shared/sdk/Entity.cpp" + "shared/sdk/EntityList.cpp" + "shared/sdk/ScriptFunctions.cpp" + "shared/sdk/Entity.hpp" + "shared/sdk/EntityList.hpp" + "shared/sdk/Game.hpp" + "shared/sdk/Math.hpp" + "shared/sdk/ScriptFunctions.hpp" +) + +list(APPEND sdk_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${sdk_SOURCES}) +add_library(sdk STATIC) + +if(sdk_SOURCES) + target_sources(sdk PRIVATE ${sdk_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${sdk_SOURCES}) + +target_compile_features(sdk PUBLIC + cxx_std_20 +) + +target_compile_options(sdk PUBLIC + "/EHa" +) + +target_include_directories(sdk PUBLIC + "shared/" + "include/" +) + +target_link_libraries(sdk PUBLIC + glm_static + spdlog +) + +target_link_libraries(sdk PRIVATE + utility +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + +# Target automatamp +set(CMKR_TARGET automatamp) +set(automatamp_SOURCES "") + +list(APPEND automatamp_SOURCES + "src/AutomataMP.cpp" + "src/Crc32.cpp" + "src/DllMain.cpp" + "src/EntitySync.cpp" + "src/ExceptionHandler.cpp" + "src/Mods.cpp" + "src/NierClient.cpp" + "src/NierServer.cpp" + "src/Player.cpp" + "src/PlayerHook.cpp" + "src/VehHooks.cpp" + "src/automata-imgui/imgui_impl_dx11.cpp" + "src/automata-imgui/imgui_impl_dx12.cpp" + "src/automata-imgui/imgui_impl_win32.cpp" + "src/hooks/D3D11Hook.cpp" + "src/hooks/D3D12Hook.cpp" + "src/hooks/WindowsMessageHook.cpp" + "src/mods/AnimTester.cpp" + "src/mods/AutomataMPConfig.cpp" + "src/mods/AutomataMPMod.cpp" + "src/mods/BuddyFeatures.cpp" + "src/AutomataMP.hpp" + "src/Crc32.hpp" + "src/EntitySync.hpp" + "src/ExceptionHandler.hpp" + "src/LicenseStrings.hpp" + "src/Mod.hpp" + "src/Mods.hpp" + "src/NierClient.hpp" + "src/NierServer.hpp" + "src/Packets.hpp" + "src/Player.hpp" + "src/PlayerHook.hpp" + "src/VehHooks.hpp" + "src/automata-imgui/automata_imconfig.hpp" + "src/automata-imgui/font_robotomedium.hpp" + "src/hooks/D3D11Hook.hpp" + "src/hooks/D3D12Hook.hpp" + "src/hooks/WindowsMessageHook.hpp" + "src/mods/AnimTester.hpp" + "src/mods/AutomataMPConfig.hpp" + "src/mods/AutomataMPMod.hpp" + "src/mods/BuddyFeatures.hpp" + "src/automata-imgui/imgui_impl_dx11.h" + "src/automata-imgui/imgui_impl_dx12.h" + "src/automata-imgui/imgui_impl_win32.h" +) + +list(APPEND automatamp_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${automatamp_SOURCES}) +add_library(automatamp SHARED) + +if(automatamp_SOURCES) + target_sources(automatamp PRIVATE ${automatamp_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${automatamp_SOURCES}) + +target_compile_definitions(automatamp PUBLIC + _WINSOCKAPI_ +) + +target_compile_features(automatamp PUBLIC + cxx_std_20 +) + +target_compile_options(automatamp PUBLIC + "/GS-" + "/bigobj" + "/EHa" +) + +target_include_directories(automatamp PUBLIC + "shared/" + "src/" + "include/" + "dependencies/enetpp/include" +) + +target_link_libraries(automatamp PUBLIC + imgui + sdk + utility + enet + shlwapi + d3d11 +) + +set_target_properties(automatamp PROPERTIES + OUTPUT_NAME + dinput8 + RUNTIME_OUTPUT_DIRECTORY_RELEASE + "${CMAKE_BINARY_DIR}/bin/${CMKR_TARGET}" + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO + "${CMAKE_BINARY_DIR}/bin/${CMKR_TARGET}" + LIBRARY_OUTPUT_DIRECTORY_RELEASE + "${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}" + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO + "${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}" + ARCHIVE_OUTPUT_DIRECTORY_RELEASE + "${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}" + ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO + "${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}" +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + diff --git a/build_vs2022.bat b/build_vs2022.bat new file mode 100644 index 0000000..e4f6900 --- /dev/null +++ b/build_vs2022.bat @@ -0,0 +1,6 @@ +git pull --recurse-submodules +git submodule update --init --recursive +mkdir build +cd build +cmake .. -G "Visual Studio 16 2022" -A x64 +cmake --build . --config Release diff --git a/cmake.toml b/cmake.toml new file mode 100644 index 0000000..f01e6b9 --- /dev/null +++ b/cmake.toml @@ -0,0 +1,113 @@ +# Reference: https://build-cpp.github.io/cmkr/cmake-toml +# to build: +# > cmake -B build +# > cmake --build build --config Release +[project] +name = "automatamp" +cmake-after = """ +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") + +if ("${CMAKE_BUILD_TYPE}" MATCHES "Release") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MT") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT") + + # Statically compile runtime + string(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "/MD" "/MT" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + string(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REGEX REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") + message(NOTICE "Building in Release mode") +endif() +""" + +[target.spdlog] +type = "static" +sources = ["dependencies/submodules/spdlog/src/*.cpp"] +include-directories = ["dependencies/submodules/spdlog/include"] +compile-definitions = ["SPDLOG_COMPILED_LIB"] + +[target.glm_static] +type = "static" +sources = ["dependencies/submodules/glm/glm/**.cpp"] +include-directories = ["dependencies/submodules/glm"] + +[target.enet] +type = "static" +sources = ["dependencies/submodules/enet/**.c"] +include-directories = ["dependencies/submodules/enet/include"] +link-libraries = [ + "ws2_32", + "winmm" +] + +[target.imgui] +type = "static" +sources = ["dependencies/submodules/imgui/*.cpp"] +include-directories = ["dependencies/submodules/imgui", "src/automata-imgui"] +compile-definitions = [ + "IMGUI_USER_CONFIG=\"${CMAKE_SOURCE_DIR}/src/automata-imgui/automata_imconfig.hpp\"", +] + +[target.utility] +type = "static" +sources = ["shared/utility/**.cpp", "shared/utility/**.c"] +headers = ["shared/utility/**.hpp", "shared/utility/**.h"] +compile-options = ["/EHa"] +compile-features = ["cxx_std_20"] +link-libraries = [ + "spdlog", + "minhook" +] + +[target.minhook] +type = "static" +sources = ["dependencies/submodules/minhook/src/**.c"] +include-directories = [ + "dependencies/submodules/minhook/include", + "dependencies/submodules/minhook/src/hde", +] + +[target.sdk] +type = "static" +sources = ["shared/sdk/**.cpp", "shared/sdk/**.c"] +headers = ["shared/sdk/**.hpp", "shared/sdk/**.h"] +include-directories = ["shared/", "include/"] +compile-options = ["/EHa"] +compile-features = ["cxx_std_20"] +link-libraries = [ + "glm_static", + "spdlog" +] +private-link-libraries = [ + "utility" +] + +[target.automatamp] +type = "shared" +sources = ["src/**.cpp", "src/**.c"] +headers = ["src/**.hpp", "src/**.h"] +include-directories = ["shared/", "src/", "include/", "dependencies/enetpp/include"] +compile-options = ["/GS-", "/bigobj", "/EHa"] +compile-features = ["cxx_std_20"] +compile-definitions = ["_WINSOCKAPI_"] +link-libraries = [ + "imgui", + "sdk", + "utility", + "enet", + "shlwapi", + "d3d11" +] + +[target.automatamp.properties] +OUTPUT_NAME = "dinput8" +RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${CMAKE_BINARY_DIR}/bin/${CMKR_TARGET}" +RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO = "${CMAKE_BINARY_DIR}/bin/${CMKR_TARGET}" +LIBRARY_OUTPUT_DIRECTORY_RELEASE = "${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}" +LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO = "${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}" +ARCHIVE_OUTPUT_DIRECTORY_RELEASE = "${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}" +ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO = "${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}" + diff --git a/cmkr.cmake b/cmkr.cmake new file mode 100644 index 0000000..7a4b662 --- /dev/null +++ b/cmkr.cmake @@ -0,0 +1,253 @@ +include_guard() + +# Change these defaults to point to your infrastructure if desired +set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) +set(CMKR_TAG "v0.2.14" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) +set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE) + +# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake +if(CMAKE_SCRIPT_MODE_FILE) + set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build") + set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}") + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}") +endif() + +# Set these from the command line to customize for development/debugging purposes +set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable") +set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation") +set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration") +mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE) + +# Disable cmkr if generation is disabled +if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION) + message(STATUS "[cmkr] Skipping automatic cmkr generation") + unset(CMKR_BUILD_SKIP_GENERATION CACHE) + macro(cmkr) + endmacro() + return() +endif() + +# Disable cmkr if no cmake.toml file is found +if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + macro(cmkr) + endmacro() + return() +endif() + +# Convert a Windows native path to CMake path +if(CMKR_EXECUTABLE MATCHES "\\\\") + string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE) + unset(CMKR_EXECUTABLE_CMAKE) +endif() + +# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher) +function(cmkr_exec) + execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})") + endif() +endfunction() + +# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment) +if(WIN32) + set(CMKR_EXECUTABLE_NAME "cmkr.exe") +else() + set(CMKR_EXECUTABLE_NAME "cmkr") +endif() + +# Use cached cmkr if found +if(DEFINED ENV{CMKR_CACHE}) + set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}") + string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}") + if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$") + set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/") + endif() + # Build in release mode for the cache + set(CMKR_BUILD_TYPE "Release") +else() + set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_") +endif() +set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}") +set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}") + +# Helper function to check if a string starts with a prefix +# Cannot use MATCHES, see: https://github.com/build-cpp/cmkr/issues/61 +function(cmkr_startswith str prefix result) + string(LENGTH "${prefix}" prefix_length) + string(LENGTH "${str}" str_length) + if(prefix_length LESS_EQUAL str_length) + string(SUBSTRING "${str}" 0 ${prefix_length} str_prefix) + if(prefix STREQUAL str_prefix) + set("${result}" ON PARENT_SCOPE) + return() + endif() + endif() + set("${result}" OFF PARENT_SCOPE) +endfunction() + +# Handle upgrading logic +if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE) + cmkr_startswith("${CMKR_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/_cmkr" CMKR_STARTSWITH_BUILD) + cmkr_startswith("${CMKR_EXECUTABLE}" "${CMKR_DIRECTORY_PREFIX}" CMKR_STARTSWITH_CACHE) + if(CMKR_STARTSWITH_BUILD) + if(DEFINED ENV{CMKR_CACHE}) + message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'") + if(EXISTS "${CMKR_CACHED_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + else() + unset(CMKR_EXECUTABLE CACHE) + endif() + else() + message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) + endif() + elseif(DEFINED ENV{CMKR_CACHE} AND CMKR_STARTSWITH_CACHE) + message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) + endif() +endif() + +if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}") + message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") +elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE) + message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found") +elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'") +else() + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'") + + message(STATUS "[cmkr] Fetching cmkr...") + if(EXISTS "${CMKR_DIRECTORY}") + cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}") + endif() + find_package(Git QUIET REQUIRED) + cmkr_exec("${GIT_EXECUTABLE}" + clone + --config advice.detachedHead=false + --branch ${CMKR_TAG} + --depth 1 + ${CMKR_REPO} + "${CMKR_DIRECTORY}" + ) + if(CMKR_COMMIT_HASH) + execute_process( + COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}" + RESULT_VARIABLE CMKR_EXEC_RESULT + WORKING_DIRECTORY "${CMKR_DIRECTORY}" + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'") + endif() + endif() + message(STATUS "[cmkr] Building cmkr (using system compiler)...") + cmkr_exec("${CMAKE_COMMAND}" + --no-warn-unused-cli + "${CMKR_DIRECTORY}" + "-B${CMKR_DIRECTORY}/build" + "-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}" + "-DCMAKE_UNITY_BUILD=ON" + "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" + "-DCMKR_GENERATE_DOCUMENTATION=OFF" + ) + cmkr_exec("${CMAKE_COMMAND}" + --build "${CMKR_DIRECTORY}/build" + --config "${CMKR_BUILD_TYPE}" + --parallel + ) + cmkr_exec("${CMAKE_COMMAND}" + --install "${CMKR_DIRECTORY}/build" + --config "${CMKR_BUILD_TYPE}" + --prefix "${CMKR_DIRECTORY}" + --component cmkr + ) + if(NOT EXISTS ${CMKR_EXECUTABLE}) + message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'") + endif() + cmkr_exec("${CMKR_EXECUTABLE}" version) + message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}") +endif() +execute_process(COMMAND "${CMKR_EXECUTABLE}" version + RESULT_VARIABLE CMKR_EXEC_RESULT +) +if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") +endif() + +# Use cmkr.cmake as a script +if(CMAKE_SCRIPT_MODE_FILE) + if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml") + execute_process(COMMAND "${CMKR_EXECUTABLE}" init + RESULT_VARIABLE CMKR_EXEC_RESULT + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new") + else() + message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build") + endif() + else() + execute_process(COMMAND "${CMKR_EXECUTABLE}" gen + RESULT_VARIABLE CMKR_EXEC_RESULT + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to generate project.") + else() + message(STATUS "[cmkr] Configure using: cmake -B build") + endif() + endif() +endif() + +# This is the macro that contains black magic +macro(cmkr) + # When this macro is called from the generated file, fake some internal CMake variables + get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE) + if(CMKR_CURRENT_LIST_FILE) + set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}") + get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) + endif() + + # File-based include guard (include_guard is not documented to work) + get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD) + if(NOT CMKR_INCLUDE_GUARD) + set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE) + + # Generate CMakeLists.txt + cmkr_exec("${CMKR_EXECUTABLE}" gen + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST) + + # Delete the temporary file if it was left for some reason + set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt") + if(EXISTS "${CMKR_TEMP_FILE}") + file(REMOVE "${CMKR_TEMP_FILE}") + endif() + + if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST) + # Copy the now-generated CMakeLists.txt to CMakerLists.txt + # This is done because you cannot include() a file you are currently in + configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY) + + # Add the macro required for the hack at the start of the cmkr macro + set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES + CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" + ) + + # 'Execute' the newly-generated CMakeLists.txt + include("${CMKR_TEMP_FILE}") + + # Delete the generated file + file(REMOVE "${CMKR_TEMP_FILE}") + + # Do not execute the rest of the original CMakeLists.txt + return() + endif() + # Resume executing the unmodified CMakeLists.txt + endif() +endmacro() diff --git a/shared/sdk/Entity.cpp b/shared/sdk/Entity.cpp new file mode 100644 index 0000000..60c0646 --- /dev/null +++ b/shared/sdk/Entity.cpp @@ -0,0 +1,2 @@ +#include "ScriptFunctions.hpp" +#include diff --git a/shared/sdk/Entity.hpp b/shared/sdk/Entity.hpp new file mode 100644 index 0000000..a89264e --- /dev/null +++ b/shared/sdk/Entity.hpp @@ -0,0 +1,255 @@ +#pragma once + +#include + +#include +#include + +#include "ScriptFunctions.hpp" + +class Entity; + +struct EntityContainer { + void assignAIRoutine(const std::string& name) { + //auto realName = findExactString(GetModuleHandle(0), name); + + //if (realName) { + static void(*assignRoutine)(const char* name, EntityContainer*) = (decltype(assignRoutine))0x1400EFD70; + assignRoutine(name.c_str(), this); + + *Address(this->entity).get(0x16478).as() = 1; + //} + } + + void* unknown; + char name[0x20]; + uint64_t flags; + uint32_t handle; + void* unknown2; + void* unknown3; + Entity* entity; + void* unknown4; + char poop[0x8]; + Entity* entity2; +}; + +enum EAnimation +{ + Walk = 1, + Run = 2, + Sprint = 3, + High_Fall = 4, + Jump = 5, + Fall = 6, + High_Fall2 = 7, + Air_Spin = 9, + Land = 11, + Get_Up_Backflip = 12, + Backflip = 13, + Vault = 14, + Lying_Down = 15, + Light_Attack = 16, + Dash = 18, + Dodge = 19, + Taunt_A2 = 20, + Parry_thing = 21, + Electrocuted = 22, + Taunt_A2_2 = 23, + Throw_Weapon = 24, + Slomo_Cutscene = 25, + Really_Powerful_Kick_2B = 26, + INVALID_CRASHES_GAME = 27, + Use_Corpse = 28, + Use_Corpse_2 = 29, + Use_Corpse_3 = 30, + Pick_Up_Item = 31, + Pervert_2B = 32, + Pick_Up_Item_2 = 33, + Pod_Fire_Rocket = 36, + Pod_Swing = 37, + Flying_Thing = 38, + Flying_Mech_Mode_Bugged = 39, + Push_Back_Weak = 42, + Push_Back_Weak_2 = 43, + Push_Back_Medium = 44, + Push_Back_Hard = 45, + Push_Back_Fall = 46, + Push_Box = 48, + Lift_Up_Fall = 51, + Die = 53, + Die_2 = 54, + Self_Destruct_Start = 55, + // does a countdown and actually blows up + Self_Destruct_Complete = 56, + Self_Destruct_Explode = 57, + // Slides with anything other than variant 0 + Slide = 58, + Turn_90_Deg_Right = 63, + INVALID_CRASHES_GAME2 = 65, + Hacking_Mode = 70, + Walk_Forward_Scripted = 85, + Flying_Mech_Mode = 94, + Land_Mechs = 95, + Open_Door = 102, + Sit_Down = 103, + INVALID_CRASHES_GAME3 = 104, + Kick = 105, + INVALID_CRASHES_GAME4 = 106, + Lie_In_Bed = 107, +}; + +enum EModel { + MODEL_2B = 0x10000, + MODEL_A2 = 0x10100, + MODEL_9S = 0x10200, +}; + +enum ERunSpeedType { + SPEED_PLAYER, + SPEED_BUDDY +}; + +class Entity { +public: + virtual void pad0() = 0; + virtual void pad1() = 0; + virtual void pad2() = 0; + virtual void pad3() = 0; + virtual void pad4() = 0; + virtual void pad5() = 0; + virtual void pad6() = 0; + virtual void pad7() = 0; + virtual void pad8() = 0; + virtual void pad9() = 0; + virtual void pad10() = 0; + virtual void pad11() = 0; + virtual void pad12() = 0; + virtual void pad13() = 0; + virtual void pad14() = 0; + virtual void pad15() = 0; + virtual void pad16() = 0; + virtual void pad17() = 0; + virtual void startAnimation(uint32_t animType, uint32_t variant, uint32_t a3 = 0, uint32_t a4 = 0) = 0; + + // Vtable indices + static constexpr uint8_t s_startAnimationIndex = 18; + +public: + struct CharacterController { + enum EButtonIndex { + INDEX_ATTACK_LIGHT = 0, + INDEX_ATTACK_HEAVY = 1, + INDEX_JUMP = 2, + INDEX_POD_SPECIAL = 4, + INDEX_POD_FIRE = 6, + INDEX_DASH = 7, + INDEX_MAX = INDEX_DASH + 1, + }; + + char crap[0x738]; + uint32_t heldFlags; + uint32_t flags; + char unknown[0x30]; + + uint32_t buttons[EButtonIndex::INDEX_MAX]; + }; + +public: + uint32_t* getModel() { + return (uint32_t*)((uintptr_t)this + 0x5B8); + } + + EntityContainer* getContainer() { + return *(EntityContainer**)((uintptr_t)this + 0x610); + } + + uint32_t* getHealth() { + return (uint32_t*)((uintptr_t)this + 0x858); + } + + uint32_t getPossessedHandle() { + return *(uint32_t*)((uintptr_t)this + 0x12A5C); + } + + void setBuddyHandle(uint32_t handle) { + *(uint32_t*)((uintptr_t)this + 0x1646c) = handle; + } + + uint32_t getBuddyHandle() { + return *(uint32_t*)((uintptr_t)this + 0x1646c); + } + + void setBuddyFlags(uint32_t flags) { + *(uint32_t*)((uintptr_t)this + 0x598) = flags; + } + + CharacterController* getCharacterController() { + return (CharacterController*)((uintptr_t)this + 0xCA0); + } + + float* getSpeed() { + return Address(getCharacterController()).get(0x794).as(); + } + + float* getFacing() { + return Address(this).get(0x94).as(); + } + + float* getFacing2() { + return Address(getCharacterController()).get(0x79C).as(); + } + + Vector3f* getPosition() { + return Address(this).get(0x50).as(); + } + + uint32_t* getWeaponIndex() { + return Address(this).get(0x107d8).as(); + } + + uint32_t* getPodIndex() { + return Address(this).get(0x10820).as(); + } + + bool* getFlashlightEnabled() { + return Address(this).get(0x17480).as(); + } + + float* getTickCount() { + return Address(this).get(0x9C).as(); + } + + bool* getShortsTorn() { + return Address(this).get(0x16ce4).as(); + } + + bool* getWearingMask() { + return Address(this).get(0x16cdc).as(); + } + + uint32_t* getRunSpeedType() { + return (uint32_t*)((uintptr_t)this + 0x16478); + } + + struct Signal { + uint32_t signal; + uint32_t unk{ 0 }; + uintptr_t unk2{ 0 }; + uint32_t unk3{ 0 }; + }; + + OBJECT_SCRIPT_FUNCTION(Behavior, terminate, void) + OBJECT_SCRIPT_FUNCTION(Behavior, isSuspend, bool); + OBJECT_SCRIPT_FUNCTION(Behavior, setSuspend, void, bool); + OBJECT_SCRIPT_FUNCTION(Behavior, signal, void, const Signal&); + OBJECT_SCRIPT_FUNCTION(Behavior, offCollision, void); + OBJECT_SCRIPT_FUNCTION(Behavior, onCollision, void); + OBJECT_SCRIPT_FUNCTION(Behavior, onTrans, void); + OBJECT_SCRIPT_FUNCTION(Behavior, offTrans, void); + OBJECT_SCRIPT_FUNCTION(Behavior, isTrans, void); + + OBJECT_SCRIPT_FUNCTION(Pl0000, setBuddyFromNpc, void); + OBJECT_SCRIPT_FUNCTION(Pl0000, changePlayer, void); + +private: +}; \ No newline at end of file diff --git a/shared/sdk/EntityList.cpp b/shared/sdk/EntityList.cpp new file mode 100644 index 0000000..8620e10 --- /dev/null +++ b/shared/sdk/EntityList.cpp @@ -0,0 +1,97 @@ +#include + +#include + +#include +#include + +using namespace std; + +EntityList* EntityList::get() { + static EntityList** entList = nullptr; + + if (!entList) + { + entList = Address(GetModuleHandle(0)).get(0x160DF98).as(); + spdlog::info("EntityList: {:x}", (uintptr_t)entList); + } + + return *entList; +} + +EntityContainer* EntityList::get(uint32_t i) +{ + return m_entities[i].ent; +} + +EntityContainer* EntityList::getByName(const std::string& name) { + for (auto& i : *this) { + if (!i.ent) + continue; + + if (name == i.ent->name) + return i.ent; + } + + return nullptr; +} + +EntityContainer* EntityList::getByHandle(uint32_t handle) { + auto index = (uint16_t)(handle >> 8); + return m_entities[index].ent; +} + +EntityContainer* EntityList::getPossessedEntity() { + static uint32_t* currentHandle = Address(0x14158A6EC).as(); + + if (!*currentHandle) { + return nullptr; + } + + return getByHandle(*currentHandle); +} + +EntityContainer* EntityList::spawnEntity(const EntitySpawnParams& params) { + static EntityContainer* (*spawn)(void*, const EntitySpawnParams&) = (decltype(spawn))0x1404F9AA0; + return spawn((void*)0x14160DFE0, params); +} + +EntityContainer* EntityList::spawnEntity(const std::string& name, uint32_t model, const Vector3f& position) { + EntitySpawnParams params; + EntitySpawnParams::PositionalData matrix; + matrix.position = Vector4f{position, 1.0f}; + params.name = (char*)name.c_str(); + params.matrix = &matrix; + params.model = model; + params.model2 = model; + matrix.unknown = *Address(getByName("Player")->entity).get(0x90).as(); + + auto ret = spawnEntity(params); + return ret; +} + +std::vector EntityList::getAllByName(const std::string& name) { + std::vector vec; + + for (auto& i : *this) { + if (!i.ent) + continue; + + if (name == i.ent->name) { + vec.push_back(i.ent); + } + } + + return vec; +} + +size_t EntityList::size() { + static uint32_t* s = nullptr; + + if (!s) { + s = Address(GetModuleHandle(0)).get(0x160DF88).as(); + spdlog::info("size: {:x}", (uintptr_t)s); + } + + return *s; +} diff --git a/shared/sdk/EntityList.hpp b/shared/sdk/EntityList.hpp new file mode 100644 index 0000000..06cecff --- /dev/null +++ b/shared/sdk/EntityList.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include +#include + +struct EntityContainer; + +struct EntityDescriptor { + uint32_t handle; + EntityContainer* ent; +}; + +struct EntitySpawnParams { + struct PositionalData { + Vector4f forward { 1.0f, 0.0f, 0.0f, 0.0f }; // 0 - 10 + Vector4f up { 0.0f, 1.0f, 0.0f, 0.0f }; // 10 - 20 + Vector4f right { 0.0f, 0.0f, 1.0f, 0.0f }; // 20 - 30 + Vector4f w { 0.0f, 0.0f, 0.0f, 1.0f }; // 30 - 40 + Vector4f position{ 0.0f, 0.0f, 0.0f, 1.0f }; // 40 - 50 + Vector4f unknown { 0.0f, 0.0f, 0.0f, 0.0f }; // 50 - 60 + Vector4f unknown2{ 1.0f, 1.0f, 1.0f, 0.0f }; // 60 - 70 + uint32_t unk{ 0 }; // 70-74 + uint32_t unk2{ 0 }; // 70 - 78 + uint32_t unk3{ 0 }; // 78 - 7c + uint32_t unk4{ 0 }; // 7c - 80 + uint32_t unk5{ 0 }; // 80 - 84 + uint32_t unk6{ 0 }; // 84 - 88 + }; + + const char* name; // 0-8 + uint32_t model; // 8 -c + uint32_t model2; // c - 10 + PositionalData* matrix{ nullptr }; // 10 - 18 + uint64_t unk1{ 0 }; // 18 - 20 + uint32_t unk2{ 1 }; // 20 - 24 + uint64_t unk3{ 0 }; // 28 - 30 + Vector4f unk4{ 0.0f, 0.0f, 0.0f, 0.0f }; // 30 - 38 + Vector4f unk5{ 0.0f, 0.0f, 0.0f, 0.0f }; // 38 - 40 + uint64_t unk6{ 0 }; // 40 -48 + char crap[0x28]{ 0 }; +}; + +class EntityList { +public: + static EntityList* get(); + +public: + EntityContainer* get(uint32_t i); + EntityContainer* getByName(const std::string& name); + EntityContainer* getByHandle(uint32_t handle); + EntityContainer* getPossessedEntity(); + + EntityContainer* spawnEntity(const EntitySpawnParams& params); + EntityContainer* spawnEntity(const std::string& name, uint32_t model, const Vector3f& position); + + std::vector getAllByName(const std::string& name); + +public: + size_t size(); + + EntityDescriptor* begin() { + return &m_entities[0]; + } + + EntityDescriptor* end() { + return begin() + size(); + } + +private: + EntityDescriptor m_entities[1]; +}; \ No newline at end of file diff --git a/shared/sdk/Game.hpp b/shared/sdk/Game.hpp new file mode 100644 index 0000000..3f1ce6f --- /dev/null +++ b/shared/sdk/Game.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace nier { + // not loading + bool isLoading() { + return *(uint8_t*)0x1414838E8 != 1; + } +} \ No newline at end of file diff --git a/shared/sdk/Math.hpp b/shared/sdk/Math.hpp new file mode 100644 index 0000000..3c1712b --- /dev/null +++ b/shared/sdk/Math.hpp @@ -0,0 +1,19 @@ +#pragma once + +#define GLM_ENABLE_EXPERIMENTAL + +#include +#include +#include +#include +#include +#include +#include +#include + +using Vector2f = glm::vec2; +using Vector3f = glm::vec3; +using Vector4f = glm::vec4; +using Matrix3x3f = glm::mat3x3; +using Matrix3x4f = glm::mat3x4; +using Matrix4x4f = glm::mat4x4; diff --git a/shared/sdk/ScriptFunctions.cpp b/shared/sdk/ScriptFunctions.cpp new file mode 100644 index 0000000..e0a13c4 --- /dev/null +++ b/shared/sdk/ScriptFunctions.cpp @@ -0,0 +1,32 @@ +#include +#include + +#include "ScriptFunctions.hpp" + +ScriptFunctions& ScriptFunctions::get() { + static ScriptFunctions scripts; + return scripts; +} + +ScriptFunctions::ScriptFunctions() + : m_scriptFunctions((ScriptFunction**)0x141415930) +{ + +} + +ScriptFunction* ScriptFunctions::find(const std::string& name) { + auto crc = crc32((uint8_t*)name.c_str(), name.length()); + + for (auto script = *m_scriptFunctions; script != nullptr; script = script->next) { + if (script->crc == crc) { + spdlog::info("Found {} at {:x}, function {:x}", name.c_str(), (uintptr_t)script, (uintptr_t)script->function); + return script; + } + + if (script->next == *m_scriptFunctions) { + break; + } + } + + return nullptr; +} diff --git a/shared/sdk/ScriptFunctions.hpp b/shared/sdk/ScriptFunctions.hpp new file mode 100644 index 0000000..52aa589 --- /dev/null +++ b/shared/sdk/ScriptFunctions.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +struct ScriptFunction { + uintptr_t vtable; // 0 - 8 + uint32_t crc; // 8 - 10 + ScriptFunction* next; // 10 - 18 + uintptr_t unk; // 18 - 20 + uintptr_t function; // 20 - 28 + uintptr_t unk2; +}; + +class ScriptFunctions { +public: + static ScriptFunctions& get(); + +public: + ScriptFunctions(); + + ScriptFunction* find(const std::string& name); + +private: + ScriptFunction** m_scriptFunctions; +}; + +#define OBJECT_SCRIPT_FUNCTION(object_name, func_name, ret_type, ...) \ + template \ + auto func_name(Args&&... args) {\ + static auto func = (ret_type (*)(decltype(this), __VA_ARGS__))ScriptFunctions::get().find(#object_name "." #func_name)->function; \ + return func(this, std::forward(args)...); \ + } diff --git a/shared/utility/Address.cpp b/shared/utility/Address.cpp new file mode 100644 index 0000000..2aa7c6f --- /dev/null +++ b/shared/utility/Address.cpp @@ -0,0 +1,17 @@ +#include + +#include "Address.hpp" + +using namespace std; + +Address::Address() + : m_ptr(nullptr) +{} + +Address::Address(void* ptr) + : m_ptr(ptr) +{} + +Address::Address(uintptr_t addr) + : m_ptr((void*)addr) +{} diff --git a/shared/utility/Address.hpp b/shared/utility/Address.hpp new file mode 100644 index 0000000..0e8a101 --- /dev/null +++ b/shared/utility/Address.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include +#include + +// sizeof(Address) should always be sizeof(void*). +class Address { +public: + Address(); + Address(void* ptr); + Address(uintptr_t addr); + + void set(void* ptr) { + m_ptr = ptr; + } + + template + Address get(T offset) const { + return Address((uintptr_t)m_ptr + offset); + } + + template + Address add(T offset) const { + return Address((uintptr_t)m_ptr + offset); + } + + template + Address sub(T offset) const { + return Address((uintptr_t)m_ptr - offset); + } + + template + T as() const { + return (T)m_ptr; + } + + // to is like as but dereferences that shit. + template + T to() const { + return *(T*)m_ptr; + } + + Address deref() const { + return to(); + } + + void* ptr() const { + return m_ptr; + } + + operator uintptr_t() const { + return (uintptr_t)m_ptr; + } + + operator void*() const { + return m_ptr; + } + + bool operator ==(bool val) { + return ((m_ptr && val) || (!m_ptr && !val)); + } + + bool operator !=(bool val) { + return !(*this == val); + } + + bool operator ==(uintptr_t val) { + return ((uintptr_t)m_ptr == val); + } + + bool operator !=(uintptr_t val) { + return !(*this == val); + } + + bool operator ==(void* val) { + return (m_ptr == val); + } + + bool operator !=(void* val) { + return !(*this == val); + } + +private: + void* m_ptr; +}; + +typedef Address Offset; diff --git a/shared/utility/Config.cpp b/shared/utility/Config.cpp new file mode 100644 index 0000000..19bb64b --- /dev/null +++ b/shared/utility/Config.cpp @@ -0,0 +1,72 @@ +#include +#include + +#include "String.hpp" +#include "Config.hpp" + +using namespace std; + +namespace utility { + Config::Config(const string& filePath) + : m_key_values{} + { + if (!filePath.empty()) { + load(filePath); + } + } + + bool Config::load(const string& filePath) { + if (filePath.empty()) { + return false; + } + + ifstream f(widen(filePath)); + + if (!f) { + return false; + } + + for (string line{}; getline(f, line); ) { + istringstream ss{ line }; + string key{}; + string value{}; + + getline(ss, key, '='); + getline(ss, value); + + set(key, value); + } + + return true; + } + + bool Config::save(const string& filePath) { + ofstream f(widen(filePath)); + + if (!f) { + return false; + } + + for (auto& keyValue : m_key_values) { + f << keyValue.first << "=" << keyValue.second << endl; + } + + return true; + } + + optional Config::get(const string& key) const { + auto search = m_key_values.find(key); + + if (search == m_key_values.end()) { + return {}; + } + + return search->second; + } + + void Config::set(const string& key, const string& value) { + if (!key.empty() && !value.empty()) { + m_key_values[key] = value; + } + } +} diff --git a/shared/utility/Config.hpp b/shared/utility/Config.hpp new file mode 100644 index 0000000..e5751b7 --- /dev/null +++ b/shared/utility/Config.hpp @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include +#include + +namespace utility { + class Config { + public: + Config(const std::string& file_path = ""); + + bool load(const std::string& file_path); + bool save(const std::string& file_path); + + // Helper for differentiating between boolean and arithmetic values. + template + using is_arithmetic_not_bool = std::bool_constant && !std::is_same_v>; + + template + static constexpr bool IS_ARITHMETIC_NOT_BOOL_V = is_arithmetic_not_bool::value; + + // get method for arithmetic types. + template + std::optional, T>> get(const std::string& key) const { + auto value = get(key); + + if (!value) { + return {}; + } + + // Use the correct conversion function based on the type. + if constexpr (std::is_integral_v) { + if constexpr (std::is_unsigned_v) { + return (T)std::stoul(*value); + } + else { + return (T)std::stol(*value); + } + } + else { + return (T)std::stod(*value); + } + } + + // get method for boolean types. + template + std::optional, T>> get(const std::string& key) const { + auto value = get(key); + + if (!value) { + return {}; + } + + if (*value == "true") { + return true; + } + + if (*value == "false") { + return false; + } + + return {}; + } + + // get method for strings. + std::optional get(const std::string& key) const; + + // set method for arithmetic types. + template + void set(const std::string& key, typename std::enable_if_t, T> value) { + set(key, std::to_string(value)); + } + + // set method for boolean types. + template + void set(const std::string& key, typename std::enable_if_t, T> value) { + if (value) { + set(key, "true"); + } + else { + set(key, "false"); + } + } + + // set method for strings. + void set(const std::string& key, const std::string& value); + + auto& get_key_values() { + return m_key_values; + } + + const auto& get_key_values() const { + return m_key_values; + } + + private: + std::map m_key_values; + }; +} diff --git a/shared/utility/Crc32.cpp b/shared/utility/Crc32.cpp new file mode 100644 index 0000000..cf19a5e --- /dev/null +++ b/shared/utility/Crc32.cpp @@ -0,0 +1,17 @@ +#include "Crc32.hpp" + +uint32_t crc32(uint8_t* data, size_t len) +{ + uint32_t crc = 0xFFFFFFFF; + + while (len--) { + crc ^= *data++; + + for (int j = 0; j < 8; j++) { + crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); + } + } + + return ~crc; +} + diff --git a/shared/utility/Crc32.hpp b/shared/utility/Crc32.hpp new file mode 100644 index 0000000..75b808f --- /dev/null +++ b/shared/utility/Crc32.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include + +uint32_t crc32(uint8_t* data, size_t len); \ No newline at end of file diff --git a/shared/utility/FunctionHook.cpp b/shared/utility/FunctionHook.cpp new file mode 100644 index 0000000..514e0e6 --- /dev/null +++ b/shared/utility/FunctionHook.cpp @@ -0,0 +1,76 @@ +#include +#include + +#include "FunctionHook.hpp" + +using namespace std; + + +bool g_isMinHookInitialized{ false }; + +FunctionHook::FunctionHook(Address target, Address destination) + : m_target{ 0 }, + m_destination{ 0 }, + m_original{ 0 } +{ + spdlog::info("Attempting to hook {:p}->{:p}", target.ptr(), destination.ptr()); + + // Initialize MinHook if it hasn't been already. + if (!g_isMinHookInitialized && MH_Initialize() == MH_OK) { + g_isMinHookInitialized = true; + } + + // Create the hook. Call create afterwards to prevent race conditions accessing FunctionHook before it leaves its constructor. + if (auto status = MH_CreateHook(target.as(), destination.as(), (LPVOID*)&m_original); status == MH_OK) { + m_target = target; + m_destination = destination; + + spdlog::info("Hook init successful {:p}->{:p}", target.ptr(), destination.ptr()); + } + else { + spdlog::error("Failed to hook {:p}: {}", target.ptr(), MH_StatusToString(status)); + } +} + +FunctionHook::~FunctionHook() { + remove(); +} + +bool FunctionHook::create() { + if (m_target == 0 || m_destination == 0 || m_original == 0) { + spdlog::error("FunctionHook not initialized"); + return false; + } + + if (auto status = MH_EnableHook((LPVOID)m_target); status != MH_OK) { + m_original = 0; + m_destination = 0; + m_target = 0; + + spdlog::error("Failed to hook {:x}: {}", m_target, MH_StatusToString(status)); + return false; + } + + spdlog::info("Hooked {:x}->{:x}", m_target, m_destination); + return true; +} + +bool FunctionHook::remove() { + // Don't try to remove invalid hooks. + if (m_original == 0) { + return true; + } + + // Disable then remove the hook. + if (MH_DisableHook((LPVOID)m_target) != MH_OK || + MH_RemoveHook((LPVOID)m_target) != MH_OK) { + return false; + } + + // Invalidate the members. + m_target = 0; + m_destination = 0; + m_original = 0; + + return true; +} \ No newline at end of file diff --git a/shared/utility/FunctionHook.hpp b/shared/utility/FunctionHook.hpp new file mode 100644 index 0000000..d419b19 --- /dev/null +++ b/shared/utility/FunctionHook.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +#include "Address.hpp" + +class FunctionHook { +public: + FunctionHook() = delete; + FunctionHook(const FunctionHook& other) = delete; + FunctionHook(FunctionHook&& other) = delete; + FunctionHook(Address target, Address destination); + virtual ~FunctionHook(); + + bool create(); + + // Called automatically by the destructor, but you can call it explicitly + // if you need to remove the hook. + bool remove(); + + auto get_original() const { + return m_original; + } + + template + T* get_original() const { + return (T*)m_original; + } + + auto is_valid() const { + return m_original != 0; + } + + FunctionHook& operator=(const FunctionHook& other) = delete; + FunctionHook& operator=(FunctionHook&& other) = delete; + +private: + uintptr_t m_target{ 0 }; + uintptr_t m_destination{ 0 }; + uintptr_t m_original{ 0 }; +}; \ No newline at end of file diff --git a/shared/utility/Memory.cpp b/shared/utility/Memory.cpp new file mode 100644 index 0000000..3ab9df1 --- /dev/null +++ b/shared/utility/Memory.cpp @@ -0,0 +1,95 @@ +#include +#include +#include + +#include + +#include "String.hpp" +#include "Memory.hpp" + +using namespace std; + +namespace utility { + thread_local vector g_pages{}; + + optional findInCache(uintptr_t ptr, size_t len) { + for (const auto& mbi : g_pages) { + auto start = (uintptr_t)mbi.BaseAddress; + auto end = start + mbi.RegionSize; + + if (start <= ptr && ptr + len < end) { + return mbi; + } + } + + return {}; + } + + bool memoryHasAccess(const MEMORY_BASIC_INFORMATION& mbi, DWORD protect) { + // Pages are commited, not guarded or no access, and same protect. + return (mbi.State & MEM_COMMIT && + !(mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) && + mbi.Protect & protect); + } + + bool isGoodPtr(uintptr_t ptr, size_t len, uint32_t access) { + // See if the address is in our cache. + auto cachedMBI = findInCache(ptr, len); + + if (cachedMBI) { + return memoryHasAccess(*cachedMBI, access); + } + + MEMORY_BASIC_INFORMATION mbi{}; + + if (VirtualQuery((LPCVOID)ptr, &mbi, sizeof(mbi)) == 0) { + return false; + } + + // Add it to our cache if its not there. + if (!findInCache((uintptr_t)mbi.BaseAddress, 0)) { + g_pages.push_back(mbi); + } + + return memoryHasAccess(mbi, access); + } + + bool isGoodReadPtr(uintptr_t ptr, size_t len) { + return isGoodPtr(ptr, len, PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); + } + + bool isGoodWritePtr(uintptr_t ptr, size_t len) { + return isGoodPtr(ptr, len, PAGE_READWRITE | PAGE_EXECUTE_READWRITE); + } + + bool isGoodCodePtr(uintptr_t ptr, size_t len) { + return isGoodPtr(ptr, len, PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE); + } + + bool is_stub_code(uint8_t* code) { + if (code == nullptr) { + return false; + } + + static const std::vector> stub_codes{ + { 0x48, 0x31, 0xc0, 0xc3 }, // xor rax, rax; ret + { 0x33, 0xc0, 0xc3 }, // xor eax, eax; ret + { 0x30, 0xc0, 0xc3 }, // xor al, al; ret + { 0x31, 0xc0, 0xc3 }, // xor al, al; ret + { 0x32, 0xc0, 0xc3 }, // xor al, al; ret + { 0xb0, 0x01, 0xc3 }, // mov al, 1; ret + { 0xb0, 0x00, 0xc3 }, // mov al, 0; ret + { 0xc2, 0x00, 0x00 }, // ret 0 + { 0xc3 } // ret + }; + + // check whether the code matches any of the stub codes + for (const auto& stub_code : stub_codes) { + if (memcmp(code, stub_code.data(), stub_code.size()) == 0) { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/shared/utility/Memory.hpp b/shared/utility/Memory.hpp new file mode 100644 index 0000000..05bc1ee --- /dev/null +++ b/shared/utility/Memory.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace utility { + bool isGoodPtr(uintptr_t ptr, size_t len, uint32_t access); + bool isGoodReadPtr(uintptr_t ptr, size_t len); + bool isGoodWritePtr(uintptr_t ptr, size_t len); + bool isGoodCodePtr(uintptr_t ptr, size_t len); + + bool is_stub_code(uint8_t* code); +} diff --git a/shared/utility/Module.cpp b/shared/utility/Module.cpp new file mode 100644 index 0000000..4d62309 --- /dev/null +++ b/shared/utility/Module.cpp @@ -0,0 +1,469 @@ +#define NOMINMAX + +#include +#include +#include + +#include +#include +#include + +#include + +#include "String.hpp" +#include "Thread.hpp" +#include "Module.hpp" + +using namespace std; + +namespace utility { + optional get_module_size(const string& module) { + return get_module_size(GetModuleHandle(module.c_str())); + } + + optional get_module_size(HMODULE module) { + if (module == nullptr) { + return {}; + } + + // Get the dos header and verify that it seems valid. + auto dosHeader = (PIMAGE_DOS_HEADER)module; + + if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + return {}; + } + + // Get the nt headers and verify that they seem valid. + auto ntHeaders = (PIMAGE_NT_HEADERS)((uintptr_t)dosHeader + dosHeader->e_lfanew); + + if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { + return {}; + } + + // OptionalHeader is not actually optional. + return ntHeaders->OptionalHeader.SizeOfImage; + } + + std::optional get_module_within(Address address) { + HMODULE module = nullptr; + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address.as(), &module)) { + return module; + } + + return {}; + } + + std::optional get_dll_imagebase(Address dll) { + if (dll == nullptr) { + return {}; + } + + // Get the dos header and verify that it seems valid. + auto dosHeader = dll.as(); + + if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + return {}; + } + + // Get the nt headers and verify that they seem valid. + auto ntHeaders = (PIMAGE_NT_HEADERS)((uintptr_t)dosHeader + dosHeader->e_lfanew); + + if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { + return {}; + } + + return ntHeaders->OptionalHeader.ImageBase; + } + + std::optional get_imagebase_va_from_ptr(Address dll, Address base, void* ptr) { + auto file_imagebase = get_dll_imagebase(dll); + + if (!file_imagebase) { + return {}; + } + + return *file_imagebase + ((uintptr_t)ptr - base.as()); + } + + + std::optional get_module_path(HMODULE module) { + wchar_t filename[MAX_PATH]{0}; + if (GetModuleFileNameW(module, filename, MAX_PATH) >= MAX_PATH) { + return {}; + } + + return utility::narrow(filename); + } + + std::optional get_module_directory(HMODULE module) { + wchar_t filename[MAX_PATH]{ 0 }; + if (GetModuleFileNameW(module, filename, MAX_PATH) >= MAX_PATH) { + return {}; + } + + PathRemoveFileSpecW(filename); + + return utility::narrow(filename); + } + + std::optional get_module_directoryw(HMODULE module) { + wchar_t filename[MAX_PATH]{ 0 }; + if (GetModuleFileNameW(module, filename, MAX_PATH) >= MAX_PATH) { + return {}; + } + + PathRemoveFileSpecW(filename); + + return filename; + } + + HMODULE load_module_from_current_directory(const std::wstring& module) { + const auto current_path = get_module_directoryw(get_executable()); + + if (!current_path) { + return nullptr; + } + + auto fspath = std::filesystem::path{ *current_path } / module; + + return LoadLibraryW(fspath.c_str()); + } + + std::vector read_module_from_disk(HMODULE module) { + auto path = get_module_path(module); + + if (!path) { + return {}; + } + + // read using std utilities like ifstream and tellg, etc. + auto file = std::ifstream{path->c_str(), std::ios::binary | std::ios::ate}; + + if (!file.is_open()) { + return {}; + } + + auto size = file.tellg(); + file.seekg(0, std::ios::beg); + + // don't brace initialize std::vector because it won't + // call the right constructor. + auto data = std::vector((size_t)size); + file.read((char*)data.data(), size); + + return data; + } + + std::optional> get_original_bytes(Address address) { + auto module_within = get_module_within(address); + + if (!module_within) { + return {}; + } + + return get_original_bytes(*module_within, address); + } + + std::optional> get_original_bytes(HMODULE module, Address address) { + auto disk_data = read_module_from_disk(module); + + if (disk_data.empty()) { + return std::nullopt; + } + + auto module_base = get_dll_imagebase(module); + + if (!module_base) { + return std::nullopt; + } + + auto module_rva = address.as() - *module_base; + + // obtain the file offset of the address now + auto disk_ptr = ptr_from_rva(disk_data.data(), module_rva); + + if (!disk_ptr) { + return std::nullopt; + } + + auto original_bytes = std::vector{}; + + auto module_bytes = address.as(); + auto disk_bytes = (uint8_t*)*disk_ptr; + + // copy the bytes from the disk data to the original bytes + // copy only until the bytes start to match eachother + for (auto i = 0; ; ++i) { + if (module_bytes[i] == disk_bytes[i]) { + bool actually_matches = true; + + // Lookahead 4 bytes to check if any other part is different before breaking out. + for (auto j = 1; j <= 4; ++j) { + if (module_bytes[i + j] != disk_bytes[i + j]) { + actually_matches = false; + break; + } + } + + if (actually_matches) { + break; + } + } + + original_bytes.push_back(disk_bytes[i]); + } + + if (original_bytes.empty()) { + return std::nullopt; + } + + return original_bytes; + } + + HMODULE get_executable() { + return GetModuleHandle(nullptr); + } + + std::mutex g_unlink_mutex{}; + + HMODULE unlink(HMODULE module) { + std::scoped_lock _{ g_unlink_mutex }; + + const auto base = (uintptr_t)module; + + if (base == 0) { + return module; + } + + // this SHOULD be thread safe...? + foreach_module([&](LIST_ENTRY* entry, _LDR_DATA_TABLE_ENTRY* ldr_entry) { + if ((uintptr_t)ldr_entry->DllBase == base) { + entry->Blink->Flink = entry->Flink; + entry->Flink->Blink = entry->Blink; + } + }); + + return module; + } + + HMODULE safe_unlink(HMODULE module) { + if (module == nullptr) { + return nullptr; + } + + utility::ThreadSuspender _{}; + + unlink(module); + return module; + } + + void foreach_module(std::function callback) try { + if (!callback) { + return; + } + + auto peb = (PEB*)__readgsqword(0x60); + + if (peb == nullptr) { + return; + } + + for (auto entry = peb->Ldr->InMemoryOrderModuleList.Flink; entry != &peb->Ldr->InMemoryOrderModuleList && entry != nullptr; entry = entry->Flink) { + if (IsBadReadPtr(entry, sizeof(LIST_ENTRY))) { + spdlog::error("[PEB] entry {:x} is a bad pointer", (uintptr_t)entry); + break; + } + + auto ldr_entry = (_LDR_DATA_TABLE_ENTRY*)CONTAINING_RECORD(entry, _LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); + + if (IsBadReadPtr(ldr_entry, sizeof(_LDR_DATA_TABLE_ENTRY))) { + spdlog::error("[PEB] ldr entry {:x} is a bad pointer", (uintptr_t)ldr_entry); + break; + } + + callback(entry, ldr_entry); + } + } catch(std::exception& e) { + spdlog::error("[PEB] exception while iterating modules: {}", e.what()); + } catch(...) { + spdlog::error("[PEB] unexpected exception while iterating modules. Continuing..."); + } + + size_t get_module_count(std::wstring_view name) { + size_t out{}; + + wchar_t lower_name[MAX_PATH]{}; + std::transform(name.begin(), name.end(), lower_name, ::towlower); + + foreach_module([&](LIST_ENTRY* entry, _LDR_DATA_TABLE_ENTRY* ldr_entry) { + wchar_t lower_dllname[MAX_PATH]{0}; + std::transform(ldr_entry->FullDllName.Buffer, ldr_entry->FullDllName.Buffer + ldr_entry->FullDllName.Length, lower_dllname, ::towlower); + + if (std::wstring_view{lower_dllname}.find(lower_name) != std::wstring_view::npos) { + ++out; + } + }); + + return out; + } + + void unlink_duplicate_modules() { + wchar_t system_dir[MAX_PATH]{0}; + GetSystemDirectoryW(system_dir, MAX_PATH); + + // to lower + std::transform(system_dir, system_dir + wcslen(system_dir), system_dir, ::towlower); + + const auto current_exe = get_executable(); + + foreach_module([&](LIST_ENTRY* entry, _LDR_DATA_TABLE_ENTRY* ldr_entry) { + if (ldr_entry->DllBase == current_exe) { + return; + } + + wchar_t lower_name[MAX_PATH]{0}; + std::transform(ldr_entry->FullDllName.Buffer, ldr_entry->FullDllName.Buffer + ldr_entry->FullDllName.Length, lower_name, ::towlower); + + if (std::wstring_view{lower_name}.find(std::wstring_view{system_dir}) == 0) { + return; + } + + auto path = std::filesystem::path{lower_name}; + auto stripped_path = path.stem().wstring(); + + if (get_module_count(stripped_path) > 1) { + entry->Flink->Blink = entry->Blink; + entry->Blink->Flink = entry->Flink; + + spdlog::info("{}", utility::narrow(lower_name)); + } + }); + } + + std::unordered_set g_skipped_paths{}; + std::mutex g_spoof_mutex{}; + + void spoof_module_paths_in_exe_dir() try { + std::scoped_lock _{g_spoof_mutex}; + + wchar_t system_dir[MAX_PATH+1]{0}; + GetSystemDirectoryW(system_dir, MAX_PATH); + + // to lower + std::transform(system_dir, system_dir + wcslen(system_dir), system_dir, ::towlower); + + std::wstring_view system_dir_view{system_dir}; + + const auto current_exe = get_executable(); + auto current_dir = *utility::get_module_directoryw(current_exe); + std::transform(current_dir.begin(), current_dir.end(), current_dir.begin(), ::towlower); + + const auto current_path = std::filesystem::path{current_dir}; + + foreach_module([&](LIST_ENTRY* entry, _LDR_DATA_TABLE_ENTRY* ldr_entry) { + if (ldr_entry == nullptr || IsBadReadPtr(ldr_entry, sizeof(_LDR_DATA_TABLE_ENTRY))) { + spdlog::error("[!] Failed to read module entry, continuing...", (uintptr_t)ldr_entry); + return; + } + + if (IsBadReadPtr(ldr_entry->FullDllName.Buffer, ldr_entry->FullDllName.Length)) { + spdlog::error("[!] Failed to read module name, continuing...", (uintptr_t)ldr_entry); + return; + } + + std::wstring previous_name{}; + + try { + if (ldr_entry != nullptr) { + previous_name = ldr_entry->FullDllName.Buffer; + } + } catch(...) { + spdlog::error("Could not determine name of module {:x}, continuing...", (uintptr_t)ldr_entry); + return; + } + + try { + if (ldr_entry->DllBase == current_exe) { + return; + } + + std::wstring lower_name = ldr_entry->FullDllName.Buffer; + std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::towlower); + + const auto path = std::filesystem::path{lower_name}; + + //if (std::wstring_view{lower_name}.find(current_dir) == std::wstring_view::npos) { + if (path.parent_path() != current_path) { + // only log it once so the log doesn't get polluted + if (g_skipped_paths.count(lower_name) == 0) { + spdlog::info("Skipping {}", utility::narrow(lower_name)); + g_skipped_paths.insert(lower_name); + } + + return; + } + + const auto stripped_path = path.stem().wstring(); + auto new_path = (path.parent_path() / "_storage_" / stripped_path).wstring() + path.extension().wstring(); + + try { + if (std::filesystem::exists(path)) { + std::filesystem::create_directory(std::filesystem::path{new_path}.parent_path()); + std::filesystem::copy_file(path, new_path, std::filesystem::copy_options::overwrite_existing); + } + } catch(...) { + spdlog::error("Failed to copy {} to {}", utility::narrow(path.wstring()), utility::narrow(new_path)); + new_path = std::filesystem::path{system_dir_view}.append(stripped_path).wstring() + path.extension().wstring(); + } + + spdlog::info("Creating new node for {} (0x{:x})", utility::narrow(lower_name), (uintptr_t)ldr_entry->DllBase); + + const auto size = std::max(MAX_PATH+1, new_path.size()+1); + auto final_chars = new wchar_t[size]{ 0 }; + + memcpy(final_chars, new_path.data(), new_path.size() * sizeof(wchar_t)); + final_chars[new_path.size()] = 0; + + ldr_entry->FullDllName.Buffer = final_chars; + ldr_entry->FullDllName.Length = new_path.size() * sizeof(wchar_t); + ldr_entry->FullDllName.MaximumLength = size * sizeof(wchar_t); + + spdlog::info("Done {} -> {}", utility::narrow(path.wstring()), utility::narrow(new_path)); + } catch (...) { + if (!previous_name.empty()) { + spdlog::error("Failed {}", utility::narrow(previous_name)); + } else { + spdlog::error("Failed to read module name (2), continuing..."); + } + } + }); + } catch(std::exception& e) { + spdlog::error("Exception in spoof_module_paths_in_exe_dir {}", e.what()); + } catch(...) { + spdlog::error("Unexpected error in spoof_module_paths_in_exe_dir. Continuing..."); + } + + optional ptr_from_rva(uint8_t* dll, uintptr_t rva) { + // Get the first section. + auto dosHeader = (PIMAGE_DOS_HEADER)&dll[0]; + auto ntHeaders = (PIMAGE_NT_HEADERS)&dll[dosHeader->e_lfanew]; + auto section = IMAGE_FIRST_SECTION(ntHeaders); + + // Go through each section searching for where the rva lands. + for (uint16_t i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i, ++section) { + auto size = section->Misc.VirtualSize; + + if (size == 0) { + size = section->SizeOfRawData; + } + + if (rva >= section->VirtualAddress && rva < ((uintptr_t)section->VirtualAddress + size)) { + auto delta = section->VirtualAddress - section->PointerToRawData; + + return (uintptr_t)(dll + (rva - delta)); + } + } + + return {}; + } +} diff --git a/shared/utility/Module.hpp b/shared/utility/Module.hpp new file mode 100644 index 0000000..7f546ae --- /dev/null +++ b/shared/utility/Module.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "Address.hpp" + +namespace utility { + // + // Module utilities. + // + std::optional get_module_size(const std::string& module); + std::optional get_module_size(HMODULE module); + std::optional get_module_within(Address address); + std::optional get_dll_imagebase(Address dll); + std::optional get_imagebase_va_from_ptr(Address dll, Address base, void* ptr); + + std::optional get_module_path(HMODULE module); + std::optional get_module_directory(HMODULE module); + std::optional get_module_directoryw(HMODULE module); + HMODULE load_module_from_current_directory(const std::wstring& module); + + std::vector read_module_from_disk(HMODULE module); + + // Returns the original bytes of the module at the given address. + // useful for un-patching something. + std::optional> get_original_bytes(Address address); + std::optional> get_original_bytes(HMODULE module, Address address); + + // Note: This function doesn't validate the dll's headers so make sure you've + // done so before calling it. + std::optional ptr_from_rva(uint8_t* dll, uintptr_t rva); + + HMODULE get_executable(); + HMODULE unlink(HMODULE module); + HMODULE safe_unlink(HMODULE module); + + void foreach_module(std::function callback); + size_t get_module_count(std::wstring_view name); + void unlink_duplicate_modules(); + void spoof_module_paths_in_exe_dir(); +} diff --git a/shared/utility/Patch.cpp b/shared/utility/Patch.cpp new file mode 100644 index 0000000..a00683c --- /dev/null +++ b/shared/utility/Patch.cpp @@ -0,0 +1,94 @@ +#include + +#include "Patch.hpp" + +using namespace std; + +std::unique_ptr Patch::create(uintptr_t addr, const std::vector& b, bool shouldEnable) { + return std::make_unique(addr, b, shouldEnable); +} + +std::unique_ptr Patch::create_nop(uintptr_t addr, uint32_t length, bool shouldEnable) { + std::vector bytes; bytes.resize(length); + std::fill(bytes.begin(), bytes.end(), 0x90); + + return std::make_unique(addr, bytes, shouldEnable); +} + +bool Patch::patch(uintptr_t address, const vector& bytes) { + auto oldProtection = protect(address, bytes.size(), PAGE_EXECUTE_READWRITE); + + if (!oldProtection) { + return false; + } + + unsigned int count = 0; + + for (auto byte : bytes) { + if (byte >= 0 && byte <= 0xFF) { + *(uint8_t*)(address + count) = (uint8_t)byte; + } + + ++count; + } + + FlushInstructionCache(GetCurrentProcess(), (LPCVOID)address, bytes.size()); + protect(address, bytes.size(), *oldProtection); + + return true; +} + +optional Patch::protect(uintptr_t address, size_t size, DWORD protection) { + DWORD oldProtection{ 0 }; + + if (VirtualProtect((LPVOID)address, size, protection, &oldProtection) != FALSE) { + return oldProtection; + } + + return {}; +} + +Patch::Patch(uintptr_t addr, const std::vector& b, bool shouldEnable /*= true*/) + : m_address{ addr }, + m_bytes{ b } +{ + if (shouldEnable) { + enable(); + } +} + +Patch::~Patch() { + disable(); +} + +bool Patch::enable() { + // Backup the original bytes. + if (m_original_bytes.empty()) { + m_original_bytes.resize(m_bytes.size()); + + unsigned int count = 0; + + for (auto& byte : m_original_bytes) { + byte = *(uint8_t*)(m_address + count++); + } + } + + return m_enabled = patch(m_address, m_bytes); +} + +bool Patch::disable() { + return !(m_enabled = !patch(m_address, m_original_bytes)); +} + +bool Patch::toggle() { + if (!m_enabled) { + return enable(); + } + + return !disable(); +} + + +bool Patch::toggle(bool state) { + return state ? enable() : disable(); +} diff --git a/shared/utility/Patch.hpp b/shared/utility/Patch.hpp new file mode 100644 index 0000000..1784f36 --- /dev/null +++ b/shared/utility/Patch.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include + +#include + +class Patch { +public: + using Ptr = std::unique_ptr; + static Ptr create(uintptr_t addr, const std::vector& b, bool should_enable = true); + static Ptr create_nop(uintptr_t addr, uint32_t length, bool should_enable = true); + + static bool patch(uintptr_t address, const std::vector& bytes); + + // Returns the old protection on success. + // Note: you don't need to call this if you're using the above patch function. + static std::optional protect(uintptr_t address, size_t size, DWORD protection); + + Patch(uintptr_t addr, const std::vector& b, bool should_enable = true); + + virtual ~Patch(); + + bool enable(); + bool disable(); + bool toggle(); + bool toggle(bool state); + +private: + uintptr_t m_address{ 0 }; + std::vector m_bytes; + std::vector m_original_bytes; + bool m_enabled{ false }; +}; \ No newline at end of file diff --git a/shared/utility/Pattern.cpp b/shared/utility/Pattern.cpp new file mode 100644 index 0000000..fc8be88 --- /dev/null +++ b/shared/utility/Pattern.cpp @@ -0,0 +1,97 @@ +#include + +#include + +#include "Memory.hpp" +#include "Pattern.hpp" + +using namespace std; + +namespace utility { + static uint8_t toByte(char digit) { + if (digit >= '0' && digit <= '9') { + return (digit - '0'); + } + + if (digit >= 'a' && digit <= 'f') { + return (digit - 'a' + 10); + } + + if (digit >= 'A' && digit <= 'F') { + return (digit - 'A' + 10); + } + + return 0; + } + + Pattern::Pattern(const string& pattern) + : m_pattern{} + { + m_pattern = move(buildPattern(pattern)); + } + + optional Pattern::find(uintptr_t start, size_t length) { + auto patternLength = m_pattern.size(); + auto end = start + length - patternLength; + + for (auto i = start; i <= end; ++i) { + auto j = i; + auto failedToMatch = false; + + // Make sure the address is readable. + if (IsBadReadPtr((const void*)i, patternLength) != FALSE) { + i += patternLength - 1; + continue; + } + + for (auto& k : m_pattern) { + if (k != -1 && k != *(uint8_t*)j) { + failedToMatch = true; + break; + } + + ++j; + } + + if (!failedToMatch) { + return i; + } + } + + return {}; + } + + vector buildPattern(string patternStr) { + // Remove spaces from the pattern string. + patternStr.erase(remove_if(begin(patternStr), end(patternStr), isspace), end(patternStr)); + + auto length = patternStr.length(); + vector pattern{}; + + for (size_t i = 0; i < length;) { + auto p1 = patternStr[i]; + + if (p1 != '?') { + // Bytes require 2 hex characters to encode, make sure we don't read + // past the end of the pattern string attempting to read the next char. + if (i + 1 >= length) { + break; + } + + auto p2 = patternStr[i + 1]; + auto value = toByte(p1) << 4 | toByte(p2); + + pattern.emplace_back(value); + + i += 2; + } + else { + // Wildcard's (?'s) get encoded as a -1. + pattern.emplace_back(-1); + i += 1; + } + } + + return pattern; + } +} diff --git a/shared/utility/Pattern.hpp b/shared/utility/Pattern.hpp new file mode 100644 index 0000000..6ddcb52 --- /dev/null +++ b/shared/utility/Pattern.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include + +namespace utility { + class Pattern { + public: + Pattern() = delete; + Pattern(const Pattern& other) = default; + Pattern(Pattern&& other) = default; + Pattern(const std::string& pattern); + ~Pattern() = default; + + std::optional find(uintptr_t start, size_t length); + + Pattern& operator=(const Pattern& other) = default; + Pattern& operator=(Pattern&& other) = default; + + auto pattern_len() const noexcept { return m_pattern.size(); } + + private: + std::vector m_pattern; + }; + + // Converts a string pattern (eg. "90 90 ? EB ? ? ?" to a vector of int's where + // wildcards are -1. + std::vector buildPattern(std::string patternStr); +} diff --git a/shared/utility/PointerHook.cpp b/shared/utility/PointerHook.cpp new file mode 100644 index 0000000..d2d9bd3 --- /dev/null +++ b/shared/utility/PointerHook.cpp @@ -0,0 +1,74 @@ +#include + +#include +#include + +#include "PointerHook.hpp" + +PointerHook::PointerHook(void** old_ptr, void* new_ptr) + : m_replace_ptr{old_ptr}, + m_destination{new_ptr} +{ + if (old_ptr == nullptr) { + spdlog::error("PointerHook: old_ptr is nullptr"); + throw std::invalid_argument("old_ptr cannot be nullptr"); + } + + if (IsBadReadPtr(old_ptr, sizeof(void*))) { + spdlog::error("PointerHook: old_ptr is not readable"); + throw std::invalid_argument("old_ptr is not readable"); + } + + ProtectionOverride overrider{old_ptr, sizeof(void*), PAGE_EXECUTE_READWRITE}; + + spdlog::info("[PointerHook] Hooking {:x}->{:x} to {:x}", (uintptr_t)old_ptr, (uintptr_t)*old_ptr, (uintptr_t)new_ptr); + + m_original = *old_ptr; + *old_ptr = new_ptr; +} + +PointerHook::~PointerHook() { + remove(); +} + +bool PointerHook::remove() { + if (m_replace_ptr != nullptr && !IsBadReadPtr(m_replace_ptr, sizeof(void*)) && *m_replace_ptr == m_destination) { + try { + ProtectionOverride overrider{m_replace_ptr, sizeof(void*), PAGE_EXECUTE_READWRITE}; + *m_replace_ptr = m_original; + } catch (std::exception& e) { + spdlog::error("PointerHook: {}", e.what()); + return false; + } + } + + return true; +} + +bool PointerHook::restore() { + if (m_replace_ptr != nullptr && !IsBadReadPtr(m_replace_ptr, sizeof(void*)) && *m_replace_ptr != m_destination) { + try { + ProtectionOverride overrider{m_replace_ptr, sizeof(void*), PAGE_EXECUTE_READWRITE}; + *m_replace_ptr = m_destination; + } catch (std::exception& e) { + spdlog::error("PointerHook: {}", e.what()); + return false; + } + } + + return true; +} + +ProtectionOverride::ProtectionOverride(void* address, size_t size, uint32_t protection) + : m_address{address}, + m_size{size} +{ + if (!VirtualProtect(address, size, protection, (DWORD*)&m_old)) { + spdlog::error("PointerHook: VirtualProtect failed"); + throw std::runtime_error("VirtualProtect failed"); + } +} + +ProtectionOverride::~ProtectionOverride() { + VirtualProtect(m_address, m_size, m_old, (DWORD*)&m_old); +} diff --git a/shared/utility/PointerHook.hpp b/shared/utility/PointerHook.hpp new file mode 100644 index 0000000..90efdb1 --- /dev/null +++ b/shared/utility/PointerHook.hpp @@ -0,0 +1,30 @@ +#pragma once + +struct ProtectionOverride { + ProtectionOverride(void* address, size_t size, uint32_t protection); + virtual ~ProtectionOverride(); + + void* m_address{}; + size_t m_size{}; + uint32_t m_old{}; +}; + +// A class to replace a pointer with a new pointer. +class PointerHook { +public: + PointerHook(void** old_ptr, void* new_ptr); + virtual ~PointerHook(); + + bool remove(); + bool restore(); + + template + T get_original() const { + return (T)m_original; + } + +private: + void** m_replace_ptr{}; + void* m_original{}; + void* m_destination{}; +}; \ No newline at end of file diff --git a/shared/utility/Registry.cpp b/shared/utility/Registry.cpp new file mode 100644 index 0000000..ad8aae6 --- /dev/null +++ b/shared/utility/Registry.cpp @@ -0,0 +1,40 @@ +#include + +#include "Registry.hpp" + +namespace utility { +std::optional get_registry_dword(HKEY key, std::string_view subkey, std::string_view value) { + HKEY subkey_handle{}; + + if (auto res = RegOpenKeyExA(key, subkey.data(), 0, KEY_QUERY_VALUE, &subkey_handle); res != ERROR_SUCCESS) { + spdlog::error("({}) Failed to open registry key {}", res, subkey); + return std::nullopt; + } + + DWORD type{}; + DWORD size{}; + + if (auto res = RegQueryValueExA(subkey_handle, value.data(), nullptr, &type, nullptr, &size); res != ERROR_SUCCESS) { + spdlog::error("({}) Failed to query registry value {}", res, value); + RegCloseKey(subkey_handle); + return std::nullopt; + } + + if (type != REG_DWORD) { + spdlog::error("Registry value is not of type REG_DWORD: {}", value); + RegCloseKey(subkey_handle); + return std::nullopt; + } + + DWORD result{}; + + if (auto res = RegQueryValueExA(subkey_handle, value.data(), nullptr, nullptr, (LPBYTE)&result, &size); res != ERROR_SUCCESS) { + spdlog::error("({}) Failed to query registry value 2 {}", res, value); + RegCloseKey(subkey_handle); + return std::nullopt; + } + + RegCloseKey(subkey_handle); + return result; +} +} \ No newline at end of file diff --git a/shared/utility/Registry.hpp b/shared/utility/Registry.hpp new file mode 100644 index 0000000..d381df8 --- /dev/null +++ b/shared/utility/Registry.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include +#include +#include +#include + +namespace utility { +std::optional get_registry_dword(HKEY key, std::string_view subkey, std::string_view value); +} \ No newline at end of file diff --git a/shared/utility/Scan.cpp b/shared/utility/Scan.cpp new file mode 100644 index 0000000..38457af --- /dev/null +++ b/shared/utility/Scan.cpp @@ -0,0 +1,174 @@ +#include + +#include "Pattern.hpp" +#include "String.hpp" +#include "Module.hpp" +#include "Scan.hpp" + +using namespace std; + +namespace utility { + optional scan(const string& module, const string& pattern) { + return scan(GetModuleHandle(module.c_str()), pattern); + } + + optional scan(const string& module, uintptr_t start, const string& pattern) { + HMODULE mod = GetModuleHandle(module.c_str()); + return scan(start, (get_module_size(mod).value_or(0) - start + (uintptr_t)mod), pattern); + } + + optional scan(HMODULE module, const string& pattern) { + return scan((uintptr_t)module, get_module_size(module).value_or(0), pattern); + } + + optional scan(uintptr_t start, size_t length, const string& pattern) { + if (start == 0 || length == 0) { + return {}; + } + + Pattern p{ pattern }; + + return p.find(start, length); + } + + std::optional scan_reverse(uintptr_t start, size_t length, const std::string& pattern) { + if (start == 0 || length == 0) { + return {}; + } + + Pattern p{ pattern }; + + for (uintptr_t i = start; i >= start - length; i--) { + if (p.find(i, length).has_value()) { + return i; + } + } + + return {}; + } + + optional scan_data(HMODULE module, const uint8_t* data, size_t size) { + const auto module_size = get_module_size(module).value_or(0); + const auto end = (uintptr_t)module + module_size; + + for (auto i = (uintptr_t)module; i < end; i += sizeof(uint8_t)) { + if (memcmp((void*)i, data, size) == 0) { + return i; + } + } + + return {}; + } + + optional scan_ptr(HMODULE module, uintptr_t ptr) { + const auto module_size = get_module_size(module).value_or(0); + const auto end = (uintptr_t)module + module_size; + + for (auto i = (uintptr_t)module; i < end; i += sizeof(void*)) { + if (*(uintptr_t*)i == ptr) { + return i; + } + } + + return std::nullopt; + } + + optional scan_string(HMODULE module, const string& str) { + if (str.empty()) { + return {}; + } + + const auto data = (uint8_t*)str.c_str(); + const auto size = str.size(); + + return scan_data(module, data, size); + } + + optional scan_string(HMODULE module, const wstring& str) { + if (str.empty()) { + return {}; + } + + const auto data = (uint8_t*)str.c_str(); + const auto size = str.size() * sizeof(wchar_t); + + return scan_data(module, data, size); + } + + optional scan_reference(HMODULE module, uintptr_t ptr, bool relative) { + if (!relative) { + return scan_ptr(module, ptr); + } + + const auto module_size = get_module_size(module).value_or(0); + const auto end = (uintptr_t)module + module_size; + + for (auto i = (uintptr_t)module; i < end; i += sizeof(uint8_t)) { + if (calculate_absolute(i, 4) == ptr) { + return i; + } + } + + return {}; + } + + optional scan_relative_reference_strict(HMODULE module, uintptr_t ptr, const string& preceded_by) { + if (preceded_by.empty()) { + return {}; + } + + const auto module_size = get_module_size(module).value_or(0); + const auto end = (uintptr_t)module + module_size; + + // convert preceded_by (IDA style string) to bytes + auto pat = utility::Pattern{ preceded_by }; + const auto pat_len = pat.pattern_len(); + + for (auto i = (uintptr_t)module; i < end; i += sizeof(uint8_t)) { + if (calculate_absolute(i, 4) == ptr) { + if (pat.find(i - pat_len, pat_len)) { + return i; + } + } + } + + return {}; + } + + + std::optional scan_opcode(uintptr_t ip, size_t num_instructions, uint8_t opcode) { + for (size_t i = 0; i < num_instructions; ++i) { + hde64s hde{}; + auto len = hde64_disasm((void*)ip, &hde); + + if (hde.opcode == opcode) { + return ip; + } + + ip += len; + } + + return std::nullopt; + } + + std::optional scan_disasm(uintptr_t ip, size_t num_instructions, const string& pattern) { + for (size_t i = 0; i < num_instructions; ++i) { + hde64s hde{}; + auto len = hde64_disasm((void*)ip, &hde); + + if (auto result = scan(ip, len, pattern); result && *result == ip) { + return ip; + } + + ip += len; + } + + return std::nullopt; + } + + uintptr_t calculate_absolute(uintptr_t address, uint8_t customOffset /*= 4*/) { + auto offset = *(int32_t*)address; + + return address + customOffset + offset; + } +} diff --git a/shared/utility/Scan.hpp b/shared/utility/Scan.hpp new file mode 100644 index 0000000..b00493c --- /dev/null +++ b/shared/utility/Scan.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +#include + +namespace utility { + std::optional scan(const std::string& module, const std::string& pattern); + std::optional scan(const std::string& module, uintptr_t start, const std::string& pattern); + std::optional scan(HMODULE module, const std::string& pattern); + std::optional scan(uintptr_t start, size_t length, const std::string& pattern); + std::optional scan_reverse(uintptr_t start, size_t length, const std::string& pattern); + + std::optional scan_data(HMODULE, const uint8_t* data, size_t size); + std::optional scan_ptr(HMODULE module, uintptr_t ptr); + std::optional scan_string(HMODULE module, const std::string& str); + std::optional scan_string(HMODULE module, const std::wstring& str); + + std::optional scan_reference(HMODULE module, uintptr_t ptr, bool relative = true); + std::optional scan_relative_reference_strict(HMODULE module, uintptr_t ptr, const std::string& preceded_by); + + std::optional scan_opcode(uintptr_t ip, size_t num_instructions, uint8_t opcode); + std::optional scan_disasm(uintptr_t ip, size_t num_instructions, const std::string& pattern); + + uintptr_t calculate_absolute(uintptr_t address, uint8_t custom_offset = 4); +} diff --git a/shared/utility/String.cpp b/shared/utility/String.cpp new file mode 100644 index 0000000..bdf584d --- /dev/null +++ b/shared/utility/String.cpp @@ -0,0 +1,51 @@ +#include + +#include + +#include "String.hpp" + +using namespace std; + +namespace utility { + string narrow(wstring_view str) { + auto length = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.length(), nullptr, 0, nullptr, nullptr); + string narrowStr{}; + + narrowStr.resize(length); + WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.length(), (LPSTR)narrowStr.c_str(), length, nullptr, nullptr); + + return narrowStr; + } + + wstring widen(string_view str) { + auto length = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.length(), nullptr, 0); + wstring wideStr{}; + + wideStr.resize(length); + MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.length(), (LPWSTR)wideStr.c_str(), length); + + return wideStr; + } + + string format_string(const char* format, va_list args) { + va_list argsCopy{}; + + va_copy(argsCopy, args); + + auto len = vsnprintf(nullptr, 0, format, argsCopy); + + va_end(argsCopy); + + if (len <= 0) { + return {}; + } + + string buffer{}; + + buffer.resize(len + 1, 0); + vsnprintf(buffer.data(), buffer.size(), format, args); + buffer.resize(buffer.size() - 1); // Removes the extra 0 vsnprintf adds. + + return buffer; + } +} diff --git a/shared/utility/String.hpp b/shared/utility/String.hpp new file mode 100644 index 0000000..70bb719 --- /dev/null +++ b/shared/utility/String.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +namespace utility { + // + // String utilities. + // + + // Conversion functions for UTF8<->UTF16. + std::string narrow(std::wstring_view std); + std::wstring widen(std::string_view std); + + std::string format_string(const char* format, va_list args); + + // FNV-1a + static constexpr auto hash(std::string_view data) { + size_t result = 0xcbf29ce484222325; + + for (char c : data) { + result ^= c; + result *= (size_t)1099511628211; + } + + return result; + } +} + +constexpr auto operator "" _fnv(const char* s, size_t) { + return utility::hash(s); +} \ No newline at end of file diff --git a/shared/utility/Thread.cpp b/shared/utility/Thread.cpp new file mode 100644 index 0000000..dc859bb --- /dev/null +++ b/shared/utility/Thread.cpp @@ -0,0 +1,83 @@ +#include + +#include +#include +#include + +#include "Thread.hpp" + +namespace utility { +namespace detail { +std::mutex g_suspend_mutex{}; +} + +ThreadStates suspend_threads() { + ThreadStates states{}; + + const auto pid = GetCurrentProcessId(); + const auto snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pid); + + if (snapshot_handle == nullptr || snapshot_handle == INVALID_HANDLE_VALUE) { + return states; + } + + THREADENTRY32 te{}; + te.dwSize = sizeof(THREADENTRY32); + + if (!Thread32First(snapshot_handle, &te)) { + CloseHandle(snapshot_handle); + return states; + } + + const auto current_thread_id = GetCurrentThreadId(); + + do { + if (te.th32OwnerProcessID == pid && te.th32ThreadID != current_thread_id) { + auto thread_handle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID); + + if (thread_handle != nullptr && snapshot_handle != INVALID_HANDLE_VALUE) { + auto state = std::make_unique(); + + spdlog::info("Suspending {}", (uint32_t)te.th32ThreadID); + + state->thread_id = te.th32ThreadID; + state->suspended = SuspendThread(thread_handle) > 0; + states.emplace_back(std::move(state)); + + CloseHandle(thread_handle); + } + } + } while (Thread32Next(snapshot_handle, &te)); + + CloseHandle(snapshot_handle); + return states; +} + +void resume_threads(const ThreadStates& states) { + for (const ThreadState::Ptr& state : states) { + auto thread_handle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, state->thread_id); + + if (thread_handle != nullptr) { + spdlog::info("Resuming {}", state->thread_id); + + ResumeThread(thread_handle); + CloseHandle(thread_handle); + } + } +} + +ThreadSuspender::ThreadSuspender() { + detail::g_suspend_mutex.lock(); + states = suspend_threads(); +} + +ThreadSuspender::~ThreadSuspender() { + resume_threads(states); + detail::g_suspend_mutex.unlock(); +} + +void ThreadSuspender::resume() { + resume_threads(states); + states.clear(); +} +} diff --git a/shared/utility/Thread.hpp b/shared/utility/Thread.hpp new file mode 100644 index 0000000..3e15609 --- /dev/null +++ b/shared/utility/Thread.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +namespace utility { +struct ThreadState { + uint32_t thread_id{0}; + bool suspended{false}; + + using Ptr = std::unique_ptr; +}; + +using ThreadStates = std::vector; + +ThreadStates suspend_threads(); +void resume_threads(const ThreadStates& states); + +struct ThreadSuspender { + ThreadSuspender(); + + virtual ~ThreadSuspender(); + + void suspend() { + states = suspend_threads(); + } + + void resume(); + + ThreadStates states{}; +}; +} \ No newline at end of file diff --git a/shared/utility/VehHook.cpp b/shared/utility/VehHook.cpp new file mode 100644 index 0000000..ffb2fd0 --- /dev/null +++ b/shared/utility/VehHook.cpp @@ -0,0 +1,150 @@ +#include +#include + +#include + +#include "VehHook.hpp" + +using namespace std; + +vector g_vehHooks; +mutex g_vehHooksMutex; +PVOID g_vehHandler = nullptr; + +bool write(Address address, const void* data, size_t size) { + ProtectionOverride prot{ address, size, PAGE_EXECUTE_READWRITE }; + memcpy((void*)address, data, size); + + return true; +} + +bool read(Address address, void* data, size_t size) { + if (address.as() == nullptr) { + return false; + } + memcpy(data, address.as(), size); + return true; +} + +static int hde(Address address) { + hde64s hs; + return hde64_disasm(address, &hs); +} + +VehHook::VehHook() + : m_hooks() +{ + lock_guard _(g_vehHooksMutex); + + g_vehHooks.push_back(this); + create(); +} + +VehHook::~VehHook() { + lock_guard _(g_vehHooksMutex); + + remove(); + g_vehHooks.erase(std::remove(g_vehHooks.begin(), g_vehHooks.end(), this), g_vehHooks.end()); +} + +void VehHook::create() { + if (!g_vehHandler) { + g_vehHandler = AddVectoredExceptionHandler(1, &VehHook::handler); + } +} + +void VehHook::remove() { + // Remove the int3's. + for (auto& hook : m_hooks) { + write(hook.target, &hook.originalByte, 1); + write(hook.next, &hook.nextOriginalByte, 1); + } + + m_hooks.clear(); +} + +bool VehHook::hook(Address target, CallbackFn cb) { + return hook(target, nullptr, cb); +} + +bool VehHook::hook(Address target, Address destination, CallbackFn cb) { + HookInfo ctx; + + ctx.target = target; + ctx.next = target + hde(target); + ctx.destination = destination; + ctx.cb = cb; + + if (!read(ctx.target, &ctx.originalByte, 1)) { + return false; + } + + if (!read(ctx.next, &ctx.nextOriginalByte, 1)) { + return false; + } + + uint8_t int3 = 0xCC; + + if (!write(ctx.target, &int3, 1)) { + return false; + } + + m_hooks.push_back(ctx); + + return true; +} + +LONG VehHook::handler(PEXCEPTION_POINTERS info) { + auto record = info->ExceptionRecord; + auto code = record->ExceptionCode; + + + if (code == EXCEPTION_BREAKPOINT) { + auto context = info->ContextRecord; + auto ip = context->Rip; + + for (auto& hook : g_vehHooks) { + for (auto& ctx : hook->m_hooks) { + if (ip != ctx.target.as() && ip != ctx.next.as()) { + continue; + } + + if (ip == ctx.target) { + // Remove the int3. + if (!write(ctx.target, &ctx.originalByte, 1)) { + continue; + } + + // Call the callback. + if (ctx.cb) { + ctx.cb(RuntimeInfo{ context, ctx }); + + // Write an int3 to the next instruction so that it can + // restore the targets int3. + uint8_t int3 = 0xCC; + + write(ctx.next, &int3, 1); + } + + // Call the hook. + if (ctx.destination) { + context->Rip = ctx.destination; + } + } + else { + // Remove the int3. + write(ctx.next, &ctx.nextOriginalByte, 1); + + // Restore the int3 to the target address. + uint8_t int3 = 0xCC; + + write(ctx.target, &int3, 1); + } + + return EXCEPTION_CONTINUE_EXECUTION; + } + } + } + + return EXCEPTION_CONTINUE_SEARCH; +} diff --git a/shared/utility/VehHook.hpp b/shared/utility/VehHook.hpp new file mode 100644 index 0000000..e7885d5 --- /dev/null +++ b/shared/utility/VehHook.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include + +#include + +#include "PointerHook.hpp" +#include "Address.hpp" + +class VehHook { +public: + struct RuntimeInfo; + + typedef std::function CallbackFn; + + struct HookInfo { + Address target; + Address next; // The next instruction after the target instruction. + Address destination; + + uint8_t originalByte; + uint8_t nextOriginalByte; + + CallbackFn cb; + }; + + struct RuntimeInfo { + PCONTEXT context; + HookInfo& info; + }; + + VehHook(); + virtual ~VehHook(); + + void create(); + void remove(); + + bool hook(Address target, CallbackFn cb); + bool hook(Address target, Address destination, CallbackFn cb); + + auto getHookResetFunction(const RuntimeInfo& hook) { + auto target = hook.info.target; + return [=]() { + ProtectionOverride prot{target, 1, PAGE_EXECUTE_READWRITE}; + *target.as() = 0xCC; + }; + } + +private: + std::vector m_hooks; + PVOID m_handler; + + static LONG CALLBACK handler(PEXCEPTION_POINTERS info); +}; \ No newline at end of file diff --git a/shared/utility/VtableHook.cpp b/shared/utility/VtableHook.cpp new file mode 100644 index 0000000..1071564 --- /dev/null +++ b/shared/utility/VtableHook.cpp @@ -0,0 +1,97 @@ +#include "VtableHook.hpp" + +using namespace std; + +VtableHook::VtableHook() + : m_rawData{}, + m_vtablePtr(), + m_newVtable(nullptr), + m_oldVtable(), + m_vtableSize(0) +{} + +VtableHook::VtableHook(Address target) + : VtableHook() +{ + create(target); +} + +VtableHook::VtableHook(VtableHook&& other) + : m_rawData(move(other.m_rawData)), + m_vtablePtr(other.m_vtablePtr), + m_newVtable(other.m_newVtable), + m_oldVtable(other.m_oldVtable), + m_vtableSize(other.m_vtableSize) +{ + other.m_vtablePtr = nullptr; + other.m_newVtable = nullptr; + other.m_oldVtable = nullptr; + other.m_vtableSize = 0; +} + +VtableHook::~VtableHook() { + remove(); +} + +bool VtableHook::create(Address target) { + if (!m_rawData.empty()) { + remove(); + m_rawData.clear(); + } + + m_vtablePtr = target; + m_oldVtable = m_vtablePtr.to
(); + m_vtableSize = getVtableSize(m_oldVtable); + // RTTI. + m_rawData.resize(m_vtableSize + 1); + m_newVtable = m_rawData.data() + 1; + + memcpy(m_rawData.data(), m_oldVtable.as() - 1, sizeof(Address) * (m_vtableSize + 1)); + + // At this point we have the address of the old vtable, and a copy of it + // stored in m_newVtable. Set the target objects vtable + // pointer to our copy of the original. + *m_vtablePtr.as() = m_newVtable; + + return true; +} + +bool VtableHook::recreate() { + if (m_vtablePtr != nullptr) { + *m_vtablePtr.as() = m_newVtable; + return true; + } + + return false; +} + +bool VtableHook::remove() { + // Can cause issues where we set the vtable/random memory of some other pointer. + if (m_vtablePtr != nullptr && IsBadReadPtr(m_vtablePtr.ptr(), sizeof(void*)) == FALSE && m_vtablePtr.to() == m_newVtable) { + *m_vtablePtr.as() = m_oldVtable; + return true; + } + + return false; +} + +bool VtableHook::hookMethod(uint32_t index, Address newMethod) { + if (m_oldVtable != nullptr && m_newVtable != nullptr && index < m_vtableSize) { + m_newVtable[index] = newMethod; + return true; + } + + return false; +} + +size_t VtableHook::getVtableSize(Address vtable) { + size_t i = 0; + + for (; vtable.as()[i] != nullptr; ++i) { + if (IsBadCodePtr(vtable.as()[i]) == TRUE) { + break; + } + } + + return i; +} diff --git a/shared/utility/VtableHook.hpp b/shared/utility/VtableHook.hpp new file mode 100644 index 0000000..0bce5de --- /dev/null +++ b/shared/utility/VtableHook.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +#include + +#include "Address.hpp" + +class VtableHook { +public: + VtableHook(); + VtableHook(Address target); + VtableHook(const VtableHook& other) = delete; + VtableHook(VtableHook&& other); + + virtual ~VtableHook(); + + bool create(Address target); + bool recreate(); + bool remove(); + + bool hookMethod(uint32_t index, Address newMethod); + + auto getInstance() { + return m_vtablePtr; + } + + // Access to original methods. + Address getMethod(uint32_t index) { + if (index < m_vtableSize && m_oldVtable && m_newVtable) { + return m_oldVtable.as()[index]; + } + else { + return nullptr; + } + } + + template + T getMethod(uint32_t index) { + return (T)getMethod(index).ptr(); + } + +private: + std::vector
m_rawData; + Address m_vtablePtr; + Address* m_newVtable; + Address m_oldVtable; + size_t m_vtableSize; + + size_t getVtableSize(Address vtable); +}; \ No newline at end of file diff --git a/src/AutomataMP.cpp b/src/AutomataMP.cpp new file mode 100644 index 0000000..e4e1b57 --- /dev/null +++ b/src/AutomataMP.cpp @@ -0,0 +1,1438 @@ +#include +#include + +#include + +#include + +// minhook, used for AllocateBuffer +extern "C" { +#include <../buffer.h> +}; + +#include +#include "automata-imgui/font_robotomedium.hpp" +#include "automata-imgui/imgui_impl_dx11.h" +#include "automata-imgui/imgui_impl_dx12.h" +#include "automata-imgui/imgui_impl_win32.h" + +#include "utility/Module.hpp" +#include "utility/Patch.hpp" +#include "utility/Scan.hpp" +#include "utility/Thread.hpp" +#include "utility/String.hpp" + +#include "Mods.hpp" + +#include "ExceptionHandler.hpp" +#include "LicenseStrings.hpp" +#include "mods/AutomataMPConfig.hpp" +#include "AutomataMP.hpp" + +namespace fs = std::filesystem; +using namespace std::literals; + + +std::unique_ptr g_framework{}; + +void AutomataMP::hook_monitor() { + std::scoped_lock _{ m_hook_monitor_mutex }; + + if (g_framework == nullptr) { + return; + } + + const auto now = std::chrono::steady_clock::now(); + + auto& d3d11 = get_d3d11_hook(); + auto& d3d12 = get_d3d12_hook(); + + const auto renderer_type = get_renderer_type(); + + if (d3d11 == nullptr || d3d12 == nullptr + || (renderer_type == AutomataMP::RendererType::D3D11 && d3d11 != nullptr && !d3d11->is_inside_present()) + || (renderer_type == AutomataMP::RendererType::D3D12 && d3d12 != nullptr && !d3d12->is_inside_present())) + { + // check if present time is more than 5 seconds ago + if (now - m_last_present_time > std::chrono::seconds(5)) { + if (m_has_last_chance) { + // the purpose of this is to make sure that the game is not frozen + // e.g. if we are debugging the game, so we don't rehook anything on accident + m_has_last_chance = false; + m_last_chance_time = now; + + spdlog::info("Last chance encountered for hooking"); + } + + if (!m_has_last_chance && now - m_last_chance_time > std::chrono::seconds(1)) { + spdlog::info("Sending rehook request for D3D"); + + // hook_d3d12 always gets called first. + if (m_is_d3d11) { + hook_d3d11(); + } else { + hook_d3d12(); + } + + // so we don't immediately go and hook it again + // add some additional time to it to give it some leeway + m_last_present_time = std::chrono::steady_clock::now() + std::chrono::seconds(5); + m_last_message_time = std::chrono::steady_clock::now() + std::chrono::seconds(5); + m_last_chance_time = std::chrono::steady_clock::now() + std::chrono::seconds(1); + m_has_last_chance = true; + } + } else { + m_last_chance_time = std::chrono::steady_clock::now(); + m_has_last_chance = true; + } + + if (m_initialized && m_wnd != 0 && now - m_last_message_time > std::chrono::seconds(5)) { + if (m_windows_message_hook != nullptr && m_windows_message_hook->is_hook_intact()) { + spdlog::info("Windows message hook is still intact, ignoring..."); + m_last_message_time = now; + m_last_sendmessage_time = now; + m_sent_message = false; + return; + } + + // send dummy message to window to check if our hook is still intact + if (!m_sent_message) { + spdlog::info("Sending initial message hook test"); + + auto proc = (WNDPROC)GetWindowLongPtr(m_wnd, GWLP_WNDPROC); + + if (proc != nullptr) { + const auto ret = CallWindowProc(proc, m_wnd, WM_NULL, 0, 0); + + spdlog::info("Hook test message sent"); + } + + m_last_sendmessage_time = std::chrono::steady_clock::now(); + m_sent_message = true; + } else if (now - m_last_sendmessage_time > std::chrono::seconds(1)) { + spdlog::info("Sending reinitialization request for message hook"); + + // if we don't get a message for 5 seconds, assume the hook is broken + //m_initialized = false; // causes the hook to be re-initialized next frame + m_message_hook_requested = true; + m_last_message_time = std::chrono::steady_clock::now() + std::chrono::seconds(5); + m_last_present_time = std::chrono::steady_clock::now() + std::chrono::seconds(5); + + m_sent_message = false; + } + } else { + m_sent_message = false; + } + } +} + +AutomataMP::AutomataMP(HMODULE AutomataMP_module) + : m_automatamp_module{AutomataMP_module} + , m_game_module{GetModuleHandle(0)} + , m_logger{spdlog::basic_logger_mt("AutomataMP", "automatamp_log.txt", true)} { + spdlog::set_default_logger(m_logger); + spdlog::flush_on(spdlog::level::info); + spdlog::info("AutomataMP entry"); + + const auto module_size = *utility::get_module_size(m_game_module); + + spdlog::info("Game Module Addr: {:x}", (uintptr_t)m_game_module); + spdlog::info("Game Module Size: {:x}", module_size); + + // preallocate some memory for minhook to mitigate failures (temporarily at least... this should in theory fail when too many hooks are made) + // but, 64 slots should be enough for now. + // so... TODO: modify minhook to use absolute jumps when failing to allocate memory nearby + const auto halfway_module = (uintptr_t)m_game_module + (module_size / 2); + const auto pre_allocated_buffer = (uintptr_t)AllocateBuffer((LPVOID)halfway_module); // minhook function + spdlog::info("Preallocated buffer: {:x}", pre_allocated_buffer); + +#ifdef DEBUG + spdlog::set_level(spdlog::level::debug); +#endif + + // Create the typedef for RtlGetVersion + typedef LONG (*RtlGetVersionFunc)(PRTL_OSVERSIONINFOW); + + const auto ntdll = GetModuleHandle("ntdll.dll"); + + if (ntdll != nullptr) { + // Manually get RtlGetVersion + auto rtl_get_version = (RtlGetVersionFunc)GetProcAddress(ntdll, "RtlGetVersion"); + + if (rtl_get_version != nullptr) { + spdlog::info("Getting OS version information..."); + + // Create an initial log that prints out the user's Windows OS version information + // With the major and minor version numbers + // Using RtlGetVersion() + OSVERSIONINFOW os_version_info{}; + ZeroMemory(&os_version_info, sizeof(OSVERSIONINFOW)); + os_version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + os_version_info.dwMajorVersion = 0; + os_version_info.dwMinorVersion = 0; + os_version_info.dwBuildNumber = 0; + os_version_info.dwPlatformId = 0; + + if (rtl_get_version(&os_version_info) != 0) { + spdlog::info("RtlGetVersion() failed"); + } else { + // Log the Windows version information + spdlog::info("OS Version Information"); + spdlog::info("\tMajor Version: {}", os_version_info.dwMajorVersion); + spdlog::info("\tMinor Version: {}", os_version_info.dwMinorVersion); + spdlog::info("\tBuild Number: {}", os_version_info.dwBuildNumber); + spdlog::info("\tPlatform Id: {}", os_version_info.dwPlatformId); + + spdlog::info("Disclaimer: AutomataMP does not send this information to the developers or any other third party."); + spdlog::info("This information is only used to help with the development of AutomataMP."); + } + } else { + spdlog::info("RtlGetVersion() not found"); + } + } else { + spdlog::info("ntdll.dll not found"); + } + + // Hooking D3D12 initially because we need to retrieve the command queue before the first frame then switch to D3D11 if it failed later + // on + // addendum: now we don't need to do that, we just grab the command queue offset from the swapchain we create + /*if (!hook_d3d12()) { + spdlog::error("Failed to hook D3D12 for initial test."); + }*/ + + std::scoped_lock _{m_hook_monitor_mutex}; + + m_last_present_time = std::chrono::steady_clock::now(); + m_last_message_time = std::chrono::steady_clock::now(); + m_d3d_monitor_thread = std::make_unique([this]() { + while (true) { + this->hook_monitor(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + }); +} + +bool AutomataMP::hook_d3d11() { + //if (m_d3d11_hook == nullptr) { + m_d3d11_hook.reset(); + m_d3d11_hook = std::make_unique(); + m_d3d11_hook->on_present([this](D3D11Hook& hook) { on_frame_d3d11(); }); + m_d3d11_hook->on_post_present([this](D3D11Hook& hook) { on_post_present_d3d11(); }); + m_d3d11_hook->on_resize_buffers([this](D3D11Hook& hook) { on_reset(); }); + //} + + // Making sure D3D12 is not hooked + if (!m_is_d3d12) { + if (m_d3d11_hook->hook()) { + spdlog::info("Hooked DirectX 11"); + m_valid = true; + m_is_d3d11 = true; + return true; + } + // We make sure to no unhook any unwanted hooks if D3D11 didn't get hooked properly + if (m_d3d11_hook->unhook()) { + spdlog::info("D3D11 unhooked!"); + } else { + spdlog::info("Cannot unhook D3D11, this might crash."); + } + + m_valid = false; + m_is_d3d11 = false; + return false; + } + + return false; +} + +bool AutomataMP::hook_d3d12() { + // windows 7? + if (LoadLibraryA("d3d12.dll") == nullptr) { + spdlog::info("d3d12.dll not found, user is probably running Windows 7."); + spdlog::info("Falling back to hooking D3D11."); + + m_is_d3d12 = false; + return hook_d3d11(); + } + + //if (m_d3d12_hook == nullptr) { + m_d3d12_hook.reset(); + m_d3d12_hook = std::make_unique(); + m_d3d12_hook->on_present([this](D3D12Hook& hook) { on_frame_d3d12(); }); + m_d3d12_hook->on_post_present([this](D3D12Hook& hook) { on_post_present_d3d12(); }); + m_d3d12_hook->on_resize_buffers([this](D3D12Hook& hook) { on_reset(); }); + m_d3d12_hook->on_resize_target([this](D3D12Hook& hook) { on_reset(); }); + //} + //m_d3d12_hook->on_create_swap_chain([this](D3D12Hook& hook) { m_d3d12.command_queue = m_d3d12_hook->get_command_queue(); }); + + // Making sure D3D11 is not hooked + if (!m_is_d3d11) { + if (m_d3d12_hook->hook()) { + spdlog::info("Hooked DirectX 12"); + m_valid = true; + m_is_d3d12 = true; + return true; + } + // We make sure to no unhook any unwanted hooks if D3D12 didn't get hooked properly + if (m_d3d12_hook->unhook()) { + spdlog::info("D3D12 Unhooked!"); + } else { + spdlog::info("Cannot unhook D3D12, this might crash."); + } + + m_valid = false; + m_is_d3d12 = false; + + // Try to hook d3d11 instead + return hook_d3d11(); + } + + return false; +} + +AutomataMP::~AutomataMP() { + spdlog::info("AutomataMP shutting down..."); + + std::scoped_lock _{ m_hook_monitor_mutex }; + + if (m_is_d3d11) { + ImGui_ImplDX11_Shutdown(); + } + + if (m_is_d3d12) { + ImGui_ImplDX12_Shutdown(); + } + + ImGui_ImplWin32_Shutdown(); + + if (m_initialized) { + ImGui::DestroyContext(); + } +} + +void AutomataMP::run_imgui_frame(bool from_present) { + std::scoped_lock _{ m_imgui_mtx }; + + m_has_frame = false; + + if (!m_initialized) { + return; + } + + const bool is_init_ok = m_error.empty() && m_game_data_initialized; + + consume_input(); + update_fonts(); + + ImGui_ImplWin32_NewFrame(); + + // from_present is so we don't accidentally + // run script/game code within the present thread. + if (is_init_ok && !from_present) { + // Run mod frame callbacks. + m_mods->on_pre_imgui_frame(); + } + + ImGui::NewFrame(); + + if (!from_present) { + call_on_frame(); + } + + draw_ui(); + m_last_draw_ui = m_draw_ui; + + ImGui::EndFrame(); + ImGui::Render(); + + m_has_frame = true; +} + +// D3D11 Draw funciton +void AutomataMP::on_frame_d3d11() { + std::scoped_lock _{ m_imgui_mtx }; + + spdlog::debug("on_frame (D3D11)"); + + m_renderer_type = RendererType::D3D11; + + if (!m_initialized) { + if (!initialize()) { + spdlog::error("Failed to initialize AutomataMP on DirectX 11"); + return; + } + + spdlog::info("AutomataMP initialized"); + m_initialized = true; + return; + } + + if (m_message_hook_requested) { + initialize_windows_message_hook(); + } + + auto device = m_d3d11_hook->get_device(); + + if (device == nullptr) { + spdlog::error("D3D11 device was null when it shouldn't be, returning..."); + m_initialized = false; + return; + } + + const bool is_init_ok = m_error.empty() && m_game_data_initialized; + + if (is_init_ok) { + // Write default config once if it doesn't exist. + if (!std::exchange(m_created_default_cfg, true)) { + if (!fs::exists({utility::widen("re2_fw_config.txt")})) { + save_config(); + } + } + } + + if (!m_has_frame) { + if (!is_init_ok) { + update_fonts(); + invalidate_device_objects(); + + ImGui_ImplDX11_NewFrame(); + // hooks don't run until after initialization, so we just render the imgui window while initalizing. + run_imgui_frame(true); + } else { + return; + } + } else { + invalidate_device_objects(); + ImGui_ImplDX11_NewFrame(); + } + + if (is_init_ok) { + m_mods->on_present(); + } + + ComPtr context{}; + float clear_color[]{0.0f, 0.0f, 0.0f, 0.0f}; + + m_d3d11_hook->get_device()->GetImmediateContext(&context); + context->ClearRenderTargetView(m_d3d11.blank_rt_rtv.Get(), clear_color); + context->ClearRenderTargetView(m_d3d11.rt_rtv.Get(), clear_color); + context->OMSetRenderTargets(1, m_d3d11.rt_rtv.GetAddressOf(), NULL); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + + // Set the back buffer to be the render target. + context->OMSetRenderTargets(1, m_d3d11.bb_rtv.GetAddressOf(), nullptr); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + + if (is_init_ok) { + m_mods->on_post_frame(); + } +} + +void AutomataMP::on_post_present_d3d11() { + if (!m_error.empty() || !m_initialized || !m_game_data_initialized) { + if (m_last_present_time <= std::chrono::steady_clock::now()){ + m_last_present_time = std::chrono::steady_clock::now(); + } + + return; + } + + for (auto& mod : m_mods->get_mods()) { + mod->on_post_present(); + } + + if (m_last_present_time <= std::chrono::steady_clock::now()){ + m_last_present_time = std::chrono::steady_clock::now(); + } +} + +// D3D12 Draw funciton +void AutomataMP::on_frame_d3d12() { + std::scoped_lock _{ m_imgui_mtx }; + + m_renderer_type = RendererType::D3D12; + + auto command_queue = m_d3d12_hook->get_command_queue(); + //spdlog::debug("on_frame (D3D12)"); + + if (!m_initialized) { + if (!initialize()) { + spdlog::error("Failed to initialize AutomataMP on DirectX 12"); + return; + } + + spdlog::info("AutomataMP initialized"); + m_initialized = true; + return; + } + + if (command_queue == nullptr) { + spdlog::error("Null Command Queue"); + return; + } + + if (m_message_hook_requested) { + initialize_windows_message_hook(); + } + + auto device = m_d3d12_hook->get_device(); + + if (device == nullptr) { + spdlog::error("D3D12 Device was null when it shouldn't be, returning..."); + m_initialized = false; + return; + } + + const bool is_init_ok = m_error.empty() && m_game_data_initialized; + + if (is_init_ok) { + // Write default config once if it doesn't exist. + if (!std::exchange(m_created_default_cfg, true)) { + if (!fs::exists({utility::widen("re2_fw_config.txt")})) { + save_config(); + } + } + } + + if (!m_has_frame) { + if (!is_init_ok) { + update_fonts(); + invalidate_device_objects(); + + ImGui_ImplDX12_NewFrame(); + // hooks don't run until after initialization, so we just render the imgui window while initalizing. + run_imgui_frame(true); + } else { + return; + } + } else { + invalidate_device_objects(); + ImGui_ImplDX12_NewFrame(); + } + + if (is_init_ok) { + m_mods->on_present(); + } + + m_d3d12.cmd_allocator->Reset(); + m_d3d12.cmd_list->Reset(m_d3d12.cmd_allocator.Get(), nullptr); + + // Draw to our render target. + D3D12_RESOURCE_BARRIER barrier{}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = m_d3d12.get_rt(D3D12::RTV::IMGUI).Get(); + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + m_d3d12.cmd_list->ResourceBarrier(1, &barrier); + + float clear_color[]{0.0f, 0.0f, 0.0f, 0.0f}; + D3D12_CPU_DESCRIPTOR_HANDLE rts[1]{}; + m_d3d12.cmd_list->ClearRenderTargetView(m_d3d12.get_cpu_rtv(device, D3D12::RTV::IMGUI), clear_color, 0, nullptr); + rts[0] = m_d3d12.get_cpu_rtv(device, D3D12::RTV::IMGUI); + m_d3d12.cmd_list->OMSetRenderTargets(1, rts, FALSE, NULL); + m_d3d12.cmd_list->SetDescriptorHeaps(1, m_d3d12.srv_desc_heap.GetAddressOf()); + ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), m_d3d12.cmd_list.Get()); + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + m_d3d12.cmd_list->ResourceBarrier(1, &barrier); + + // Draw to the back buffer. + auto swapchain = m_d3d12_hook->get_swap_chain(); + auto bb_index = swapchain->GetCurrentBackBufferIndex(); + barrier.Transition.pResource = m_d3d12.rts[bb_index].Get(); + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + m_d3d12.cmd_list->ResourceBarrier(1, &barrier); + rts[0] = m_d3d12.get_cpu_rtv(device, (D3D12::RTV)bb_index); + m_d3d12.cmd_list->OMSetRenderTargets(1, rts, FALSE, NULL); + m_d3d12.cmd_list->SetDescriptorHeaps(1, m_d3d12.srv_desc_heap.GetAddressOf()); + ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), m_d3d12.cmd_list.Get()); + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + m_d3d12.cmd_list->ResourceBarrier(1, &barrier); + m_d3d12.cmd_list->Close(); + + command_queue->ExecuteCommandLists(1, (ID3D12CommandList* const*)m_d3d12.cmd_list.GetAddressOf()); + + if (is_init_ok) { + m_mods->on_post_frame(); + } +} + +void AutomataMP::on_post_present_d3d12() { + if (!m_error.empty() || !m_initialized || !m_game_data_initialized) { + if (m_last_present_time <= std::chrono::steady_clock::now()){ + m_last_present_time = std::chrono::steady_clock::now(); + } + + return; + } + + for (auto& mod : m_mods->get_mods()) { + mod->on_post_present(); + } + + if (m_last_present_time <= std::chrono::steady_clock::now()){ + m_last_present_time = std::chrono::steady_clock::now(); + } +} + +void AutomataMP::on_reset() { + std::scoped_lock _{ m_imgui_mtx }; + + spdlog::info("Reset!"); + + if (m_initialized) { + // fixes text boxes not being able to receive input + imgui::reset_keystates(); + } + + // Crashes if we don't release it at this point. + if (m_is_d3d11) { + deinit_d3d11(); + } + + if (m_is_d3d12) { + deinit_d3d12(); + } + + if (m_game_data_initialized) { + m_mods->on_device_reset(); + } + + m_has_frame = false; + m_first_initialize = false; + m_initialized = false; +} + +bool AutomataMP::on_message(HWND wnd, UINT message, WPARAM w_param, LPARAM l_param) { + m_last_message_time = std::chrono::steady_clock::now(); + + if (!m_initialized) { + return true; + } + + bool is_mouse_moving{false}; + switch (message) { + case WM_INPUT: { + // RIM_INPUT means the window has focus + if (GET_RAWINPUT_CODE_WPARAM(w_param) == RIM_INPUT) { + uint32_t size = sizeof(RAWINPUT); + RAWINPUT raw{}; + + // obtain size + GetRawInputData((HRAWINPUT)l_param, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER)); + + auto result = GetRawInputData((HRAWINPUT)l_param, RID_INPUT, &raw, &size, sizeof(RAWINPUTHEADER)); + + if (raw.header.dwType == RIM_TYPEMOUSE) { + m_accumulated_mouse_delta[0] += (float)raw.data.mouse.lLastX; + m_accumulated_mouse_delta[1] += (float)raw.data.mouse.lLastY; + + // Allowing camera movement when the UI is hovered while not focused + if (raw.data.mouse.lLastX || raw.data.mouse.lLastY) { + is_mouse_moving = true; + } + } + } + } break; + + /*case RE_TOGGLE_CURSOR: { + const auto is_internal_message = l_param != 0; + const auto return_value = is_internal_message || !m_draw_ui; + + if (!is_internal_message) { + m_cursor_state = (bool)w_param; + m_cursor_state_changed = true; + } + + return return_value; + } break;*/ + default: + break; + } + + ImGui_ImplWin32_WndProcHandler(wnd, message, w_param, l_param); + + { + // If the user is interacting with the UI we block the message from going to the game. + const auto& io = ImGui::GetIO(); + if (m_draw_ui && !m_ui_passthrough) { + // Fix of a bug that makes the input key down register but the key up will never register + // when clicking on the ui while the game is not focused + if (message == WM_INPUT && GET_RAWINPUT_CODE_WPARAM(w_param) == RIM_INPUTSINK) + return false; + + if (m_is_ui_focused) { + if (io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput) + return false; + } else { + if (!is_mouse_moving && (io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput)) + return false; + } + } + } + + bool any_false = false; + + if (m_game_data_initialized) { + for (auto& mod : m_mods->get_mods()) { + if (!mod->on_message(wnd, message, w_param, l_param)) { + any_false = true; + } + } + } + + return !any_false; +} + +// this is unfortunate. +void AutomataMP::on_direct_input_keys(const std::array& keys) { + /*const auto menu_key = AutomataMPConfig::get()->get_menu_key()->value(); + + if (keys[menu_key] && m_last_keys[menu_key] == 0) { + std::lock_guard _{m_input_mutex}; + + set_draw_ui(!m_draw_ui); + } + + m_last_keys = keys;*/ +} + +void AutomataMP::save_config() { + std::scoped_lock _{m_config_mtx}; + + spdlog::info("Saving config re2_fw_config.txt"); + + utility::Config cfg{}; + + for (auto& mod : m_mods->get_mods()) { + mod->on_config_save(cfg); + } + + if (!cfg.save("re2_fw_config.txt")) { + spdlog::info("Failed to save config"); + return; + } + + spdlog::info("Saved config"); +} + +void AutomataMP::set_draw_ui(bool state, bool should_save) { + std::scoped_lock _{m_config_mtx}; + + spdlog::info("Setting draw ui to {}", state); + + bool prev_state = m_draw_ui; + m_draw_ui = state; + + if (m_game_data_initialized) { + AutomataMPConfig::get()->get_menu_open()->value() = state; + } + + if (state != prev_state && should_save && m_game_data_initialized) { + save_config(); + } +} + +void AutomataMP::consume_input() { + m_mouse_delta[0] = m_accumulated_mouse_delta[0]; + m_mouse_delta[1] = m_accumulated_mouse_delta[1]; + + m_accumulated_mouse_delta[0] = 0.0f; + m_accumulated_mouse_delta[1] = 0.0f; +} + +int AutomataMP::add_font(const std::filesystem::path& filepath, int size, const std::vector& ranges) { + // Look for a font already matching this description. + for (int i = 0; i < m_additional_fonts.size(); ++i) { + const auto& font = m_additional_fonts[i]; + + if (font.filepath == filepath && font.size == size && font.ranges == ranges) { + return i; + } + } + + m_additional_fonts.emplace_back(AutomataMP::AdditionalFont{filepath, size, ranges, (ImFont*)nullptr}); + m_fonts_need_updating = true; + + return m_additional_fonts.size() - 1; +} + +void AutomataMP::update_fonts() { + if (!m_fonts_need_updating) { + return; + } + + m_fonts_need_updating = false; + + auto& fonts = ImGui::GetIO().Fonts; + + fonts->Clear(); + fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, (float)m_font_size); + + for (auto& font : m_additional_fonts) { + const ImWchar* ranges = nullptr; + + if (!font.ranges.empty()) { + ranges = font.ranges.data(); + } + + if (fs::exists(font.filepath)) { + font.font = fonts->AddFontFromFileTTF(font.filepath.string().c_str(), (float)font.size, nullptr, ranges); + } else { + font.font = fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, (float)font.size, nullptr, ranges); + } + } + + fonts->Build(); + m_wants_device_object_cleanup = true; +} + +void AutomataMP::invalidate_device_objects() { + if (!m_wants_device_object_cleanup) { + return; + } + + if (m_renderer_type == RendererType::D3D11) { + ImGui_ImplDX11_InvalidateDeviceObjects(); + } else if (m_renderer_type == RendererType::D3D12) { + ImGui_ImplDX12_InvalidateDeviceObjects(); + } + + m_wants_device_object_cleanup = false; +} + +void AutomataMP::draw_ui() { + std::lock_guard _{m_input_mutex}; + + if (!m_draw_ui) { + m_is_ui_focused = false; + if (m_last_draw_ui) { + m_windows_message_hook->window_toggle_cursor(m_cursor_state); + } + //m_dinput_hook->acknowledge_input(); + // ImGui::GetIO().MouseDrawCursor = false; + return; + } + + // UI Specific code: + m_is_ui_focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow); + + if (m_ui_option_transparent) { + auto& style = ImGui::GetStyle(); + if (m_is_ui_focused) { + style.Alpha = 1.0f; + } else { + if (ImGui::IsWindowHovered(ImGuiFocusedFlags_AnyWindow)) { + style.Alpha = 0.9f; + } else { + style.Alpha = 0.8f; + } + } + } else { + auto& style = ImGui::GetStyle(); + style.Alpha = 1.0f; + } + + auto& io = ImGui::GetIO(); + + if (io.WantCaptureKeyboard) { + //m_dinput_hook->ignore_input(); + } else { + //m_dinput_hook->acknowledge_input(); + } + + // ImGui::GetIO().MouseDrawCursor = true; + if (!m_last_draw_ui || m_cursor_state_changed) { + m_cursor_state_changed = false; + m_windows_message_hook->window_toggle_cursor(true); + } + + ImGui::SetNextWindowPos(ImVec2(50, 50), ImGuiCond_::ImGuiCond_Once); + ImGui::SetNextWindowSize(ImVec2(300, 500), ImGuiCond_::ImGuiCond_Once); + ImGui::Begin("AutomataMP", &m_draw_ui); + ImGui::Text("Default Menu Key: Insert"); + ImGui::Checkbox("Transparency", &m_ui_option_transparent); + ImGui::SameLine(); + ImGui::Text("(?)"); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Makes the UI transparent when not focused."); + ImGui::Checkbox("Input Passthrough", &m_ui_passthrough); + ImGui::SameLine(); + ImGui::Text("(?)"); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Allows mouse and keyboard inputs to register to the game while the UI is focused."); + + // Mods: + draw_about(); + + if (m_error.empty() && m_game_data_initialized) { + m_mods->on_draw_ui(); + } else if (!m_game_data_initialized) { + ImGui::TextWrapped("AutomataMP is currently initializing..."); + ImGui::TextWrapped("This menu will close after initialization if you have the remember option enabled."); + } else if (!m_error.empty()) { + ImGui::TextWrapped("AutomataMP error: %s", m_error.c_str()); + } + + m_last_window_pos = ImGui::GetWindowPos(); + m_last_window_size = ImGui::GetWindowSize(); + + ImGui::End(); + + // save the menu state in config + if (m_draw_ui != m_last_draw_ui) { + set_draw_ui(m_draw_ui, true); + } + + // if we pressed the X button to close the menu. + if (m_last_draw_ui && !m_draw_ui) { + m_windows_message_hook->window_toggle_cursor(m_cursor_state); + } +} + +void AutomataMP::draw_about() { + if (!ImGui::CollapsingHeader("About")) { + return; + } + + ImGui::TreePush("About"); + + ImGui::Text("Author: praydog"); + ImGui::Text("Dead project revived."); + ImGui::Text("https://github.com/praydog/AutomataMP"); + ImGui::Text("http://praydog.com"); + + if (ImGui::CollapsingHeader("Licenses")) { + ImGui::TreePush("Licenses"); + + struct License { + std::string name; + std::string text; + }; + + static std::array licenses{ + License{ "glm", license::glm }, + License{ "imgui", license::imgui }, + License{ "minhook", license::minhook }, + License{ "spdlog", license::spdlog }, + License{ "json", license::json }, + License{ "zydis", utility::narrow(license::zydis) } + }; + + for (const auto& license : licenses) { + if (ImGui::CollapsingHeader(license.name.c_str())) { + ImGui::TextWrapped(license.text.c_str()); + } + } + + ImGui::TreePop(); + } + + ImGui::Separator(); + + ImGui::TreePop(); +} + +void AutomataMP::set_imgui_style() noexcept { + ImGui::StyleColorsDark(); + + auto& style = ImGui::GetStyle(); + style.WindowRounding = 0.0f; + style.ChildRounding = 0.0f; + style.PopupRounding = 0.0f; + style.FrameRounding = 0.0f; + style.ScrollbarRounding = 2.0f; + style.GrabRounding = 0.0f; + style.TabRounding = 0.0f; + style.WindowBorderSize = 2.0f; + style.WindowPadding = ImVec2(2.0f, 0.0f); + + auto& colors = ImGui::GetStyle().Colors; + // Window BG + colors[ImGuiCol_WindowBg] = ImVec4{0.1f, 0.105f, 0.11f, 1.0f}; + + // Navigatation highlight + colors[ImGuiCol_NavHighlight] = ImVec4{0.3f, 0.305f, 0.31f, 1.0f}; + + // Progress Bar + colors[ImGuiCol_PlotHistogram] = ImVec4{0.3f, 0.305f, 0.31f, 1.0f}; + + // Headers + colors[ImGuiCol_Header] = ImVec4{0.2f, 0.205f, 0.21f, 1.0f}; + colors[ImGuiCol_HeaderHovered] = ImVec4{0.3f, 0.305f, 0.31f, 1.0f}; + colors[ImGuiCol_HeaderActive] = ImVec4{0.55f, 0.5505f, 0.551f, 1.0f}; + + // Buttons + colors[ImGuiCol_Button] = ImVec4{0.2f, 0.205f, 0.21f, 1.0f}; + colors[ImGuiCol_ButtonHovered] = ImVec4{0.3f, 0.305f, 0.31f, 1.0f}; + colors[ImGuiCol_ButtonActive] = ImVec4{0.55f, 0.5505f, 0.551f, 1.0f}; + + // Checkbox + colors[ImGuiCol_CheckMark] = ImVec4(0.55f, 0.5505f, 0.551f, 1.0f); + + // Frame BG + colors[ImGuiCol_FrameBg] = ImVec4{0.211f, 0.210f, 0.25f, 1.0f}; + colors[ImGuiCol_FrameBgHovered] = ImVec4{0.3f, 0.305f, 0.31f, 1.0f}; + colors[ImGuiCol_FrameBgActive] = ImVec4{0.55f, 0.5505f, 0.551f, 1.0f}; + + // Tabs + colors[ImGuiCol_Tab] = ImVec4{0.25f, 0.2505f, 0.251f, 1.0f}; + colors[ImGuiCol_TabHovered] = ImVec4{0.38f, 0.3805f, 0.381f, 1.0f}; + colors[ImGuiCol_TabActive] = ImVec4{0.28f, 0.2805f, 0.281f, 1.0f}; + colors[ImGuiCol_TabUnfocused] = ImVec4{0.25f, 0.2505f, 0.251f, 1.0f}; + colors[ImGuiCol_TabUnfocusedActive] = ImVec4{0.8f, 0.805f, 0.81f, 1.0f}; + + // Resize Grip + colors[ImGuiCol_ResizeGrip] = ImVec4{0.2f, 0.205f, 0.21f, 0.0f}; + colors[ImGuiCol_ResizeGripHovered] = ImVec4{0.3f, 0.305f, 0.31f, 1.0f}; + colors[ImGuiCol_ResizeGripActive] = ImVec4{0.55f, 0.5505f, 0.551f, 1.0f}; + + // Title + colors[ImGuiCol_TitleBg] = ImVec4{0.25f, 0.2505f, 0.251f, 1.0f}; + colors[ImGuiCol_TitleBgActive] = ImVec4{0.55f, 0.5505f, 0.551f, 1.0f}; + colors[ImGuiCol_TitleBgCollapsed] = ImVec4{0.25f, 0.2505f, 0.251f, 1.0f}; + + // Font + set_font_size(m_font_size); +} + +bool AutomataMP::initialize() { + if (m_initialized) { + return true; + } + + automatamp::setup_exception_handler(); + + if (m_first_initialize) { + m_frames_since_init = 0; + m_first_initialize = false; + } + + if (m_frames_since_init < 60) { + m_frames_since_init++; + return false; + } + + if (m_is_d3d11) { + spdlog::info("Attempting to initialize DirectX 11"); + + if (!m_d3d11_hook->is_hooked()) { + return false; + } + + auto device = m_d3d11_hook->get_device(); + auto swap_chain = m_d3d11_hook->get_swap_chain(); + + // Wait. + if (device == nullptr || swap_chain == nullptr) { + m_first_initialize = true; + + spdlog::info("Device or SwapChain null. DirectX 12 may be in use. Unhooking D3D11..."); + + // We unhook D3D11 + if (m_d3d11_hook->unhook()) { + spdlog::info("D3D11 unhooked!"); + } else { + spdlog::error("Cannot unhook D3D11, this might crash."); + } + + m_is_d3d11 = false; + m_valid = false; + + // We hook D3D12 + if (!hook_d3d12()) { + spdlog::error("Failed to hook D3D12 after unhooking D3D11."); + } + return false; + } + + ID3D11DeviceContext* context = nullptr; + device->GetImmediateContext(&context); + + DXGI_SWAP_CHAIN_DESC swap_desc{}; + swap_chain->GetDesc(&swap_desc); + + m_wnd = swap_desc.OutputWindow; + + + spdlog::info("Window Handle: {0:x}", (uintptr_t)m_wnd); + spdlog::info("Initializing ImGui"); + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + set_imgui_style(); + + ImGui::GetIO().IniFilename = "ref_ui.ini"; + + spdlog::info("Initializing ImGui Win32"); + + if (!ImGui_ImplWin32_Init(m_wnd)) { + spdlog::error("Failed to initialize ImGui."); + return false; + } + + spdlog::info("Creating render target"); + + if (!init_d3d11()) { + spdlog::error("Failed to init D3D11"); + return false; + } + } else if (m_is_d3d12) { + spdlog::info("Attempting to initialize DirectX 12"); + + if (!m_d3d12_hook->is_hooked()) { + return false; + } + + auto device = m_d3d12_hook->get_device(); + auto swap_chain = m_d3d12_hook->get_swap_chain(); + + if (device == nullptr || swap_chain == nullptr) { + m_first_initialize = true; + + spdlog::info("Device: {:x}", (uintptr_t)device); + spdlog::info("SwapChain: {:x}", (uintptr_t)swap_chain); + + spdlog::info("Device or SwapChain null. DirectX 11 may be in use. Unhooking D3D12..."); + + // We unhook D3D12 + if (m_d3d12_hook->unhook()) + spdlog::info("D3D12 unhooked!"); + else + spdlog::error("Cannot unhook D3D12, this might crash."); + + m_valid = false; + m_is_d3d12 = false; + + // We hook D3D11 + if (!hook_d3d11()) { + spdlog::error("Failed to hook D3D11 after unhooking D3D12."); + } + return false; + } + + DXGI_SWAP_CHAIN_DESC swap_desc{}; + swap_chain->GetDesc(&swap_desc); + + m_wnd = swap_desc.OutputWindow; + + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + set_imgui_style(); + + ImGui::GetIO().IniFilename = "ref_ui.ini"; + + if (!ImGui_ImplWin32_Init(m_wnd)) { + spdlog::error("Failed to initialize ImGui ImplWin32."); + return false; + } + + if (!init_d3d12()) { + spdlog::error("Failed to init D3D12."); + return false; + } + } else { + return false; + } + + initialize_windows_message_hook(); + + // TODO + /*if (m_first_frame) { + m_dinput_hook = std::make_unique(m_wnd); + } else { + m_dinput_hook->set_window(m_wnd); + }*/ + + if (m_first_frame) { + m_first_frame = false; + + spdlog::info("Starting game data initialization thread"); + + // Game specific initialization stuff + std::thread init_thread([this]() { + try { + //automatamp::initialize_sdk(); // TODO + m_mods = std::make_unique(); + + auto e = m_mods->on_initialize(); + + if (e) { + if (e->empty()) { + m_error = "An unknown error has occurred."; + } else { + m_error = *e; + } + + spdlog::error("Initialization of mods failed. Reason: {}", m_error); + } + + m_game_data_initialized = true; + } catch(...) { + m_error = "An exception has occurred during initialization."; + m_game_data_initialized = true; + spdlog::error("Initialization of mods failed. Reason: exception thrown."); + } + + spdlog::info("Game data initialization thread finished"); + }); + + init_thread.detach(); + } + + return true; +} + +bool AutomataMP::initialize_windows_message_hook() { + if (m_wnd == 0) { + return false; + } + + if (m_first_frame || m_message_hook_requested || m_windows_message_hook == nullptr) { + m_last_message_time = std::chrono::steady_clock::now(); + m_windows_message_hook.reset(); + m_windows_message_hook = std::make_unique(m_wnd); + m_windows_message_hook->on_message = [this](auto wnd, auto msg, auto w_param, auto l_param) { + return on_message(wnd, msg, w_param, l_param); + }; + + m_message_hook_requested = false; + return true; + } + + m_message_hook_requested = false; + return false; +} + +void AutomataMP::call_on_frame() { + const bool is_init_ok = m_error.empty() && m_game_data_initialized; + + if (is_init_ok) { + // Run mod frame callbacks. + m_mods->on_frame(); + } +} + +// DirectX 11 Initialization methods + +bool AutomataMP::init_d3d11() { + deinit_d3d11(); + + auto swapchain = m_d3d11_hook->get_swap_chain(); + auto device = m_d3d11_hook->get_device(); + + // Get back buffer. + spdlog::info("[D3D11] Creating RTV of back buffer..."); + + ComPtr backbuffer{}; + + if (FAILED(swapchain->GetBuffer(0, IID_PPV_ARGS(&backbuffer)))) { + spdlog::error("[D3D11] Failed to get back buffer!"); + return false; + } + + // Create a render target view of the back buffer. + if (FAILED(device->CreateRenderTargetView(backbuffer.Get(), nullptr, &m_d3d11.bb_rtv))) { + spdlog::error("[D3D11] Failed to create back buffer render target view!"); + return false; + } + + // Get backbuffer description. + D3D11_TEXTURE2D_DESC backbuffer_desc{}; + + backbuffer->GetDesc(&backbuffer_desc); + backbuffer_desc.BindFlags |= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + + spdlog::info("[D3D11] Back buffer format is {}", backbuffer_desc.Format); + + // Create our blank render target. + spdlog::info("[D3D11] Creating render targets..."); + + if (FAILED(device->CreateTexture2D(&backbuffer_desc, nullptr, &m_d3d11.blank_rt))) { + spdlog::error("[D3D11] Failed to create render target texture!"); + return false; + } + + // Create our render target. + if (FAILED(device->CreateTexture2D(&backbuffer_desc, nullptr, &m_d3d11.rt))) { + spdlog::error("[D3D11] Failed to create render target texture!"); + return false; + } + + // Create our blank render target view. + spdlog::info("[D3D11] Creating rtvs..."); + + if (FAILED(device->CreateRenderTargetView(m_d3d11.blank_rt.Get(), nullptr, &m_d3d11.blank_rt_rtv))) { + spdlog::error("[D3D11] Failed to create render terget view!"); + return false; + } + + + // Create our render target view. + if (FAILED(device->CreateRenderTargetView(m_d3d11.rt.Get(), nullptr, &m_d3d11.rt_rtv))) { + spdlog::error("[D3D11] Failed to create render terget view!"); + return false; + } + + // Create our render target shader resource view. + spdlog::info("[D3D11] Creating srvs..."); + + if (FAILED(device->CreateShaderResourceView(m_d3d11.rt.Get(), nullptr, &m_d3d11.rt_srv))) { + spdlog::error("[D3D11] Failed to create shader resource view!"); + return false; + } + + m_d3d11.rt_width = backbuffer_desc.Width; + m_d3d11.rt_height = backbuffer_desc.Height; + + spdlog::info("[D3D11] Initializing ImGui D3D11..."); + + ComPtr context{}; + + device->GetImmediateContext(&context); + + if (!ImGui_ImplDX11_Init(device, context.Get())) { + spdlog::error("[D3D11] Failed to initialize ImGui."); + return false; + } + + return true; +} + +void AutomataMP::deinit_d3d11() { + ImGui_ImplDX11_Shutdown(); + m_d3d11 = {}; +} + +// DirectX 12 Initialization methods + +bool AutomataMP::init_d3d12() { + deinit_d3d12(); + + auto device = m_d3d12_hook->get_device(); + + spdlog::info("[D3D12] Creating command allocator..."); + + if (FAILED(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_d3d12.cmd_allocator)))) { + spdlog::error("[D3D12] Failed to create command allocator."); + return false; + } + + spdlog::info("[D3D12] Creating command list..."); + + if (FAILED(device->CreateCommandList( + 0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_d3d12.cmd_allocator.Get(), nullptr, IID_PPV_ARGS(&m_d3d12.cmd_list)))) { + spdlog::error("[D3D12] Failed to create command list."); + return false; + } + + if (FAILED(m_d3d12.cmd_list->Close())) { + spdlog::error("[D3D12] Failed to close command list after creation."); + return false; + } + + spdlog::info("[D3D12] Creating RTV descriptor heap..."); + + { + + D3D12_DESCRIPTOR_HEAP_DESC desc{}; + + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + desc.NumDescriptors = (int)D3D12::RTV::COUNT; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + desc.NodeMask = 1; + + if (FAILED(device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_d3d12.rtv_desc_heap)))) { + spdlog::error("[D3D12] Failed to create RTV descriptor heap."); + return false; + } + } + + spdlog::info("[D3D12] Creating SRV descriptor heap..."); + + { + D3D12_DESCRIPTOR_HEAP_DESC desc{}; + + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.NumDescriptors = (int)D3D12::SRV::COUNT; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + + if (FAILED(device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_d3d12.srv_desc_heap)))) { + spdlog::error("[D3D12] Failed to create SRV descriptor heap."); + return false; + } + } + + spdlog::info("[D3D12] Creating render targets..."); + + { + // Create back buffer rtvs. + auto swapchain = m_d3d12_hook->get_swap_chain(); + + for (auto i = 0; i <= (int)D3D12::RTV::BACKBUFFER_3; ++i) { + if (SUCCEEDED(swapchain->GetBuffer(i, IID_PPV_ARGS(&m_d3d12.rts[i])))) { + device->CreateRenderTargetView(m_d3d12.rts[i].Get(), nullptr, m_d3d12.get_cpu_rtv(device, (D3D12::RTV)i)); + } + } + + // Create our imgui and blank rts. + auto& backbuffer = m_d3d12.get_rt(D3D12::RTV::BACKBUFFER_0); + auto desc = backbuffer->GetDesc(); + + spdlog::info("[D3D12] Back buffer format is {}", desc.Format); + + D3D12_HEAP_PROPERTIES props{}; + props.Type = D3D12_HEAP_TYPE_DEFAULT; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + + D3D12_CLEAR_VALUE clear_value{}; + clear_value.Format = desc.Format; + + if (FAILED(device->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, &clear_value, + IID_PPV_ARGS(&m_d3d12.get_rt(D3D12::RTV::IMGUI))))) { + spdlog::error("[D3D12] Failed to create the imgui render target."); + return false; + } + + if (FAILED(device->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, &clear_value, + IID_PPV_ARGS(&m_d3d12.get_rt(D3D12::RTV::BLANK))))) { + spdlog::error("[D3D12] Failed to create the blank render target."); + return false; + } + + // Create imgui and blank rtvs and srvs. + device->CreateRenderTargetView(m_d3d12.get_rt(D3D12::RTV::IMGUI).Get(), nullptr, m_d3d12.get_cpu_rtv(device, D3D12::RTV::IMGUI)); + device->CreateRenderTargetView(m_d3d12.get_rt(D3D12::RTV::BLANK).Get(), nullptr, m_d3d12.get_cpu_rtv(device, D3D12::RTV::BLANK)); + device->CreateShaderResourceView( + m_d3d12.get_rt(D3D12::RTV::IMGUI).Get(), nullptr, m_d3d12.get_cpu_srv(device, D3D12::SRV::IMGUI)); + device->CreateShaderResourceView(m_d3d12.get_rt(D3D12::RTV::BLANK).Get(), nullptr, m_d3d12.get_cpu_srv(device, D3D12::SRV::BLANK)); + + m_d3d12.rt_width = (uint32_t)desc.Width; + m_d3d12.rt_height = (uint32_t)desc.Height; + } + + spdlog::info("[D3D12] Initializing ImGui..."); + + auto& bb = m_d3d12.get_rt(D3D12::RTV::BACKBUFFER_0); + auto bb_desc = bb->GetDesc(); + + if (!ImGui_ImplDX12_Init(device, 1, bb_desc.Format, m_d3d12.srv_desc_heap.Get(), + m_d3d12.get_cpu_srv(device, D3D12::SRV::IMGUI_FONT), m_d3d12.get_gpu_srv(device, D3D12::SRV::IMGUI_FONT))) { + spdlog::error("[D3D12] Failed to initialize ImGui."); + return false; + } + + return true; +} + +void AutomataMP::deinit_d3d12() { + ImGui_ImplDX12_Shutdown(); + m_d3d12 = {}; +} diff --git a/src/AutomataMP.hpp b/src/AutomataMP.hpp new file mode 100644 index 0000000..c11c494 --- /dev/null +++ b/src/AutomataMP.hpp @@ -0,0 +1,271 @@ +#pragma once + +#include +#include +#include + +#include +#include + +#include + +class Mods; + +#include "hooks/D3D11Hook.hpp" +#include "hooks/D3D12Hook.hpp" +#include "hooks/WindowsMessageHook.hpp" + +// Global facilitator +class AutomataMP { +private: + void hook_monitor(); + +public: + AutomataMP(HMODULE AutomataMP_module); + virtual ~AutomataMP(); + + auto get_automatamp_module() const { return m_automatamp_module; } + + bool is_valid() const { return m_valid; } + + bool is_dx11() const { return m_is_d3d11; } + + bool is_dx12() const { return m_is_d3d12; } + + const auto& get_mods() const { return m_mods; } + + const auto& get_mouse_delta() const { return m_mouse_delta; } + const auto& get_keyboard_state() const { return m_last_keys; } + + Address get_module() const { return m_game_module; } + + bool is_ready() const { return m_initialized && m_game_data_initialized; } + + void run_imgui_frame(bool from_present); + + void on_frame_d3d11(); + void on_post_present_d3d11(); + void on_frame_d3d12(); + void on_post_present_d3d12(); + void on_reset(); + bool on_message(HWND wnd, UINT message, WPARAM w_param, LPARAM l_param); + void on_direct_input_keys(const std::array& keys); + + void save_config(); + + enum class RendererType : uint8_t { + D3D11, + D3D12 + }; + + auto get_renderer_type() const { return m_renderer_type; } + auto& get_d3d11_hook() const { return m_d3d11_hook; } + auto& get_d3d12_hook() const { return m_d3d12_hook; } + + auto get_window() const { return m_wnd; } + auto get_last_window_pos() const { return m_last_window_pos; } // AutomataMP imgui window + auto get_last_window_size() const { return m_last_window_size; } // AutomataMP imgui window + + bool is_drawing_ui() const { + return m_draw_ui; + } + + void set_draw_ui(bool state, bool should_save = true); + + auto& get_hook_monitor_mutex() { + return m_hook_monitor_mutex; + } + + void set_font_size(int size) { + if (m_font_size != size) { + m_font_size = size; + m_fonts_need_updating = true; + } + } + + auto get_font_size() const { return m_font_size; } + + int add_font(const std::filesystem::path& filepath, int size, const std::vector& ranges = {}); + + ImFont* get_font(int index) const { + if (index >= 0 && index < m_additional_fonts.size()) { + return m_additional_fonts[index].font; + } else { + return nullptr; + } + } + +private: + void consume_input(); + void update_fonts(); + void invalidate_device_objects(); + + void draw_ui(); + void draw_about(); + + bool hook_d3d11(); + bool hook_d3d12(); + + bool initialize(); + bool initialize_windows_message_hook(); + + void call_on_frame(); + + HMODULE m_automatamp_module{}; + + bool m_first_frame{true}; + bool m_is_d3d12{false}; + bool m_is_d3d11{false}; + bool m_valid{false}; + bool m_initialized{false}; + bool m_created_default_cfg{false}; + std::atomic m_game_data_initialized{false}; + + // UI + bool m_has_frame{false}; + bool m_wants_device_object_cleanup{false}; + bool m_draw_ui{true}; + bool m_last_draw_ui{m_draw_ui}; + bool m_is_ui_focused{false}; + bool m_cursor_state{false}; + bool m_cursor_state_changed{true}; + bool m_ui_option_transparent{true}; + bool m_ui_passthrough{false}; + + ImVec2 m_last_window_pos{}; + ImVec2 m_last_window_size{}; + + struct AdditionalFont { + std::filesystem::path filepath{}; + int size{16}; + std::vector ranges{}; + ImFont* font{}; + }; + + bool m_fonts_need_updating{true}; + int m_font_size{16}; + std::vector m_additional_fonts{}; + + std::mutex m_input_mutex{}; + std::recursive_mutex m_config_mtx{}; + std::recursive_mutex m_imgui_mtx{}; + + HWND m_wnd{0}; + HMODULE m_game_module{0}; + + float m_accumulated_mouse_delta[2]{}; + float m_mouse_delta[2]{}; + std::array m_last_keys{0}; + std::unique_ptr m_d3d11_hook{}; + std::unique_ptr m_d3d12_hook{}; + std::unique_ptr m_windows_message_hook; + std::shared_ptr m_logger; + + std::string m_error{""}; + + // Game-specific stuff + std::unique_ptr m_mods; + + std::recursive_mutex m_hook_monitor_mutex{}; + std::unique_ptr m_d3d_monitor_thread{}; + std::chrono::steady_clock::time_point m_last_present_time{}; + std::chrono::steady_clock::time_point m_last_message_time{}; + std::chrono::steady_clock::time_point m_last_sendmessage_time{}; + std::chrono::steady_clock::time_point m_last_chance_time{}; + uint32_t m_frames_since_init{0}; + bool m_has_last_chance{true}; + bool m_first_initialize{true}; + + bool m_sent_message{false}; + bool m_message_hook_requested{false}; + + RendererType m_renderer_type{RendererType::D3D11}; + + template using ComPtr = Microsoft::WRL::ComPtr; + +private: // D3D misc + void set_imgui_style() noexcept; + +private: // D3D11 Init + bool init_d3d11(); + void deinit_d3d11(); + +private: // D3D12 Init + bool init_d3d12(); + void deinit_d3d12(); + +private: // D3D11 members + struct D3D11 { + ComPtr blank_rt{}; + ComPtr rt{}; + ComPtr blank_rt_rtv{}; + ComPtr rt_rtv{}; + ComPtr rt_srv{}; + uint32_t rt_width{}; + uint32_t rt_height{}; + ComPtr bb_rtv{}; + } m_d3d11{}; + +public: + auto& get_blank_rendertarget_d3d11() { return m_d3d11.blank_rt; } + auto& get_rendertarget_d3d11() { return m_d3d11.rt; } + auto get_rendertarget_width_d3d11() const { return m_d3d11.rt_width; } + auto get_rendertarget_height_d3d11() const { return m_d3d11.rt_height; } + +private: // D3D12 members + struct D3D12 { + ComPtr cmd_allocator{}; + ComPtr cmd_list{}; + + enum class RTV : int{ + BACKBUFFER_0, + BACKBUFFER_1, + BACKBUFFER_2, + BACKBUFFER_3, + IMGUI, + BLANK, + COUNT, + }; + + enum class SRV : int { + IMGUI_FONT, + IMGUI, + BLANK, + COUNT + }; + + ComPtr rtv_desc_heap{}; + ComPtr srv_desc_heap{}; + ComPtr rts[(int)RTV::COUNT]{}; + + auto& get_rt(RTV rtv) { return rts[(int)rtv]; } + + D3D12_CPU_DESCRIPTOR_HANDLE get_cpu_rtv(ID3D12Device* device, RTV rtv) { + return {rtv_desc_heap->GetCPUDescriptorHandleForHeapStart().ptr + + (SIZE_T)rtv * (SIZE_T)device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV)}; + } + + D3D12_CPU_DESCRIPTOR_HANDLE get_cpu_srv(ID3D12Device* device, SRV srv) { + return {srv_desc_heap->GetCPUDescriptorHandleForHeapStart().ptr + + (SIZE_T)srv * (SIZE_T)device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)}; + } + + D3D12_GPU_DESCRIPTOR_HANDLE get_gpu_srv(ID3D12Device* device, SRV srv) { + return {srv_desc_heap->GetGPUDescriptorHandleForHeapStart().ptr + + (SIZE_T)srv * (SIZE_T)device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)}; + } + + uint32_t rt_width{}; + uint32_t rt_height{}; + } m_d3d12{}; + +public: + auto& get_blank_rendertarget_d3d12() { return m_d3d12.get_rt(D3D12::RTV::BLANK); } + auto& get_rendertarget_d3d12() { return m_d3d12.get_rt(D3D12::RTV::IMGUI); } + auto get_rendertarget_width_d3d12() { return m_d3d12.rt_width; } + auto get_rendertarget_height_d3d12() { return m_d3d12.rt_height; } + +private: +}; + +extern std::unique_ptr g_framework; diff --git a/src/Crc32.cpp b/src/Crc32.cpp new file mode 100644 index 0000000..cf19a5e --- /dev/null +++ b/src/Crc32.cpp @@ -0,0 +1,17 @@ +#include "Crc32.hpp" + +uint32_t crc32(uint8_t* data, size_t len) +{ + uint32_t crc = 0xFFFFFFFF; + + while (len--) { + crc ^= *data++; + + for (int j = 0; j < 8; j++) { + crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); + } + } + + return ~crc; +} + diff --git a/src/Crc32.hpp b/src/Crc32.hpp new file mode 100644 index 0000000..75b808f --- /dev/null +++ b/src/Crc32.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include + +uint32_t crc32(uint8_t* data, size_t len); \ No newline at end of file diff --git a/src/DllMain.cpp b/src/DllMain.cpp new file mode 100644 index 0000000..27fb23e --- /dev/null +++ b/src/DllMain.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "ExceptionHandler.hpp" +#include "AutomataMP.hpp" + +HMODULE g_dinput = 0; +std::mutex g_load_mutex{}; + +void failed() { + MessageBox(0, "AutomataMP: Unable to load the original dinput8.dll. Please report this to the developer.", "AutomataMP", 0); + ExitProcess(0); +} + +bool load_dinput8() { + std::scoped_lock _{g_load_mutex}; + + if (g_dinput) { + return true; + } + + wchar_t buffer[MAX_PATH]{0}; + if (GetSystemDirectoryW(buffer, MAX_PATH) != 0) { + // Load the original dinput8.dll + if ((g_dinput = LoadLibraryW((std::wstring{buffer} + L"\\dinput8.dll").c_str())) == NULL) { + failed(); + return false; + } + + return true; + } + + failed(); + return false; +} + +extern "C" { +// DirectInput8Create wrapper for dinput8.dll +__declspec(dllexport) HRESULT WINAPI + direct_input8_create(HINSTANCE hinst, DWORD dw_version, const IID& riidltf, LPVOID* ppv_out, LPUNKNOWN punk_outer) { +// This needs to be done because when we include dinput.h in DInputHook, +// It is a redefinition, so we assign an export by not using the original name +#pragma comment(linker, "/EXPORT:DirectInput8Create=direct_input8_create") + + load_dinput8(); + return ((decltype(direct_input8_create)*)GetProcAddress(g_dinput, "DirectInput8Create"))(hinst, dw_version, riidltf, ppv_out, punk_outer); +} +} + +void startup_thread(HMODULE automatamp_module) { + // We will set it once here, then do it continuously + // every now and then because it gets replaced + automatamp::setup_exception_handler(); + +#ifndef NDEBUG + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); +#endif + + if (load_dinput8()) { + g_framework = std::make_unique(automatamp_module); + + const auto our_dll = utility::get_module_within(&load_dinput8); + } +} + +BOOL APIENTRY DllMain(HANDLE handle, DWORD reason, LPVOID reserved) { + if (reason == DLL_PROCESS_ATTACH) { + CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)startup_thread, handle, 0, nullptr); + } + + return TRUE; +} diff --git a/src/EntitySync.cpp b/src/EntitySync.cpp new file mode 100644 index 0000000..b65f6b5 --- /dev/null +++ b/src/EntitySync.cpp @@ -0,0 +1,105 @@ +#include + +#include "mods/AutomataMPMod.hpp" +#include "EntitySync.hpp" + +using namespace std; + +void EntitySync::onEntityCreated(EntityContainer* entity, EntitySpawnParams* data) { + auto guid = m_maxGuid++; + + addEntity(entity, guid); + + nier_server::EntitySpawn packet; + packet.guid = guid; + packet.model = data->model; + packet.model2 = data->model2; + + if (data->name) { + strcpy_s(packet.name, data->name); + } + + if (data->matrix) { + packet.matrix = *data->matrix; + } + + spdlog::info("Sending enemy spawn {:x} with guid {}", (uintptr_t)entity, packet.guid); + + AutomataMPMod::get()->sendPacket(packet.data(), sizeof(packet)); +} + +void EntitySync::onEntityDeleted(EntityContainer* entity) { + lock_guard _(m_mapMutex); + + if (m_handleMap.find(entity->handle) == m_handleMap.end()) { + return; + } + + auto guid = m_handleMap[entity->handle]->getEntityData().guid; + + m_handleMap.erase(entity->handle); + removeEntity(guid); +} + +NetworkEntity& EntitySync::addEntity(EntityContainer* entity, uint32_t guid) { + spdlog::info("Adding entity {:x} with guid {}", (uintptr_t)entity, guid); + + lock_guard _(m_mapMutex); + auto& networkEntity = m_networkEntities[guid]; + m_handleMap[entity->handle] = &networkEntity; + networkEntity.getEntityData().guid = guid; + networkEntity.setEntity(entity); + + return networkEntity; +} + +void EntitySync::removeEntity(uint32_t identifier) { + if (m_networkEntities.find(identifier) != m_networkEntities.end()) { + spdlog::info("Removing entity from EntitySync"); + m_networkEntities.erase(identifier); + } +} + +void EntitySync::think() { + lock_guard _(m_mapMutex); + + for (auto& networkedEnt : m_networkEntities) { + auto ent = networkedEnt.second.getEntity(); + auto& packet = networkedEnt.second.getEntityData(); + auto npc = ent->entity; + + if (AutomataMPMod::get()->isServer()) { + packet.position = *npc->getPosition(); + packet.facing = *npc->getFacing(); + packet.facing2 = *npc->getFacing2(); + packet.health = *npc->getHealth(); + + AutomataMPMod::get()->sendPacket(packet.data(), sizeof(packet)); + } + else { + *npc->getPosition() = packet.position; + *npc->getFacing() = packet.facing; + *npc->getFacing2() = packet.facing2; + *npc->getHealth() = packet.health; + } + + npc->setSuspend(false); + } +} + +void EntitySync::processEntityData(nier_server::EntityData* data) { + spdlog::info("Processing %i entity data", data->guid); + + lock_guard _(m_mapMutex); + if (m_networkEntities.find(data->guid) != m_networkEntities.end()) { + auto ent = m_networkEntities[data->guid]; + auto npc = ent.getEntity()->entity; + + *npc->getPosition() = data->position; + *npc->getFacing() = data->facing; + *npc->getFacing2() = data->facing2; + *npc->getHealth() = data->health; + + ent.setEntityData(*data); + } +} diff --git a/src/EntitySync.hpp b/src/EntitySync.hpp new file mode 100644 index 0000000..be23818 --- /dev/null +++ b/src/EntitySync.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include + +#include "Packets.hpp" +#include +#include + +class NetworkEntity { +public: + void setEntity(EntityContainer* entity) { + m_entity = entity; + } + + auto getEntity() { + return m_entity; + } + + auto& getEntityData() { + return m_entityData; + } + + void setEntityData(nier_server::EntityData& data) { + m_entityData = data; + } + +private: + EntityContainer* m_entity; + nier_server::EntityData m_entityData; +}; + +class EntitySync { +public: + void onEntityCreated(EntityContainer* entity, EntitySpawnParams* data); + void onEntityDeleted(EntityContainer* entity); + + NetworkEntity& addEntity(EntityContainer* entity, uint32_t guid); + void removeEntity(uint32_t identifier); + + void think(); + void processEntityData(nier_server::EntityData* data); + +private: + uint32_t m_maxGuid{ 0 }; + std::unordered_map m_networkEntities; + std::unordered_map m_handleMap; + std::mutex m_mapMutex; +}; \ No newline at end of file diff --git a/src/ExceptionHandler.cpp b/src/ExceptionHandler.cpp new file mode 100644 index 0000000..e7dd007 --- /dev/null +++ b/src/ExceptionHandler.cpp @@ -0,0 +1,104 @@ +#include +#include +#include + +#include +#include +#include + +#include "ExceptionHandler.hpp" + +LONG WINAPI automatamp::global_exception_handler(struct _EXCEPTION_POINTERS* ei) { + spdlog::flush_on(spdlog::level::err); + + spdlog::error("Exception occurred: {:x}", ei->ExceptionRecord->ExceptionCode); + spdlog::error("RIP: {:x}", ei->ContextRecord->Rip); + spdlog::error("RSP: {:x}", ei->ContextRecord->Rsp); + spdlog::error("RCX: {:x}", ei->ContextRecord->Rcx); + spdlog::error("RDX: {:x}", ei->ContextRecord->Rdx); + spdlog::error("R8: {:x}", ei->ContextRecord->R8); + spdlog::error("R9: {:x}", ei->ContextRecord->R9); + spdlog::error("R10: {:x}", ei->ContextRecord->R10); + spdlog::error("R11: {:x}", ei->ContextRecord->R11); + spdlog::error("R12: {:x}", ei->ContextRecord->R12); + spdlog::error("R13: {:x}", ei->ContextRecord->R13); + spdlog::error("R14: {:x}", ei->ContextRecord->R14); + spdlog::error("R15: {:x}", ei->ContextRecord->R15); + spdlog::error("RAX: {:x}", ei->ContextRecord->Rax); + spdlog::error("RBX: {:x}", ei->ContextRecord->Rbx); + spdlog::error("RBP: {:x}", ei->ContextRecord->Rbp); + spdlog::error("RSI: {:x}", ei->ContextRecord->Rsi); + spdlog::error("RDI: {:x}", ei->ContextRecord->Rdi); + spdlog::error("EFLAGS: {:x}", ei->ContextRecord->EFlags); + spdlog::error("CS: {:x}", ei->ContextRecord->SegCs); + spdlog::error("DS: {:x}", ei->ContextRecord->SegDs); + spdlog::error("ES: {:x}", ei->ContextRecord->SegEs); + spdlog::error("FS: {:x}", ei->ContextRecord->SegFs); + spdlog::error("GS: {:x}", ei->ContextRecord->SegGs); + spdlog::error("SS: {:x}", ei->ContextRecord->SegSs); + + const auto module_within = utility::get_module_within(ei->ContextRecord->Rip); + + if (module_within) { + const auto module_path = utility::get_module_path(*module_within); + + if (module_path) { + spdlog::error("Module: {:x} {}", (uintptr_t)*module_within, *module_path); + } else { + spdlog::error("Module: Unknown"); + } + } else { + spdlog::error("Module: Unknown"); + } + + auto dbghelp = LoadLibrary("dbghelp.dll"); + + if (dbghelp) { + const auto mod_dir = utility::get_module_directory(GetModuleHandle(0)); + const auto real_mod_dir = mod_dir ? (*mod_dir + "\\") : ""; + const auto final_path = real_mod_dir + "automatamp_crash.dmp"; + + spdlog::error("Attempting to write dump to {}", final_path); + + auto f = CreateFile(final_path.c_str(), + GENERIC_WRITE, + FILE_SHARE_WRITE, + nullptr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + nullptr + ); + + if (!f || f == INVALID_HANDLE_VALUE) { + spdlog::error("Exception occurred, but could not create dump file"); + return EXCEPTION_CONTINUE_SEARCH; + } + + MINIDUMP_EXCEPTION_INFORMATION ei_info{ + GetCurrentThreadId(), + ei, + FALSE + }; + + auto minidump_write_dump = (decltype(MiniDumpWriteDump)*)GetProcAddress(dbghelp, "MiniDumpWriteDump"); + + minidump_write_dump(GetCurrentProcess(), + GetCurrentProcessId(), + f, + MINIDUMP_TYPE::MiniDumpNormal, + &ei_info, + nullptr, + nullptr + ); + + CloseHandle(f); + } else { + spdlog::error("Exception occurred, but could not load dbghelp.dll"); + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +void automatamp::setup_exception_handler() { + SetUnhandledExceptionFilter(global_exception_handler); +} diff --git a/src/ExceptionHandler.hpp b/src/ExceptionHandler.hpp new file mode 100644 index 0000000..d3389ae --- /dev/null +++ b/src/ExceptionHandler.hpp @@ -0,0 +1,6 @@ +#include + +namespace automatamp { +LONG WINAPI global_exception_handler(struct _EXCEPTION_POINTERS* ei); +void setup_exception_handler(); +} diff --git a/src/LicenseStrings.hpp b/src/LicenseStrings.hpp new file mode 100644 index 0000000..9cad2fd --- /dev/null +++ b/src/LicenseStrings.hpp @@ -0,0 +1,793 @@ +#pragma once + +namespace license { + static constexpr auto glm = +R"(================================================================================ +OpenGL Mathematics (GLM) +-------------------------------------------------------------------------------- +GLM is licensed under The Happy Bunny License or MIT License + +================================================================================ +The Happy Bunny License (Modified MIT License) +-------------------------------------------------------------------------------- +Copyright (c) 2005 - G-Truc Creation + +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. + +Restrictions: + By making use of the Software for military purposes, you choose to make a + Bunny unhappy. + +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. + +================================================================================ +The MIT License +-------------------------------------------------------------------------------- +Copyright (c) 2005 - G-Truc Creation + +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.)"; +} + +namespace license { + static constexpr auto imgui = +R"(The MIT License (MIT) + +Copyright (c) 2014-2021 Omar Cornut + +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.)"; +} + +namespace license { + static constexpr auto minhook = +R"(MinHook - The Minimalistic API Hooking Library for x64/x86 +Copyright (C) 2009-2017 Tsuda Kageyu. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================================ +Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov. +================================================================================ +Hacker Disassembler Engine 32 C +Copyright (c) 2008-2009, Vyacheslav Patkov. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- +Hacker Disassembler Engine 64 C +Copyright (c) 2008-2009, Vyacheslav Patkov. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.)"; +} + +namespace license { + static constexpr auto spdlog = +R"(The MIT License (MIT) + +Copyright (c) 2016 Gabi Melman. + +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. + +-- NOTE: Third party dependency used by this software -- +This software depends on the fmt lib (MIT License), +and users must comply to its license: https://github.com/fmtlib/fmt/blob/master/LICENSE.rst)"; +} + +namespace license { + static constexpr auto roboto = +R"(Apache License v2.00 + +This license can also be found at this permalink: http://www.fontsquirrel.com/license/roboto + +Font data copyright Google 2012 + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + “License” shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + “Licensor” shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + “Legal Entity” shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + “control” means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + “You” (or “Your”) shall mean an individual or Legal Entity + exercising permissions granted by this License. + + “Source” form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + “Object” form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + “Work” shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + “Derivative Works” shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + “Contribution” shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, “submitted” + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as “Not a Contribution.” + + “Contributor” shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an “AS IS” BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.)"; +} + +namespace license { +static constexpr auto openvr = R"( +Copyright (c) 2015, Valve Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.)"; +} + +namespace license { +static constexpr auto sol = R"( +The MIT License (MIT) + +Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors + +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.)"; +} + +namespace license { +static constexpr auto json = R"( +MIT License + +Copyright (c) 2013-2021 Niels Lohmann + +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.)"; +} + +namespace license { +static constexpr auto lua = R"( +Copyright (c) 1994-2021 Lua.org, PUC-Rio. + +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.)"; +} + +namespace license { +static constexpr auto asmjit = R"( +Copyright (c) 2008-2020 The AsmJit Authors + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +)"; +} + +namespace license { +static constexpr auto zydis = LR"( +The MIT License (MIT) + +Copyright (c) 2014-2021 Florian Bernd +Copyright (c) 2014-2021 Joel Höner + +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. +)"; +} + +namespace license { +static constexpr auto openxr = R"( + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +)"; +} + +namespace license { +static constexpr auto imguizmo = R"( +The MIT License (MIT) + +Copyright (c) 2016 Cedric Guillemet + +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. +)"; +} \ No newline at end of file diff --git a/src/Mod.hpp b/src/Mod.hpp new file mode 100644 index 0000000..a59695b --- /dev/null +++ b/src/Mod.hpp @@ -0,0 +1,264 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +class IModValue { +public: + using Ptr = std::unique_ptr; + + virtual ~IModValue() {}; + virtual bool draw(std::string_view name) = 0; + virtual void draw_value(std::string_view name) = 0; + virtual void config_load(const utility::Config& cfg) = 0; + virtual void config_save(utility::Config& cfg) = 0; +}; + +// Convenience classes for imgui +template +class ModValue : public IModValue { +public: + using Ptr = std::unique_ptr>; + + static auto create(std::string_view config_name, T default_value = T{}) { + return std::make_unique>(config_name, default_value); + } + + ModValue(std::string_view config_name, T default_value) + : m_config_name{ config_name }, + m_value{ default_value }, + m_default_value{ default_value } + { + } + + virtual ~ModValue() override {}; + + virtual void config_load(const utility::Config& cfg) override { + auto v = cfg.get(m_config_name); + + if (v) { + m_value = *v; + } + }; + + virtual void config_save(utility::Config& cfg) override { + cfg.set(m_config_name, m_value); + }; + + operator T&() { + return m_value; + } + + T& value() { + return m_value; + } + + const T& default_value() const { + return m_default_value; + } + + const auto& get_config_name() const { + return m_config_name; + } + +protected: + T m_value{}; + T m_default_value{}; + std::string m_config_name{ "Default_ModValue" }; +}; + +class ModToggle : public ModValue { +public: + using Ptr = std::unique_ptr; + + ModToggle(std::string_view config_name, bool default_value) + : ModValue{ config_name, default_value } + { + } + + static auto create(std::string_view config_name, bool default_value = false) { + return std::make_unique(config_name, default_value); + } + + bool draw(std::string_view name) override { + ImGui::PushID(this); + auto ret = ImGui::Checkbox(name.data(), &m_value); + ImGui::PopID(); + + return ret; + } + + void draw_value(std::string_view name) override { + ImGui::Text("%s: %i", name.data(), m_value); + } + + bool toggle() { + return m_value = !m_value; + } +}; + +class ModFloat : public ModValue { +public: + using Ptr = std::unique_ptr; + + ModFloat(std::string_view config_name, float default_value) + : ModValue{ config_name, default_value } { } + + static auto create(std::string_view config_name, float default_value = 0.0f) { + return std::make_unique(config_name, default_value); + } + + bool draw(std::string_view name) override { + ImGui::PushID(this); + auto ret = ImGui::InputFloat(name.data(), &m_value); + ImGui::PopID(); + + return ret; + } + + void draw_value(std::string_view name) override { + ImGui::Text("%s: %f", name.data(), m_value); + } +}; + +class ModSlider : public ModFloat { +public: + using Ptr = std::unique_ptr; + + static auto create(std::string_view config_name, float mn = 0.0f, float mx = 1.0f, float default_value = 0.0f) { + return std::make_unique(config_name, mn, mx, default_value); + } + + ModSlider(std::string_view config_name, float mn = 0.0f, float mx = 1.0f, float default_value = 0.0f) + : ModFloat{ config_name, default_value }, + m_range{ mn, mx } + { + } + + bool draw(std::string_view name) override { + ImGui::PushID(this); + auto ret = ImGui::SliderFloat(name.data(), &m_value, m_range.x, m_range.y); + ImGui::PopID(); + + return ret; + } + + void draw_value(std::string_view name) override { + ImGui::Text("%s: %f [%f, %f]", name.data(), m_value, m_range.x, m_range.y); + } + + auto& range() { + return m_range; + } + +protected: + Vector2f m_range{ 0.0f, 1.0f }; +}; + +class ModInt32 : public ModValue { +public: + using Ptr = std::unique_ptr; + + static auto create(std::string_view config_name, uint32_t default_value = 0) { + return std::make_unique(config_name, default_value); + } + + ModInt32(std::string_view config_name, uint32_t default_value = 0) + : ModValue{ config_name, static_cast(default_value) } + { + } + + bool draw(std::string_view name) override { + ImGui::PushID(this); + auto ret = ImGui::InputInt(name.data(), &m_value); + ImGui::PopID(); + + return ret; + } + + void draw_value(std::string_view name) override { + ImGui::Text("%s: %i", name.data(), m_value); + } +}; + +class ModCombo : public ModValue { +public: + using Ptr = std::unique_ptr; + + static auto create(std::string_view config_name, std::vector options, int32_t default_value = 0) { + return std::make_unique(config_name, options, default_value); + } + + ModCombo(std::string_view config_name, const std::vector& options, int32_t default_value = 0) + : ModValue{ config_name, default_value }, + m_options_stdstr{ options } + { + for (auto& o : m_options_stdstr) { + m_options.push_back(o.c_str()); + } + } + + bool draw(std::string_view name) override { + // clamp m_value to valid range + m_value = std::clamp(m_value, 0, static_cast(m_options.size()) - 1); + + ImGui::PushID(this); + auto ret = ImGui::Combo(name.data(), &m_value, m_options.data(), static_cast(m_options.size())); + ImGui::PopID(); + + return ret; + } + + void draw_value(std::string_view name) override { + m_value = std::clamp(m_value, 0, static_cast(m_options.size()) - 1); + + ImGui::Text("%s: %s", name.data(), m_options[m_value]); + } + + const auto& options() const { + return m_options; + } + +protected: + std::vector m_options{}; + std::vector m_options_stdstr{}; +}; + +class Mod { +protected: + using ValueList = std::vector>; + +public: + virtual ~Mod() {}; + virtual std::string_view get_name() const { return "UnknownMod"; }; + + // can be used for ModValues, like Mod_ValueName + virtual std::string generate_name(std::string_view name) { return std::string{ get_name() } + "_" + name.data(); } + + virtual std::optional on_initialize() { return std::nullopt; }; + + // This gets called after updating stuff like keyboard/mouse input to imgui + // can be used to override these inputs e.g. with a custom input system + // like VR controllers + virtual void on_pre_imgui_frame() {}; + virtual void on_frame() {}; // BeginRendering, can be used for imgui + virtual void on_present() {}; // actual present frame, CANNOT be used for imgui + virtual void on_post_frame() {}; // after imgui rendering is done + virtual void on_post_present() {}; // actually after present gets called + virtual void on_draw_ui() {}; + virtual void on_device_reset() {}; + virtual bool on_message(HWND wnd, UINT message, WPARAM w_param, LPARAM l_param) { return true; }; + + virtual void on_config_load(const utility::Config& cfg) {}; + virtual void on_config_save(utility::Config& cfg) {}; + + // game specific + virtual void on_think() {}; +}; \ No newline at end of file diff --git a/src/Mods.cpp b/src/Mods.cpp new file mode 100644 index 0000000..900fa89 --- /dev/null +++ b/src/Mods.cpp @@ -0,0 +1,71 @@ +#include + +#include "mods/AutomataMPConfig.hpp" +#include "mods/AutomataMPMod.hpp" +#include "mods/AnimTester.hpp" +#include "mods/BuddyFeatures.hpp" + +#include "Mods.hpp" + +Mods::Mods() { + m_mods.emplace_back(new AutomataMPConfig()); + /*m_mods.emplace_back(AutomataMPMod::get()); + m_mods.emplace_back(new AnimTester()); + m_mods.emplace_back(new BuddyFeatures());*/ +} + +std::optional Mods::on_initialize() const { + for (auto& mod : m_mods) { + spdlog::info("{:s}::on_initialize()", mod->get_name().data()); + + if (auto e = mod->on_initialize(); e != std::nullopt) { + spdlog::info("{:s}::on_initialize() has failed: {:s}", mod->get_name().data(), *e); + return e; + } + } + + utility::Config cfg{ "automatamp_config.txt" }; + + for (auto& mod : m_mods) { + spdlog::info("{:s}::on_config_load()", mod->get_name().data()); + mod->on_config_load(cfg); + } + + return std::nullopt; +} + +void Mods::on_pre_imgui_frame() const { + for (auto& mod : m_mods) { + mod->on_pre_imgui_frame(); + } +} + +void Mods::on_frame() const { + for (auto& mod : m_mods) { + mod->on_frame(); + } +} + +void Mods::on_present() const { + for (auto& mod : m_mods) { + mod->on_present(); + } +} + +void Mods::on_post_frame() const { + for (auto& mod : m_mods) { + mod->on_post_frame(); + } +} + +void Mods::on_draw_ui() const { + for (auto& mod : m_mods) { + mod->on_draw_ui(); + } +} + +void Mods::on_device_reset() const { + for (auto& mod : m_mods) { + mod->on_device_reset(); + } +} diff --git a/src/Mods.hpp b/src/Mods.hpp new file mode 100644 index 0000000..fda2db0 --- /dev/null +++ b/src/Mods.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "Mod.hpp" + +class Mods { +public: + Mods(); + virtual ~Mods() {} + + std::optional on_initialize() const; + + void on_pre_imgui_frame() const; + void on_frame() const; + void on_present() const; + void on_post_frame() const; + void on_draw_ui() const; + void on_device_reset() const; + + const auto& get_mods() const { + return m_mods; + } + +private: + std::vector> m_mods; +}; \ No newline at end of file diff --git a/src/NierClient.cpp b/src/NierClient.cpp new file mode 100644 index 0000000..fa0fda5 --- /dev/null +++ b/src/NierClient.cpp @@ -0,0 +1,56 @@ +#include + +#include +#include + +#include "Packets.hpp" +#include "mods/AutomataMPMod.hpp" +#include "NierClient.hpp" + +using namespace std; + +NierClient::NierClient(const std::string& host) +{ + set_trace_handler([](const std::string& s) { spdlog::info("{}", s); }); + connect(enetpp::client_connect_params().set_channel_count(1).set_server_host_name_and_port(host.c_str(), 6969).set_timeout(chrono::seconds(1))); + + while (get_connection_state() == enetpp::CONNECT_CONNECTING) { + think(); + this_thread::yield(); + } +} + +NierClient::~NierClient() +{ + disconnect(); +} + +void NierClient::think() +{ + consume_events( + [this]() { onConnect(); }, + [this]() { onDisconnect(); }, + [this](auto a, auto b) { onDataReceived((const Packet*)a, b); } + ); +} + +void NierClient::onConnect() +{ + spdlog::set_default_logger(spdlog::basic_logger_mt("AutomataMPClient", "automatamp_clientlog.txt", true)); + spdlog::info("Connected"); +} + +void NierClient::onDisconnect() +{ + spdlog::info("Disconnected"); +} + +void NierClient::onDataReceived(const Packet* data, size_t size) +{ + if (data->id >= ID_SHARED_START && data->id < ID_SHARED_END) { + AutomataMPMod::get()->sharedPacketProcess(data, size); + } + else if (data->id >= ID_SERVER_START && data->id < ID_SERVER_END) { + AutomataMPMod::get()->serverPacketProcess(data, size); + } +} diff --git a/src/NierClient.hpp b/src/NierClient.hpp new file mode 100644 index 0000000..564c264 --- /dev/null +++ b/src/NierClient.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +struct Packet; + +class NierClient : public enetpp::client { +public: + NierClient(const std::string& host); + ~NierClient(); + + void think(); + bool isConnected() { return get_connection_state() == enetpp::CONNECT_CONNECTED; } + +private: + void onConnect(); + void onDisconnect(); + void onDataReceived(const Packet* data, size_t size); +}; \ No newline at end of file diff --git a/src/NierServer.cpp b/src/NierServer.cpp new file mode 100644 index 0000000..072efee --- /dev/null +++ b/src/NierServer.cpp @@ -0,0 +1,57 @@ +#include + +#include +#include + +#include "Packets.hpp" +#include "AutomataMP.hpp" +#include "mods/AutomataMPMod.hpp" +#include "NierServer.hpp" + +using namespace std; +using namespace std::placeholders; + +NierServer::NierServer() { + spdlog::set_default_logger(spdlog::basic_logger_mt("AutomataMPServer", "automatamp_serverlog.txt", true)); + + start_listening(enetpp::server_listen_params().set_max_client_count(2) + .set_channel_count(1) + .set_listen_port(6969) + .set_initialize_client_function([this](auto& a, auto b) { initClient(a, b); })); + + spdlog::info("Server created"); +} + +NierServer::~NierServer() { + stop_listening(); +} + +void NierServer::think() { + consume_events( + [this](auto& a) { onClientConnect(a); }, + [this](auto a) { onClientDisconnect(a); }, + [this](auto& a, auto b, auto c) { onClientDataReceived(a, (const Packet*)b, c); } + ); + + for (auto c : get_connected_clients()) { + + } +} + +void NierServer::initClient(NierServerClient& client, const char* ip) { + client.uid = m_uid++; +} + +void NierServer::onClientConnect(NierServerClient& client) { + spdlog::info("Client connect"); +} + +void NierServer::onClientDisconnect(uint32_t uid) { + spdlog::info("Client disconnect"); +} + +void NierServer::onClientDataReceived(NierServerClient& client, const Packet* data, size_t size) { + if (data->id >= ID_SHARED_START && data->id < ID_SHARED_END) { + AutomataMPMod::get()->sharedPacketProcess(data, size); + } +} diff --git a/src/NierServer.hpp b/src/NierServer.hpp new file mode 100644 index 0000000..f11b680 --- /dev/null +++ b/src/NierServer.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include + +struct Packet; + +struct NierServerClient { + uint32_t uid; + uint32_t get_id() const { return uid; } //MUST return globally unique value here +}; + +class NierServer : public enetpp::server { +public: + NierServer(); + ~NierServer(); + + void think(); + +private: + void initClient(NierServerClient& client, const char* ip); + void onClientConnect(NierServerClient& client); + void onClientDisconnect(uint32_t uid); + void onClientDataReceived(NierServerClient& client, const Packet* data, size_t size); + +private: + uint32_t m_uid{ 1 }; +}; \ No newline at end of file diff --git a/src/Packets.hpp b/src/Packets.hpp new file mode 100644 index 0000000..48743ba --- /dev/null +++ b/src/Packets.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include +#include + +#include +#include + +#include +#include + +struct Packet { + uint32_t id{ 0 }; + + enet_uint8* data() { + return (enet_uint8*)this; + } +}; + +template +struct PacketT : public Packet { + PacketT() { id = idT; } +}; + +enum { + ID_SERVER_START = 1, + ID_SPAWN_ENTITY = ID_SERVER_START, + ID_ENTITY_DATA, + ID_SERVER_END, + ID_SHARED_START = 100, + ID_PLAYER_DATA = ID_SHARED_START, + ID_ANIMATION_START, + ID_CHANGE_PLAYER, + ID_BUTTONS, + ID_SHARED_END, +}; + +namespace nier_client_and_server { + struct PlayerData : public PacketT { + bool flashlight; + float speed; + float facing; + float facing2; + uint32_t weaponIndex; + uint32_t podIndex; + uint32_t heldButtonFlags; + Vector3f position; + }; + + struct AnimationStart : public PacketT { + uint32_t anim; + uint32_t variant; + uint32_t a3; + uint32_t a4; + }; + + struct ChangePlayer : public PacketT { }; + + struct Buttons : public PacketT { + uint32_t buttons[Entity::CharacterController::INDEX_MAX]; + }; +} + +namespace nier_client { + +} + +namespace nier_server { + template + struct EntityPacket : public PacketT { + uint32_t guid; + }; + + struct EntitySpawn : public EntityPacket { + char name[0x20]; + uint32_t model; + uint32_t model2; + EntitySpawnParams::PositionalData matrix; + }; + + struct EntityData : public EntityPacket { + float facing; + float facing2; + uint32_t health; + Vector3f position; + }; +} diff --git a/src/Player.cpp b/src/Player.cpp new file mode 100644 index 0000000..ff33e0d --- /dev/null +++ b/src/Player.cpp @@ -0,0 +1,17 @@ +#include +#include +#include "Player.hpp" + +Entity* Player::getEntity() { + if (!m_entityHandle) { + return nullptr; + } + + auto ent = EntityList::get()->getByHandle(m_entityHandle); + + if (!ent) { + return nullptr; + } + + return ent->entity; +} diff --git a/src/Player.hpp b/src/Player.hpp new file mode 100644 index 0000000..ee1e581 --- /dev/null +++ b/src/Player.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "Packets.hpp" + +class Entity; + +class Player { +public: + void setPlayerData(const nier_client_and_server::PlayerData& movement) { + m_playerData = movement; + } + + auto& getPlayerData() { + return m_playerData; + } + + uint32_t getHandle() { + return m_entityHandle; + } + + void setHandle(uint32_t handle) { + m_entityHandle = handle; + } + + float getStartTick() { + return m_startTick; + } + + void setStartTick(float tick) { + m_startTick = tick; + } + + Entity* getEntity(); + +private: + uint32_t m_entityHandle{ 0 }; + float m_startTick{ 0.0f }; + nier_client_and_server::PlayerData m_playerData; +}; \ No newline at end of file diff --git a/src/PlayerHook.cpp b/src/PlayerHook.cpp new file mode 100644 index 0000000..b862ac2 --- /dev/null +++ b/src/PlayerHook.cpp @@ -0,0 +1,57 @@ +#include + +#include + +#include +#include +#include "mods/AutomataMPMod.hpp" +#include "PlayerHook.hpp" + +using namespace std; + +unordered_set g_unreplicatedAnims { + EAnimation::Light_Attack, + EAnimation::Dash +}; + +PlayerHook* g_playerHook = nullptr; + +PlayerHook::PlayerHook() { + g_playerHook = this; +} + +void PlayerHook::reHook(Entity* player) { + if (m_hook.getInstance().as() == player) { + return; + } + + if (m_hook.create(player)) { + m_hook.hookMethod(18, &startAnimationHook); + } +} + +void __thiscall PlayerHook::startAnimationHook(Entity* ent, uint32_t anim, uint32_t variant, uint32_t a3, uint32_t a4) { + /*auto partners = EntityList::get()->getAllByName("partner"); + + for (auto partner : partners) { + if (partner && partner->entity) { + partner->entity->startAnimation(anim, variant, a3, a4); + //partner->entity->setBuddyFlags(0); + } + }*/ + + if (g_unreplicatedAnims.count(anim) == 0) { + nier_client_and_server::AnimationStart animation; + animation.anim = anim; + animation.variant = variant; + animation.a3 = a3; + animation.a4 = a4; + + AutomataMPMod::get()->sendPacket(animation.data(), sizeof(animation)); + } + + spdlog::info("anim: {}, variant: {}, a3: {}, return: {:x}", anim, variant, a3, (uintptr_t)_ReturnAddress()); + + auto original = g_playerHook->getHook().getMethod(Entity::s_startAnimationIndex); + original(ent, anim, variant, a3, a4); +} diff --git a/src/PlayerHook.hpp b/src/PlayerHook.hpp new file mode 100644 index 0000000..70717e2 --- /dev/null +++ b/src/PlayerHook.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +class Entity; + +class PlayerHook { +public: + PlayerHook(); + + void reHook(Entity* player); + + auto& getHook() { + return m_hook; + } + +public: + static void __thiscall startAnimationHook(Entity* ent, uint32_t anim, uint32_t variant, uint32_t a3, uint32_t a4); + +private: + VtableHook m_hook; +}; \ No newline at end of file diff --git a/src/VehHooks.cpp b/src/VehHooks.cpp new file mode 100644 index 0000000..bc72dad --- /dev/null +++ b/src/VehHooks.cpp @@ -0,0 +1,227 @@ +#include + +#include +#include + +#include "Mods.hpp" +#include "mods/AutomataMPMod.hpp" +#include "AutomataMP.hpp" + +#include "VehHooks.hpp" + +using namespace std; + +VehHooks::VehHooks() { + // required to allow button to be held down without resetting + m_hook.hook(0x140262B22, [=](const VehHook::RuntimeInfo& info) { + auto entity = Address(info.context->Rcx).get(-0xCA0).as(); + + auto& player = AutomataMPMod::get()->getPlayers()[1]; + + if (entity == player.getEntity()) { + entity->getCharacterController()->heldFlags = player.getPlayerData().heldButtonFlags; + } + }); + + // Early version hooks + /*addHook(0x140263006, &VehHooks::onProcessedButtons); + addHook(0x1404F9AA0, &VehHooks::onPreEntitySpawn); + addHook(0x1404F9BE9, &VehHooks::onPostEntitySpawn); + addHook(0x1404F8DE0, &VehHooks::onEntityTerminate); + addHook(0x140519460, &VehHooks::onUpdate);*/ + + addHook(0x140263006, &VehHooks::onProcessedButtons); + addHook(0x1404F9AA0, &VehHooks::onPreEntitySpawn); + addHook(0x1404F9BE9, &VehHooks::onPostEntitySpawn); + addHook(0x1404F8DE0, &VehHooks::onEntityTerminate); + addHook(0x140519460, &VehHooks::onUpdate); +} + +void VehHooks::onLightAttack(const VehHook::RuntimeInfo& info) { + auto entity = Address(info.context->R8).get(-0xCA0).as(); + + if (m_overridenEntities.count(entity) != 0) { + nier_client_and_server::Buttons buttons; + buttons.buttons[Entity::CharacterController::INDEX_ATTACK_LIGHT] = (uint32_t)info.context->Rax; + buttons.buttons[Entity::CharacterController::INDEX_ATTACK_HEAVY] = (uint32_t)info.context->Rdx; + AutomataMPMod::get()->sendPacket(buttons.data(), sizeof(buttons)); + } +} + +void VehHooks::onHeavyAttack(const VehHook::RuntimeInfo & info) { + auto entity = Address(info.context->R8).get(-0xCA0).as(); + + if (m_overridenEntities.count(entity) != 0) { + nier_client_and_server::Buttons buttons; + buttons.buttons[Entity::CharacterController::INDEX_ATTACK_LIGHT] = (uint32_t)info.context->Rdx; + buttons.buttons[Entity::CharacterController::INDEX_ATTACK_HEAVY] = (uint32_t)info.context->Rax; + AutomataMPMod::get()->sendPacket(buttons.data(), sizeof(buttons)); + } +} + +void VehHooks::onProcessedButtons(const VehHook::RuntimeInfo& info) +{ + auto entity = Address(info.context->R8).get(-0xCA0).as(); + + if (m_overridenEntities.count(entity) != 0) { + for (auto button : entity->getCharacterController()->buttons) { + if (button != 0) { + nier_client_and_server::Buttons buttons; + memcpy(&buttons.buttons, &entity->getCharacterController()->buttons, sizeof(buttons.buttons)); + AutomataMPMod::get()->sendPacket(buttons.data(), sizeof(buttons)); + break; + } + } + } +} + +void VehHooks::onPreEntitySpawn(const VehHook::RuntimeInfo& info) { + if (!AutomataMPMod::get()->isServer()) { + return; + } + + auto spawnParams = (EntitySpawnParams*)info.context->Rdx; + + if (spawnParams->name) { + if (spawnParams->name != string("FreeEnemy")) { + return; + } + + lock_guard _(m_spawnMutex); + m_threadIdToSpawnParams[GetCurrentThreadId()] = spawnParams; + } +} + +void VehHooks::onPostEntitySpawn(const VehHook::RuntimeInfo& info) { + auto threadId = GetCurrentThreadId(); + + if (m_threadIdToSpawnParams.find(threadId) == m_threadIdToSpawnParams.end()) { + return; + } + + auto entity = (EntityContainer*)info.context->Rax; + + if (entity) { + AutomataMPMod::get()->getNetworkEntities().onEntityCreated(entity, m_threadIdToSpawnParams[threadId]); + } + + lock_guard _(m_spawnMutex); + m_threadIdToSpawnParams.erase(threadId); +} + +void VehHooks::onEntityTerminate(const VehHook::RuntimeInfo& info) { + auto ent = (EntityContainer*)info.context->Rcx; + + AutomataMPMod::get()->getNetworkEntities().onEntityDeleted(ent); +} + +// Potential OnUpdate candidates +/* +Function calls: +0x0000000140519460: 1 +0x000000014051DCF0: 1 +0x00000001401A35C0: 5 +0x00000001405B6AC0: 5 +0x00000001401A34F0: 5 +0x00000001401A3440: 5 +0x00000001401A3640: 5 +0x00000001401A36C0: 5 +0x00000001408E6730: 5 +0x0000000140519470: 1 +0x0000000140001060: 1 +0x00000001408E6A10: 5 +0x00000001408134B0: 5 +0x00000001408082C0: 5 +0x0000000140813520: 5 +0x00000001408710A0: 5 +0x00000001408710F0: 5 +0x00000001408711A0: 5 +0x00000001408E6900: 5 +0x00000001408135F0: 5 +0x0000000140938030: 5 +*/ + +void VehHooks::onUpdate(const VehHook::RuntimeInfo& info) { + auto entityList = EntityList::get(); + auto player = entityList->getByName("Player"); + + if (!player) { + return; + } + + spdlog::info("In here"); + + //static std::unordered_map> functionCalls; + //static std::mutex mut; + + /*mut.lock(); + functionCalls[Address(info.context->Rbx).get(0x20).to()].insert(info.context->Rbx); + //auto rcx = (Entity*)info.context->Rcx; + + //spdlog::info("{:x} ({})", (uintptr_t)rcx, rcx->getContainer()->name); + + spdlog::info("Function calls: "); + + for (auto& i : functionCalls) { + spdlog::info("{:x}: {}", (uintptr_t)i.first, i.second.size()); + } + mut.unlock();*/ + + auto& mods = g_framework->get_mods()->get_mods(); + + for (auto& mod : mods) { + mod->on_think(); + } + + if ((GetAsyncKeyState(VK_F1) & 1) && AutomataMPMod::get()->isServer()) { + /*static std::unordered_map models{ { EModel::MODEL_2B, EModel::MODEL_9S }, + { EModel::MODEL_9S, EModel::MODEL_A2 }, + { EModel::MODEL_A2, EModel::MODEL_2B }}; + + auto ent = entityList->spawnEntity("Player", models[*player->entity->getModel()], *player->entity->getPosition()); + + if (ent) { + player->entity->setBuddyHandle(ent->handle); + ent->entity->setSuspend(false); + player->entity->changePlayer(); + }*/ + + EntitySpawnParams params; + EntitySpawnParams::PositionalData matrix; + matrix.position = Vector4f{*player->entity->getPosition(), 1.0f}; + matrix.unknown = *Address(player->entity).get(0x90).as(); + params.name = "FreeEnemy"; + params.matrix = &matrix; + params.model = 0x21020; + params.model2 = 0x21020; + + auto test = entityList->spawnEntity(params); + + if (test) { + test->entity->setSuspend(false); + AutomataMPMod::get()->getNetworkEntities().onEntityCreated(test, ¶ms); + } + + return; + } + + if (GetAsyncKeyState(VK_F2) & 1) { + auto enemies = entityList->getAllByName("FreeEnemy"); + + for (auto i : enemies) { + if (!i->entity) { + continue; + } + + i->entity->terminate(); + } + } +} + +void VehHooks::addOverridenEntity(Entity* ent) { + m_overridenEntities.insert(ent); +} + +void VehHooks::addHook(uintptr_t address, MemberCallbackFn cb) { + m_hook.hook(address, [=](const VehHook::RuntimeInfo& info) { invoke(cb, this, info); }); +} diff --git a/src/VehHooks.hpp b/src/VehHooks.hpp new file mode 100644 index 0000000..b2f1f33 --- /dev/null +++ b/src/VehHooks.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include + +#include + +class Entity; +struct EntitySpawnParams; + +class VehHooks { +public: + VehHooks(); + + void onLightAttack(const VehHook::RuntimeInfo& info); + void onHeavyAttack(const VehHook::RuntimeInfo& info); + void onProcessedButtons(const VehHook::RuntimeInfo& info); + void onPreEntitySpawn(const VehHook::RuntimeInfo& info); + void onPostEntitySpawn(const VehHook::RuntimeInfo& info); + void onEntityTerminate(const VehHook::RuntimeInfo& info); + void onUpdate(const VehHook::RuntimeInfo& info); + + void addOverridenEntity(Entity* ent); + + auto& getHook() { + return m_hook; + } + + typedef void (VehHooks::*MemberCallbackFn)(const VehHook::RuntimeInfo&); + +private: + void addHook(uintptr_t address, MemberCallbackFn cb); + +private: + VehHook m_hook; + std::unordered_set m_overridenEntities; + + std::mutex m_spawnMutex; + std::unordered_map m_threadIdToSpawnParams; +}; \ No newline at end of file diff --git a/src/automata-imgui/automata_imconfig.hpp b/src/automata-imgui/automata_imconfig.hpp new file mode 100644 index 0000000..af28845 --- /dev/null +++ b/src/automata-imgui/automata_imconfig.hpp @@ -0,0 +1,122 @@ +//----------------------------------------------------------------------------- +// COMPILE-TIME OPTIONS FOR DEAR IMGUI +// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. +// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. +//----------------------------------------------------------------------------- +// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) +// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. +//----------------------------------------------------------------------------- +// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp +// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. +// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. +// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. +//----------------------------------------------------------------------------- + +#pragma once + +#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD + +//---- Define assertion handler. Defaults to calling assert(). +// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. +//#define IM_ASSERT(_EXPR) MyAssert(_EXPR) +#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts + +//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows +// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. +// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() +// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. +//#define IMGUI_API __declspec( dllexport ) +//#define IMGUI_API __declspec( dllimport ) + +//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. +//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS + +//---- Disable all of Dear ImGui or don't implement standard windows. +// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. +//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. +//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. +//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty. + +//---- Don't implement some functions to reduce linkage requirements. +//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) +//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a) +//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). +//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). +//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) +//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. +//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. +//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). + +//---- Include imgui_user.h at the end of imgui.h as a convenience +//#define IMGUI_INCLUDE_IMGUI_USER_H + +//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) +//#define IMGUI_USE_BGRA_PACKED_COLOR + +//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) +#define IMGUI_USE_WCHAR32 + +//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version +// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. +//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" +//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" +//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION +//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION + +//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) +// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. +// #define IMGUI_USE_STB_SPRINTF + +//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) +// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). +// On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'. +//#define IMGUI_ENABLE_FREETYPE + +//---- Use stb_truetype to build and rasterize the font atlas (default) +// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. +//#define IMGUI_ENABLE_STB_TRUETYPE + +//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. +// This will be inlined as part of ImVec2 and ImVec4 class declarations. +/* +#define IM_VEC2_CLASS_EXTRA \ + ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ + operator MyVec2() const { return MyVec2(x,y); } + +#define IM_VEC4_CLASS_EXTRA \ + ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ + operator MyVec4() const { return MyVec4(x,y,z,w); } +*/ + +//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. +// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). +// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. +// Read about ImGuiBackendFlags_RendererHasVtxOffset for details. +//#define ImDrawIdx unsigned int + +//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) +//struct ImDrawList; +//struct ImDrawCmd; +//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); +//#define ImDrawCallback MyImDrawCallback + +//---- Debug Tools: Macro to break in Debugger +// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) +//#define IM_DEBUG_BREAK IM_ASSERT(0) +//#define IM_DEBUG_BREAK __debugbreak() + +//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(), +// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.) +// This adds a small runtime cost which is why it is not enabled by default. +//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX + +//---- Debug Tools: Enable slower asserts +//#define IMGUI_DEBUG_PARANOID + +//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. +/* +namespace ImGui +{ + void MyFunction(const char* name, const MyMatrix44& v); +} +*/ \ No newline at end of file diff --git a/src/automata-imgui/font_robotomedium.hpp b/src/automata-imgui/font_robotomedium.hpp new file mode 100644 index 0000000..c76ce20 --- /dev/null +++ b/src/automata-imgui/font_robotomedium.hpp @@ -0,0 +1,2468 @@ +// File: 'Roboto-Medium.ttf' (168644 bytes) +// Exported using binary_to_compressed_c.cpp +static const unsigned int RobotoMedium_compressed_size = 118118; +static const unsigned int RobotoMedium_compressed_data[118120/4] = +{ + 0x0000bc57, 0x00000000, 0xc4920200, 0x00000400, 0x00010025, 0x82120000, 0x043e0804, 0x44472000, 0x42b44645, 0x020082b0, 0x0000a015, 0x50476202, + 0x6ef9534f, 0x0200864b, 0x00000418, 0x53472e65, 0x82eb4255, 0x020059e4, 0x0000347d, 0x534f9015, 0xe697322f, 0x0200bab1, 0x45823c03, 0x6d63603c, + 0xeec67061, 0x02006d51, 0x0000b408, 0x76638206, 0x1c312074, 0x02004b06, 0x1f824812, 0x70665c38, 0xfc876d67, 0x0200ab24, 0x0000380f, 0x6167bc01, + 0x08007073, 0x6f821300, 0x1f829420, 0x6c670c28, 0x1a2f6679, 0x1b82af87, 0x01002c2c, 0x64683ce3, 0x8764786d, 0x5f829274, 0x00009c30, 0x65681805, + 0x9ffc6461, 0x010072d2, 0x2f82a8ee, 0x82683621, 0xef0a2310, 0x1f82c70a, 0x0f821820, 0x6d682428, 0xcbf27874, 0x1f82f74d, 0x0000e03c, 0x6f6c3814, + 0xc8ed6163, 0x0100a86e, 0x000088e4, 0x616d1e0a, 0x3e077078, 0x0f820f03, 0x2f826820, 0x616e2028, 0x963e656d, 0x9f82526d, 0xef82a420, 0x6f70ce28, + 0x6dff7473, 0x8f826400, 0x1f837420, 0x6572702b, 0xa3021a70, 0x10020029, 0x229382f4, 0x82050053, 0x03003d1b, 0x00b00528, 0x00060003, 0x000c0009, + 0xb26f000f, 0x1111100c, 0x0cb03912, 0xd000b010, 0x06200583, 0x09200584, 0x0d2f0584, 0x00b000d0, 0x02b05845, 0x02b11b2f, 0x84593e20, 0x8200200c, + 0x1000270c, 0x04b2593e, 0x39820002, 0x8505b221, 0x85072006, 0x84082006, 0x0ab02406, 0x840cb2dc, 0x0db22109, 0x4a080684, 0xb01002b0, 0x3130dc0e, + 0x21112121, 0x01011103, 0x21030111, 0x21013501, 0x3cfd2803, 0xfe36c402, 0x01bafeee, 0x0302e40c, 0x0201fefe, 0xb005fdfd, 0x0705a4fa, 0x77027dfd, + 0x780211fb, 0x5e025efd, 0x005e0288, 0xff8f0002, 0x84a301f2, 0x000d26bf, 0x0e06b23c, 0x247f820f, 0xb01006b0, 0x20a79301, 0x20a7820c, 0x2ba7820c, + 0xb00d06b1, 0x21582b0a, 0x59f41bd8, 0x2e082982, 0x302f01b0, 0x03230131, 0x36340121, 0x14151632, 0x01262206, 0x0117d17e, 0x4af9fe00, 0x84484a80, + 0x04ad0148, 0x39c3fa03, 0x37394b4b, 0x82004a4a, 0x03652c75, 0x064002f4, 0x00040000, 0x41250009, 0x03200510, 0x03385b82, 0xb0593e22, 0x02b0d002, + 0xd007b02f, 0xb02f07b0, 0x08b01003, 0x2f08b0d0, 0x03245e82, 0x05331123, 0x01260483, 0xae8b2313, 0x04822d01, 0xfe770526, 0x890c027d, 0x53820483, + 0x4e826020, 0xc982bc20, 0x1f001b24, 0x53858f00, 0x6441af84, 0x82102007, 0x87102060, 0x8202200c, 0x8202200c, 0x00b025c9, 0x1ab05845, 0x1a200c82, + 0xb2230c82, 0x83020c1d, 0x2f1d24fe, 0x890300b1, 0xd00426e0, 0xb0101db0, 0x26058406, 0x0bb0d00b, 0x8a08b12f, 0x100b231d, 0x14820eb0, 0x12b01028, + 0x1008b0d0, 0x268414b0, 0xb0d01626, 0x18b01000, 0x1e211184, 0x26bd82d0, 0x13230323, 0x84213523, 0x03332303, 0x03821333, 0x03231523, 0x82038233, + 0x23133205, 0x4ce0cf02, 0x01e74ca8, 0x01f33a05, 0x4ea74e11, 0x380382e1, 0xdd3aeed0, 0x76a74cfb, 0x01e03ae0, 0x0166fe9a, 0x39019e9a, 0xfea0019f, + 0x3b038360, 0x9ec7fe9f, 0x380266fe, 0x01003901, 0x2dff6400, 0x9b062604, 0x80002c00, 0x2e2d2ab2, 0xfe92c282, 0xe4820920, 0xfe870920, 0x0c822320, + 0xfe872320, 0x0c822020, 0x0c822020, 0x0c19b223, 0x253b8220, 0xb11019b0, 0xfe880102, 0x090fb223, 0x05cd4223, 0x8a13b121, 0x23272215, 0x23158309, + 0x2ab11023, 0xe8821589, 0x26348a08, 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, 0xff630005, 0x058905ec, 0x000d00c5, 0x0027001a, 0x00390035, + 0x3a05b28d, 0x259f833b, 0x13b01005, 0x0582b0d0, 0x05841b20, 0x05842820, 0x00d0362e, 0xb02f36b0, 0x00b02f38, 0x03b05845, 0x0320fe82, 0x20071841, + 0x2f0c8225, 0x593e1025, 0xb01003b0, 0x0ab0d00a, 0x0211b12f, 0x82080a41, 0x18b12114, 0x252c0e8a, 0xd01eb010, 0xb02f1eb0, 0x2bb11025, 0x1e23178a, + 0x8932b110, 0x3130280e, 0x33363413, 0x82151632, 0x222324ff, 0x84173526, 0x353527fc, 0x06222634, 0x1a880115, 0x198b2020, 0x1a822320, 0x27057b08, + 0xaa631701, 0xa9a98c8a, 0xaaaf878a, 0x4c3e3f4d, 0x024b7e4d, 0x8887ae12, 0xe8fea7ad, 0x3e4faaab, 0x3d4e4940, 0x02fe4d3e, 0x7dc7027d, 0xa9849804, + 0x834889a9, 0x068ca5a8, 0x49555545, 0x57564549, 0x86d0fc47, 0x478da6a6, 0x89a7a982, 0x53574405, 0x54464b4b, 0x48f44a54, 0x00487204, 0xff560003, + 0x051105ec, 0x001c00c4, 0x00310025, 0x322eb29a, 0x39121133, 0xb0102eb0, 0x0583d010, 0x01441e20, 0x0c384206, 0x1b2f1b24, 0x38421bb1, 0x82182007, + 0x8218200c, 0x20b2230c, 0x3a82091b, 0x0928b223, 0x2206831b, 0x83282003, 0x28102206, 0x20068320, 0x221b8513, 0x83181311, 0x1819220d, 0x22068313, + 0x82191116, 0x1bb02406, 0x421db110, 0xb223093d, 0x83111d1f, 0x10092315, 0x15892fb1, 0x13313028, 0x26373634, 0x29413526, 0x148e0805, 0x01070706, + 0x10333536, 0x27211707, 0x05242006, 0x07013732, 0x16141506, 0x37171403, 0x34353637, 0x06222326, 0x55a26e56, 0x9fb0d043, 0x63695ccb, 0xd33d1901, + 0xe6fed67e, 0x50fe9c52, 0xe201fdfe, 0xc2fe6b7b, 0x1982781f, 0x3e1f6f67, 0x54474256, 0xa9658901, 0x46966b74, 0x8abbc7ab, 0x484c995b, 0x9378b4fe, + 0xfdacf3fe, 0x23e57561, 0x16770152, 0x7e65755b, 0x7f54aa03, 0x5637194c, 0x00605139, 0x52000100, 0x0b01fc03, 0x04000006, 0xbb441600, 0x06ac4413, + 0x1a0b013c, 0x8305b99f, 0x040279fe, 0x80000100, 0xa20231fe, 0x10005f06, 0x07b21000, 0xe7821211, 0x04b00026, 0x2f0db02f, 0x3708df83, 0x17371212, + 0x07030206, 0x07171210, 0x80020226, 0x3086f07c, 0x0108af8d, 0x86309aab, 0x50027bf1, 0x019f01e7, 0x6b8e4247, 0xe5fe49fe, 0xfed1fe56, 0x42877c25, + 0x9d014901, 0x28205782, 0x51205782, 0x12205782, 0x13215783, 0x20578714, 0x0857820e, 0x0214013f, 0x36270702, 0x10351112, 0x37272702, 0x17121216, + 0xf87a5102, 0xaf963087, 0x301f8e98, 0x0880f080, 0xfede4002, 0x41adfe63, 0xdd017487, 0x01173201, 0x8ac90116, 0xfe3e881c, 0xd079fec4, 0x2a5d8200, + 0x034d021b, 0x00b00574, 0x8520000e, 0x2f0431e9, 0x2004b11b, 0x00b0593e, 0x00b019d0, 0x09b0182f, 0x09220782, 0xf382182f, 0x37253508, 0x03330305, + 0x13051725, 0x27030307, 0xcffe4c01, 0x0f2e0137, 0x29010fb3, 0xc8cafe36, 0x92b2b491, 0xa958cc03, 0xfe580175, 0x58ac73a2, 0x016af6fe, 0x66e9fe20, + 0x442e6583, 0x2a049200, 0x0b00b604, 0xb0001b00, 0x5b822f09, 0x1009b024, 0x034206b1, 0x03b02209, 0x086082d0, 0x21152120, 0x21112311, 0x33112135, + 0x7c01ae02, 0xfeec84fe, 0xec7e0182, 0xfede2103, 0xdeb1014f, 0x4b839501, 0xb8fe1c37, 0xeb005d01, 0x19000900, 0x0b0a09b2, 0x00391211, 0xb12f0ab0, + 0x09b04605, 0x1331303e, 0x37363627, 0x06073335, 0x3a839f06, 0x01db012b, 0xb8fe6901, 0x46875b4e, 0xd56aafbd, 0x4730f582, 0x54020902, 0x0300cd02, + 0xb0001200, 0x01b12f02, 0x820ce144, 0x54022880, 0x0d02f3fd, 0x83c40902, 0xff872e71, 0x01a201f5, 0x000a0000, 0x0b00b223, 0x087d450c, 0x1b2f0629, + 0x3e1006b1, 0x8b00b159, 0x3201227b, 0x05074416, 0x01363433, 0x4a4a4414, 0x4a4c4144, 0x3a4d0001, 0x744a4b39, 0x267b824d, 0x0283ff02, 0x82b005fe, + 0x0013237b, 0xa14400b0, 0x48022005, 0x2208062b, 0x23173130, 0xbfc13301, 0x7dbf3d02, 0x00002d06, 0xff690002, 0x052204ec, 0x000d00c4, 0xb248001b, + 0x821d1c03, 0x03b0247d, 0x4311b010, 0x0a2006bb, 0x0a213982, 0x06654820, 0x0c820320, 0x90820320, 0x100ab024, 0xd28911b1, 0xb1212f82, 0x08e18c18, + 0x23021050, 0x35030222, 0x32331210, 0x34271312, 0x06222326, 0x16141107, 0x37363233, 0xf0eb2204, 0xeb03efec, 0x03ebeff1, 0x777a70f3, 0x7a720370, + 0x02037075, 0xfec6fe65, 0x013701c1, 0x3a01fc31, 0xcefe3a01, 0xcd14cffe, 0xfec0b5bf, 0xb9c8ccb6, 0xd78200c5, 0x0000a82a, 0xb505ff02, 0x3a000600, + 0x20054942, 0x208d8205, 0x11004905, 0x83050021, 0x2f0423c2, 0x928903b1, 0x0302b222, 0x30351583, 0x11232131, 0x33253505, 0xfef2ff02, 0x1f38029b, + 0xcd7a9104, 0x2e5b82d1, 0x04000051, 0x00c40540, 0xb2500019, 0x411b1a11, 0x11200881, 0x11206282, 0x03226290, 0x21820011, 0x1011b024, 0x628a09b1, + 0x15851620, 0x41100021, 0x21240d0b, 0x36013521, 0x08065544, 0x34231539, 0x32333636, 0x06141516, 0x04210107, 0x012dfc40, 0x755969e5, 0xf3827663, + 0xd493e179, 0xfe8c7bf5, 0xa7a4029c, 0x9d751102, 0x9080684f, 0x76d5857d, 0xef6dbcd5, 0x8283fe98, 0xff4f24a3, 0x821504ec, 0x002926a3, 0x2a07b271, + 0x20a3882b, 0x20a3820f, 0x45a3870f, 0xb222075d, 0xc5830f01, 0x2f01b02e, 0x01011fb2, 0x019fb271, 0x3fb25d01, 0xb0240982, 0x07b1100f, 0xb024b589, + 0x28b11001, 0xb2230e89, 0x45012815, 0x22200656, 0x200cd041, 0x20c29333, 0x23c88216, 0x24222304, 0x08068d47, 0x26343553, 0x86012323, 0x6d837094, + 0xf37e6270, 0xda84d577, 0x78637df9, 0xdbf3fe7d, 0xf3f4fed2, 0x82716d81, 0x038f8688, 0x6c720147, 0x5b717368, 0xdb67b870, 0x2cad62c3, 0xc47ab029, + 0x60bae0e8, 0x73727878, 0x0002007c, 0x04000034, 0x00b00558, 0x000e000a, 0x05e9414a, 0x200c4046, 0x27ef8204, 0x593e1004, 0x040901b2, 0x0121ab83, + 0x0b6c482f, 0xd006b022, 0xb026d382, 0x08b2d00b, 0x1e820b06, 0x840db221, 0x30370825, 0x15330131, 0x11231123, 0x33012721, 0x07112101, 0xb5b5a303, + 0x078bfdf3, 0xfdfb7402, 0x127d0190, 0xfec30702, 0x944401bc, 0x57fcd803, 0x00206002, 0xff810001, 0x823a04ec, 0x001d2687, 0x1e1ab26d, 0x086f411f, + 0x7f820120, 0x6f410120, 0x820d2007, 0x820d200c, 0x4273828c, 0x07220c6f, 0x30820d01, 0x2f07b024, 0x47411ab1, 0x05b22309, 0x15831a07, 0xb1100d23, + 0x21158a14, 0x15831411, 0x1a1db223, 0x371c8214, 0x13133130, 0x03211521, 0x12323336, 0x23001415, 0x33272422, 0x32331616, 0x08064142, 0x4fae0739, + 0xbcfd0e03, 0xd07f6528, 0xdf00ffe7, 0x0bf9fec8, 0x647c0eeb, 0x798a7d70, 0x02365c42, 0xd2de02d2, 0xfe3aa4fe, 0xfedee1f6, 0x6abae3f9, 0x858aa071, + 0x0033239b, 0x82750002, 0x05372ccd, 0x001400b7, 0xb265001f, 0x82212015, 0x15b0236b, 0x4d4cb010, 0x82002007, 0x900020c8, 0x100021d5, 0x220bba44, + 0x860007b2, 0x83c982d5, 0x15b12109, 0xb020c689, 0x1b20d582, 0x240c3342, 0x06062315, 0x08c78807, 0x3511005b, 0x03210010, 0x15070622, 0x36321614, + 0x61032610, 0x17f4cc1e, 0xdfc1b675, 0xdad4fbfe, 0x7501f1fe, 0x50ec5e01, 0xd8881f85, 0xb705807e, 0xc8da03c9, 0xd7f0fe7b, 0x01edfede, 0x53050142, + 0xb2017f01, 0x4b5a49fd, 0xa2bfa24a, 0x00a60801, 0x00450001, 0x05360400, 0x000600b0, 0x120f4433, 0xcf820120, 0x3e100126, 0x1005b059, 0x200c9841, + 0x06084400, 0x2301013c, 0x21352101, 0xbafd3604, 0xfd4502ff, 0x05f1030f, 0x04d7fa29, 0x0300c3ed, 0x13456800, 0x00172a06, 0x002b0021, 0x2c09b277, + 0x0555482d, 0xd01ab027, 0xb01009b0, 0x061b4524, 0x63821520, 0x33411520, 0x82092007, 0x8209200c, 0x29b22370, 0x2d831509, 0xb22f2926, 0x7101291f, + 0x220cff41, 0x82291a03, 0x0fb2231a, 0x4f851a29, 0x411fb121, 0xb0240930, 0x25b11015, 0x220c3f41, 0x43070614, 0xc0480861, 0x3403290a, 0x15062226, + 0x36321614, 0x54080989, 0x5f6e0204, 0xfcfe7b72, 0xfbfed9d8, 0x6d5e707c, 0xf0cdccf0, 0x7fd481d3, 0x1f7bdc7d, 0x6d6cba6e, 0x30046dba, 0x3530a76b, + 0xe1c074b8, 0xba75bfe2, 0x6ba73032, 0xfcdadaba, 0x84856caf, 0x7c806b6d, 0x7b5ffd02, 0x76646575, 0x00020076, 0x04faff5d, 0x00c40512, 0x24fd8215, + 0x2209b267, 0x21ab8523, 0xf58616b0, 0x200c8c43, 0x20f58211, 0x22f58311, 0x82091116, 0xb07c2427, 0x4b182f16, 0x00210cfb, 0x24178302, 0xb11011b0, + 0x21dc8912, 0xb64909b0, 0x31303c0c, 0x22230601, 0x36343502, 0x00323336, 0x00101511, 0x33352305, 0x32033636, 0x86353736, 0x035408ed, 0xc0a37a1e, + 0x8dd674e4, 0xfe0201dc, 0x1d9ffe9c, 0xdce6d723, 0x84238049, 0x027e7dd2, 0x0d018161, 0x82ea90db, 0xedfeb8fe, 0xfe76fe44, 0x03c90362, 0x540f01c9, + 0xc4a15f4a, 0xa88984ad, 0x8200ffff, 0x9d01f5ff, 0x26005104, 0x00fb1200, 0x12000700, 0x5103fbff, 0x2e241782, 0x8801b8fe, 0x27201782, 0xe6321182, + 0x06005103, 0x00121000, 0x3f000100, 0x8403a400, 0x0f824e04, 0x00b21724, 0xfd430807, 0x82052008, 0x1c0523f0, 0xb382593e, 0x15052308, 0x15013501, + 0x4e023601, 0x4503bbfc, 0xf3e07702, 0x01c17501, 0x0200f374, 0x64019100, 0xd603ef03, 0x69820300, 0xb000272c, 0x03b02f07, 0x2f03b0d0, 0x034100b1, + 0x1007230a, 0xef4104b1, 0x3521230c, 0x03821121, 0xfcef0325, 0x835e03a2, 0x0c032503, 0xc98efdca, 0x80248d83, 0xe003a500, 0x02208d92, 0x02208d82, + 0x25208d85, 0x35328b83, 0x96fdea02, 0xa0fc6003, 0xefe37c02, 0xfec18cfe, 0x8d82ef8c, 0xf4ff3c30, 0xc4059803, 0x23001800, 0x09b26000, 0xd1412524, + 0x411c2006, 0xd74e06d1, 0x8222200c, 0x10222552, 0x1cb1593e, 0x29097448, 0xb0d000b0, 0x04b22f00, 0x39831000, 0xf7461020, 0x100c220d, 0x21158200, + 0x1c8415b2, 0x01313025, 0x4b363634, 0x15210745, 0x06ee4623, 0x06070724, 0x7e4b0307, 0x22360807, 0x425e0126, 0x5d281ac3, 0xf369565a, 0xc9c3ed02, + 0x427b98e1, 0x3f4af402, 0x84484a40, 0x85ac0147, 0x3d28bd9e, 0x61635e47, 0xccceb153, 0x799ea3b7, 0xc9fe904b, 0xfa4f493b, 0x00023205, 0x063bfe5b, + 0x009005d9, 0x00420036, 0x433bb280, 0x247d8244, 0xb0103bb0, 0x23cd8223, 0x33b02f2a, 0x4805f148, 0x002408aa, 0x08b05845, 0x0820d382, 0xb223d382, + 0x82083305, 0x0fb2212d, 0xb0270684, 0x08b02f0f, 0x4d3ab110, 0xb0270968, 0x33b0d015, 0x8a1bb110, 0x102a2311, 0x0e8a23b1, 0xb1100f23, 0x820e8940, + 0x062108ed, 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, 0x47000a00, 0x520faf4b, 0xbc4d0773, 0x079e4a07, 0x0409b228, 0x39121102, + 0xdf4209b0, 0x0ab2210c, 0x30291584, 0x03210131, 0x01330121, 0x08078221, 0xfdc30327, 0xf9fe76cc, 0x02e32602, 0xfdf8fe27, 0xd3a6019c, 0xadfe5301, + 0x50fab005, 0x5c021f02, 0x00030000, 0x04000094, 0x288182a3, 0x0016000e, 0xb270001f, 0x05a94602, 0xb0100225, 0x82b0d011, 0x421e2005, 0x854706b3, + 0x08fd520c, 0x01001722, 0x17288983, 0x171fb22f, 0x0fb17101, 0x23095f43, 0x170f08b2, 0x00231a83, 0x4810b110, 0x1e200dfe, 0x30270e89, 0x21113331, + 0x45150432, 0x01200879, 0x36240e82, 0x25273435, 0x08068047, 0x01942346, 0x0201f7f3, 0x8176686c, 0xfef5f9fe, 0x771901ea, 0xd2fee886, 0x7b8576f8, + 0xb005f682, 0xa064c4c6, 0x7cb1202c, 0x9102dccd, 0x697639fe, 0x6bba05e3, 0x00606c62, 0x66000100, 0xeb04ecff, 0x1d00c405, 0x03b24200, 0x520a4d48, + 0xb4420c60, 0x100c2108, 0x220b2a51, 0x461003b0, 0x30350b46, 0x00060131, 0x02242223, 0x12343527, 0x00323324, 0x26262317, 0x05584723, 0x5608a782, + 0x16eb0437, 0xaef9d4fe, 0x0390f7fe, 0xb3110192, 0x182601f1, 0x8e9312fc, 0xa902b1a5, 0x149695a3, 0xfee9da01, 0x3001a5fb, 0x01ce88c9, 0xfafeaa3a, + 0xf18b9def, 0xf8ec81e9, 0x00009c86, 0x00940002, 0x05d20400, 0x000b00b0, 0xb2480015, 0x11171602, 0x02b03912, 0x4115b010, 0xb0241b77, 0x0cb11001, + 0x24094641, 0xb11000b0, 0x1055410d, 0x15151228, 0x23040214, 0xa3831103, 0x34352b08, 0x01942326, 0x2b01c1ae, 0xcffea5a4, 0xc7a5a6c5, 0xc4ce02d5, + 0xfeacb005, 0xcf49ccc4, 0x04aac6fe, 0xf9e6fbe4, 0xfaed51e9, 0x93840100, 0x93844c20, 0x93425120, 0x2f062405, 0x4706b11b, 0x0f4a0778, 0x060b2208, + 0x20ac8304, 0x0c86420b, 0x5204b021, 0xb0240c8b, 0x08b11006, 0x230d7545, 0x21152111, 0x03380385, 0x02aafde7, 0x0348fcbb, 0x024cfdb1, 0xfe8a0256, + 0xb005ca40, 0x006efecc, 0x31208386, 0x09228382, 0x17434200, 0x150a431a, 0x8b4e8383, 0x3130250a, 0x23112101, 0xdb2d7286, 0x03fdb6fd, 0x0260fd9d, + 0xfd69024a, 0x206e8397, 0x2e6d824f, 0x04ecff6a, 0x00c405f0, 0xb258001e, 0x46201f0b, 0x0b20087d, 0x0b20f882, 0x20108d4d, 0x1b8d4d0b, 0x0b1eb223, + 0x233f8203, 0xb12f1eb0, 0x220c9e49, 0x42040625, 0x51080543, 0x32210010, 0x02231704, 0x07062221, 0x33121415, 0x21113732, 0xf0042135, 0xb2e8fe4f, + 0x99e6feb7, 0x013c0103, 0x1e01f31b, 0xfe2af81d, 0x03b1aaf9, 0x52c2b1c7, 0x2802d4fe, 0xa66a67bd, 0x72ce3501, 0x73014a01, 0x0701e2f0, 0xec70edf5, + 0x0158fbfe, 0x2f41c01d, 0x18052706, 0x0b00b005, 0xb3414d00, 0x0c554e12, 0x2407bd43, 0x584500b0, 0x08cd41b0, 0x00060922, 0x54065444, 0x30290a4a, + 0x11232131, 0x11231121, 0x34058233, 0xfc180533, 0xfdfd75fd, 0x02fc8b02, 0x0579fd87, 0x02a2fdb0, 0x207b835e, 0x200482a3, 0x227b829f, 0x571d0003, + 0x4b841a2a, 0x9f013324, 0x2a82fcfc, 0x00010027, 0x03ecff2d, 0x260a82e4, 0xb230000f, 0x41111005, 0x194b0873, 0x2f05270c, 0x1005b11b, 0xee42593e, + 0x3130290b, 0x14113301, 0x26222304, 0x2b07084d, 0xfefce802, 0xf8e4d6fb, 0x666d73fc, 0xfc299782, 0xe6f6d103, 0x877574cd, 0x0b194177, 0x53000c22, + 0x20124942, 0x20608208, 0x14635608, 0x19820b20, 0x7a820b20, 0x0400b223, 0x289c8202, 0x7a006ab4, 0xb25d0200, 0x250d8506, 0x06750665, 0x8a825d02, + 0x11072b08, 0x11331123, 0x01210137, 0x36022101, 0x8cfdfda5, 0x3201aa01, 0x3c02e3fd, 0x7502d4fe, 0x053afeaf, 0xad55fdb0, 0x7bfdfe01, 0xd742d5fc, + 0x82262006, 0x000522f5, 0x208d9229, 0x06e45602, 0x300bb848, 0x21253130, 0x33112115, 0x95029101, 0xcafd6efc, 0x263d82ca, 0x00940001, 0x826a0600, + 0x000e2209, 0x4147856e, 0xab580c36, 0x07e2410c, 0x4700b021, 0x0c840a9a, 0x1d580c20, 0x01b22306, 0xe2830400, 0x75016523, 0x20e28201, 0x230d8507, + 0x077a076a, 0x0a200d82, 0x0a220d86, 0xf0830a7a, 0x21020922, 0x1324f182, 0x13012301, 0x24080782, 0xa401dc01, 0x4701a301, 0x52fe19fc, 0x1953feb5, + 0xfbb005fc, 0xfa5c04a4, 0x02e00150, 0x049efb82, 0xfe7ffd61, 0x05ef4120, 0x0521b182, 0x240a8217, 0xb24c0009, 0x06e75101, 0x56509183, 0x0c8e410c, + 0x450ca842, 0xb22307ab, 0x82000502, 0x07b221ab, 0x30240684, 0x01232131, 0x33318782, 0x05331101, 0x77fdfd17, 0x8b02fdfd, 0xfb0904fb, 0x368882f7, + 0x000d04f3, 0xff660002, 0x051e05ec, 0x001000c4, 0xb248001e, 0x82201f04, 0x04b0243d, 0x4514b010, 0x11460661, 0x082b410c, 0x334e0c20, 0x432f820c, + 0x01220dcd, 0xce430214, 0x12342c06, 0x12042024, 0x02340717, 0x43022223, 0x400805d0, 0x1e053512, 0xb3edfe94, 0x97ebfeb1, 0x13019701, 0x13016401, + 0xb7fd0196, 0x02b9a4a8, 0xb5a8a6bb, 0xfed6b202, 0x01adadbd, 0xd552d140, 0xabad4601, 0x05d5bffe, 0xfe0201f2, 0xf054ebff, 0x0001fafe, 0x061746f6, + 0xb005d42c, 0x13000a00, 0x0ab24f00, 0xb5831514, 0xb0100a23, 0x57b5860c, 0x01200c03, 0x23067c4d, 0x03010bb2, 0x20129245, 0x0cdd4603, 0x01313024, + 0x76472311, 0x042f0805, 0x32212523, 0x26343536, 0x91012127, 0xf42d02fd, 0xe7fe1f01, 0x01d3fefd, 0x908e8730, 0x02c9fe7e, 0x05e3fd1d, 0xd6d1feb0, + 0x787fcbee, 0x82028d76, 0xff602e97, 0x051a0504, 0x001500c4, 0xb2480023, 0x05db4a08, 0xb0100823, 0x51978620, 0x08200cc1, 0x2406074a, 0xb11011b0, + 0x09054619, 0x1008b024, 0x144620b1, 0x0214260c, 0x25071707, 0x0a644706, 0x17120425, 0x41263407, 0x19290b52, 0xa4fa7683, 0x463dcafe, 0x065641b0, + 0x01b4b139, 0xfe019613, 0xb9a3a8b8, 0xa9a7b902, 0xcfb202b5, 0xc359d1fe, 0x410df594, 0xf6280d5a, 0xeafffefe, 0xf6feec55, 0x2c095941, 0x00b005de, + 0x0017000e, 0x1805b25c, 0x06755819, 0xc1861020, 0x30550420, 0x0a804908, 0x020fb223, 0x20278304, 0x0c5b540f, 0x010bb223, 0x06af470f, 0xb0d00e26, + 0x17b11004, 0x2120d58c, 0x25076741, 0x15010706, 0x6a410121, 0x02410807, 0xfde6feab, 0x01fc0002, 0x017e8d12, 0xfdf1fe47, 0x800401c2, 0xfe848590, + 0xfd3102f5, 0xe2b005cf, 0x35c592d6, 0x020da1fd, 0x757081fc, 0x00000280, 0xff4a0001, 0x058a04ec, 0x002700c4, 0x2811b266, 0x082b4529, 0x200c1b4e, + 0x27b8821d, 0x593e101d, 0x091d02b2, 0xb2232182, 0x821d090e, 0x09b02106, 0x200dad46, 0x21a58c02, 0x2b8422b2, 0x4f1db021, 0x34290f0c, 0x26272426, + 0x33243435, 0x0c135a32, 0x5a07204f, 0x40080811, 0xa0fe878d, 0x1f01c768, 0x88ee98e5, 0x7c858ffc, 0x54019489, 0xe9fe60ce, 0xf7fe9eef, 0x99a4fd93, + 0x77018584, 0x416a6860, 0xe4b0c97d, 0x727ecf70, 0x505f6a81, 0xa781656b, 0x75d7b670, 0x887c89ce, 0x2add826b, 0x0400002d, 0x00b005b0, 0x462f0007, + 0x022012bb, 0x22061345, 0x4d1006b0, 0x04210ccf, 0x07d847d0, 0x04213532, 0xfb3afeb0, 0x83043efe, 0x1cfbe404, 0x00cce404, 0x7d245582, 0xbd04ecff, + 0x10245582, 0x04b23d00, 0x2306bf57, 0xb0584500, 0x4d0c3341, 0x04200c8a, 0x4906e952, 0x31080d4c, 0x00141101, 0x35002223, 0x14113311, 0x11203316, + 0xfebd0411, 0xfefaf7d7, 0x9094fcda, 0xb0052401, 0xfee833fc, 0xed0b01f1, 0x32fccc03, 0x34019a92, 0x7d83c603, 0x00001224, 0x7d821d05, 0x38000622, + 0x4b0ccf4e, 0xfa440c47, 0x08e0440c, 0x03010025, 0x82391211, 0x210138dc, 0x21012301, 0x72019502, 0xf4fd1601, 0x01f6fdf5, 0x043d0115, 0x8250fa73, + 0x00012657, 0x06000030, 0x260982e5, 0xb260000c, 0x530e0d05, 0x4f45152f, 0x15cd480c, 0x58450023, 0x085a4cb0, 0xb2217b85, 0x21828405, 0x06840ab2, + 0x13218982, 0x82898233, 0x332e0802, 0x05330113, 0xfefbe00a, 0xebfef2b0, 0xfef3e5fe, 0x01e2fbb0, 0x6801d416, 0x50fa4804, 0xd9fb2704, 0xbafbb005, + 0x01004604, 0x00002900, 0x9d82e904, 0x75470b20, 0x48f88c07, 0x9f460c8f, 0x2f072b0c, 0x1007b11b, 0x00b2593e, 0xd2820401, 0x8506b221, 0x00032206, + 0x480d8306, 0x1a4105a4, 0x21012205, 0x08028401, 0x01890228, 0xfe240132, 0xfec20148, 0xfec7fed9, 0x01dafec6, 0x0147fec3, 0x02a20324, 0xfd2efd0e, + 0xfd160222, 0x02de02ea, 0x958200d2, 0x95820720, 0x9582d620, 0x31000822, 0x8c056942, 0x4a7b8495, 0x888510e6, 0x113d7385, 0x21011123, 0x4f016f02, + 0x18fe1801, 0x0117fefe, 0x02fe0219, 0xfd68fcb2, 0x031802e8, 0x24618398, 0x04000050, 0x2261828c, 0x85460009, 0x47548c61, 0xb22313df, 0x82020004, + 0x07b024db, 0x4405b110, 0xb223093e, 0x82070509, 0x05fc4715, 0x21013538, 0x01152135, 0xfb0a0382, 0xfdf102c4, 0xca1f0414, 0x4004a4ca, 0x7183a0cc, + 0xbcfe8430, 0x8e061c02, 0x24000700, 0x2f04b000, 0x8f4b07b0, 0x0a985710, 0x2335c682, 0x21153311, 0x1c022111, 0x68fea5a5, 0xd0059801, 0x07bda9f9, + 0x244983d2, 0x0383ff14, 0x25bb8264, 0x00130003, 0xd74f02b0, 0x54002005, 0x303606a7, 0x01331331, 0x02f01423, 0xb005f060, 0x0100d3f9, 0xbcfe0c00, + 0x7784a601, 0x2d842720, 0xb02f0123, 0x21c28c02, 0x125a01b0, 0x8241820c, 0x33353176, 0x010c2311, 0xa766fe9a, 0xf88e06a7, 0x5706bd2e, 0x35247983, + 0x3503d902, 0x06227982, 0x2d432700, 0x09e5460c, 0x01b2d024, 0x7e560307, 0x05b02205, 0x22c682d0, 0x82012303, 0xb5013190, 0x2b01ceb2, 0xcd2a01ab, + 0x33fea604, 0x29fdd702, 0x032a9982, 0x980341ff, 0x03000000, 0x83411c00, 0x22468405, 0x49593e10, 0x052b0d56, 0x03213521, 0x036bfc98, 0x82bfbf95, + 0x04312535, 0x060902d1, 0x24293583, 0x2f01b000, 0x01010fb2, 0x0546525d, 0x030fb429, 0x5d02031f, 0x830100b2, 0xb0192481, 0x82182f00, 0x23220880, + 0x09022101, 0x01f2feca, 0x01d10415, 0x0200002f, 0xecff5a00, 0x4e04fb03, 0x29001e00, 0x17b28800, 0xaf832b2a, 0x1b471720, 0x2f172509, 0x1c17b11b, + 0x4206db59, 0x504f0cf5, 0x17022208, 0x21348204, 0x06840bb2, 0x2f0bb025, 0x4f1017b0, 0x12220c55, 0x1f820f0b, 0x0c09402e, 0x2c121c12, 0x04123c12, + 0x1004b05d, 0x240cd654, 0x23b1100b, 0x08005f07, 0x21313033, 0x23062726, 0x34352622, 0x35333324, 0x22232634, 0x07155906, 0x14111729, 0x32251517, + 0x5f353736, 0x510805f0, 0x0c100303, 0xcea3a874, 0x95ef0101, 0x6a53605e, 0x7dcb76f3, 0x2903e2be, 0x7f48fdfd, 0x88878320, 0x79461f5d, 0xb9ad89ba, + 0x53655447, 0x589b5940, 0x18feadbf, 0xaf115792, 0x5ecc3b46, 0x00534656, 0x7c000200, 0x3204ecff, 0x0f000006, 0x66001b00, 0xdd5a13b2, 0x48132005, + 0x092005b5, 0x24055042, 0xb11b2f0c, 0x0704410c, 0x20079841, 0x0c8444b0, 0x030c0522, 0xb221e482, 0x2006840a, 0x119b4fb0, 0x2f0dfb5a, 0x22230214, + 0x11230727, 0x33361133, 0x27111232, 0x0723e383, 0x82331611, 0x042f08d8, 0xbec5e132, 0xf3dc0c6a, 0xe2c6b269, 0x9e767cf3, 0x729f4140, 0x1202027c, + 0x89d6fefc, 0xfd000675, 0xdafe7cd2, 0xb007f8fe, 0x42fe8ab0, 0x59acaa8d, 0x032b05f5, 0x004e04f5, 0xb24d001c, 0x451e1d00, 0x0f200855, 0x0f20b682, + 0x0820b687, 0x4206d748, 0xb2230b4f, 0x820f0803, 0x13b2232d, 0x0682080f, 0x100fb024, 0xcd4316b1, 0x31302209, 0x218e8225, 0xaa820e33, 0x35110027, + 0x32330034, 0x0a445016, 0x39024608, 0xe504785b, 0x75ca7604, 0x01f6fee3, 0xf3c1e408, 0x7704e506, 0x0180765c, 0x4e6aae7f, 0x0166af65, 0x19030126, + 0xe12901f7, 0xab785db7, 0xadb027ae, 0x00020000, 0x04ecff4f, 0x00000603, 0x0019000e, 0x1a17b266, 0x2776831b, 0x03b01017, 0x06b000d0, 0x20056b41, + 0x20a78203, 0x20b48703, 0x06ec4b0c, 0x230c064c, 0x0c0305b2, 0xb2213782, 0x2106840a, 0x36560cb0, 0x4803200d, 0x46080c2b, 0x34133130, 0x17323312, + 0x23113311, 0x22230627, 0x16143702, 0x11373233, 0x06222326, 0xacc3e84f, 0x0cdcf36a, 0xebbeb66d, 0x95757ff3, 0x76954345, 0xfa250280, 0x02782f01, + 0x7000fa2a, 0xf2320184, 0x0185b9a5, 0x83bb82ce, 0x825320bb, 0x040b2cbb, 0x0015004e, 0xb286001d, 0x821f1e16, 0x16b02483, 0x4908b010, 0x08200683, + 0x0820ab82, 0x1c43b887, 0x001a2208, 0x33278308, 0xbfb42f1a, 0x021acf1a, 0x1a5fb45d, 0x71021a6f, 0x2f1a1fb4, 0xef220683, 0x0682ff1a, 0x1a8cb226, + 0x0cb15d01, 0x20090243, 0x0d8252b0, 0x0812b228, 0x39121100, 0xa04108b0, 0x22052e0e, 0x34353500, 0x32333636, 0x21151112, 0x08d98316, 0x06061740, + 0x07062203, 0x26263521, 0xfee75902, 0x8be27de1, 0x3dfdf1dd, 0xa7779d0b, 0xd9418369, 0x117b64a4, 0x7208cf01, 0xf2230114, 0x8effa21e, 0xfefee6fe, + 0x879c8662, 0x036b617d, 0x127d8c9f, 0xdb487d7a, 0xd6022b05, 0x14001506, 0x07b25500, 0x4f421615, 0x20e18408, 0x0b0b4422, 0xb025ee8f, 0x10b01004, + 0x0c9752d0, 0x83d00121, 0x0eea51b6, 0x33352322, 0x3c08b782, 0x07173233, 0x15222326, 0x23153315, 0xa5a5d211, 0x4840b4c8, 0xae352806, 0x8603dcdc, + 0xc4b463b4, 0xb308be12, 0x7afcb460, 0x00020000, 0x0456fe52, 0x004e040c, 0x00240019, 0x2522b286, 0x24958226, 0xb01022b0, 0x0b5b4c0b, 0x06248e87, + 0x06b11b2f, 0x0b200c87, 0x0b210c82, 0x20b58612, 0x270c8217, 0x593e1017, 0x170305b2, 0x16514183, 0x0fb2220d, 0x21158311, 0x1c8515b2, 0x81581720, + 0x03b0230c, 0xf05cb110, 0x0559420c, 0x4f333721, 0x272705d7, 0x32331637, 0x42353536, 0x4c080e64, 0xb9c4ed52, 0xfedb0b6a, 0xe377e1f7, 0xa470733b, + 0xaf698c79, 0x85f2f1be, 0x45479376, 0x02857893, 0x2d01fc25, 0xe7fb6d81, 0x5063f6d5, 0x7f838592, 0x2e017549, 0x7ebba3f6, 0xbe7bdc01, 0x00010000, + 0x03000079, 0x000006f8, 0xb2430010, 0x06114a0a, 0x29431020, 0x82022005, 0x870220cb, 0x08645ce5, 0x240b9544, 0xb11002b0, 0x0cde4b0a, 0x20333626, + 0x11231113, 0x3e056f44, 0x01331123, 0x01b6776c, 0x61f3055a, 0xf348925e, 0x8ac403f3, 0x3dfd75fe, 0x5d70ba02, 0x82fbfc82, 0x00022e75, 0x0100007d, + 0x00d50590, 0x000d0003, 0x17b9673f, 0x505b8487, 0x10022808, 0xb0d00cb0, 0x67b12f0c, 0x4b510ac2, 0x09bc6706, 0xf3f37f3d, 0x8447fefe, 0x47844848, + 0x19013a04, 0x384a4a38, 0x00494937, 0xfeb5ff02, 0x8285014b, 0x000c2873, 0xb24b0016, 0x60181703, 0xed4c066f, 0x0c8e4507, 0x1b2f0427, 0x3e1204b1, + 0x0b675f59, 0x100cb02a, 0xb0d015b0, 0x0fb12f15, 0x2c0c1561, 0x23061411, 0x16352722, 0x11373233, 0x29888903, 0x439fa57a, 0x7930263e, 0x8d871503, + 0xa666fb29, 0x09c011af, 0x89a30484, 0x00012997, 0x0400007d, 0x00000636, 0x430d9551, 0xff430710, 0x0cf9670c, 0x20099551, 0x0c955108, 0x95510d85, + 0x012a0814, 0xf3f36cdc, 0x012b014c, 0x016efe24, 0x01e7febd, 0x9ffe6fd0, 0x8afc0006, 0xfe51015f, 0x0089fd3d, 0x008c0001, 0x067f0100, 0xc1520000, + 0x448d870d, 0x75410780, 0xf37f2206, 0x822a82f3, 0x007c2c35, 0x04790600, 0x001d004e, 0x5604b278, 0x76450a63, 0x2f07240c, 0x4307b11b, 0x0c870cdb, + 0x200c9965, 0x20268215, 0x07e95715, 0x28099751, 0x12111b03, 0x0705b239, 0x06214a15, 0x280b4b57, 0x3130d018, 0x33361701, 0x21038332, 0x8a421716, + 0x063e0806, 0x11231307, 0x07222326, 0x01112311, 0xc6720761, 0xd67650d9, 0xf302afb3, 0x6953685a, 0x05f30115, 0xf33d92be, 0x85713a04, 0xc1c6a6a6, + 0xc00239fd, 0x48596067, 0xc8021afd, 0xf0fc77bf, 0x27433a04, 0x24d78208, 0xb2540010, 0x0a394d0b, 0x0020d78c, 0x0020b082, 0x0e20ca87, 0x0e200c82, + 0xc24bbd87, 0x0e012208, 0x056d4203, 0x430bb121, 0xaf820c38, 0x2c0c3943, 0x78075e01, 0x065201c3, 0x936559f3, 0x2c9b8248, 0x7dfe917d, 0xbd0235fd, + 0xfc856367, 0x269282fe, 0xff4f0002, 0x823d04ec, 0x000f2891, 0xb245001a, 0x681c1b0c, 0xb02105df, 0x0bb34f18, 0x5d0fe846, 0x04200c01, 0x330e2662, + 0x36363413, 0x17003233, 0x06061417, 0x35002223, 0x32161417, 0x0806f35f, 0xe47e4f35, 0x1101db94, 0xe57b010b, 0xedfee596, 0x89f68af3, 0x8c77798d, + 0xff9f2702, 0xe9e6fe89, 0x8afca039, 0x09fe3101, 0xb9c0bda7, 0x00bdc0a4, 0xfe7c0002, 0x86300460, 0xb270229d, 0x489d8513, 0x002306f5, 0x43b05845, + 0x09240c63, 0x09b11b2f, 0x450c5c45, 0x004e074f, 0x32ff4808, 0x11231124, 0xff481733, 0x042e080f, 0xb2c0e430, 0x0ae0f36b, 0xe1c6b86b, 0x957881f2, + 0x74964241, 0xfb120283, 0xfd75d5fe, 0x6eda05ff, 0xfed9fe82, 0xbea206fa, 0x7e20fe7b, 0xc98200bb, 0xc9824f20, 0xc9820220, 0x19000e24, 0x53486d00, + 0x0879690e, 0x1249bc8c, 0x42c9870c, 0x5d4808bf, 0x0c8f410c, 0x21155a48, 0xc8823337, 0x080ef545, 0xc6e84f2a, 0xd80e6ab5, 0xc2aa6af3, 0x7483f3ea, + 0x8e464690, 0x26028574, 0x7f2a01fe, 0x0126fa6b, 0x2f0170fc, 0x7bbda6f6, 0xba76ec01, 0x21059343, 0xc182b402, 0x47000d26, 0x0f0e09b2, 0x460d6f47, + 0x0c870cc6, 0x1b2f0529, 0x3e1005b1, 0x580bb059, 0xb2230cb9, 0x82050b09, 0x3130223d, 0x064c4301, 0x3617333e, 0x02173233, 0xa73330b3, 0x06e8f33a, + 0x22349c58, 0x80085c03, 0x3a041cfd, 0x000e8d79, 0x4b247b82, 0xca03ecff, 0x26267b82, 0x09b26b00, 0xa5512827, 0x206e870d, 0x206e821c, 0x236e821c, + 0x091c02b2, 0xb0272182, 0x16b01002, 0x5b09b0d0, 0xb2230c26, 0x8210160d, 0x0cb42b1b, 0x020d1c0d, 0x101cb05d, 0x404324b1, 0x21b22309, 0x1c830224, + 0x13210325, 0x6b5d0221, 0x33210ac0, 0x0bbd6b32, 0xb5661620, 0x35262106, 0x0805cf62, 0x6bdb023c, 0xecb653f8, 0xf3efc2b6, 0x65505668, 0xa31e015e, + 0x85c4f24f, 0x05ec74d0, 0x64606378, 0x44412601, 0xa7582834, 0x99c0bc8c, 0x3e4a5d46, 0x573f3e38, 0xb592577a, 0x5661a860, 0xdd83495d, 0xecff082c, + 0x41057202, 0x54001400, 0xc94800b2, 0x8213200a, 0x471320d0, 0x1326103a, 0xd001b010, 0x028200b0, 0x01b02f22, 0x210c795f, 0x125a0db0, 0x05e6480c, + 0x4008c682, 0x23153311, 0x33161411, 0x06153732, 0x11112023, 0x11333523, 0xbfbfad01, 0x2b2a3f31, 0xe8fe4d53, 0x4105b2b2, 0xfdb4f9fe, 0x0a373ea4, + 0x350117bc, 0x01b46502, 0x00010007, 0x03ecff77, 0x003a04f7, 0x47978210, 0x002307d5, 0x45b05845, 0x0d200c78, 0x0d20a482, 0x5046a487, 0x820f200c, + 0x100f2719, 0x00b2593e, 0x8f410d02, 0x0de64705, 0x23062529, 0x11352622, 0x82141133, 0x3b068299, 0x6b0c0323, 0xf3b5b0c5, 0xf33eb1ab, 0xce7e6ae5, + 0xfdbd02c3, 0x037fce46, 0x00c6fb09, 0x16248d82, 0xda030000, 0xf7518d82, 0x0c724214, 0x220f034d, 0x510500b2, 0x133506f7, 0x01230133, 0xe5fa0133, + 0xd389fefb, 0x01fc86fe, 0xfb060334, 0x059b45c6, 0x00002124, 0x0a82cc05, 0x4314f551, 0xec420c8c, 0x15704d14, 0x830b0021, 0x05b22179, 0x0a200685, + 0x30220684, 0x87830131, 0x82030321, 0x1322088a, 0x33043313, 0xd9feedac, 0xc8e4e8c8, 0xafedd8fe, 0x4f01b7de, 0xc6fbeb02, 0x19fde702, 0x1dfd3a04, + 0xfb83e302, 0xfb821f20, 0x9b82e820, 0x870df351, 0x2f0a2487, 0x4e0ab11b, 0x304614fd, 0x0a002708, 0x39121104, 0x068506b2, 0x260ff351, 0x01012113, + 0x83030321, 0x01022e05, 0xfe0e01ce, 0xfe5601b5, 0xfed7d8f4, 0x3a0782f2, 0x020c01b6, 0xfd6401d6, 0x01dbfdeb, 0x028efe72, 0x00150225, 0xfe0c0001, + 0x82d6034b, 0x000f2491, 0x5a00b240, 0xcd4d0a63, 0x8205200c, 0x12052798, 0x00b2593e, 0xba4d0f05, 0x01b02405, 0x6105b0d0, 0x30220c75, 0x7e820131, + 0x23022f08, 0x17352722, 0x37373632, 0xf7012101, 0xfe0301dc, 0x35ed6352, 0x5d5c2e40, 0x84fe231b, 0x5c010601, 0x22fbde02, 0xbc12effe, 0x5d4f4303, + 0x81823504, 0x00005224, 0x8182c003, 0x420d0f52, 0x484e0f89, 0x280f520c, 0x40028032, 0x250292fc, 0x4f03e5fd, 0x029fc2c2, 0x009ac4d7, 0x382e7182, + 0x910298fe, 0x17003d06, 0x12b23700, 0xd1821918, 0x0cb00022, 0x2005e54a, 0x21e98200, 0xe9821800, 0x0c000622, 0xb0241782, 0x05b12f06, 0x2309284d, + 0x060512b2, 0x0805f144, 0x35032424, 0x32352334, 0x36363535, 0x07061737, 0x16071415, 0x17161515, 0x9ffe6102, 0x03c1c107, 0xad30b0b5, 0x0282ad06, + 0x6398fe37, 0xe1d56001, 0xb4d4e2b2, 0x388c32de, 0x5be1d8fa, 0xfad5e35c, 0x24858238, 0x01f2feae, 0x18156b55, 0x1123012b, 0xa7550133, 0x06f2fea7, + 0x20b383be, 0x20b3821b, 0x20b38275, 0x22b38218, 0x841a1905, 0x850b20b3, 0x821820b3, 0x831820b3, 0x181122b3, 0x2417820b, 0xb12f11b0, 0x22b38a12, + 0x84111205, 0x36172cb3, 0x37343537, 0x26353526, 0x82163727, 0x142d08ad, 0x15221533, 0x07061415, 0xb604b01b, 0x30b004b6, 0xc2c2b2b6, 0x39dbb5b3, + 0x56e7d0ff, 0xffcfea56, 0xe5338c39, 0xb2e1c8b9, 0xe5bbc5e1, 0x2c838333, 0x04830175, 0x002f03dc, 0xb2410017, 0x06374111, 0xb22f0f25, 0x820f1803, + 0x03b02460, 0x440fb02f, 0x03260db7, 0xd00bb010, 0x275a03b0, 0x100f2d0d, 0x30d017b0, 0x06140131, 0x022e2223, 0x08066c51, 0x1e32333f, 0x36323302, + 0xbedc0435, 0x9a7d4a8e, 0x4d432643, 0x4a94b6c1, 0x27439185, 0x12035443, 0x8938dfb0, 0xab546821, 0x22843bdb, 0x02005470, 0x94fe8600, 0x4d049901, + 0x0f000300, 0x07b23f00, 0x24e18310, 0xb01007b0, 0x06ed4800, 0x2c0ccc44, 0xb11b2f03, 0x593e1803, 0xb1100db0, 0x09a14b07, 0x25057a45, 0x33133130, + 0x8d842113, 0x35263508, 0x32333634, 0x18d1aa16, 0x0701fffe, 0x48424148, 0x48414248, 0xfefb9602, 0x4b383705, 0x4b37384b, 0x0100004b, 0x0bff6400, + 0x26050a04, 0x5f002000, 0x22211bb2, 0x430d996b, 0x4f530cca, 0x03b2220e, 0x22a7840a, 0x74b0100a, 0x112b0509, 0xd014b010, 0xb22f14b0, 0x820a1118, + 0x11b02246, 0x0d425b10, 0x36322525, 0x72063337, 0x02240560, 0x12343535, 0x08058072, 0x26231740, 0x03222326, 0x02161407, 0x0678594f, 0x92c504e4, + 0xccccb7c8, 0xb99ec8b7, 0x7607e404, 0x0110e65b, 0x5068ae7f, 0xea1ccd88, 0x1f0122ea, 0x01d51cdc, 0xe0e12220, 0x609cd81c, 0x48c8fe75, 0xc583adb0, + 0x00005e2e, 0xc3057c04, 0x68001f00, 0x21201ab2, 0x1224c588, 0x12b11b2f, 0x5e07e155, 0x1666085b, 0x08b0260a, 0x051eb2d0, 0x06c05f12, 0x290b2e68, + 0x1eb0d00c, 0xd00fb010, 0x1e8516b2, 0xd25a1220, 0x3130350c, 0x07141701, 0x35210721, 0x35363633, 0x33352327, 0x20363427, 0x08088f47, 0x1521174a, + 0x4007fd01, 0xfb01b802, 0x2b2752e7, 0x089ba107, 0xe89601fa, 0x595e69f5, 0x37010967, 0x87b05602, 0x09caca55, 0xc7b95b6f, 0xdaeacaf2, 0x82695fb8, + 0x00c7f268, 0x5d000200, 0x4f05e5ff, 0x1b00f104, 0x41002800, 0x2a2902b2, 0x2105a346, 0xed751fb0, 0x3e102d0b, 0xd010b059, 0xb02f10b0, 0x20b11002, + 0x24091d43, 0xb11010b0, 0x080e8926, 0x25313086, 0x27222306, 0x26372707, 0x27373435, 0x33361737, 0x17371732, 0x14151607, 0x01071707, 0x32161614, + 0x26343636, 0x06062226, 0xcb9f3d04, 0x8d819eca, 0x906d6487, 0xc09b8e8d, 0x8e919bc2, 0x8b626b94, 0x6e78fc8e, 0x6dbedcbe, 0xbedebd6d, 0x7e7f6b6d, + 0x9c899084, 0x93a5c8c5, 0x75739190, 0x9f979194, 0x8d9cc1ca, 0x787b0291, 0xce7675ce, 0x7575ccee, 0x010000cc, 0x00000b00, 0xb0053404, 0x71001600, + 0x181700b2, 0x4d15a958, 0x0b2109d8, 0x23218201, 0x0b0107b2, 0xca670682, 0x75052009, 0x07230ac1, 0x8a09b110, 0xd00d390e, 0xb01007b0, 0x05b0d00f, + 0xd011b010, 0xb01003b0, 0x01b0d013, 0xd015b010, 0x2205b557, 0x83211533, 0x058a7001, 0x21353b08, 0x21013335, 0x06012102, 0xabfe0d01, 0x01d1feea, + 0xfcd1fe2f, 0x3401ccfe, 0xfef8ccfe, 0x031101a9, 0xfd61024f, 0x978a9836, 0x2d01d3fe, 0x02988a97, 0x020000ca, 0xf2fe8800, 0xc3826d01, 0x07000327, + 0xb0001800, 0x059c4400, 0x1b2f0632, 0x3e2006b1, 0x0105b259, 0x31302b03, 0x11331113, 0x332e6582, 0xe5e5e588, 0x1b03f2fe, 0xc803e5fc, 0x3d82f602, + 0x26fe5a30, 0xc4058c04, 0x3d002f00, 0x20b28600, 0xda833f3e, 0xb0102025, 0x8300d030, 0x450024e1, 0x8220b058, 0x8320204a, 0x2039224a, 0x201d8307, + 0x0cb45d39, 0x3902b223, 0x82158313, 0x4a0e20f9, 0x0b210a0a, 0x2115830e, 0x328532b2, 0xb1103223, 0x221c8a2c, 0x852c321a, 0x27b12166, 0x2422158a, + 0x1582272c, 0x0131302f, 0x15160714, 0x22230414, 0x14373524, 0x056f6516, 0x022e272d, 0x26373435, 0x24343526, 0x76043233, 0x162d0a0a, 0x27262516, + 0x16141506, 0x3536021f, 0x08cb8234, 0xfe87ab81, 0xfef6eaf2, 0x889cf2e0, 0xbb868d79, 0xa95dbebc, 0x13014441, 0x0c01f0e6, 0x7b7891f3, 0x8301788b, + 0xcdfd5ac2, 0x636c4c51, 0x732eb395, 0xb8c70188, 0xadb96459, 0x01cfd9c6, 0x4f5f786e, 0x33375b4d, 0xb86d9a6e, 0x6488325a, 0xcce1ccaa, 0x525f806a, + 0x71685754, 0x1c156e99, 0x56517c28, 0x2f10352f, 0x00615175, 0x045d0002, 0x052303df, 0x000800cc, 0x00230011, 0xb22f07b0, 0x5d01070f, 0x560502b1, + 0xb02508e2, 0x07b0d00b, 0x05ff4210, 0x1331302b, 0x16323634, 0x26220614, 0x28088725, 0x4476435d, 0x01437644, 0x280785c9, 0x44325605, 0x44446444, + 0x3f068531, 0x00030000, 0x05ecff57, 0x00c405e2, 0x0028001a, 0xb2920036, 0x1138371f, 0x1fb03912, 0xd009b010, 0x33200583, 0x31066b43, 0xb11b2f33, + 0x593e1033, 0xb0d02db0, 0x02b22f2d, 0x26832d33, 0xb42f022c, 0x021f020f, 0x09b25d02, 0x1083332d, 0xb42f0926, 0x09100900, 0x0d221082, 0x10820209, + 0x6810b121, 0xb02409c1, 0x17b11002, 0xb2230e89, 0x8209021a, 0x2db02521, 0x081fb110, 0x3323d189, 0x8925b110, 0x3130270e, 0x20061401, 0xc0453526, + 0x07954105, 0xb4411520, 0x34252e05, 0x22232402, 0x12100204, 0x12242004, 0x058d6025, 0x9c601020, 0x047c0805, 0xc0feaf5e, 0xa39ebfbd, 0x585c9cad, + 0x5b68675c, 0xa6015a59, 0xa3eefe96, 0x9ceffe9f, 0x0111019b, 0x98130140, 0x01bbeffa, 0x0180014b, 0xfebbbb4a, 0xfec1c2b8, 0x5402bcb7, 0xb4d5a298, + 0xa5d5ae71, 0x88536095, 0x86767576, 0xa6856251, 0xa4ab1d01, 0xacfee0fe, 0xaaa7e0fe, 0xcaa72001, 0xc7c75a01, 0x6cfea6fe, 0xc8c9a6fe, 0x02005a01, + 0xb3028d00, 0xc4051103, 0x24001a00, 0x0db29200, 0x23055554, 0x1cb0100d, 0x2b063d41, 0xb11b2f14, 0x593e2014, 0x142503b2, 0x27065147, 0x00b0d000, + 0x0301b22f, 0xb2210f83, 0x2706840a, 0xb02f0ab0, 0x0db11014, 0x220a2341, 0x820d0a10, 0xb221082f, 0x5d0110cc, 0x100c1340, 0x102c101c, 0x104c103c, + 0x106c105c, 0x108c107c, 0xbab25d09, 0xb0710110, 0x0d486a03, 0xb1100a23, 0x0c396a1f, 0x23062730, 0x34352622, 0x35333336, 0x06222334, 0x0a822715, + 0x16327208, 0x17141115, 0x37363225, 0x06062335, 0x60021415, 0x767c4d11, 0x66ada883, 0xad494174, 0x9a8988af, 0x28a0fe1a, 0x4c6a1b54, 0x44c10256, + 0x6e697b52, 0x337f3379, 0x81680e30, 0xc4fe8491, 0x24825161, 0x3c018919, 0xff005831, 0x005700ff, 0x0385038a, 0x012600a9, 0x0000eb92, 0x01920107, + 0x00000052, 0x017f0001, 0x03c20376, 0x00050025, 0x04b0001b, 0x057d7b2f, 0x4e04b021, 0x30360c6c, 0x11230131, 0x03213521, 0x85fdc8c2, 0x76014303, + 0x00ab0401, 0x99420400, 0x820d2008, 0x0031313b, 0xb2a1003a, 0x113c3b0a, 0x0ab03912, 0xd012b010, 0x31200583, 0xa1420584, 0x092f5b07, 0xb0584527, + 0xb11b2f0a, 0x0519790a, 0x4212b121, 0x3582094e, 0x8918b121, 0x1db2230e, 0x427b030a, 0x1fb22305, 0x09830a03, 0xb42f1f2c, 0x1f101f00, 0x32b25d02, + 0x10831f1d, 0xb12f3223, 0x22308a1c, 0x84321c25, 0xb0102830, 0x1fb0d02c, 0x893ab110, 0x3130221b, 0x0c814213, 0x200e9d42, 0x31e48211, 0x14151632, + 0x14161607, 0x23151716, 0x26343526, 0x7b442723, 0x57232106, 0x210f8842, 0xac421105, 0x25fd380f, 0x99190197, 0x344178ac, 0x0d9b0a07, 0x8f9e4d42, + 0x5d475d45, 0x42d9028d, 0xcb200e8e, 0x080eae42, 0xaffe5b2a, 0x7d875203, 0x6f1d3f75, 0x101744a3, 0x434ca022, 0x46363e86, 0x0100013b, 0x0c059b00, + 0xaa054a03, 0x19000300, 0x050401b2, 0x0022da82, 0x4f7c02b0, 0x3020080c, 0x35210131, 0xfd4a0321, 0x05af0251, 0x02009e0c, 0xaf037f00, 0xc4058b02, + 0x13000900, 0x00b23b00, 0x42069d63, 0x896506e8, 0xd00a2608, 0xb12f0ab0, 0x09854205, 0x1000b022, 0x820b0c44, 0x32330857, 0x23061416, 0x36342622, + 0x35363213, 0x06222634, 0x87011614, 0x6c989a6a, 0x6b9d9b6d, 0x6a454535, 0xc4054948, 0x9b9bdc9e, 0x78fe9edc, 0x4c343547, 0x8248684c, 0x005f2c7f, + 0x04f30301, 0x000b00fc, 0x7748000f, 0x45220581, 0xb756b058, 0x10092408, 0x77d000b0, 0xb0231191, 0x46b1100d, 0x05220b3d, 0xed82060e, 0x050bb426, + 0x5d02051b, 0x830dae77, 0x9c023cf0, 0xa9fe5701, 0x019bfed8, 0x3201d865, 0x5103affc, 0xfec78303, 0xc784017c, 0x82fb7901, 0x01002ffc, 0x9b023c00, + 0xbb05b202, 0x5b001700, 0x334b08b2, 0x82002006, 0x0c237589, 0x1b2f0029, 0x3e1400b1, 0x4116b159, 0xb2230909, 0x82160002, 0x03b2237b, 0x724d000f, + 0x08b12105, 0x0c201c8a, 0xb2211584, 0x83068413, 0x01352198, 0x21069b53, 0xb5432315, 0x142b0805, 0x0221020f, 0x019cfdb2, 0x3436711d, 0xa9ba423a, + 0x6a9c8f87, 0x73018c62, 0x017d9b02, 0x2a436705, 0x74364235, 0x6b738099, 0x82715766, 0x023724a7, 0x82a90290, 0x002426a7, 0x251eb280, 0x21728226, + 0xa783b000, 0x9a820d20, 0x0f4a0d20, 0x82172007, 0x8217200c, 0x01b223a7, 0x21820d17, 0x01b07c37, 0x40b6182f, 0x60015001, 0xb2710301, 0x5d010190, + 0xb1100db0, 0x21a78a06, 0x28830109, 0x6e01b021, 0xb2230cb3, 0x82012312, 0x1bb2213e, 0xb0244584, 0x1eb11017, 0x210c8744, 0x865d3233, 0x43332009, + 0x1522050d, 0xcd680614, 0x3435080a, 0x0c012327, 0x3e368451, 0xa5ba4130, 0x87a38f82, 0x878fb195, 0x3c45baab, 0x5c863d3f, 0x23616d04, 0x63232735, + 0x7769797c, 0x6a8e2933, 0x26717f7e, 0x652a3735, 0x31e58201, 0x02d10470, 0x00000648, 0x00230003, 0xb22f02b0, 0xb282020f, 0xd0002708, 0xb42f00b0, + 0x001f000f, 0x02b05d02, 0xd003b010, 0x2f03b019, 0x01313018, 0x01230121, 0xfe150133, 0x0006c3eb, 0x3f82d1fe, 0x60fe922c, 0x3a041f04, 0x61001200, + 0x997a0db2, 0x45002206, 0x213f8258, 0xea55b11b, 0x0c565108, 0x1b2f1024, 0xf55310b1, 0x0c365907, 0x20087c44, 0x0cfc510d, 0x0d0bb223, 0x057e4807, + 0x16161122, 0x20065051, 0x08fc8227, 0x23112725, 0x02840111, 0x3ba86a59, 0x5c07dff3, 0xf24d7993, 0x84fd3a04, 0x0379828d, 0x56c6fb12, 0x3efe376b, + 0x7400da05, 0x032a0585, 0x00b00556, 0xb22b000a, 0xbb790b02, 0x69082009, 0x315c0bc7, 0x00012208, 0x3d6d8408, 0x22231121, 0x24343524, 0x02112133, + 0xfee65084, 0xe60a01f7, 0x08022101, 0xffd5d6fe, 0x578350fa, 0x45028e26, 0x5203a901, 0x17225782, 0x578608b2, 0xb02f022e, 0x2b0ab008, 0xdc1bd858, + 0x13313059, 0x3306e458, 0x8e262223, 0x4e4b864a, 0x024c4140, 0x4e4e3aca, 0x4a4a3b3a, 0x6d2e4183, 0xc90141fe, 0x0e000300, 0x09b23500, 0x7782100f, + 0x5708875d, 0x0623081e, 0x8707b010, 0x0db22351, 0x24820e07, 0x0d01b222, 0x29080683, 0x07253130, 0x06141516, 0x36322723, 0x27263435, 0x0b3e0137, + 0x079bac96, 0x50474742, 0x1b360320, 0x89766992, 0x232d2a2f, 0x6b838b05, 0x9b02802c, 0xae050202, 0x3a000600, 0x2d7301b2, 0x07cf420f, 0x77430020, + 0x04b22306, 0xf3680005, 0x03b12105, 0x2c0c8942, 0x35071123, 0x02023325, 0x6f01c9b9, 0x36518213, 0x7792303a, 0x00020000, 0x03b20277, 0x00c4052c, + 0x001a000c, 0x5609b242, 0x092205cf, 0x335ab010, 0x7a022007, 0x1a8206dd, 0xf0480220, 0x1ae24805, 0x13313025, 0x7f203634, 0x37200e4b, 0x08060243, + 0x01bf773f, 0x9dbcc036, 0x5dafbe9e, 0x015b4e50, 0x5d4e4f5d, 0xc3a06104, 0x9f48a6c2, 0x05a3c4c3, 0x616c6e62, 0x6d6e6150, 0xffff0066, 0x8a005d00, + 0xa9039903, 0x93012600, 0x07000009, 0x7e019301, 0x2e178300, 0x05000059, 0x00ab0583, 0xffc60127, 0x829802d9, 0x01942e07, 0x0108001b, 0x02200207, + 0x000000c5, 0x0dad7610, 0xff313025, 0x825000ff, 0x05cc2233, 0x232b83ae, 0x0800f000, 0xd0283b84, 0x07019b02, 0x1a03c501, 0x09203389, 0x0923e882, + 0x84593e20, 0x82672033, 0x05fc2233, 0x205f84bb, 0x2d3383a8, 0x3e032002, 0x07010000, 0x30001f02, 0x67879b02, 0x3507c74b, 0x02003130, 0x7ffe4200, + 0x4e04a503, 0x23001900, 0x10b26300, 0xcf732524, 0x1db02105, 0x20062a46, 0x20608221, 0x07554f21, 0x0c821020, 0x3e181028, 0x1021b059, 0xc94f1db1, + 0x03b2210f, 0x221b0c74, 0x82001016, 0x31302759, 0x07060601, 0x1a4a0607, 0x06332f06, 0x26222306, 0x37373435, 0x13373736, 0x0b830614, 0x32363608, + 0x02760216, 0x5a674935, 0x6a585962, 0xc2ef02f3, 0x5c9be2ce, 0xf7020a4e, 0x48488447, 0x95024784, 0x6a4f917c, 0x5d5e6a61, 0xd0b15364, 0xa3a5b8c9, + 0x3573485d, 0x09215001, 0xf6ff022e, 0x57070000, 0x0f00b005, 0x7b001200, 0x6b12af67, 0x5e6e0cb5, 0x6e112008, 0x1121055e, 0x0bad762f, 0x210e1d70, + 0x24850bb2, 0x6d2f0b21, 0xb0210bee, 0x0db54600, 0x24841220, 0x21313024, 0x01820321, 0x15210124, 0x03841321, 0x21014608, 0xfc570703, 0x0afe0f7e, + 0x03defeb8, 0xfde00343, 0x2402117a, 0x0214e4fd, 0x01edfa97, 0x54011b79, 0xb005acfe, 0xc568fec5, 0x670136fe, 0x00008802, 0x004d0001, 0x04ec03d6, + 0x000b0086, 0x03b00038, 0x0c09b22f, 0x05d04203, 0x090ab222, 0xb2230983, 0x82090304, 0x01b22310, 0x0682040a, 0x1003b029, 0xb2d005b0, 0x840a0407, + 0xb0103e24, 0x3130d00b, 0x37010113, 0x01170101, 0x01010701, 0xfe3c014d, 0x3b0194c4, 0xfe943c01, 0x2a0484c4, 0x6c01c5fe, 0x42014201, 0x84befe96, + 0xbefe3b04, 0xfe410196, 0x030000bf, 0xa1ff6900, 0xee052205, 0x20001700, 0x68002900, 0x2f6410b2, 0x10102505, 0xb0d01db0, 0x26200582, 0x68062342, + 0xb22214a2, 0x9183101a, 0x8423b221, 0x23b02406, 0x831bb010, 0x9c411834, 0x1ab02a0b, 0xd024b010, 0xb11004b0, 0x0c7d5b26, 0x0402142a, 0x07272223, + 0x11263723, 0x0805cf72, 0x33371741, 0x05131607, 0x26011714, 0x07022223, 0x01273405, 0x12323316, 0x94220535, 0xa4b4edfe, 0x91a95b84, 0x140196c3, + 0x578fc5b2, 0x019d93a7, 0x014744fc, 0xa48757f6, 0xbf0202b9, 0x4e17fe2c, 0x6cb5a969, 0x240805d0, 0xc3ee964b, 0xd5436701, 0x65af4401, 0xfec1f38f, + 0x80cf4bc3, 0xfe553a03, 0xa608ebff, 0x36dcfc72, 0x00f60001, 0x05f17200, 0xb0057e2d, 0x14000c00, 0x02b25900, 0x72111615, 0x0f2005f1, 0x200f3e49, + 0x0ac34a00, 0x0a01b223, 0x05fd6500, 0x850eb221, 0x2f0e2109, 0x200ca55e, 0x0e027301, 0x3311012d, 0x14150432, 0x11232304, 0x82131123, 0x34363e0c, + 0x87012726, 0x1201f4f1, 0xf2f3eefe, 0x7df6f3f3, 0x057a8c91, 0xeee8feb0, 0xfeefc7c8, 0x370982d4, 0x821afe25, 0x000284de, 0x88000100, 0x9b04ecff, + 0x2c001506, 0x23b25d00, 0x0a9f4518, 0x1b2f0525, 0x602205b1, 0xb25d06ff, 0x0872460c, 0x15050e22, 0x2105ea7b, 0x76411cb1, 0x22b22309, 0x666c0515, + 0x2ab12105, 0x30241589, 0x11232131, 0x2406cf48, 0x1415020e, 0x2603821e, 0x26222306, 0x4f163727, 0x2e230590, 0x48343502, 0x5b0805f8, 0xf27a0107, + 0xd7bbcee5, 0x4116451b, 0xc6d951b2, 0x3126ab50, 0x61367f2d, 0x51ae465a, 0xb8505c7e, 0xd6510404, 0x3ea9bbee, 0x27417162, 0x8994542c, 0x27b9ab4b, + 0x251cc319, 0x5b314356, 0x58508888, 0x61514dc9, 0x030000f7, 0xecff4800, 0x50048406, 0x34002900, 0xd0003c00, 0x3e3d02b2, 0x26067f41, 0x02b0d02d, + 0x4138b010, 0xab660685, 0x20f6840c, 0x27f68310, 0x2f00b0d0, 0x17050cb2, 0x0c283383, 0x0c8fb22f, 0x17b05d01, 0x820cbb5a, 0x1bb0290e, 0x2f1bb0d0, + 0x1b0038b2, 0x382c2683, 0x381fb42f, 0x7102382f, 0xff38efb4, 0x5f220683, 0x06836f38, 0xcf38bf2a, 0xb25d0238, 0x5d01388c, 0x230cb352, 0x23b11000, + 0x22092341, 0x411005b0, 0xb0240b32, 0x2fb1100c, 0x2409d152, 0xb1101bb0, 0x222c8935, 0x78053130, 0x3522061c, 0xee663634, 0x82272008, 0x1732310b, + 0x12321736, 0x16211515, 0x37323316, 0x06061737, 0x0809f44d, 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, + 0x7c07b268, 0x072305eb, 0x4128b010, 0x19240679, 0x19b11b2f, 0x59076342, 0x0f2c081a, 0x12111907, 0x2f0fb039, 0x070f11b2, 0x19200983, 0x210cd05e, + 0x50630fb0, 0x07b0240c, 0x4328b110, 0x12290cf5, 0x02141511, 0x26222306, 0x05e46426, 0x27261732, 0x26372707, 0x17163727, 0x27031737, 0x22232626, + 0x08073746, 0xfe420357, 0x8a8ce57e, 0xce717ee2, 0x31719284, 0xac4ecc7e, 0xee4ba27e, 0x8f4eb4b1, 0x4e7b2001, 0x6e8d8b7e, 0x1705896f, 0x6ffef7fe, + 0xf9fea652, 0x88e27e92, 0x5b7de795, 0x6d877aa9, 0xc32a5272, 0x6d788732, 0x301219fd, 0x7e95a838, 0x00adc8a8, 0x00430003, 0x04370493, 0x260982cc, + 0x0019000d, 0x6604b257, 0x042505ab, 0xd000b010, 0x200582b0, 0x7bf98211, 0x03230eac, 0x4909b010, 0xb1210728, 0x0b0c4704, 0x11b01022, 0x17201888, + 0x230c9162, 0x01213521, 0x20084f4d, 0x06574303, 0x042df283, 0x030cfc37, 0x4409fef4, 0x43444a4a, 0x2000824a, 0x34098543, 0x01d44602, 0x4b724cb2, + 0xfc4c724b, 0x4c4c3a4a, 0x4a4a393a, 0x32a58200, 0x0477ff4f, 0x00bb043d, 0x001d0015, 0xb2680025, 0x49272604, 0xb021053f, 0x20af841b, 0x13756023, + 0x2208475c, 0x820f0418, 0x20b2212d, 0xb0240684, 0x19b01020, 0xfb563483, 0x18b0270b, 0xd021b010, 0xe8420fb0, 0x3130210c, 0x27059260, 0x07333717, + 0x06141116, 0x2725b882, 0x26372307, 0x05974513, 0x96450620, 0x36560806, 0x94e47e4f, 0x9147586a, 0xe57bc466, 0x485a5d96, 0xf3ce6691, 0x2f2b0140, + 0x028c7739, 0xd8fe3a09, 0x897b332b, 0xff9f2702, 0xd08f2289, 0xa0c0fe99, 0x931e8afc, 0x360196cf, 0x6102629c, 0x94a7bd16, 0x11a7fd5d, 0x020000c0, + 0x60fe8200, 0x00063704, 0x1a000f00, 0xb5606600, 0x13ab690e, 0x1b2f0624, 0xab6006b1, 0x10ab6947, 0xe337042e, 0xf36bb2c2, 0xc5b06af3, 0x7683f3e3, + 0x3107aa60, 0x75d1fef7, 0xa007fffd, 0xfe77d7fd, 0x05fafeda, 0xab60baa6, 0xecff2309, 0xbf82b204, 0x21001629, 0x1fb28f00, 0x53112322, 0x102405b3, + 0x13b000d0, 0x84126b6a, 0x451020bf, 0x022006bb, 0x0220cc82, 0xb2260c82, 0x5d01132f, 0x04830fb2, 0x13021622, 0x16234183, 0x4400b12f, 0xb2230960, + 0x82060c04, 0x0eb22115, 0xb02c0684, 0x16b0d00f, 0xd011b010, 0xb11006b0, 0x0a684218, 0x100cb022, 0x240b836b, 0x23013130, 0x05226911, 0x1234112e, + 0x35173233, 0x35333523, 0x01331533, 0x22093069, 0x69afb204, 0xe82b052d, 0xfb6aacc3, 0xfcaff3fb, 0x69757f90, 0x04330536, 0x7038fbc8, 0x01320184, + 0x2f01fa07, 0x8eaaf278, 0x699efc8e, 0x1f2c0a3b, 0x9d050000, 0x1300b005, 0x6d001700, 0x20057f49, 0x9244180f, 0x8208200b, 0x8308200c, 0x081422da, + 0x25ba820f, 0xb22f14b0, 0x09841410, 0xb02f1029, 0x10b0d000, 0x8917b110, 0x03b02de0, 0x1008b0d0, 0xb0d005b0, 0x07b11014, 0x24093244, 0xb01017b0, + 0x282c830a, 0xb0d00db0, 0x12b0100f, 0xd24318d0, 0x82112009, 0x333521dd, 0x08051378, 0x35210136, 0x7f1e0521, 0x75fdfc7f, 0xfc7c7cfc, 0xfcfc8b02, + 0xfd8b0279, 0xa2ae0475, 0x8702f4fb, 0x0c0479fd, 0xfe0201a2, 0xfd0201fe, 0x0100baa2, 0x00008f00, 0x3a048201, 0x650e6965, 0xbb820c1f, 0x21313029, + 0x01331123, 0x82f3f382, 0x2435822a, 0x0400008e, 0x05f55e6b, 0x0424f185, 0x04b11b2f, 0x5f14ee5e, 0x54580cdc, 0x73062008, 0x062d05be, 0x061fb42f, + 0x7102062f, 0x01068fb2, 0x6b43185d, 0x010a220c, 0x05424b06, 0xda82dc82, 0x21013323, 0x3c028201, 0xf2f26fef, 0x01500155, 0x0161fe2c, 0x01cbfeb9, + 0x0454feac, 0x0150fe3a, 0xfdf3fdb0, 0x21ca82d3, 0x99822200, 0xb0053626, 0x5d000d00, 0x12c24d18, 0x21077342, 0x3f4201b2, 0x2f012905, 0xb0d000b0, + 0x02b11001, 0x200d8141, 0x0c244f06, 0x03b03b08, 0xd008b010, 0xb0d009b0, 0x0bb01000, 0xd00ab0d0, 0x37013130, 0x21110715, 0x07112115, 0x33113735, + 0xeaeaa101, 0x6efc9502, 0x03fd8282, 0x47934767, 0x02caf6fd, 0x27932787, 0x93839602, 0x0000212a, 0x00062e02, 0x4b000b00, 0x0a249385, 0x0ab11b2f, + 0x20075246, 0xcf451804, 0x05c74a08, 0xd0229398, 0x818407b0, 0x82d00921, 0x2081868d, 0x087f8623, 0x94949a27, 0xf38686f3, 0x92357903, 0x0219fd35, + 0x2f922f90, 0x0000de02, 0xfe900001, 0x0509054b, 0x001300b0, 0x1406b268, 0x15d57915, 0x4411d24a, 0xa46c0757, 0x08364f0c, 0x8b5f0420, 0x0db2230c, + 0x57820c00, 0x0e12b222, 0x6806f44c, 0x3725058a, 0x35323316, 0x060c7835, 0x09052408, 0x3c46a9be, 0x7b3a280e, 0xfcfc81fd, 0xb0057f02, 0xc6b718fa, + 0xb80cc711, 0xfb150431, 0xfbb005eb, 0x831404ec, 0xfe7e2eaf, 0x0406044b, 0x001a004e, 0x1b15b263, 0x66af881c, 0x0a2419eb, 0x0ab11b2f, 0x4d18af87, + 0x01220850, 0x97550318, 0x0bae6f05, 0x1003b022, 0x0bb24518, 0x2106ae67, 0xb08a1716, 0x08083e6a, 0x0d5c013d, 0xb5b0c473, 0x45a6bb01, 0x3b280e3a, + 0x91695d7c, 0x3a04f34b, 0xd2d6aa96, 0xc2b41bfd, 0xb00cc611, 0x7078d902, 0x04e0fc67, 0x0002003a, 0x07ecff64, 0x00c4052d, 0x00230017, 0x4e01b296, + 0x01230559, 0x461ab010, 0xd578069b, 0x820e200c, 0x7c0e20b2, 0xda5110c6, 0x3e102408, 0x490eb059, 0xb2230cc4, 0x830e0012, 0x2f1221ce, 0xb021bf8b, + 0x0c0f6e00, 0x1820dd83, 0x200a3144, 0x0ce26b0c, 0x21313023, 0x05d07721, 0x12341126, 0x17323324, 0x0808f67d, 0x37320563, 0x22232611, 0x14110706, + 0xfc2d0716, 0xa779a79d, 0x0294f7fe, 0xa80b0191, 0x5c03a77b, 0x56024cfd, 0xbb02aafd, 0x68637dfb, 0xafa15b72, 0x9314b201, 0x01aa0d01, 0x1201ac3a, + 0xfecc1496, 0x40fec86e, 0x38040d1c, 0xfebccf0e, 0x00d1c1ca, 0xff5b0003, 0x04f206ec, 0x001e004f, 0x0032002a, 0x3319b29e, 0x05214934, 0xd024b027, + 0xb01019b0, 0x0613412e, 0x6a0cd341, 0x17240c62, 0x17b11b2f, 0x69071b46, 0xb2230797, 0x82170805, 0x2fb22347, 0x06820817, 0x2f2fb02c, 0x2f2f1fb4, + 0xb271022f, 0x616e2f8c, 0x0d014b0e, 0x8419b221, 0x22b02437, 0x4903b0d0, 0xb02b0c86, 0x3130d02b, 0x33003413, 0x4a361732, 0x36270a8e, 0x06061737, + 0x82272223, 0x11002303, 0xfa4b1417, 0x23262405, 0x4a250622, 0x67080697, 0xe00f015b, 0xb74186f9, 0xfdeed66d, 0x75910b56, 0x4f478f59, 0xf778cd47, + 0xe3f6868c, 0x86f2f2fe, 0x87867779, 0x03887578, 0x147855e1, 0x0271b501, 0x2f01f827, 0x015e54b1, 0x88ecfdfe, 0x322a9e8b, 0xae413f9e, 0x012d01ae, + 0xbaaa0902, 0xbea6c0b9, 0x7989baba, 0x007a6f19, 0x008b0001, 0x06950200, 0x000c0015, 0x0d03b233, 0x24094376, 0xb11b2f04, 0x0ffe6a04, 0x8643b020, + 0x3130250d, 0x36341133, 0x3307776e, 0xb0c28b11, 0x2a19593f, 0x9c04a332, 0xb915c3b6, 0x68fbba0b, 0x00225c82, 0x7d7bff51, 0x00162605, 0xb25e001e, + 0x057d7b00, 0x90411720, 0x0cb74606, 0x2708414d, 0x11000f05, 0x05b03912, 0x42107161, 0x05200e7e, 0x310c8347, 0x20053130, 0x21351100, 0x22232626, + 0x37270707, 0x0e823336, 0x14155208, 0x32270402, 0x15213736, 0xb8021614, 0xbdfedcfe, 0xdf05d003, 0x3497a7cc, 0xdab02131, 0x6b013a01, 0xa9e5fea2, + 0xfd12be96, 0x0114ba2f, 0x89490160, 0x1334f0e0, 0xfe480fc6, 0x6bb7fe8b, 0xafc3fec3, 0x1fbddad4, 0x0000bfb9, 0xfee4ff01, 0x06d3024b, 0x22c78215, + 0x1814b274, 0x240a2340, 0xb11b2f15, 0x072b4115, 0x0c821020, 0x97461020, 0x821d2007, 0x651d200c, 0x12240cf3, 0x1db0593e, 0x820dc678, 0x0a1d6bc5, + 0x1000b02a, 0xb0d00eb0, 0x15b0d00f, 0x0121dd8e, 0x07354423, 0x32331625, 0x6f231135, 0x4c080bf5, 0x02331507, 0xa4b5c984, 0x070f3648, 0xa5781244, + 0x3db1c2a5, 0x3b26195b, 0x03c9019d, 0xb035fc86, 0x03bf11c0, 0xca03ae0a, 0xc3b662b4, 0xad0abc15, 0x02000067, 0xecff5800, 0x2e06aa05, 0x26001800, + 0x04b25e00, 0x12112827, 0x1004b039, 0x07dd4ab0, 0x1b570d20, 0x0834460b, 0x040d0f22, 0x2105874c, 0xf65916b1, 0x0db02209, 0x0bed4e10, 0xc24d4582, + 0x3130210b, 0x2b0c2d7d, 0x36173233, 0x14333536, 0x17160706, 0x240ee27b, 0xedfe9410, 0x08de7bb4, 0x4fa2ff30, 0x7c79bb4c, 0xb8fd0457, 0x02b9a4a8, + 0x6850a8b9, 0x7dad2007, 0xa82f0739, 0xa482830d, 0xdfa723d1, 0xfefef612, 0x7b54ebff, 0x4f2a08e3, 0xbb04ecff, 0x1700a804, 0xdb822200, 0x24231422, + 0x1420b383, 0x48098975, 0x14200c3e, 0x1427e882, 0xb2593e10, 0x65140406, 0x0d200615, 0x1420db8a, 0x830c8841, 0x0cbb7cdb, 0x8806b54b, 0x141522d2, + 0x07c84306, 0x3536323c, 0x22232634, 0xe47d4f06, 0x358ae194, 0x6758a730, 0xe77b023f, 0xecfee395, 0x546c8af2, 0xa12b0807, 0x139589fd, 0xb386726a, + 0x1d9e7d25, 0x018afca0, 0x0901012e, 0xb9c0bda7, 0x00bdbda7, 0xff7d0001, 0x063d06ec, 0x00180001, 0x650cb256, 0x00240619, 0x18b05845, 0x1820b482, + 0x7d07d245, 0x7c6b0c74, 0x0c012208, 0x05325118, 0x8a08b121, 0x460c20ce, 0x15200f92, 0xe67aba86, 0x5e6d2511, 0xfec5bbb5, 0x280beb7a, 0xa1820adc, + 0xfd09d6e4, 0x10f27aa5, 0x7700012f, 0x2805ecff, 0x19009304, 0x07b26300, 0xd34f181a, 0x690d2009, 0x08200b7a, 0x18069c4a, 0x290c7b42, 0xb0100db0, + 0x15b2d013, 0xaf830813, 0xb12f1523, 0x22af8903, 0x841506b2, 0x46082015, 0x30250c9f, 0x06140131, 0x05634b07, 0x820a9c69, 0x373727ca, 0xa28f2805, + 0xa36906e5, 0x41482a08, 0x93040205, 0xfc0ba5b2, 0x0bad69cf, 0x42078832, 0x01004c4c, 0x4bfeb5ff, 0x3a049301, 0x30000c00, 0x6d0c0145, 0x04200cb3, + 0x82121771, 0x11360882, 0x22230606, 0x33163727, 0x01113532, 0xa7b80193, 0x270f3846, 0x3a047c3a, 0xc2b285fb, 0xc00dbf11, 0x02006c04, 0xecff5900, + 0x4f04f803, 0x1e001600, 0x08b26100, 0xe483201f, 0xb0100822, 0x6f070445, 0x1f410c48, 0x0cb22207, 0x22f68400, 0x74b02f0c, 0xb0210dbe, 0x0d834708, + 0xb1100c23, 0x094b4a1a, 0x322a9482, 0x14151500, 0x22270606, 0x0c453502, 0x07062505, 0x13363627, 0x08070445, 0x01e40033, 0x86da7b14, 0xaa02efd5, + 0x56778f0b, 0x464f4e8b, 0x785691d2, 0x714bfe13, 0xd4fe4f04, 0xfb9a1ff6, 0x0101018d, 0xa18888ed, 0x3e9e3527, 0x8e60fc43, 0x052b4674, 0xe0049435, + 0x01064303, 0x45000800, 0x2f04b000, 0x01040fb2, 0x8350b25d, 0x82702004, 0xb0210804, 0x02b0d002, 0xd001b02f, 0x2f01b019, 0x1004b018, 0xb0d007b0, + 0x0fb42f07, 0x02071f07, 0x0703b25d, 0x23f68304, 0x05b01001, 0x05222182, 0xa982182f, 0x2723153d, 0x01352307, 0xc3430333, 0x01c19596, 0xeb048f0f, + 0x0d9c9c0b, 0x00001401, 0x82720001, 0x8434206d, 0x8825206d, 0x053a5f6d, 0x010fb424, 0x5282011f, 0x01040022, 0x08245283, 0x2f08b0d0, 0x373d4d82, + 0x23011533, 0x01333501, 0xfed092d2, 0xebfe96e9, 0x9b6605ce, 0x01e9fe0a, 0xff000918, 0x08e55dff, 0x70000623, 0x2d5f8300, 0x02cc0475, 0x00e605fb, + 0x0030000b, 0xcd8203b0, 0x5d010327, 0xb0d006b0, 0x27b28206, 0x02061f06, 0x1003b05d, 0x270b935c, 0xb01006b0, 0x0bb0d00b, 0x30086a83, 0x26200614, + 0x16143335, 0x02353632, 0xdafeb0fb, 0x844bb6b0, 0x7ee6054a, 0x427e9c9c, 0x00424949, 0x04810001, 0x058701df, 0x000900d5, 0x0a03b21e, 0x20a7820b, + 0x22a58200, 0x62080fb2, 0x545a0dba, 0x26222509, 0x447e4481, 0x05320282, 0x47473559, 0x46463435, 0x78000200, 0x33028d04, 0x45822a06, 0x2c001425, + 0x8205b000, 0x820520a5, 0xd01327a5, 0xb12f13b0, 0x2f620a00, 0x10052309, 0x0e890db1, 0x200b565e, 0x074e4807, 0x06222208, 0x805d5601, 0x7d61607d, + 0x2e42117f, 0x623f412f, 0x7b2a063f, 0xaa7878aa, 0x412fd07b, 0x432e3040, 0x2cb78243, 0x0152fe29, 0x003c00a1, 0xb223000f, 0x0a2f6b0f, 0xf34a0a20, + 0x65b12006, 0x302a0a85, 0x06062131, 0x32331415, 0x67581737, 0x8c013806, 0x2c474a57, 0x5c49152e, 0x38f4745f, 0x1744315e, 0x5b6e2c8e, 0x82006cb5, + 0x047a3e59, 0x055703db, 0x001500f5, 0x03b00042, 0xd008b02f, 0xb62f08b0, 0x081f080f, 0x5d03082f, 0x054c69b0, 0x17820b20, 0x0fb11022, 0x230ada65, + 0x12b11003, 0x0f200e8a, 0x6906d465, 0x3c08095e, 0x33363427, 0x32331632, 0x57033536, 0x3927607f, 0x261a2b69, 0x5f7f9535, 0x2634a139, 0x6ee90536, + 0x0c3c1192, 0x6e082e39, 0x2f395a96, 0x00020000, 0x03d10449, 0x00ff0556, 0x00070003, 0x20255d40, 0x1000b02b, 0xb0d005b0, 0x02b02f05, 0x051d4210, + 0x2208a983, 0xb019d007, 0x30182f07, 0x01330131, 0x03330323, 0xee680223, 0x90c5f6fe, 0x05b9dee9, 0x01d2feff, 0x82d2fe2e, 0xfe823369, 0xffec016a, + 0x000b00be, 0x003f0017, 0xb02f18b0, 0xf982d003, 0x000f403a, 0x20031003, 0x40033003, 0x60035003, 0xb05d0703, 0x0fb0d00f, 0x0909b12f, 0x8209d041, + 0x891520f6, 0x3130220e, 0x0acd5217, 0x0808ad65, 0x0622232d, 0x494e6982, 0x4e496a6a, 0x22306569, 0x212d2d21, 0x49ee3022, 0x4a4b6163, 0x2148605e, + 0x24222d2e, 0x00003030, 0x048efc01, 0x5e66fed1, 0xd97c0717, 0x0e581807, 0x10012107, 0x2005ba43, 0x05c464b4, 0x2105d87c, 0xd87c66fe, 0xfd012609, + 0xffd1045e, 0x5e3f8736, 0x01240757, 0x2f01b0d0, 0x5e068b43, 0xfe221057, 0x575e0121, 0xff230807, 0x0473fcff, 0x0550ffdb, 0x000700f5, 0x00f9fba5, + 0xfd010000, 0xfee6043e, 0x007f0699, 0x002b000e, 0x412f00b0, 0xb22d055a, 0x5d01061f, 0x060001b2, 0xb1391211, 0x0a024607, 0x4d010d21, 0x330806e8, + 0x35363627, 0x32372334, 0x06141516, 0x51fd1507, 0x96414907, 0x4eaba907, 0x92e60448, 0x48231c05, 0x3c58687b, 0x00450a4e, 0x0cfc0200, 0x34ffe404, + 0x0300ee05, 0x37217582, 0x20aa8200, 0x41f08ab0, 0x062d05d2, 0x2f06b0d0, 0x1f060fb6, 0x03062f06, 0x059d415d, 0x1000b02a, 0x19d004b0, 0x182f04b0, + 0x37050941, 0x33032301, 0xfed007fe, 0x020601d5, 0xfaf5c322, 0x0a01e404, 0x0a01f6fe, 0x1c30c583, 0x2ffe94fe, 0x08008bff, 0xb0001200, 0x06b12f02, + 0x22099466, 0x66053130, 0xfd21077f, 0x055a5b1c, 0x4735f130, 0x46466a47, 0xc6000100, 0xe201e904, 0x9b824106, 0x37831720, 0xb0229982, 0x43412f00, + 0x03332b0d, 0xdf030123, 0x4106908c, 0x2782a8fe, 0xdf046726, 0xaf06ba03, 0x0c270982, 0x3c001500, 0x8214b000, 0x0670452f, 0x21148641, 0xae4414b0, + 0x22948b06, 0x82d00fb0, 0x885a82d4, 0x0824679b, 0xe5ee012e, 0xa8fe9282, 0x43437644, 0x56024476, 0x24052a67, 0xd6feaf06, 0x0526672f, 0x22072d67, + 0x5f00ffff, 0x02330629, 0x00780006, 0x00010000, 0x0400009b, 0x00b00537, 0x512c0005, 0x49180a9b, 0x04201052, 0x180cf64a, 0x2a07ba43, 0x60fd3704, + 0x049c03fc, 0x821cfbe4, 0x02002742, 0x00001900, 0x0a82a005, 0x06000324, 0x48183000, 0x102217d9, 0x5118593e, 0xb2220bcb, 0x20420206, 0x01333a06, + 0x01212521, 0x02f36f02, 0x0179fa3e, 0xfee00255, 0xfab00598, 0xbb03ca50, 0x05274e00, 0x05130523, 0x260982c4, 0x00220014, 0x4a08b279, 0x08250517, + 0xd001b010, 0x6b0582b0, 0x9e500753, 0x0891470c, 0x10080235, 0x7c391211, 0x182f02b0, 0x700260b4, 0xb45d0202, 0x82400230, 0x00b22406, 0x52710102, + 0xb0210b4b, 0x0d9b5710, 0x1d540820, 0x3521230f, 0x48180521, 0x3c081d40, 0x40fea303, 0x7001c001, 0xb3edfe94, 0x99eefeb0, 0x14019603, 0x13016401, + 0xb7fc0196, 0x02b9a4a9, 0xb5a9a6bb, 0x89c27902, 0xadbdfed6, 0xcd3c01aa, 0x4401d55d, 0xbffeabaf, 0x01ef05d5, 0x48481805, 0x01002b0a, 0x00002000, + 0xb0051205, 0x42180600, 0x032407f3, 0x03b11b2f, 0x7a079f41, 0x49180866, 0x1026088a, 0x00b2593e, 0x44180103, 0x20080882, 0x02210133, 0xfe97fe98, + 0xf5fe01f1, 0xf0feff01, 0xbcfb4404, 0x50fab005, 0x00030000, 0x0400006c, 0x265b822e, 0x00070003, 0x414e000b, 0x082005af, 0x530b8a61, 0xe170078e, + 0x0805220c, 0x05e14d02, 0x0c325c18, 0x73100821, 0x37210d79, 0x05da5d21, 0x07820320, 0xc2036c36, 0x02643efc, 0x570afdf6, 0x67fc9903, 0x4d03caca, + 0xcc2903c6, 0x21067f42, 0x83821405, 0x39000722, 0x21278d5e, 0x7d6706b0, 0x2321240e, 0x82112111, 0x14052703, 0xfc7ffdfc, 0x8f427904, 0x00012207, + 0x20e18247, 0x225d824d, 0x923e000c, 0x584218dd, 0x51012008, 0x05220a07, 0xca8db0d0, 0x6c07b021, 0x15250588, 0x01013521, 0x08cd8235, 0x1c030129, + 0xbc0275fe, 0xc901fafb, 0xe20337fe, 0x88016bfd, 0xfafdd002, 0x420297ca, 0xcc983f02, 0x0000fffd, 0x004a0003, 0x82ae0500, 0x00142879, 0x0022001b, + 0x4209b26e, 0x092505ad, 0xd018b010, 0x420582b0, 0x132407ad, 0x13b11b2f, 0x4207ce41, 0x122008ad, 0x26054c4b, 0x00b02f12, 0x8520b2d0, 0x2f20210c, + 0x230ce155, 0x20b0d00a, 0xca6e4c84, 0x1fb0210d, 0x6c08ad83, 0x10160416, 0x15070406, 0x24263523, 0x36343526, 0x33353724, 0x17161401, 0x05060611, + 0x11272634, 0x7c033636, 0x8b0401a3, 0xa4fefe8c, 0xfefea8fd, 0x02018e8b, 0xc6fdfda5, 0xa29b9da0, 0x99a17403, 0xfe049e9c, 0xfefb8f04, 0x058df7c2, + 0x8c04a9a9, 0xfea09ff7, 0xfdb2048d, 0x06b09c1f, 0xb605ae02, 0x06b59e9f, 0xb10753fd, 0x00010000, 0x20e98244, 0x24e9825c, 0xb25d0017, 0x0a456600, + 0x200cd64c, 0x20e68216, 0x9c451816, 0x550c870c, 0x152208e4, 0x404c160b, 0x21f38205, 0x511815b0, 0x09200d22, 0x362ed483, 0x33113536, 0x07000611, + 0x26112311, 0x0b822700, 0xd1821620, 0x03333108, 0xfd90834c, 0xf6e9fe03, 0xe8fef0fc, 0x8f01fc04, 0x4302fc80, 0x01a7be17, 0xf606fef1, 0xfe19cffe, + 0x1775018a, 0x01f53001, 0x9d0bfeff, 0x6c0318c2, 0x6b2eb382, 0xdd040000, 0x2500c305, 0x07b25e00, 0x77822726, 0x20051e42, 0x20a6821a, 0x2099871a, + 0x200c820f, 0x0756520f, 0x0c822420, 0x0c832420, 0x49180f20, 0x0e210d90, 0x20ae83d0, 0x0d7d571a, 0xb0101126, 0x23b0d022, 0x2522b482, 0x2d631236, + 0x14152a07, 0x21151712, 0x02263335, 0x05b95f35, 0x12045b08, 0x02141515, 0x21153307, 0x7b74df02, 0x8e909d01, 0xfe777f9b, 0x786bd807, 0xa405018e, + 0x900601a5, 0xfed46b77, 0x0120cf10, 0xca6de710, 0x64cdd9da, 0x1eebfeeb, 0x0167cbcf, 0xb6629e1f, 0x9e9f1d01, 0x65b5e2fe, 0x67dcfe97, 0x020000cb, + 0xebff5600, 0x4e047904, 0x21001600, 0x51597c00, 0x5113200a, 0x132006ae, 0x1320c182, 0x7b0caa57, 0xb0200f72, 0x0b624e18, 0x0c075a18, 0x0c130a27, + 0xb2391211, 0x21068415, 0x534f0cb0, 0x4513200d, 0x11210f20, 0x06564a16, 0x23062723, 0x25ed8222, 0x32331210, 0x3e593717, 0x033a080a, 0x114603fd, + 0x4c33180a, 0xc16635a2, 0xc4e4e3c3, 0xfe1367b5, 0x8c767a1c, 0x738a4646, 0xfc3a047f, 0xb4047bfa, 0x01a2a31e, 0x010df81d, 0x9736010a, 0x9ebffd83, + 0xc70188ad, 0xe983c58e, 0x77fe962e, 0xc4056a04, 0x28001400, 0x27b26800, 0x23055571, 0x00b01027, 0x0f21e982, 0x69c5842f, 0xc17b08c5, 0x3e102508, + 0x0027b259, 0xb022c683, 0x91792f27, 0x2406220c, 0x21dc8227, 0xf64500b0, 0x100c230d, 0x835d1eb1, 0x05b7480c, 0x15161623, 0x2dd58214, 0x11231127, + 0x01363634, 0x22232634, 0xf0831506, 0x35365b08, 0x23272634, 0x02323335, 0x63f2cf69, 0xf2827958, 0xf27aa5d1, 0x4c01d97c, 0x81605d71, 0x89719d58, + 0x487b677a, 0xd8c405d4, 0x309b5fb2, 0xcd82bd2c, 0x38fe53ec, 0xc173a905, 0x5a6dfe70, 0xfc687e76, 0x6e8952e5, 0xb901916d, 0x20000100, 0xf5035ffe, + 0x08003a04, 0x00b23800, 0x73710a09, 0x07b6410d, 0x4e0ccb67, 0xb22307e4, 0x45040700, 0x132205fc, 0xa4820133, 0x33012a08, 0xfbec0e02, 0xfef38ffe, + 0x3b01fb8f, 0xf0fbff02, 0xd00135fe, 0x00000b04, 0xff540002, 0x063804ec, 0x001f0020, 0xb265002b, 0x05cb5e16, 0x43521620, 0x18032009, 0x24072268, + 0xb0584500, 0x200c8216, 0x068f6c16, 0x18410920, 0x0eb22309, 0x6f820316, 0x2f0eb024, 0x158a29b1, 0x0e291d22, 0x16201583, 0x2e11245d, 0x17163233, + 0x22232615, 0x17141506, 0x51171216, 0x34260770, 0x26273736, 0xf04c1326, 0x27510807, 0xd4d00622, 0x4f7149b7, 0x5a4e6997, 0x02dee0bc, 0xe295e17a, + 0x89b8eefe, 0x76685b02, 0x87777989, 0x89796d91, 0xa591ea04, 0x35c31b16, 0x425d343d, 0xcceafe4f, 0x87f69b1c, 0x03012301, 0x0522ffa5, 0x7dfd8928, + 0xb6bcbca2, 0xbe17cb78, 0x00010000, 0x28eb8260, 0x004d040c, 0xb28e0027, 0x834d1816, 0x0751410f, 0xe3822520, 0xe3822520, 0x0917b223, 0x2fbe8225, + 0x2f17b07c, 0x1740b418, 0x5d021750, 0xe017d0b4, 0xb1210682, 0x09ae4f18, 0x1803b223, 0x054a6417, 0xd87fb120, 0x0db2230a, 0x15821017, 0x0d1cb226, + 0x0bb25d01, 0xb0210482, 0x0c494225, 0x1e21b223, 0x261f8218, 0x142104b4, 0x185d0221, 0x200e6d65, 0x054f4223, 0x33161425, 0x66231533, 0x3e080809, + 0x22230414, 0x62696024, 0xd2f86157, 0x7af2ffbf, 0x60725e59, 0xd2d1c769, 0x8262667d, 0xcbfcfef2, 0x01f8fed5, 0x207f5c32, 0x96487924, 0x3c91b5a5, + 0x3c3f4d4f, 0x9303ad4b, 0x4259573f, 0x82b2ba9b, 0xfe612afd, 0x05ca037e, 0x001e00b0, 0x06c3504c, 0x43b00021, 0x14631329, 0x0c125409, 0x1c01b223, + 0x22b38200, 0x181015b0, 0x220e0e56, 0x83060115, 0x175308a5, 0x15161617, 0x27070614, 0x27363536, 0x26272627, 0x37011035, 0xca033521, 0x465660fe, + 0x61dd4b3d, 0x7d527a4f, 0x686e025d, 0x01394ac4, 0xc4fddc25, 0xfe91b005, 0x6bba6d0a, 0x42185a54, 0x4751621f, 0x67653eba, 0x1b213d46, 0x8b506932, + 0x51012001, 0x8200c3fd, 0xfe7e2eb5, 0x04060461, 0x0011004e, 0x120cb254, 0x22dd5913, 0x1b2f0728, 0x3e1207b1, 0xc66cb059, 0x3e102608, 0x0301b259, + 0x213b820f, 0x534603b0, 0x3130290c, 0x33361701, 0x11171632, 0x09044418, 0x5c013308, 0xb6c1770c, 0x5ef303ad, 0xf3469668, 0x97833a04, 0x9cfbc5c4, + 0x696e5304, 0x04effc7a, 0x0300003a, 0xecff7300, 0xc4052c04, 0x16000d00, 0x7c001e00, 0x115203b2, 0x05b57405, 0x1b200582, 0x20066d45, 0x2089820a, + 0x0fb4590a, 0x030eb223, 0x2f89820a, 0x2f0eb07c, 0x0e60b418, 0x5d020e70, 0x400e30b4, 0xb2260682, 0x71010e00, 0x35740ab0, 0x0eb0210c, 0x820d9144, + 0x935618bf, 0x1001210c, 0x0b376418, 0x54210521, 0x330805ae, 0x15210515, 0x36321614, 0xf82c0437, 0x05fadfe3, 0xf6e2e6f6, 0x013afd05, 0x6f717ad4, + 0xfed4017a, 0x77e07b2c, 0xfe720202, 0x01b6fec4, 0xe92d0141, 0x4c013501, 0xd3340c82, 0xcbce3023, 0x2aefcecb, 0xcacad1d0, 0xa9000100, 0x6102f4ff, + 0x0c22f282, 0xc74b2900, 0x0728430a, 0xdd820920, 0xc74b0920, 0x3130220e, 0x0b007e01, 0x329c0137, 0x4a2b2a3e, 0x04e8fe56, 0x3df6fc3a, 0x17bc0a36, + 0x11033501, 0x2c5b8200, 0x04eeff16, 0x00fb054a, 0xb2520019, 0x076b5403, 0x00b02f25, 0x48b05845, 0x0c84070d, 0x65821020, 0xdb7f1020, 0x0adc5e06, + 0x000fb22e, 0x3912110b, 0xb0100fb0, 0x00b0d012, 0x080f1155, 0x17163250, 0x17171601, 0x23061737, 0x03272622, 0x27012103, 0x07232726, 0x12013627, + 0x011f786c, 0x203124ab, 0x342a0411, 0xca2b756d, 0x01f7fef6, 0x49225b81, 0x3b031b22, 0x5055fb05, 0x0756bffb, 0x0ac00101, 0x14026f58, 0x0f0437fd, + 0x02034bda, 0xb18210b6, 0x76fe642c, 0xc405d403, 0x59002c00, 0x516603b2, 0x85162006, 0x822a20b1, 0x202a25a4, 0x02b1593e, 0x220afe44, 0x832a2d08, + 0x2f0821a1, 0x210be566, 0x15851db2, 0x11691d20, 0x0924220d, 0x05b04508, 0x2e051445, 0x23153321, 0x16141120, 0x16171604, 0x82060615, 0x35362bb7, + 0x27242634, 0x34352626, 0x05833736, 0x33245108, 0x83031732, 0x887a578a, 0x8c891c01, 0x01819efe, 0x51236f19, 0x83507b02, 0xfe3f2e35, 0x767f4cfd, + 0x7c6e90a3, 0x99e30201, 0x24da047d, 0xc6b84b56, 0x8862e3fe, 0x38182542, 0x3bbb486d, 0x29503964, 0x20442d23, 0x9194b735, 0x8e282dc4, 0x2cc5a661, + 0x2d2ee182, 0xcf04f4ff, 0x14003a04, 0x0bb25e00, 0x6b431615, 0x0c354808, 0x4308166e, 0xb0220b5e, 0x73611013, 0x0ab0210b, 0x0d464e18, 0xb010002a, + 0x0eb0d00d, 0xd011b0d0, 0x18058660, 0x080c2640, 0x2311213d, 0x21352311, 0x319fa904, 0x4a2f263f, 0xfee8fe56, 0x04abf3b4, 0xfd7c037c, 0x0a373eb6, + 0x350117bc, 0x84fc5302, 0x00be7c03, 0xfe800002, 0x04310460, 0x000e004e, 0xb259001a, 0x821c1b11, 0x11b021a5, 0x5d05f747, 0xe57a080e, 0x070a440c, + 0x22088865, 0x82070009, 0x18b12034, 0x5a0b8e67, 0x302b0d97, 0x12320131, 0x02141511, 0x82272223, 0x0034229b, 0x09d15b03, 0x02153808, 0xe0fbe056, + 0xf36ab3c1, 0x43100301, 0x7c7d7695, 0x04776672, 0xfecbfe4e, 0xfef20fef, 0xfdfd77e5, 0x01f2db03, 0x75d5fc21, 0xc5b8b3ad, 0x0000a0c1, 0xfe520001, + 0x82e9038a, 0x002226b3, 0x231bb24f, 0x0d515f24, 0x1427ab87, 0x14b11b2f, 0x50593e18, 0x058205bf, 0x230be94b, 0x00231cb2, 0xb0213682, 0x0f23691c, + 0x76163221, 0x04240a4d, 0x14171616, 0x08072d42, 0x26262757, 0x36343527, 0xc4380236, 0x606de4ed, 0x01948371, 0x0131602e, 0x337f4c7f, 0xee413c2a, + 0xdc7801ed, 0xbbdd4e04, 0xaabc7461, 0x569b831a, 0x48425339, 0x376538bf, 0x2a282c4e, 0xd1fe370f, 0x89fa9d27, 0x00020000, 0x04ecff52, 0x003a047e, + 0x001b000f, 0x1c07b24e, 0x2286831d, 0x4ab01007, 0x0e200751, 0x0e20b682, 0x200c8d48, 0x058b5e10, 0x61180020, 0x6e180db8, 0xdb820ac7, 0xd019b027, + 0x21013130, 0x07f94716, 0x00343525, 0x5d012137, 0x3b080a38, 0xf5fe7e04, 0x91de7aba, 0x01f0fee2, 0x4102df0c, 0x7a85c7fc, 0x75838175, 0x76038776, + 0xec8efb92, 0x012c0183, 0x01ee0c03, 0xd8fd0223, 0xbdbcbba9, 0x00b0b39c, 0x3f000100, 0xec03ecff, 0x1024ad82, 0x01b24b00, 0x0af74618, 0xa5820f20, + 0x08fb4d18, 0x2008c142, 0x0cd0500f, 0x8317b442, 0x05d444a8, 0x06172808, 0x11032023, 0x03213521, 0x2b98feec, 0x26372733, 0xecfe6c50, 0x03aefe05, + 0xfd7903ad, 0x163b3bb0, 0x39012cb1, 0x82c15402, 0xff802489, 0x820804eb, 0x00122489, 0x710eb239, 0x0e201789, 0x0e239682, 0x4b593e10, 0xb0240b67, + 0x08b01000, 0x08061157, 0x33101147, 0x26353632, 0x11163303, 0x22230010, 0x01112726, 0x9171a172, 0x73f16e03, 0xcbe7fcfe, 0x3a0401d1, 0xfdfe76fd, + 0x01e7a0e9, 0xe2fee61d, 0xc1fef4fe, 0x9502d8e2, 0x00020000, 0x0522fe44, 0x00410485, 0x0023001a, 0x0ab76e61, 0x00d01b24, 0xb54419b0, 0x82112005, + 0x1811207d, 0x20140a46, 0x20198200, 0x18978300, 0x830aa84c, 0xd0182c97, 0xb0100db0, 0x11b0d01b, 0x6921b110, 0x243b0cb4, 0x12343500, 0x06061737, + 0x17161407, 0x33363411, 0x15161632, 0x11050014, 0x82361323, 0x264c08c1, 0x02152223, 0xfefcfe65, 0x98737ee3, 0x9a024c48, 0x937c9e94, 0xdefe87ec, + 0xf3f3f5fe, 0x8d02a595, 0x1c0e3774, 0xa4ff3701, 0x92530501, 0xa168bc46, 0x80021ecd, 0xfb8d9277, 0xd7fef392, 0x0231fe1a, 0x97c11994, 0x003ebf97, + 0x4f000100, 0x7e28d982, 0x18003a04, 0x00b24500, 0x20064f5b, 0x20d1850d, 0x20b78214, 0x20d18714, 0x06ba4d0f, 0x0bd25718, 0xd001b026, 0xb01014b0, + 0x062bc782, 0x100fb0d0, 0x30d00cb0, 0x83110131, 0x056341a1, 0x1136af82, 0x11030024, 0x05101133, 0x93520311, 0xee7005a7, 0xfee1fe79, 0xbb82f3f3, + 0xf301f531, 0x3a041d01, 0xce1b7dfc, 0x1401e2a4, 0x82edfee3, 0x1aca3314, 0xd00132fe, 0x0133011e, 0xfeed010a, 0x3ca2fe18, 0xa5838203, 0xecff6624, + 0xa5822d06, 0x57002024, 0x857f1ab2, 0x0c2b5a0a, 0xa2821820, 0x48101821, 0x461806aa, 0x54180756, 0x00340d43, 0x3912111c, 0xb0d00eb0, 0x13b01000, + 0x2f13b0d0, 0x18051ab2, 0x20052b46, 0x061a5802, 0x6d6cad82, 0x265c0805, 0x10163303, 0x27222302, 0x02222306, 0xe5013710, 0x58610786, 0x02fb605b, + 0x61585a5f, 0x8df18507, 0x5ce8cbd5, 0xd6cbe65c, 0xfe3a048d, 0xcbbdede9, 0x4601949d, 0x988eaffe, 0x01efbdcb, 0xc8fde815, 0xdeded2fe, 0x38022e01, + 0x020000e8, 0xecff7600, 0xc4059804, 0x29002000, 0x0fb26e00, 0x2305db6e, 0x21b0100f, 0x4f06dd48, 0x26650c27, 0x1a242208, 0x229d8206, 0x182f24b0, + 0x230cf64e, 0x0bb2d002, 0x06201885, 0x0c0d5318, 0x1024b028, 0xb0d01eb0, 0xe07c101a, 0x3130260b, 0x15070601, 0x24c48214, 0x37113500, 0x05154411, + 0x26357008, 0x34352700, 0x16323336, 0x37361115, 0x17161401, 0x22232611, 0x3a980406, 0xd3d5fa44, 0x82ecfefe, 0xd16d626e, 0xc50300ff, 0x4bbca7a5, + 0x7daafd2a, 0x346d046b, 0x14570243, 0xfdda750b, 0x01d40501, 0xdefe021d, 0x83868f7d, 0x1301267c, 0xcca91bc0, 0xcefebbd0, 0x23010b0c, 0x0120a26c, + 0x00499a45, 0x00e1ff01, 0x059e0400, 0x001a00c3, 0x6400b243, 0x04240a49, 0x04b11b2f, 0x0fe96918, 0x0400b223, 0x056f5f0d, 0x280bdf47, 0xb0d012b0, + 0x17b01004, 0x21c482d0, 0x5b613613, 0x01072507, 0x01112311, 0x0721af82, 0x08128227, 0x02171649, 0x7a2bd23f, 0x26424660, 0x1f41280d, 0xfefcd9fe, + 0x2b4021db, 0x4a3c240a, 0x032c7d67, 0x64f80107, 0x05c21a60, 0xfd6bfd45, 0x021002ee, 0xc1054597, 0x006c641b, 0xff330002, 0x045406ec, 0x0012003a, + 0xb2720026, 0x83282708, 0x1008237f, 0x91411eb0, 0x11d04306, 0x44075b42, 0x112008f2, 0x230cf244, 0x061108b2, 0x0f2d4383, 0xd010b0d0, 0xb0d015b0, + 0x0ab0d016, 0x0be86a10, 0x101fb223, 0x2021830a, 0x22d08324, 0x42151623, 0x112a085e, 0x35233734, 0x27260121, 0x86420621, 0x375b0805, 0x16153335, + 0x36323316, 0x37805406, 0x5ceebcca, 0xc8bdee5c, 0x21066f36, 0x3d04c5fe, 0x043cc6fc, 0x665c4b53, 0x6302fa01, 0x03534b5d, 0xfeaf9e83, 0xe2d4fee2, + 0x012e01e2, 0xb79cb11c, 0xada0fcfd, 0xcabe9cb1, 0xeee89597, 0x00ca978f, 0xff220001, 0x05bc05f2, 0x001800b0, 0x5f11b271, 0x17240a35, 0x17b11b2f, + 0x4a078b41, 0xb0250782, 0xb0584500, 0x20198213, 0x20f08313, 0x22e38d17, 0x83091704, 0x2f0423c1, 0x9e5409b0, 0x04b0210c, 0x220c905e, 0x411000b0, + 0x302d0501, 0x11210131, 0x04323336, 0x27230410, 0x05bc4432, 0x11073408, 0x35211123, 0xfe900421, 0xfb729413, 0xeefe1801, 0x8c8901fe, 0x868f8f01, + 0x7cfefd78, 0xe4046e04, 0xf02674fe, 0xbfec50fe, 0x87778479, 0x0474fd20, 0x8200cce4, 0xff682cc5, 0x05ef04ec, 0x001f00c4, 0x1803b274, 0x650ac542, + 0x47180cdb, 0x551808d1, 0xb2230d27, 0x4e030c17, 0x30290880, 0x02174017, 0x1760b45d, 0x09874e70, 0x1700b225, 0x65b17101, 0x03200bbf, 0x180cb14d, + 0x2018f564, 0x05446f21, 0x37364f08, 0xfe16ee04, 0xfeaff8d4, 0x920191f5, 0xf3b41101, 0xfc182501, 0xa18e9412, 0xfb0108b0, 0xab0704fe, 0x1496939d, + 0xfee8d901, 0x3601a5fb, 0x01cf7bcf, 0xf6feaa3a, 0xe58e9cec, 0xe5ddcad2, 0x02009d87, 0x00002d00, 0xb0054108, 0x22001900, 0xdf547700, 0x07c3660a, + 0x600ce360, 0xd74b0c39, 0x00b22307, 0xe5820818, 0x2f00b024, 0x9e4118b0, 0x1010210d, 0x0c6e4c18, 0x70520020, 0x1012270d, 0xb0d01bb0, 0xe482d01c, + 0x1e216508, 0x04141502, 0x21112107, 0x06020203, 0x37352323, 0x1337023e, 0x21111121, 0x34353632, 0x0d052726, 0xeb993101, 0xe5ebfe7f, 0x42fecafd, + 0xbc630f1a, 0x5728409e, 0x1c0a315f, 0x2901ab03, 0x7a8f917e, 0x7501a103, 0xfdce87d4, 0xfde40405, 0xfef8fecd, 0x03ca86dd, 0xd1d76a08, 0x26fdc902, + 0x7593f4fd, 0x00028f73, 0x9b20ed82, 0x4720ed82, 0x1328ed82, 0x8a001c00, 0x1e1d01b2, 0x2006105f, 0xc9431814, 0x079b420b, 0x4c0cd455, 0xb27a08c5, + 0x3e102608, 0x1000b259, 0x28fa8513, 0x01009fb2, 0x0d04b25d, 0x06a84202, 0x0f20eb82, 0x21095e47, 0x461804b0, 0x0d200da1, 0x220fed4c, 0x82331121, + 0x16162deb, 0x23041415, 0x11211121, 0x01331123, 0x2335fc86, 0x80029701, 0x9c2b01fc, 0xe3fe7fee, 0xfde0fdf3, 0x03fcfc80, 0x08f5827c, 0x7c949224, + 0x6b024503, 0xcb6ed2fd, 0x02f7cd85, 0x0586fd7a, 0xfe08fdb0, 0x6f708618, 0x01000083, 0x00003100, 0xeb82c805, 0x58001522, 0x2005fb4d, 0x06fc7f14, + 0x4d0c2054, 0x14200da2, 0x210e7843, 0xcf851410, 0x4648b120, 0xd012240e, 0x43d013b0, 0x20220666, 0x7c4f1504, 0x2126080a, 0x92042135, 0x8f8311fe, + 0x07010c01, 0x8c9a7dfc, 0x8afefc86, 0xe4046104, 0xec1b9bfe, 0x0137fee5, 0x1c7a8bca, 0x5d434dfd, 0xfe922406, 0x820d0598, 0x000b22a3, 0x08417d49, + 0x450cf453, 0x3d6e0cb8, 0x0710450c, 0x210bb14d, 0x948203b0, 0x11331324, 0x03831121, 0x11232108, 0x02fd9221, 0x4bfefd81, 0x0537fefd, 0x041afbb0, + 0xfe50fae6, 0x00680198, 0x90000200, 0xc1040000, 0x0d287982, 0x5e001600, 0x181710b2, 0x20061578, 0x13bb6903, 0x20087c45, 0x0d1f410c, 0x0a0c0222, + 0x02223683, 0xd27db12f, 0x0ab0210a, 0x230c2047, 0x21013130, 0x2007db41, 0x41098207, 0x273007d7, 0x61fd2c04, 0xeea02a01, 0xefebfe7c, 0x9c03d3fd, + 0x29390d82, 0x7c8c8f80, 0x9ffee404, 0xcc85ca6e, 0xb00502f8, 0x12fe08fd, 0x806e738b, 0x24b18202, 0x059afe24, 0x28b182dc, 0x0014000e, 0x1512b267, + 0x207a8316, 0x31561812, 0x595e1809, 0x2f04250c, 0x1804b11b, 0x280e686f, 0xb01004b0, 0x02b0d001, 0x0cf25910, 0x4605d74d, 0x0b200540, 0x820c1657, + 0x234908ba, 0x23112111, 0x12363303, 0x11211337, 0x11212133, 0x05020321, 0x41fcf0cf, 0x577508f4, 0x03260f68, 0xdbfbb996, 0x57fe7002, 0x9afe1b18, + 0x9afe6601, 0x01543002, 0x8602cb41, 0x1a041afb, 0x65fe66fe, 0x00010000, 0x07000016, 0x22b9829b, 0x427e0015, 0x5f180589, 0x0d200cfe, 0x580be366, + 0x466e0c6e, 0x0cfc410c, 0x33821420, 0x3e10142c, 0x0910b259, 0x39121102, 0x5d1810b0, 0xd0240e6f, 0x001008b2, 0x10271884, 0xb2d00bb0, 0x6e100013, + 0x23200957, 0x2005556e, 0x08606e33, 0xff042108, 0xfeaafca3, 0x01c5fe9b, 0x014afed5, 0x9d5c0132, 0x590196fc, 0x4efe3101, 0xc6fed101, 0x8cfd7402, + 0x03270383, 0xfda90207, 0x846002a0, 0xfc592203, 0x2ed782f7, 0x04edff49, 0x00c3057f, 0xb2890029, 0x4e2b2a25, 0x89410815, 0x8217200c, 0x501720aa, + 0x032006fe, 0x23091244, 0x170b28b2, 0x7c343082, 0x182f28b0, 0x012810b2, 0x2830b45d, 0x5d022840, 0x702860b4, 0xa0220683, 0x0682b028, 0x2806b223, + 0x18258203, 0x230b2471, 0x282511b2, 0xb0211282, 0x0caf5717, 0x251cb223, 0x18e2851f, 0x180b5e5c, 0x210ad56b, 0x67182622, 0x218208a9, 0x35234208, + 0x6c032033, 0x926d7f94, 0x8dea84fc, 0x781501fa, 0xfe817a6c, 0xf99afad4, 0x789cfc7d, 0x8a8fa386, 0x0c01a2ab, 0x74622304, 0xba775b73, 0x63c4da67, + 0xab2a30a6, 0x6ee7c47f, 0x815e7bbe, 0x6f7b657e, 0x2aff82c8, 0x05000094, 0x00b0050d, 0x5e450009, 0x07201225, 0x0720f882, 0x5c10825e, 0x04220ce2, + 0xb4820200, 0x8409b221, 0x30200806, 0x11330131, 0x23011123, 0x04113311, 0xfdfdfd10, 0x05fdfd81, 0x0450fab0, 0x05f3fb0d, 0x00f2fbb0, 0x2d207182, + 0x11247186, 0x04b24f00, 0x440a4b54, 0x4e5d0c33, 0x0960480c, 0x0c137318, 0x1009b022, 0x0e105518, 0x7d467a82, 0x0d05220c, 0x0d6a46fc, 0x5d468b84, + 0x2b93820f, 0x04ebff39, 0x00b005dd, 0xb24a000f, 0x10df4e18, 0x5d4bff87, 0x0f002108, 0x2005af49, 0x05486510, 0x4706b021, 0xb2230c32, 0x5d0f060d, + 0x450808f4, 0x27230607, 0x32331637, 0x21013737, 0x2401a002, 0x05fe1901, 0x68e0642e, 0x6c3d1802, 0x0efe342c, 0xb7021401, 0x48fbf902, 0xc806b25b, + 0x047b5c04, 0x03000024, 0xc4ff4f00, 0xec051806, 0x22001900, 0x5d002b00, 0x0f580cb2, 0x100c2505, 0xb0d021b0, 0x232c0582, 0x0bb000d0, 0x2f18b02f, + 0x0b1816b2, 0xb0276a82, 0x00b02f16, 0x8525b2d0, 0x5225200c, 0xb0240cea, 0x16b0d00d, 0x080db447, 0xb0102527, 0x1ab0d020, 0xd023b010, 0x33013130, + 0x15120432, 0x07040214, 0x35231523, 0x02242223, 0x24123435, 0x33353333, 0x05c87601, 0x82113321, 0x325c0801, 0x26343536, 0x16ae0323, 0x991301a8, + 0xa8f1fe99, 0xa918f31a, 0x9897ecfe, 0x18aa1201, 0xa8f5fef3, 0x15acbcbd, 0xbba818f3, 0x2605abbb, 0xabeefe97, 0x96f1feaa, 0x97bebe01, 0xaba90e01, + 0xc6991201, 0xb9d26ffe, 0x0e03cfb4, 0xb3d2f2fc, 0x0100d2b7, 0xa1fe9200, 0xb005bd05, 0x3c000b00, 0x46223546, 0x06201428, 0x21092846, 0x28460333, + 0x14b02407, 0x46d1fbe8, 0xfb250528, 0x01d5fd1c, 0x246b825f, 0x0400008e, 0x226b82ee, 0x42400011, 0xc84412e3, 0x0777420c, 0x010eb229, 0x39121109, + 0x4e2f0eb0, 0x30290b08, 0x23110131, 0x20230611, 0x05f35c24, 0x32332508, 0xee041137, 0xfeb0a2fc, 0x01f4fefb, 0x977e01fc, 0xb005a4ae, 0x3d0250fa, + 0x01e8e629, 0x8b30fece, 0xa7022a76, 0x98248182, 0x03070000, 0x4920ed84, 0x48608192, 0x0c72430c, 0x2008dd55, 0x0d175f01, 0x0120fa83, 0x20062247, + 0x29078233, 0xbc019601, 0xfcb901fc, 0xfa8695f9, 0xe6041a24, 0x708250fa, 0xfe237b83, 0x82ad07a2, 0x000f250a, 0x0bb00055, 0x9912945b, 0x2f0d277e, + 0x100db11b, 0x9461593e, 0xd0052f0c, 0xb0d006b0, 0x0ab0d009, 0xd002b0d0, 0x87893130, 0x23033322, 0xaa248b8a, 0xddf9de14, 0xfb258e89, 0x01e0fd12, + 0x2687825e, 0x00180002, 0x47d40500, 0x612206b7, 0xb74701b2, 0x10012305, 0xb97c0eb0, 0x0002211c, 0x2106a847, 0x3e5800b0, 0x02b0210c, 0x470cc555, + 0x132010ba, 0x2e15ba47, 0x01870218, 0x7deea02a, 0xfdeee9fe, 0x8275fed4, 0x8029320d, 0x057c8c8f, 0x6ed3fdb0, 0xf7cd86c9, 0xfded0402, 0x07b947cb, + 0x9b000326, 0x58060000, 0x0b22b382, 0xbf820f00, 0x02b26f27, 0x12111a19, 0x227b8239, 0x83d00db0, 0x07856a05, 0x720c3746, 0x784b0c2f, 0x2f0c2b0c, + 0x100cb11b, 0x00b2593e, 0x7d4a0b08, 0x0bb95a05, 0x4708b021, 0x21230fc3, 0x4b161632, 0x3321055e, 0x0a584a01, 0x98012722, 0x27097e48, 0xfcc004fd, + 0x0140fbfc, 0x0321c784, 0x077f4883, 0x4850fa21, 0x35490d83, 0x000b2607, 0xb24f0014, 0x0583480e, 0xb0100e23, 0x067d4101, 0x8042c18c, 0x00b22207, + 0x18a78709, 0x200b3071, 0x0f095509, 0xf94ba78a, 0x8d012108, 0x9d8fa38a, 0x2c091d49, 0xff6b0001, 0x05f104ec, 0x001f00c4, 0x0ca74d82, 0x510cc44b, + 0xb23607a0, 0x111c1309, 0xb07c3912, 0xb4182f09, 0x09700960, 0xd0b45d02, 0x0683e009, 0x40093022, 0xb2820682, 0x49710121, 0x1c200c25, 0x230c3e46, + 0x030600b2, 0xb0214082, 0x0c4d4213, 0x090fb223, 0x05bd450c, 0x33161626, 0x21373632, 0x0807fc6b, 0x00362355, 0x12043233, 0x02141517, 0x00222304, + 0x14680127, 0xab9c9397, 0x02fefd06, 0xa0b10802, 0xfc12958c, 0xf2250118, 0x931001b3, 0xf4fe8f01, 0xd4fef8b0, 0x9ed90116, 0xccd7e486, 0x9e8ce4d8, + 0xa80801ee, 0x7bcdc8fe, 0xa8c7fecf, 0x00e80501, 0xffa00002, 0x820707ec, 0x001728ed, 0xb2810025, 0x4a272612, 0x1d20060b, 0x500b2560, 0xb5610cef, + 0x0f54500c, 0x0a0eb223, 0x5a41820d, 0x225c0bd1, 0x5ae6830b, 0xb0210ab3, 0x0ce77c04, 0x70313021, 0x2329085a, 0x33112311, 0x12363311, 0x18ee8424, + 0x350d8f6d, 0xfe940707, 0xfea7b3ed, 0xb60e9ef8, 0x06b3fcfc, 0xad0f019a, 0x6d1801b2, 0x982d1294, 0xfdbd1c01, 0xfdb005a3, 0x3501c971, 0x996d18a5, + 0x00203014, 0x055f0400, 0x000c00b0, 0xb2630015, 0x49171610, 0x0a2006eb, 0x2013b75b, 0x060b5500, 0x5b18b020, 0xff82083d, 0x0a11b223, 0x21348300, + 0xa0442f11, 0x05b2230b, 0x15831101, 0xb94e0a20, 0x3056080c, 0x21112131, 0x26012101, 0x37243411, 0x14011121, 0x11333316, 0x03062223, 0xfee6fe62, + 0x01f1fee7, 0x1301fe45, 0xfdef01f6, 0xeb8a8a04, 0x02888ceb, 0x02e0fd20, 0x1101786b, 0xfa02e9d1, 0x7be90350, 0x8600028a, 0x5b000200, 0x3c04ebff, + 0x1a001306, 0x56002600, 0xfd510eb2, 0x100e2305, 0xfd511bb0, 0x07c5720b, 0x2208ec58, 0x43071100, 0xb22105e5, 0x05f65819, 0x200b8a41, 0x0ec65507, + 0x12320136, 0x00141515, 0x11002223, 0x37121035, 0x33353636, 0x07060614, 0x36210282, 0x085c7e17, 0x26345a08, 0xf6cc7a02, 0xdfe5f5fe, 0xf6f8eefe, + 0x42c4518a, 0x9f98a688, 0x7693911b, 0x797a8486, 0xfe038585, 0x0ceaeffe, 0x01defeea, 0x46000128, 0x98015e01, 0x363f1c33, 0x234f7e65, 0x9591a420, + 0x9ca59fc3, 0x8cb0afae, 0x000300a3, 0x0400008f, 0x003a043a, 0x0015000e, 0xb27b001c, 0x05514f02, 0xb0100223, 0x0cd94415, 0x1b2f0124, 0xb56201b1, + 0x3e10260c, 0x0116b259, 0x2fd98200, 0x2f16b07c, 0x1640b418, 0x5d021650, 0xe016d0b4, 0xb1210682, 0x0a9f5f0f, 0x160f0822, 0xeb51ff84, 0x5201200d, + 0x30240ce4, 0x21113331, 0x200bda61, 0x080e8201, 0x2334353f, 0x35323325, 0x8f232734, 0xe8deb701, 0x7c6a5b5d, 0xf8fed1df, 0xbebb0a01, 0xcfc8f9fe, + 0x3a04d3c4, 0x774b919b, 0x5b861620, 0xcd019e97, 0x8786f3fe, 0x04807aae, 0x00010000, 0x03000085, 0x69d7824d, 0x58180d4f, 0xb0200f31, 0x2a154f69, + 0x2afe4d03, 0x03c802f2, 0x828afc76, 0x02002742, 0xbefe2700, 0x0a82c504, 0x14000e24, 0xb94d5d00, 0xd004210a, 0x08155818, 0x480c0c73, 0x815908b1, + 0xd006290b, 0xb0d007b0, 0x09b0100c, 0x10210882, 0x05af4db0, 0x11208082, 0x0809dd47, 0x37313040, 0x13373636, 0x11331121, 0x11211123, 0x21211323, + 0x02072111, 0x07456581, 0x96ef020e, 0xf64afdf2, 0x01760101, 0x07effe9f, 0xcb71c20e, 0xfc9e019e, 0x01fcfd88, 0x02befe42, 0xcfa70204, 0xf982d6fe, + 0x00001e24, 0xab825c06, 0x83001522, 0x870aab4d, 0x0c4772f9, 0x4d0cac54, 0x112d23ab, 0x39121102, 0xb22f10b0, 0x5d01108f, 0x20dc8bb1, 0x1cb04d04, + 0x01210327, 0x33132101, 0x20018211, 0x3e0a8313, 0xf3813504, 0xd6fef980, 0xacfe6701, 0x72f52901, 0x01f673f3, 0x01adfe29, 0x01d2fe69, 0x834dfeb3, + 0x33022703, 0x57fe0702, 0x0383a901, 0xfdfcfd23, 0x2cd982ca, 0x03ecff4d, 0x004d04c4, 0xb2900027, 0x0a3b621e, 0x1b2f2524, 0xc67c25b1, 0x3e10260c, + 0x2519b259, 0x2fac8208, 0x2f19b07c, 0x1940b418, 0x5d021950, 0xe019d0b4, 0xb1210682, 0x0a9b4216, 0x19160322, 0x2105c155, 0x158a10b1, 0x10160d22, + 0xb42b1582, 0x0d130d03, 0x25b05d02, 0x8a1eb110, 0x1921221c, 0x311c821e, 0x210b0940, 0x212b211b, 0x5d04213b, 0x14013130, 0x5e180706, 0x445b092a, + 0x35232308, 0x4c183633, 0x39080ca7, 0x4f57b003, 0x7ccbf2ba, 0x76f272cc, 0x5c69595a, 0xa3b4ae60, 0x6e50525e, 0xc9b9f0f2, 0x481203e0, 0xba412479, + 0x9953b195, 0x53594269, 0xaf464f43, 0x4a428402, 0xb78f3c4f, 0xff8200a4, 0x00008626, 0x3a041204, 0x5b0ead4d, 0xe0420cf8, 0x0dad4d10, 0xad4d0720, + 0x4d068405, 0x03330bad, 0xfef2f220, 0x04f2f258, 0x02c6fb3a, 0x042efdd2, 0x832efd3a, 0x828f2071, 0x82652071, 0x000c2271, 0x054b4269, 0x790ce542, + 0x3e420cfc, 0x0e317e0c, 0x06b07c2f, 0xd3b4182f, 0x0206e306, 0x0643b45d, 0x22068253, 0x6b0613b2, 0xb2210dee, 0x143a7e0a, 0xf37bfd2f, 0x2b016bf3, + 0x79fe2c01, 0xc4fea801, 0x093a7e01, 0xccfdfa26, 0x21000100, 0x1420a182, 0x0f24a182, 0x04b24f00, 0x590a6b71, 0x4f4e0ce3, 0x0989490c, 0x6a0c1048, + 0xec4b0e6d, 0x03213a05, 0x23230602, 0x36363727, 0x14041337, 0x14cefef3, 0x4bb0ab13, 0x49503201, 0x2f74820a, 0x7603c6fb, 0xf0fe87fe, 0x0b05caed, + 0xce01e5ad, 0x21063141, 0x8f826f05, 0x59000c22, 0x45053141, 0x0b240c38, 0x0bb11b2f, 0x1807a341, 0x2114455e, 0x711800b0, 0x1024075c, 0x00b2593e, + 0x0c525e18, 0x0d840820, 0x01279982, 0x11231121, 0x82012301, 0x02213d05, 0x014001ff, 0xd6fef330, 0xf3d5fea5, 0x2b013201, 0xc6fb0f03, 0x34fdcc02, + 0x30fdd002, 0x2405f77f, 0x04000086, 0x220a8211, 0x8586000b, 0x8d681893, 0x180a200c, 0x470b515e, 0xae780c69, 0x47092008, 0x09330569, 0x09bfb42f, + 0x5d0209cf, 0x6f095fb4, 0xb4710209, 0x82ff09ef, 0x5fb23406, 0xb4720109, 0x093f092f, 0xbfb27202, 0xb4710109, 0x832f091f, 0x098f2717, 0x8fb45d01, + 0x17829f09, 0x230be353, 0x23213130, 0x090e7918, 0xf3110433, 0xf3f35bfe, 0x01f3a501, 0x044bfeb5, 0x013dfe3a, 0x0aeb42c3, 0x6c000721, 0x80460b8f, + 0x0d00770f, 0x27178f6c, 0xfef31204, 0x8c03f35a, 0x2c07cf45, 0x00230001, 0x04d00300, 0x0007003a, 0x12114132, 0x8208ca42, 0x0de34450, 0x5505b021, + 0xbf820533, 0x21353008, 0xa1fed003, 0x03a5fef3, 0xfc7903ad, 0xc1790387, 0x54000300, 0x7f0560fe, 0x1a000006, 0x2f002400, 0x07b28100, 0x12113130, + 0x1007b039, 0x83d020b0, 0xd02a2105, 0x15556c18, 0x240c8341, 0xb11b2f13, 0x07316113, 0x520cb556, 0x0a210889, 0x0b146910, 0x6710b021, 0xb0270cde, + 0x1eb0d028, 0x822db010, 0x10132daa, 0x17323312, 0x36113311, 0x11123233, 0x2e074c61, 0x02222306, 0x26342527, 0x11072223, 0x6a323316, 0x5c080a10, + 0x4cbbd154, 0x5640f23e, 0xb7d4d3ba, 0x3df24553, 0x09d1af4f, 0x6a743704, 0x3321252d, 0x6cbafcdc, 0x22212d6a, 0x0270682a, 0x0109010e, 0xce011c37, + 0xfe202efe, 0xf3e0fecb, 0xfe1ee6fe, 0x1aa60156, 0x3ce30301, 0xfd0dc7b6, 0x4b010a3a, 0x020aa9a2, 0x00c10ac9, 0xfe860001, 0x04a504bf, 0x05ed4f3a, + 0x834e0820, 0xc760180a, 0x470c870c, 0xc863083b, 0x4fb0200a, 0x86350fed, 0xf3a601f3, 0xfcdd1493, 0xfc3a04d2, 0xfc780388, 0x01fdfd88, 0x2a6b8241, + 0x0300005f, 0x003b04e0, 0x52490011, 0x66180c5f, 0x5f7c0c30, 0x08f44f0c, 0x09010d2a, 0x7c391211, 0x182f0db0, 0x250b1771, 0x23213130, 0x62180611, + 0x200807be, 0x37323316, 0xe0033311, 0xde685ef3, 0x6c69f3ea, 0x01f36462, 0xc7d51669, 0xb4fe4c01, 0x02176276, 0x05bb420c, 0x84030621, 0x0bef4fef, + 0x450cf643, 0xef4f14b4, 0x01792828, 0x5301f352, 0x8783faf2, 0x780323fc, 0xeb43c6fb, 0xfe7e2405, 0x82b406bf, 0x000f220a, 0x089a484c, 0x7f0c0b45, + 0xba6a0cbe, 0x17ef4f0c, 0xe64f0920, 0x85712013, 0x14b92482, 0x89bbfadd, 0x05864185, 0x24053349, 0x0400001f, 0x260a82ea, 0x0015000d, 0x4b00b25e, + 0xe44f05e1, 0x180c2007, 0x6f0bbf70, 0x002a086e, 0x1211080c, 0x2f00b039, 0x54530cb0, 0xbc4e180c, 0x08b0210e, 0x600f9f57, 0x340805ea, 0x11210706, + 0x11213521, 0x36323311, 0x02272634, 0xc685ee4a, 0xfec4ec67, 0x02c8fe1d, 0x6759ed2b, 0xe2025665, 0xa76ea65c, 0x760301ca, 0xfee5fdc4, 0x5fa459a3, + 0x05034b01, 0x82c90521, 0x000b2aa9, 0x0017000f, 0x1807b26f, 0x06b54319, 0xb0d00d24, 0x7a181007, 0xa54308e3, 0x0c74630c, 0x22095346, 0x4fb05845, + 0x0e2009dd, 0xdd4fce86, 0x4fbc891d, 0xbe8506dd, 0x87820121, 0x04f326be, 0xfbf3f347, 0x25c18cb9, 0xc6fb3a04, 0xc4883a04, 0x00020027, 0x0400008f, + 0x26c58422, 0xb24f0013, 0x8315140e, 0x0ad94fc3, 0x7241bd8c, 0x870a2009, 0x0bd94fa3, 0xd94f0820, 0x41a38a0f, 0x9f8a075e, 0x9589998e, 0x5100012e, + 0xe803ecff, 0x20004e04, 0x10b28000, 0x480a8361, 0xe4440c3b, 0x45778208, 0xb2230a70, 0x8210081e, 0xb07c2fc4, 0xb4182f1e, 0x1e501e40, 0x03b25d02, + 0x1282001e, 0x031cb226, 0x0bb25d01, 0xb1210482, 0x0999491b, 0x230e3174, 0x181b15b2, 0xb4292b82, 0x15141504, 0x31305d02, 0xb4731801, 0x15002108, + 0x5705f464, 0xe84f0851, 0x023c0805, 0xe5765501, 0xdc72ca74, 0xdc790b01, 0x6ec87b91, 0x665676e5, 0xacfe0c7e, 0x7e0e5301, 0x4f698b03, 0xfe68af64, + 0x9b19fcd2, 0xba6788fc, 0x99775d75, 0x8f84a889, 0x91000200, 0x3806ecff, 0x1424e382, 0x88001f00, 0x12a58a18, 0x670c3449, 0x11240cc8, 0x11b11b2f, + 0x11af6c18, 0x84131121, 0x820120f6, 0x01d029f6, 0x5d0201e0, 0x500140b4, 0x45180682, 0x0c210c15, 0x0c556310, 0x44180420, 0x01350e37, 0x33243633, + 0x17170032, 0x23060614, 0x23270022, 0x33112311, 0x9f6b1801, 0x01220809, 0x011bcc84, 0x01dbcb0a, 0x7b010b11, 0xfed296e5, 0xf3ca15f3, 0x8ab901f3, + 0x788d88f6, 0x87028c77, 0x6b18f8cf, 0x042707a6, 0x043cfed4, 0x7fd8fd3a, 0x0230074f, 0x00002700, 0x3a04df03, 0x16000d00, 0x14b26300, 0x2305c353, + 0x04b01014, 0x4406074f, 0x7d490c71, 0x8205200c, 0x820520f1, 0x12b223f1, 0xe4820100, 0x1812b021, 0x220df18e, 0x83120307, 0x6b002015, 0x8b490c80, + 0x03232b05, 0x26261323, 0x37363435, 0xbe4f1403, 0xdf3a0807, 0xfce7e3f2, 0xe96b64ff, 0x4f65bcc6, 0x6a59e0ef, 0xc6fb3a04, 0x73fe8d01, 0x9c2ab501, + 0x02c19765, 0x5544a0fe, 0x005a3801, 0xdbff0100, 0xf8034bfe, 0x21000006, 0x15b28e00, 0x66822322, 0x1eb00022, 0x41058c46, 0x0a200ca0, 0x4618a182, + 0xb62f1099, 0x1eaf1e9f, 0x5d031ebf, 0x011e2fb2, 0x830fb25d, 0x18212204, 0x2244821e, 0x182f21b0, 0x220cea4a, 0x50041802, 0x3e5e067f, 0x758c180e, + 0x1000270b, 0xb0d01ab0, 0x3c5f1021, 0x36152406, 0x18132033, 0x22079842, 0x18353233, 0x0808ce46, 0x3335234e, 0x21153335, 0xf5fe7702, 0x5a01b677, + 0x46a6b905, 0x3b270f3a, 0x925e617b, 0x9e9ef348, 0x040b01f3, 0xfe8ae9ad, 0xb2fefc75, 0x0dbf11c4, 0x70ed02bf, 0xfbfc825d, 0xa8abad04, 0x010000a8, + 0xecff5400, 0x4e04f903, 0x7d001d00, 0x1f1e16b2, 0x6708df5a, 0x75180c8b, 0x19211487, 0x093d4d0f, 0x2f191f25, 0x43710219, 0xb2230b69, 0x821b0003, + 0x04b4264c, 0x02031403, 0xa675185d, 0x13b2230e, 0x1c821619, 0x131cb226, 0x0bb25d01, 0x30210482, 0xb7751831, 0x21470818, 0x02122115, 0x0678593e, + 0xca7803e4, 0xf8fee474, 0xc0e40801, 0x07e404f5, 0x7d6e5b76, 0xfe5b010a, 0x68ae19a6, 0x64b06650, 0x02012701, 0x2901f719, 0x7560b6e2, 0xfea88d94, + 0x000200ec, 0x0600001e, 0x003a049a, 0x821f0016, 0x200922df, 0x05057021, 0x1d134018, 0x926eb020, 0x8300200d, 0x01b024e6, 0x4600b02f, 0x5e740d71, + 0x4301200e, 0x08200d6c, 0x290c116e, 0x11013130, 0x15161633, 0x00610614, 0x07062105, 0x8206324c, 0x32440816, 0x26343536, 0xf8fa0327, 0xc3e9e5c3, + 0xe6fe19fe, 0xafa81315, 0x5232024e, 0x02140a47, 0x6858edf3, 0x3a045664, 0xbc0387fe, 0x02c1a09f, 0x87fe7603, 0x01eef2fe, 0xaf0b05ca, 0xfdce01e3, + 0x58c1fec5, 0x0151484d, 0x8620eb82, 0xb120eb82, 0x1226eb82, 0x85001b00, 0x036a01b2, 0x6a012005, 0x02240903, 0x02b11b2f, 0x4f075548, 0x0b200cd7, + 0x0b201982, 0x20076344, 0x200c820f, 0x260c820f, 0x0b1101b2, 0x82391211, 0x04b221f8, 0x04220985, 0x5318b02f, 0xb0210dfd, 0x0c844304, 0x610bb021, + 0xf3820c01, 0x33112122, 0x1123f68a, 0x87331123, 0x012325ef, 0xf3a50179, 0x5b2df287, 0x9802f3f3, 0x64665aed, 0x019f025b, 0x25eb879b, 0x23fedd01, + 0xe2833a04, 0x464b5a31, 0xff010054, 0x030000ee, 0x000006f8, 0x187b0018, 0x2008a343, 0x129f4315, 0xc2820720, 0xcf900720, 0x0115bf25, 0x832fb25d, + 0x830f2004, 0x0f182204, 0x20de8315, 0x0e9b4318, 0x83070421, 0x46d88215, 0x00270bec, 0xd011b010, 0x611018b0, 0x8c430610, 0x43232005, 0x8b241083, + 0xb677e1fe, 0x08997418, 0xf38b8b2b, 0xb5041f01, 0x75fe8af1, 0x9e7418fd, 0xb5043407, 0x00a1a1aa, 0xfe860001, 0x0412049a, 0x000b003a, 0x4ab00046, + 0x834913ef, 0x1654180c, 0x0af94d09, 0x590bd254, 0x232d0964, 0x01112111, 0xf3a60179, 0xfef3b5fe, 0x057649b2, 0xfec6fb25, 0x8266019a, 0x00012e6d, + 0x06ebff88, 0x00b005c1, 0xb261001e, 0x5b471806, 0x0c5b5d0a, 0x180cf664, 0x180c0b90, 0x480c4b7b, 0x06220820, 0xa96d0400, 0xd01a210f, 0x14219283, + 0x05e56806, 0x11352624, 0xf1501133, 0x869e8205, 0x06390808, 0xe5d2f9c1, 0xcfe9716d, 0x5e67fdf3, 0x01017269, 0x6e61636d, 0xfffbb005, 0xa5a5eed6, + 0x0104d5ef, 0x8275fcfb, 0x03047781, 0x8374fcfb, 0x0304797f, 0x00010000, 0x05ebff70, 0x94c982ed, 0x07db42bf, 0x840c394a, 0x0c454cbf, 0x89071842, + 0x961520bf, 0x920620bf, 0x08c888bf, 0x01ed0526, 0x60c7bdda, 0xd5b8cb66, 0x534654f3, 0x4f5cf466, 0x3a045b4a, 0xdcc14efd, 0xc3dd8e8e, 0x51fdaf02, + 0x726c6c72, 0x00320789, 0xe0ff0200, 0x21040000, 0x12001806, 0x74001b00, 0xa34315b2, 0x10152205, 0x079162b0, 0x1b2f0f24, 0x1d560fb1, 0x07ec4b07, + 0x0f12b223, 0x06084709, 0x0b315118, 0x15850220, 0xb02f022a, 0x0bb01000, 0x1012b0d0, 0x69056a5a, 0x09200cd2, 0x44129243, 0x23260787, 0x33113335, + 0x92432111, 0x27420807, 0xdefea302, 0xe5e5c4f7, 0xae12fec0, 0x2201f3ae, 0x5beddefe, 0x04576365, 0x03c9fe3a, 0xd3adaece, 0xab3a0404, 0xcdfe3301, + 0x82fe5bfd, 0x69555965, 0x01000002, 0xedff9800, 0xc505cd06, 0x91002500, 0x9f790eb2, 0x8224200a, 0x182420c9, 0x870c016a, 0x07a0590c, 0x4500b025, + 0x8222b058, 0x10222726, 0x00b2593e, 0xe3832422, 0xb22f002a, 0x7101001f, 0x1c2408b2, 0x05200e83, 0x830c7b59, 0xd00f21e8, 0xd66c0582, 0x12b0240b, + 0x651cb0d0, 0xb2210c6b, 0x223c8418, 0x58013130, 0x002805a5, 0x26262317, 0x07062223, 0x26085167, 0x23000633, 0x48022422, 0x570806f1, 0x960bb594, + 0xf1ab0901, 0xfc182601, 0xa18e9312, 0xe9010bab, 0xa80216fe, 0x149695a2, 0xd3fe16fc, 0xf8feacf8, 0xfcb40393, 0xbe4f03fc, 0xfe9b1d01, 0x8b9deffa, + 0xe1c3ccdd, 0xe99c86f2, 0x01a1fbfe, 0x74fdca34, 0x0100b005, 0xecff8600, 0x4e04ba05, 0x95002300, 0x25240db2, 0x48084b47, 0x23200c3c, 0x2320f182, + 0x18079042, 0x2507024d, 0x584500b0, 0x198220b0, 0x3e102027, 0x040eb259, 0x08a9591b, 0x500e402a, 0xb05d020e, 0x04b0d000, 0x230ccd60, 0x0b0e08b2, + 0xb0222482, 0x4857100e, 0x1bb0210b, 0x230c9145, 0x0f1316b2, 0x0f262483, 0xd01eb010, 0xf0493130, 0x41162005, 0x0320050e, 0x24090d41, 0x2223020e, + 0x060c4124, 0x149d7926, 0xc1d20401, 0x28056047, 0x7c011adb, 0x7d0a85fe, 0x077e476e, 0xfed32e08, 0xf39e14fd, 0xde7102f3, 0x60b6e2ff, 0xabe6fe75, + 0x50688e8a, 0xfe64b066, 0x043afedc, 0x0002003a, 0x0500001c, 0x00b00517, 0x000e000b, 0x12c97d57, 0x630c0454, 0x0a200cef, 0x0a20fe82, 0x0d22fe83, + 0xb4830208, 0xef630d20, 0x840e2010, 0x21c78218, 0x01821123, 0x21032008, 0x21013301, 0x03032101, 0x73e17e83, 0x02fafe8f, 0x0002f506, 0xe0fdfafe, + 0x01a85301, 0x8356feaa, 0xb0052703, 0x680250fa, 0x9982f801, 0x00000a24, 0xa3824504, 0x10000b22, 0x1055998c, 0x21999614, 0x99860802, 0x230b6f5f, + 0x0fb2d004, 0x2320998d, 0x03829982, 0x07270339, 0xc35de402, 0x01f7685b, 0xab01e7a9, 0xf85cfef7, 0x01191964, 0x83e9fe17, 0x3a042a03, 0xc401c6fb, + 0x64640601, 0x2c9d8200, 0x070000ac, 0x00b00530, 0x00160013, 0xdd8b187d, 0x2f122212, 0x516d181b, 0x14874509, 0x407bb020, 0x0cf2670b, 0x0215b223, + 0x0cb07d04, 0x4f580620, 0x0ab02a09, 0x1006b0d0, 0xb2d00eb0, 0x23248416, 0x21013130, 0x2121bd82, 0x06634103, 0xa8681320, 0x21230805, 0x01a80103, + 0xf52b0168, 0xfafe0002, 0x72e27e8e, 0x98fafe8f, 0xfcfcdbfe, 0x53016202, 0x036702a9, 0x4150fa49, 0x01290773, 0x0555feab, 0x01b8fcb0, 0x26d782f9, + 0x0600009d, 0x823a0418, 0x001822d7, 0x41d78a80, 0xd7840775, 0x9a1c9f45, 0x100021d7, 0x23050b4c, 0xd001b02f, 0x300c9e67, 0x07b0d00b, 0x1001b0d0, + 0xb0d014b0, 0x17b2d015, 0x82ff8312, 0x133324da, 0x86230133, 0x132321da, 0x0805f04c, 0x27033321, 0xfe900107, 0xab01e7f8, 0xc35d6af7, 0x6df7685b, + 0x01f3f3ba, 0x1964f8ed, 0x02c40119, 0x41c6fb76, 0xb54107b1, 0x8afd2105, 0x2007b341, 0x34db8280, 0x00b0056e, 0x001d001a, 0x1e1bb27c, 0x3912111f, + 0xb0101bb0, 0x615a180d, 0x14945d0b, 0xde5f0c20, 0x20db8406, 0x260c8213, 0x593e1013, 0x831900b2, 0x00b021a6, 0x2c0da063, 0x0fb0d00e, 0x1000b0d0, + 0xb2d018b0, 0x2021851b, 0x0f416c19, 0x1716162a, 0x26112311, 0x07232326, 0x23220782, 0x06830622, 0x36363f08, 0x01210121, 0x7a042113, 0xfc05f1fe, + 0x688f7602, 0x8f7efc06, 0x03fc0375, 0xfe0f01fa, 0xfde40485, 0x2ffee98e, 0xd9042803, 0x018dfed8, 0x0b6f816c, 0x5c02affd, 0x90fe7e6e, 0xdbe16c01, + 0xe8828802, 0x0200a92a, 0x00008200, 0x3a046405, 0x4f6be590, 0x82052007, 0x550520be, 0x574a1476, 0x2ee5880c, 0x11000504, 0x04b03912, 0xd007b02f, + 0x591004b0, 0xda6d0b55, 0x1bb22105, 0x05202185, 0x3324e58e, 0x37363635, 0xec82d182, 0x35231525, 0x88272626, 0x821520ec, 0x823908e5, 0xfeccc502, + 0xfef403eb, 0x02bec6ea, 0x725e01f3, 0x2df2012f, 0x01036079, 0xd6fe9585, 0x0dd2ceb2, 0x24fedb01, 0xb3c7d311, 0x02727fb1, 0x015ffe03, 0xba7c6ea4, + 0x22016902, 0x30e38200, 0x080000a3, 0x00b005b3, 0x00230020, 0x241cb299, 0x21a18325, 0x4f18101c, 0x746308a3, 0x0c00610c, 0x490c0e57, 0x11200ca8, + 0x200bb94f, 0x260c8219, 0x593e1019, 0x840709b2, 0x4e0920fd, 0xb0300cd4, 0x0db01009, 0x1003b0d0, 0xb0d01cb0, 0x21b2d017, 0x0b202485, 0x2a0e835f, + 0x37341121, 0x11231121, 0x41211133, 0xf3410506, 0x1301310f, 0x3bc50221, 0xfcfc9ffe, 0x87fe3003, 0x84fee504, 0x3807f941, 0x917ffc05, 0x08020373, + 0x012efee9, 0xfd65a160, 0xfdb0059a, 0xfd85027b, 0x08fc4178, 0xadfd0937, 0x7c715c02, 0x390391fe, 0x0000aa01, 0x008f0002, 0x04760700, 0x0613413a, + 0x13411d20, 0x411d2005, 0xf7410e13, 0x580b2007, 0x13410bb6, 0x410b2030, 0xaa510813, 0x0f13410a, 0x13412485, 0x36352110, 0x420d1341, 0x0237121a, + 0xfe350195, 0x02f3f3b7, 0x03ecfea5, 0xc5eafef4, 0x01f202be, 0x422e735e, 0xb02f0a20, 0x58fe6494, 0x27fe3a04, 0x24fed901, 0x42c6d411, 0x28301425, + 0xaa0340fe, 0x27008807, 0xaa003000, 0x323102b2, 0x2406e163, 0xb000d028, 0x05874c2c, 0x9f180520, 0x17200bbb, 0x17200c82, 0x4207a657, 0x0520080e, + 0x230c545a, 0x110526b2, 0x7c2b4682, 0x182f26b0, 0x012610b2, 0x8240b25d, 0x60b42604, 0x02267026, 0xdd51185d, 0x0cb2230b, 0x28822623, 0x5111b021, + 0xb2380cc5, 0x5d012c0f, 0xb0102cb0, 0x29b0d029, 0x290fb42f, 0x5d02291f, 0x292c28b2, 0x30332a83, 0x2f30b0d0, 0x34013130, 0x35212326, 0x15043221, + 0x82070614, 0x23043804, 0x14150623, 0x26260717, 0x37363427, 0x35363633, 0x35232134, 0x18032033, 0x0807da4d, 0x85960264, 0x01e5fe7a, 0x0b01ed15, + 0x0c016e7d, 0x35e8f7fe, 0x8452987a, 0xa4b102a2, 0xfe89723f, 0x018989cf, 0xcf939410, 0xfe97eafe, 0x2104ceeb, 0xcfc76a5e, 0x2ca370b5, 0xe8c5fe57, + 0x416b6303, 0x7fb72899, 0x01028b86, 0xc7f3657d, 0x0a9b9f03, 0x1801e9fe, 0x02000009, 0x48fe3300, 0x1c068803, 0x30002700, 0x3f419800, 0x0754421a, + 0x2a0c3f41, 0xb11b2f12, 0x593e1012, 0x571005b0, 0xb2230b7b, 0x82051225, 0xb07c2deb, 0xb4182f25, 0x25502540, 0x24b15d02, 0x21094542, 0xb7420cb2, + 0x41122005, 0x30410c35, 0x2c292111, 0x41053041, 0x1622092d, 0xb05d1415, 0x0c2d4106, 0x2d413220, 0x41322006, 0x6308092d, 0xfe697374, 0xdc1701e4, + 0xd95761f8, 0x7e36d0f6, 0x96825190, 0x35a1a902, 0xf9fe776c, 0xa0e29591, 0xe9fed092, 0xcdebfe96, 0x473cfe02, 0x4f8da5b9, 0xac422477, 0x6204af96, + 0x3091416b, 0x877d70b6, 0x943f5001, 0x9b1203a9, 0x01eafe0b, 0x03000a17, 0xecff5f00, 0xc4051705, 0x17001000, 0x69001e00, 0x201f04b2, 0x04259d83, + 0xd011b010, 0x200582b0, 0x13bf6e18, 0x20081348, 0x0c1b660c, 0x0414b223, 0x243c820c, 0x2f14b07c, 0x723b8218, 0x14230c88, 0x411cb110, 0xe363092a, + 0x3435370a, 0x04202412, 0x22011712, 0x26210706, 0x36320326, 0x16162137, 0x49181705, 0xfd321125, 0x08b6a0a4, 0xb408bc02, 0x0ab39fa0, 0xb80a44fd, + 0x4918b202, 0x012b102a, 0xdbd9f0ef, 0xe5cafbee, 0x82ead9de, 0x184f20dd, 0x26086380, 0x001d0016, 0x4704b26a, 0xd7820537, 0xdd841020, 0x4b072967, + 0x30470c35, 0x0b275707, 0x861bb221, 0x2f1b2bda, 0x1b40b418, 0x5d021b50, 0xcf8913b1, 0x9018ed83, 0x13220c27, 0x80183634, 0x11210b8a, 0x20d68501, + 0x08e48513, 0xe47d4f4b, 0x1301da94, 0xe77b010b, 0xecfee395, 0x856bf701, 0x10fffd10, 0x856a6b84, 0x10000210, 0xa1270285, 0xe7fe89fd, 0xfca039ea, + 0x012e018a, 0x9293fe01, 0x02938889, 0x828295dd, 0x00010095, 0x04000010, 0x00c205f3, 0xb247000f, 0x0a655e02, 0x0cd29718, 0x0c875718, 0xb226d287, + 0x110f0c01, 0x67183912, 0x30250ea3, 0x37170131, 0x08b08213, 0x2307172a, 0x23010706, 0x61022101, 0x35e41b1b, 0x022d7a9c, 0xfe275418, 0x0efef498, + 0x8b010d01, 0xf7026f72, 0xd70197ac, 0x94fb7c02, 0x2005cf69, 0x24898220, 0x004e0418, 0x6d898311, 0xa7470a3f, 0x0cff510c, 0x1b2f0e2b, 0x3e100eb1, + 0x0501b259, 0x06754d0e, 0x0d818518, 0x12278982, 0x07173233, 0x84222326, 0x3324088b, 0x1414e301, 0x43cf5a7a, 0x200c1727, 0xfe0d3b22, 0x92fed3f6, + 0x616e01fb, 0x01be0161, 0x06c01622, 0xe2fc2a36, 0x3005e359, 0x0576ff5f, 0x002e0617, 0x00270013, 0x2805b257, 0x20608529, 0x079f78b0, 0x7b820d20, + 0x08196e18, 0x2608ef5e, 0x0db0d006, 0x8310b010, 0x18b12005, 0x230bff5f, 0x03b0d017, 0x0ca47f18, 0x30394782, 0x00100131, 0x35231507, 0x35030026, + 0x35370010, 0x00161533, 0x26342711, 0x26138227, 0x15150606, 0x82171614, 0x36550813, 0x17053536, 0xc6e9f3fe, 0x03effee8, 0xc6e91201, 0xfd0d01ea, + 0x79c67882, 0xc67b8485, 0xb2028079, 0x8bfedafe, 0x237e7e23, 0x1d017301, 0x01240155, 0x7271237a, 0xfe86fe23, 0xf5ce06d9, 0x23616023, 0xc74ccff5, + 0x5f6025fd, 0x00cff623, 0xff4f0002, 0x043d0488, 0x26d782b4, 0xb25a0025, 0x83272603, 0x5a0320d7, 0xc0510909, 0x08bd580c, 0xda822082, 0xb0101024, + 0x925dd00d, 0x8414200f, 0x4b1d20da, 0x1a260a99, 0x133130d0, 0xd0841234, 0xc6821220, 0xe4840220, 0x01350222, 0xdd88ca82, 0x5508dc84, 0xb8bddd4f, + 0xbfdfddbf, 0x02ddbbb8, 0x5a5a5250, 0x584fb850, 0x02b84f56, 0x2601da27, 0x1f6d6e1f, 0x11ddd8fe, 0x1dd9fedb, 0x011f6c6b, 0xa7fedd26, 0x8297b51e, + 0x60601fb2, 0x8395b221, 0x006821ae, 0x88000300, 0xb506ebff, 0x2a003f07, 0x46003d00, 0x30b2be00, 0xd1834847, 0xb0103025, 0x82b0d009, 0x44452005, + 0x29520673, 0x4c12200c, 0x75530b94, 0x08de610c, 0x07000922, 0x12204783, 0x210c974e, 0x716e0bb0, 0x1eb2230c, 0x2483120b, 0xb0d02339, 0x2ab01013, + 0x1012b0d0, 0xb0d036b0, 0x2cb02f36, 0x2f2cb0d0, 0x18082bb1, 0x2909b151, 0x32b0102c, 0x2f32b0d0, 0x148d39b1, 0xb0d0422e, 0x46b02f42, 0x2f46b0d0, + 0x32013130, 0x07fb5d18, 0x2223062c, 0x34112726, 0x22153336, 0x83521506, 0x333f0807, 0x33161611, 0x11353632, 0x13232634, 0x2e222315, 0x15222302, + 0x34352315, 0x021e3233, 0x35373601, 0x06141533, 0xcef40407, 0xd0f101f2, 0xe37272e3, 0xf304f0ce, 0x66665fcf, 0xf572695f, 0x83687101, 0x6a5a0809, + 0xbf8a5321, 0x86681430, 0xc94625eb, 0x4129fe6f, 0x3b60a903, 0xddfab005, 0xfbddeafd, 0xd5f69e9e, 0xfddd2002, 0xfd808ecc, 0x818e80ed, 0xfe820177, + 0x8e807379, 0x80130280, 0x86e3018e, 0x680a4b23, 0x0fdc2210, 0x87fe1a4f, 0x67683c52, 0x001f7831, 0x74000300, 0xd105ebff, 0x8341e305, 0xb2b32206, + 0x05834109, 0xb0100925, 0x82b0d03a, 0x41462005, 0x334d0683, 0x08644b0c, 0xb0101231, 0x00b0d000, 0x100bb02f, 0xb2d007b0, 0x410b1209, 0x2d233a78, + 0x412db0d0, 0x2d200d78, 0x26137841, 0x41b01036, 0x4141b0d0, 0x15200c78, 0x4108f653, 0x15260878, 0x32331614, 0x7b7a3736, 0x35352107, 0x081d7841, + 0xdcba3a4d, 0xc5b5d401, 0xb2c26361, 0xbbdc04d3, 0x43535b49, 0xec015e50, 0x42515e01, 0xbd495b54, 0xc18a5324, 0x8768152c, 0xc54625eb, 0x4130fe70, + 0x3b60a903, 0xcce54704, 0x91e7ccf8, 0x01c5e091, 0xc3e7cd03, 0x7cf57c75, 0xca6a7075, 0x84706aca, 0xe7012e0a, 0x094c2386, 0xdc221068, 0xfe1b4e0f, + 0x07744185, 0x88000230, 0xc106ebff, 0x1e001107, 0x7f002600, 0xaf6906b2, 0x4a062005, 0x9f4409e5, 0x0732540c, 0xd004b026, 0x0d0806b2, 0x67061666, + 0xb02d0a9d, 0x15b0100d, 0x2f15b0d0, 0xb01011b0, 0x2608821a, 0xd01eb010, 0x832f1eb0, 0xd0252c17, 0xb02f25b0, 0x26b0d026, 0x4220b12f, 0x26200abc, + 0xb0226c83, 0x31552f23, 0x35252720, 0x15211721, 0x39553523, 0x39fc2714, 0xfe015503, 0x4155b5a6, 0x7ae7261b, 0x007f7f7a, 0x05455502, 0x84b10521, + 0x8a8b20f3, 0x182520f3, 0x5513f77e, 0x1e240c40, 0x1eb11b2f, 0x231cad4f, 0x150806b2, 0x89110d56, 0xd01f23ff, 0xff8d1fb0, 0x4d181f20, 0x01210882, + 0x1c715511, 0x7955ff87, 0x9dfc2714, 0xfe043803, 0x8155b5b2, 0x7bfc221b, 0x2eff827b, 0xfe660001, 0x05b6048c, 0x001800c5, 0x7c17b255, 0x48180ab5, + 0x00200c09, 0x0020ea82, 0x26105d77, 0x0eb0100a, 0x6a0ab0d0, 0x97180da7, 0x30320dea, 0x11230131, 0x11350026, 0x33241234, 0x23150020, 0x7b442110, + 0x17300805, 0xfb340333, 0x8d00ffd3, 0x01a30101, 0xfc1f0100, 0xa98cddfe, 0xfe9f8aa9, 0x2066018c, 0x01f94701, 0x1801af11, 0xe9f7fe9b, 0xbcdf2601, + 0xdfb6edfe, 0x00292482, 0x0389fe5c, 0x004e04f3, 0x20ab821a, 0x0aed7e19, 0x980cab5f, 0x840f20ab, 0x461220ab, 0xab820a54, 0x0e891920, 0x0228ab85, + 0x36343535, 0x16323336, 0x0ba64418, 0x33173708, 0xb3f3d502, 0x92db79d3, 0xe56fc67c, 0x82715874, 0xfe98707e, 0x206a0189, 0x1cdc2301, 0x6789fc9b, + 0x7a5b76bb, 0xa11ba8bd, 0x010002bb, 0x00006d00, 0x3e059304, 0x01821300, 0x590eb021, 0x10220a94, 0x6582593e, 0x25070528, 0x25132303, 0x03840537, + 0x82033321, 0x0249080f, 0x4821015b, 0xafb5ddfe, 0x47dffee1, 0xfeca2501, 0x230149de, 0x01e4acb9, 0xe0fe4c25, 0x80acc101, 0x01c1feaa, 0xab80ab8e, + 0x82ab6801, 0xfe4601ab, 0xaa7fab6b, 0x66fc0100, 0x39ffa204, 0x0700fd05, 0xb0001200, 0x03b12f00, 0x081d4606, 0x15366882, 0x27213727, 0x17fd1517, + 0x220201b1, 0x2005b101, 0x6cee017e, 0x3782dc01, 0x17057336, 0x15066dff, 0x30000f00, 0x2f0bb000, 0xb0d007b0, 0x00b12f07, 0x2c0a8943, 0x04b0100b, + 0x2f04b0d0, 0xb1100bb0, 0x8217890c, 0x32400855, 0x35231515, 0x04222334, 0x33352307, 0x7ffe2436, 0x366a88ee, 0x298be2fe, 0x18017927, 0x22dc1506, + 0x01776810, 0x00770186, 0x7bfd0100, 0x72fe1605, 0x05006006, 0xb0000c00, 0x05b02f01, 0x2f05b0d0, 0x35304382, 0x07170733, 0x01bd7bfd, 0xdc05523b, + 0x44709684, 0xa5202b82, 0x9c202b82, 0x03212b87, 0x05c0452f, 0x273a2b82, 0x15332737, 0x3b52f7fd, 0x1605bd01, 0x84967044, 0x24fa0800, 0xbf01c4fe, + 0x5582af05, 0x27001a37, 0x42003500, 0x5c004f00, 0x7f006a00, 0x2f45b000, 0xb02f53b0, 0xb8b31860, 0x2f022708, 0x2002b11b, 0x5818593e, 0x452a0ceb, + 0xd010b010, 0xb11045b0, 0x3041094c, 0x17b02708, 0x1053b0d0, 0x05831eb0, 0x8a5ab121, 0xd0252617, 0xb01060b0, 0x2105832b, 0x178a67b1, 0xb0d03226, + 0x3fb11038, 0xac821189, 0x32363422, 0x23083842, 0x33363401, 0x13200d89, 0x22200d88, 0x08d0b318, 0xbc782320, 0x8c288205, 0x860c8c35, 0x89348242, + 0x82232041, 0x11fd3f0d, 0x7074be73, 0x332e3033, 0x5d74de01, 0x3571755f, 0x48332c2e, 0x745f5d75, 0x335c3570, 0x1382cbfe, 0x2e240982, 0x4ffd332d, + 0xfd222887, 0x3286744d, 0x87defe21, 0x82352028, 0x333b8308, 0xf304332d, 0x54686854, 0x3035372e, 0x6854ebfe, 0x34315567, 0x092a0982, 0x54686755, + 0x2e373431, 0x1d83f9fd, 0xfe210983, 0x232785e4, 0x1a052e37, 0x278a3188, 0x85675521, 0x002e083b, 0x4dfa0800, 0x8c0163fe, 0x0400c605, 0x0e000900, + 0x18001300, 0x22001d00, 0x2f002700, 0x2f21b000, 0xb02f16b0, 0x0bb02f12, 0x2f1bb02f, 0x264326b0, 0x0c5c5205, 0x2f023908, 0x1202b11b, 0x3130593e, + 0x23031705, 0x13270313, 0x37010333, 0x05251505, 0x05352507, 0x17253701, 0x05070105, 0x27032527, 0x01133703, 0x03071317, 0x7a0b50fe, 0x0c3a4660, + 0x3c080482, 0x010d1d02, 0xfba6fe4d, 0xb3fe0d75, 0x9c035a01, 0x44400102, 0xf3fcdbfe, 0x45c0fe02, 0x112b2601, 0x03c64194, 0x42941160, 0xfe0e3cc4, + 0x046101ad, 0x52010ea2, 0x11fea0fe, 0x47627c0c, 0x0804833b, 0x10ae013c, 0xfcc84499, 0x4599118e, 0x02e402c8, 0xfe454601, 0x02e3fcd5, 0x0147bbfe, + 0xffff002b, 0x7efe9400, 0x2407dd05, 0xdc002600, 0x27000000, 0x1c01a100, 0x07013e01, 0x80041000, 0xeb82c6ff, 0x5218b020, 0x20270897, 0x0db0593e, + 0x833130dc, 0xfe862635, 0x05e4047e, 0x203582d9, 0x233585f0, 0xf3ff9700, 0x03213583, 0x20358e87, 0x5b35871c, 0x6226082b, 0x1b001200, 0x2b5b7700, + 0x0c994712, 0x1b2f1124, 0x421811b1, 0x11201070, 0x0cef4a18, 0x0d02b227, 0x39121109, 0x08315bb0, 0xb0d00c23, 0x0d974a02, 0x221e2e5b, 0x5b153335, + 0x0523202e, 0x5bfefd05, 0x0526052e, 0xb2b2ab05, 0x2c5b90fc, 0x00022a07, 0x04000094, 0x00b005d9, 0x22d1820e, 0x5b04b24f, 0x042005fd, 0x09a16018, + 0x680c6877, 0x16220874, 0xc3790103, 0x64b12005, 0x87180af8, 0xff620e0f, 0x21310805, 0x14150432, 0x27071707, 0x36132306, 0x27263435, 0x32211121, + 0x01372737, 0x2d02fd91, 0x751f01f4, 0x79886d7a, 0x901cf9aa, 0x01c9fe7e, 0x733a4f30, 0x78a0186e, 0xc1260807, 0x96648777, 0x35430137, 0x028d764a, + 0x801604fe, 0x02000064, 0x60fe7c00, 0x4e043004, 0x22001300, 0x17b27000, 0x937c2423, 0x10b02105, 0x69062748, 0x36700c24, 0x0c21630c, 0x2208e572, + 0x82071009, 0x0eb22141, 0xb0210684, 0x0d306110, 0xed550720, 0x8601200e, 0x272221c9, 0x13738f18, 0x1729d582, 0x6e300436, 0x59686f6a, 0x7b8f1870, + 0x32462e0f, 0x22596e6a, 0x97f41202, 0x3678637a, 0x828f1875, 0x7b213310, 0x00586764, 0x008f0001, 0x07340400, 0x00090010, 0x6018b236, 0xb024093d, + 0xb0584500, 0x280cb64f, 0xb11b2f04, 0x593e1004, 0x0f3e6cb0, 0x1523013b, 0x11231121, 0x04331121, 0x60fd0834, 0xf3b202fd, 0xfb09ed04, 0x01b0051c, + 0x285f8260, 0x0300007e, 0x0073055b, 0xb15b1807, 0x106f5a0c, 0x29156172, 0x5b033311, 0x01f316fe, 0x946cf2eb, 0x39012105, 0x9b315182, 0x9d04c6fe, + 0x1400b005, 0x0fb25e00, 0x12111615, 0x081c7b39, 0x540c0477, 0x1320086c, 0x0dcc4018, 0x09130322, 0xb0273382, 0x09b02f03, 0x510ab110, 0x03200a2b, + 0x2f0f2f69, 0x20331121, 0x00101100, 0x36322723, 0x23250235, 0x2908e683, 0x60fd3704, 0x012201a8, 0xf3f6fe3c, 0x02888301, 0xfcbcabfe, 0xe4049c03, + 0xcdfe5ffe, 0xf4feecfe, 0xb3bad6fe, 0x097b01c2, 0x895087fd, 0xfe7e2e05, 0x04db03e2, 0x0015003a, 0x160bb24c, 0x20ad8417, 0x05f3440a, 0x0c034a18, + 0x532f1221, 0x421806da, 0x03220e9a, 0xad850a14, 0x240bf551, 0x21013130, 0x2a9b8215, 0x06061415, 0x35362707, 0x84232634, 0x0324089c, 0x492bfe46, + 0x20010101, 0x5573ab5e, 0x4e8e9bde, 0x03c802f3, 0xfafee576, 0x8dc260dd, 0xd44aae1d, 0x3afe9781, 0xff278c82, 0xfe1600ff, 0x8205089a, 0x002634a2, + 0x000000da, 0x06510207, 0xff0000b6, 0xfe1e00ff, 0x82b4069a, 0x00262222, 0x211785ee, 0x17846505, 0x9afe9b24, 0x2f837f05, 0x852c0221, 0x30042117, + 0x8f241784, 0xc2049afe, 0xf1202f84, 0x03211785, 0x2c078273, 0x00900001, 0x05360500, 0x001400b0, 0x05f15a62, 0x200c344f, 0x20ed820c, 0x14337f0c, + 0x19820a20, 0x3e100a27, 0x0a0fb259, 0x26f8830c, 0x9fb22f0f, 0x775d010f, 0xb2230ba6, 0x830f0801, 0x053d081a, 0x100fb0d0, 0x30d012b0, 0x21020931, + 0x23152301, 0x23112335, 0x33113311, 0x33153335, 0xfe0d0501, 0xfead017c, 0x41d3fec1, 0xfdfd59a3, 0x0137a359, 0xfdb0051b, 0x02f5fc5b, 0xfde9e96d, + 0x240b8293, 0x02fefe9a, 0x06fb7c66, 0xc382ae20, 0x6f181420, 0xc7430757, 0x0ca6410c, 0x0c535018, 0xab820320, 0xab830320, 0x20055678, 0x267818b0, + 0x01b2220d, 0x05495209, 0x0eb0d022, 0x0320a688, 0x2708a68e, 0xfe940413, 0xfe5601c4, 0x9b2fd8cb, 0x57f2f257, 0x04cf279b, 0xfdfefd3a, 0xb2ac01c8, + 0x0454feb2, 0xc750fe3a, 0x00b001c7, 0x342aa582, 0xa2060000, 0x0e00b005, 0x8d6f6300, 0x0744410a, 0x5e0cb74b, 0xcc840c60, 0x0827a583, 0x12110206, + 0x7808b039, 0xb0200c09, 0x0d0e7018, 0x010cb223, 0x42421808, 0x212b0809, 0x33112135, 0x01012101, 0xadb60321, 0x0227fefc, 0xad018bd5, 0x0cfe3601, + 0xd0fe1f02, 0x90fd7002, 0xfdc4ec04, 0xfd64029c, 0x8209fd47, 0x003d26a1, 0x04a80500, 0x20a1823a, 0x122f706d, 0x950cad4b, 0x0a0921a1, 0x092aa184, + 0x092fb22f, 0x8cb27101, 0x3e750109, 0x21ab8f0d, 0xab940900, 0x7b402d08, 0x026afef2, 0x2a016c88, 0x78fe2d01, 0xc5fea801, 0x54feac01, 0xfec47603, + 0xfdb00150, 0xffcdfdf9, 0xfe9400ff, 0x05db059a, 0x002600b0, 0x2a07cf42, 0xff00008c, 0xfe8600ff, 0x82d5049a, 0x002622c3, 0x06cf42f4, 0x07828620, + 0x94000126, 0x83070000, 0x0d222f82, 0x995e8900, 0x0ccf4212, 0x2215375f, 0x66060201, 0x9f26064a, 0xb25d0101, 0xe082016f, 0x0483df20, 0x01010f24, + 0x1382b272, 0x3fb27122, 0xb4280e82, 0x013f012f, 0x7cb27202, 0xb0212482, 0x0ce65702, 0x1801b021, 0x220fd056, 0x45211121, 0x233a067c, 0x91013311, + 0x67038b02, 0xfdfc95fd, 0x03fdfd75, 0xc35e0252, 0x870213fb, 0x874479fd, 0x00002306, 0xd7826605, 0x68000d22, 0x6412815e, 0xbf960c2e, 0xbf830c20, + 0x01b07c24, 0x676b182f, 0x329eae06, 0x02a50171, 0xf3a3fe50, 0xf3f35bfe, 0xc3017702, 0x728afcc4, 0x002705cb, 0xfe9b0001, 0x82ef07c4, 0x00162ca8, + 0x1710b26b, 0x39121118, 0x4507b000, 0x7c650525, 0x394b180c, 0x45002f08, 0x2f10b058, 0x1010b11b, 0x01b2593e, 0x5a410715, 0x07b02405, 0x4508b110, + 0xaa670ad1, 0x5815200e, 0x30220c15, 0xde450131, 0x23112611, 0x14052111, 0x0ce0457d, 0xfdfc9128, 0x7904fc7f, 0xe1454103, 0x1889200e, 0x2c09b95f, + 0x06e6fe7e, 0x003a04ba, 0xb2590018, 0x064d4f12, 0x2006d266, 0x20a58217, 0x07ef4617, 0xb282cc84, 0xbf83b020, 0x2307f245, 0x081701b2, 0xb96cbf85, + 0x4917200c, 0xad850c96, 0x4506f045, 0xaf8309f1, 0x7d0a042f, 0x2c010701, 0x5573ab5d, 0x9aa56975, 0x05c6737f, 0xfe940231, 0xbf61defb, 0x28ad1d8e, + 0x9782678f, 0x790336fe, 0x673008a7, 0xd705ebff, 0x2500c505, 0x89003200, 0x343316b2, 0x16227d83, 0x7e18b010, 0x554a0705, 0x821d200c, 0x441d20bf, + 0x05480765, 0xd0002808, 0xb22f00b0, 0x4a1d0402, 0x8518064c, 0xb0230ded, 0x6bb11004, 0x45180dc8, 0xb02a0bd9, 0x29b01002, 0x101db0d0, 0x51182fb1, + 0x222a0c99, 0x22230627, 0x35270224, 0xab541234, 0x14152705, 0x37323312, 0x10821126, 0x1232332d, 0x07101511, 0x14013316, 0x82361716, 0x266e0811, + 0x15062223, 0xb3dfd705, 0xfebbb794, 0x7d03a9d4, 0x7e668ce1, 0x2931b2db, 0xc2b8ede2, 0x6a5cbbf3, 0x63658efd, 0x545860a2, 0x4747155e, 0xbf3601ae, + 0x1e01afc9, 0xbde1d4a1, 0xf9fed7b8, 0x4401cb07, 0x3501f0cb, 0xfafebffe, 0xcadafec6, 0x84190214, 0x018f48d5, 0xabaed509, 0x0200a1af, 0xebff6100, + 0x4e04c904, 0x2e002200, 0x04b29000, 0x7b5a302f, 0x49232006, 0xea5d06f5, 0x2f1a240c, 0x521ab11b, 0x00201410, 0x00271982, 0xb2593e10, 0x411a0402, + 0x0b200628, 0x6a0dcd65, 0x00240e3d, 0x0322b110, 0x2909994e, 0x25b01002, 0x101ab0d0, 0x28412bb1, 0x11002611, 0x33123435, 0x05dc5715, 0x26373322, + 0x07b28b18, 0x07141528, 0x14013316, 0x10823617, 0x23265b08, 0x04150622, 0x7a93bac9, 0xd4fee590, 0x4b40aadb, 0x8f257d9a, 0xbd9694b6, 0xfe584d81, + 0x3d63780e, 0x123b3231, 0x42013936, 0xcf420401, 0x04ca0c01, 0xa6497b94, 0xe29502cc, 0xffeabb7a, 0x94d377cd, 0xaa8f0111, 0x7ba9636c, 0x6a78876b, + 0x2900ffff, 0x22059afe, 0x2600b005, 0x1d453c00, 0x00d32c06, 0x00ffff00, 0x049afe1f, 0x823a0427, 0x855c2017, 0xd8022117, 0x01260782, 0xa1fe2d00, + 0x2f82b706, 0x51000f25, 0x430db000, 0x082005d0, 0x10b26318, 0x18075d42, 0x20088375, 0x0cb14902, 0xd005b024, 0x49180eb0, 0x3a080dcb, 0x3130d00a, + 0x21352101, 0x21112115, 0x33113311, 0x21112303, 0xa0fe8d01, 0x9ffebe03, 0xb0fc8102, 0xd1fbe714, 0xc4c4ec04, 0xe604defb, 0xd5fd1cfb, 0x00005f01, + 0xfe260001, 0x823a05bf, 0x000f22a5, 0x588d884d, 0x0f200ca3, 0x2106f76b, 0x784503b0, 0xd000230d, 0x808d0fb0, 0xb0100328, 0x06b0d008, 0x8984b010, + 0x89822320, 0x89888182, 0x02f51b25, 0x7501dbc3, 0x0325067a, 0xfdc3c377, 0x087c754b, 0x00ffff2d, 0x059afe8e, 0x00b005ad, 0x41e10026, 0x042d052d, + 0xff00005e, 0xfe5f00ff, 0x04a4049a, 0x2017823b, 0x211785f9, 0x07825503, 0x80000126, 0xe1040000, 0x18242f82, 0x05b25000, 0x18065d44, 0x41084158, + 0x9161073c, 0x0749410c, 0x0e05b229, 0x39121100, 0x832f05b0, 0x690520ae, 0xb02a0c08, 0x3130d011, 0x17161101, 0xb8821716, 0x82373621, 0x11232304, + 0x3b600706, 0x11370805, 0x4f027d01, 0x6ca36e35, 0x60fdfd64, 0xfaf6a370, 0xfeb00501, 0x2739982c, 0xfe2b0105, 0x02190adc, 0x0250faa7, 0xeb0a183c, + 0xdfea06e5, 0x0000cd01, 0x00740001, 0x82f50300, 0x001624bd, 0x4506b252, 0xa58306c3, 0x460c3c55, 0xde4d0c68, 0x010f2108, 0x22059f5d, 0x18182f0f, + 0x200c3564, 0x08e14904, 0x9a8a2120, 0xb3823320, 0x2608b186, 0x45f3f503, 0xbeb6a331, 0x8201f201, 0xf33b3ba3, 0x050e6901, 0xd0138b8a, 0xfe5001b1, + 0x011facb0, 0x06effe0b, 0x820c020e, 0x00842c9d, 0x05e50400, 0x001100b0, 0x5c05b247, 0x83840a11, 0x61074341, 0x7a6a0cb4, 0x01052108, 0x65064341, + 0x30220b5e, 0x83833331, 0x04203322, 0x08067564, 0x11072235, 0xb2a0fd84, 0x0a010601, 0x7e01fd02, 0x05a4ae96, 0x29c2fdb0, 0x31fee5e7, 0x768bcf01, + 0x005afd2a, 0xff160002, 0x05bc05e9, 0x001c00c4, 0xb2670024, 0x45262516, 0x57440679, 0x0c451807, 0x083d440c, 0x0e001e22, 0x1e212783, 0x6650182f, + 0xd004290c, 0xb0101eb0, 0x00b0d00a, 0x200d444e, 0x0e31630e, 0x0020052e, 0x26263511, 0x17143335, 0x17241234, 0x6c080d82, 0x14152115, 0x37323316, + 0x01060617, 0x26343521, 0x03062223, 0xfed2fedc, 0xb5a79baa, 0x0801948d, 0x0108019e, 0xcb98fc22, 0x31acb1bd, 0x05fed843, 0x949a6c02, 0x0117b08e, + 0x3c2b0154, 0xb6aad418, 0x1c01ae2a, 0x9cfe01a0, 0x3584b9fe, 0xc546d7ca, 0x6c032e28, 0xddc0b81f, 0xff020000, 0x04ecffcb, 0x004e048b, 0x0021001a, + 0x2220b28f, 0x20b98323, 0x09135c20, 0x880c5a4b, 0x001c22e1, 0x3327830d, 0xbfb42f1c, 0x021ccf1c, 0x1c5fb45d, 0x71021c6f, 0x2f1c1fb4, 0xb2280682, + 0x5d011c8f, 0xff1cefb4, 0xb1210b82, 0x0adf4711, 0xb0d00423, 0x0702411c, 0x210a6f46, 0x4e8517b2, 0xaf180d20, 0x05240efa, 0x27272422, 0x25050941, + 0x32332436, 0xa5181112, 0x3408097b, 0x26352101, 0x02062226, 0xe6fed4d8, 0x86820314, 0x011f68a9, 0xf1ddbb07, 0x9d0b3dfd, 0x8467a877, 0x6dfeda41, + 0x7208cf01, 0xfb147aca, 0xc11d32d1, 0xc5309593, 0x84a518f3, 0x9602350a, 0x8c7d7a12, 0x90000100, 0xed04bffe, 0x1600b005, 0x15b26800, 0x20060543, + 0x05f84410, 0x0ce34f18, 0x3a110545, 0xb2593e10, 0x11020407, 0xb07c3912, 0xb4182f07, 0x07100700, 0x0ab05d02, 0x4810b0d0, 0xb0220cb7, 0xa7181007, + 0x01200dee, 0x09457c18, 0x00164008, 0x23001015, 0x02112027, 0x95012125, 0x71fdfd08, 0x3201b201, 0x01e922fe, 0xf4f0fe00, 0x02090101, 0xf8feaefe, + 0x8ffd7102, 0xa4fdb005, 0x8afd5c02, 0xf9d7fe1f, 0xd3fef3fe, 0x016f01c2, 0x8200067a, 0xfe8e26c1, 0x044304ea, 0x22c1823a, 0x490db25a, 0x315f0d8b, + 0x0cd7430c, 0x23073945, 0x0f1514b2, 0x1420c184, 0x4025c182, 0x02145014, 0x0b35435d, 0x1400b223, 0x241e820e, 0x16013130, 0x06cb4816, 0x26342723, + 0x08c08827, 0xafcd0222, 0x73aa5ebc, 0x8d02e055, 0xf2f2ae8b, 0x01410155, 0x2961022d, 0xba60ade3, 0x47ad1c88, 0x098576ca, 0x2705144d, 0xffffb001, + 0x7efe2d00, 0x2a06c34b, 0x000000dd, 0x04100007, 0x82c6ff7e, 0xfe212417, 0x82e5047e, 0x002622c1, 0x231785f2, 0xc6ff8803, 0x9b2cd982, 0x13054bfe, + 0x1400b005, 0x0ab27600, 0x0a355e18, 0x210c9a4e, 0x6a182f03, 0xa2490ab1, 0x53b02007, 0x122608d3, 0x02b2593e, 0xe3841200, 0x109d6b18, 0x1178b020, + 0x02b0210d, 0x700c2359, 0x142107a1, 0xc9731806, 0x21250808, 0x01112311, 0xfd7f0297, 0x3c45a9be, 0x7b3e240e, 0x05fc81fd, 0x0283fdb0, 0xb718fa7d, + 0x0cc711c6, 0xfd9802ba, 0x06c14b97, 0x044bfe23, 0x24d58209, 0xb26f0014, 0x7bbd8f0b, 0xbd961436, 0xbd890320, 0x50024025, 0xa55d0202, 0x8e0620b6, + 0x01713fb6, 0xba01f3a5, 0x0f3a45a6, 0xfe7c3b27, 0x3a04f35b, 0xc3013dfe, 0xc1b385fb, 0xc00dbf11, 0xae82e701, 0x2f553a20, 0x4de82007, 0x002d0969, + 0xff8b0410, 0x00ffffc6, 0x047efe86, 0x09694de2, 0x03100023, 0x24178485, 0x077efe94, 0x202f8431, 0x05bd4131, 0x84d40521, 0xfe8f2417, 0x8441067e, + 0x85f3202f, 0xe4043017, 0x0200c6ff, 0xebff5100, 0xc4051e05, 0x18001600, 0x451af374, 0xf07007e1, 0x740d2008, 0x0d2305d2, 0x4100b02f, 0x74180ca4, + 0x0d200ff3, 0x2a0ca55f, 0x20013130, 0x14151100, 0x82270402, 0x21353f07, 0x22232626, 0x37270707, 0x36320136, 0x14152137, 0x01710216, 0xa06d0140, + 0xfea9e3fe, 0x7a18fedc, 0x1b360900, 0x962901a6, 0x2ffd12be, 0xfec405ba, 0x6bb6fe8c, 0xb1c2fec1, 0x7a180101, 0x0d300804, 0xdafcfa4a, 0xbfb91fbd, + 0x5b000100, 0x4b04ebff, 0x1b26ff82, 0x0bb26e00, 0x416f1d1c, 0x58022008, 0x621806d0, 0x2a490d79, 0x04b2230d, 0x30820002, 0x0b1bb223, 0x29068202, + 0x2f1bb07c, 0xd005b018, 0x0e8410b2, 0x4c0bb021, 0xb0240c51, 0x19b1101b, 0x2a0cfa64, 0x17213521, 0x15161601, 0x18230414, 0x080f4651, 0xfdff022d, + 0x01910392, 0xdac886fe, 0x8beae5fe, 0x87fc7ee2, 0x99907968, 0xe4048c91, 0x4ffea3cc, 0xc5c2ea18, 0x83bf67e8, 0x647f805f, 0x82ac8594, 0xfe5d2ac5, + 0x04460475, 0x001b003a, 0x20c5885f, 0x0507450b, 0x1c22c884, 0xcb55593e, 0x04b2220b, 0x86b18300, 0xc6b782b8, 0xf44a08b6, 0x8c039bfd, 0xcb88fe01, + 0xebeafed7, 0xf37be489, 0x947a6c89, 0x038f939a, 0xfe9bc476, 0xbfe91943, 0xbf68eac2, 0x80856081, 0xab839669, 0x00ffff00, 0x044bfe34, 0x00b00589, + 0x52b10026, 0x02260000, 0x0029a426, 0x01540207, 0x1d830035, 0x49fe2d24, 0xd582a203, 0xec00262c, 0x27000055, 0x9dff2602, 0x1f847aff, 0xfeff0b2a, + 0x2900ffff, 0x51054bfe, 0x220a1f4b, 0x84c30354, 0x821f2037, 0x84552055, 0x005c2837, 0x02070000, 0x82c70254, 0x00022107, 0x04216282, 0x2e2f8283, + 0x0014000b, 0x1504b252, 0x39121116, 0x181004b0, 0x4808e54d, 0x6e520c9d, 0x01002208, 0x05277203, 0x0e246618, 0x7c00b021, 0x112b0f90, 0x22211133, + 0x34352626, 0x82013724, 0x06350809, 0x17161415, 0xfdfd8603, 0x80ee9dda, 0x01eb1501, 0x7cd7fe34, 0x03798b92, 0xfa15029b, 0x88d47450, 0xfd03fccc, + 0x8906022f, 0x03917475, 0x00020000, 0x06000068, 0x269f82b0, 0x00210018, 0x4707b262, 0x072405cd, 0xd019b010, 0x46054450, 0xcd470cc5, 0x08072308, + 0xc7821100, 0x2e780720, 0x11b2210f, 0x19231885, 0x4307b0d0, 0xb02a0c56, 0x21b01019, 0x213130d0, 0xaa832422, 0xb6822120, 0x3636332e, 0x27263637, + 0x07161633, 0x25070606, 0x0224bc87, 0xe2feec72, 0x3308b984, 0x6c5e4bfc, 0x1d210205, 0x02261ff5, 0xfeccf304, 0x7dd6feb1, 0xfd7a8e90, 0x03faced3, + 0x1afb1502, 0x4a7d8a02, 0xcc5e4cd9, 0x03fcd445, 0x8a0602ca, 0x01927574, 0x5e31d182, 0x7f06e7ff, 0x1f001806, 0x86002b00, 0x2d2c19b2, 0x82a98211, + 0x862a207e, 0x2f0627d1, 0x2206b11b, 0x4b18593e, 0x5a450944, 0x82182007, 0x025f1819, 0x05b22310, 0x41831803, 0x98721820, 0x8410200d, 0x1ab22115, + 0xb0210684, 0x0c914903, 0x181cb021, 0x220ca87f, 0x18133130, 0x21077e42, 0xf5841606, 0x17332733, 0x020e0716, 0x06270423, 0x27022223, 0x22232601, + 0x05b04906, 0x5e276108, 0x65a3c3e4, 0x434e02f3, 0x04048274, 0x2f17ec40, 0xe27d0203, 0x55fffe8c, 0xe0b9cb6b, 0x47ae020b, 0x7a7f7383, 0x06458d76, + 0x0a010e02, 0x02783601, 0x4f4ffb42, 0xa9b70269, 0xb759d5be, 0x85f9a883, 0x01b3b704, 0x5101de05, 0x9ecdc168, 0x004472aa, 0x3c000100, 0xe305e7ff, + 0x2900b005, 0x23b26600, 0x0add5518, 0x0cf35118, 0x2208a374, 0x50092a01, 0x895906ab, 0x1809200b, 0x210c516e, 0xb57c0fb2, 0x50222005, 0xb2220c05, + 0x3a83221a, 0x3520ef82, 0x2a056f6b, 0x16213521, 0x07141504, 0x88151316, 0x841620f9, 0x26063bf9, 0x26343527, 0x93a7e623, 0xfef3fe84, 0xfa6401a5, + 0xf6ff0601, 0x333c0105, 0xf7827265, 0x1af53008, 0x7a02022b, 0xb2a78ada, 0x02677c08, 0x6d01cd62, 0x01cdd175, 0x64e6ccd3, 0x4dfefe3f, 0xb6024939, + 0x62d5bea3, 0xf8a967ca, 0xaaa70485, 0x827e6e3e, 0xff2f2de5, 0x04fe04e2, 0x0024003a, 0x250fb263, 0x09959518, 0x7f181d20, 0x0e200b37, 0x0e230c82, + 0x18593e10, 0x230b8745, 0x1d0e07b2, 0xb222f182, 0x06832516, 0x2f16b024, 0x344514b1, 0x1db02109, 0x0c9e4b18, 0x1422b223, 0x232b8216, 0x06253130, + 0x8206c941, 0x060622cf, 0x26cf8423, 0x33272323, 0x82343536, 0x21460806, 0x07101616, 0x01031716, 0x605a4e02, 0xec410403, 0x0401182d, 0xa09ebce9, + 0x02e6a208, 0xffcbb9c2, 0xcb140106, 0x06b9b0e4, 0x8f0258eb, 0x86a9967f, 0xf2cc3980, 0x48837103, 0x8304bd7f, 0xa602c396, 0x304acafe, 0xd58200ac, + 0xbafe482e, 0xb0053704, 0x62002200, 0x24230bb2, 0x00227b82, 0x654517b0, 0x0cbe4105, 0xd8821b20, 0xd8821b20, 0x0901b223, 0x28be411b, 0x4e181b20, + 0x13200e1c, 0xc082bf82, 0x27212122, 0x2908b741, 0x06141533, 0x36362707, 0xb1412337, 0x973b0805, 0x8191ce01, 0xeafeebfe, 0xef2e0103, 0xe3e40301, + 0x5a64cd03, 0x08382483, 0x7e033ca3, 0xc35c0274, 0xeb6f7301, 0xc9dc03c3, 0xfe4766df, 0x63ac86f6, 0x394d4bd8, 0xb1314977, 0x83857184, 0xfe7426cf, + 0x041a04a9, 0x20cf843a, 0x20cf8606, 0x43cf8a18, 0x5018078b, 0x012208e0, 0xcf871c09, 0x4e0c366f, 0xb2210b46, 0x058e4210, 0xfe461c20, 0x3130290c, + 0x32332713, 0x23263435, 0x3228cf82, 0x14151617, 0x15171607, 0x4108d08d, 0xe101b323, 0xfe636bd2, 0x200104e1, 0xad6a78e3, 0x68bb02b1, 0x38268355, + 0x012ba606, 0xb39b01c3, 0xc1534a8e, 0x9e925964, 0x24c33c4f, 0x47da65ac, 0x4f7e3d4d, 0xa654831e, 0x42000100, 0x7f07ebff, 0xc982b005, 0x00b26522, + 0x5d18c986, 0x20200852, 0x24065f44, 0xb11b2f1f, 0x72c5181f, 0x0db0210f, 0x200dfd50, 0x0cf55506, 0x411fb021, 0xb2370c95, 0x110d1f17, 0x31303912, + 0x02032101, 0x23070602, 0x36363735, 0x67211313, 0x372305e6, 0x43332736, 0x47080551, 0x04352622, 0x1861fe07, 0x9cb9610e, 0x687a284a, 0x8e031c0f, + 0x7f6e3f4c, 0xf6410404, 0x0202291c, 0xc38ce07f, 0xfde304c6, 0xfef6fee0, 0xca028ad3, 0x01df0903, 0xfbdf021c, 0xb46452bc, 0x66d8bba7, 0xfba766c7, + 0x00bdc184, 0x402ad982, 0x5a06ebff, 0x21003a04, 0xdf4d6500, 0x050b4606, 0x200cda4f, 0x20d9821e, 0x20d9871e, 0x200c8205, 0x180c8305, 0x210d565c, + 0x354405b0, 0x1eb0210c, 0x230ce64c, 0x0c1e16b2, 0x2b7ed988, 0x68212008, 0xd88305b6, 0x08052445, 0x27262245, 0xf7fe1703, 0xada81113, 0x50320253, + 0x02140a49, 0x455101e1, 0x04046758, 0x3016ec40, 0xc7700203, 0x01c7c27d, 0x9afe7403, 0x03f4e9fe, 0xad0b05ca, 0xfdce01e5, 0xa064522b, 0x50c8b599, + 0xe69b7cb1, 0x83b9be7c, 0xff942dd7, 0x058607e7, 0x001d00b0, 0x1e14b267, 0x09054018, 0x200c1d4c, 0x20ca8219, 0xc4991819, 0x20e4870c, 0x20198211, + 0x646c1811, 0x09b2230e, 0xc3821700, 0x841cb221, 0x1cb02106, 0x0ce18618, 0x01313024, 0xf1451411, 0x063c080d, 0x21352726, 0x33112311, 0x05112111, + 0x703e4d0a, 0x4104047e, 0x032f17f6, 0x8ee27c02, 0xfd09c3bb, 0x02fcfc82, 0xfbb0057e, 0x026056bc, 0xd8bba6b3, 0xa883b759, 0xc00487f7, 0x97fdffc3, + 0x8305374c, 0xff772ec9, 0x045c06e3, 0x001c003a, 0x1d1bb27a, 0x4181821e, 0x4d6e05a1, 0x5a44180c, 0x0c8e590c, 0xc9821a20, 0xc9821a20, 0x0807b222, + 0x29098d4e, 0x07e007d0, 0x40b45d02, 0x06825007, 0x200c855f, 0x0c74481a, 0x8412b221, 0x87dc8234, 0x113321c8, 0x080edd45, 0x0303044b, 0xf350fe1a, + 0xf3b001f3, 0x5e465202, 0x40040364, 0x022b1aeb, 0x7ec77002, 0x01138afe, 0x0446feba, 0x0143fe3a, 0x522dfdbd, 0x91a60266, 0xbf5dceaf, 0x7ce69b61, + 0x00840108, 0xff5d0001, 0x05bb04eb, 0x002100c5, 0x2200b249, 0xf7ac1823, 0x10c7510d, 0x56180920, 0x6d180df6, 0xb2210d7d, 0x063f5a1a, 0x24220528, + 0x34112702, 0xdf6d2412, 0x41152007, 0x3f080e98, 0xfeacbb02, 0x9a029beb, 0xdfad1701, 0xa2863f88, 0x9ec4c59d, 0x0303837d, 0x1327f535, 0xea810201, + 0x18019c15, 0xaf0f01ad, 0x599e1d01, 0xbce744b8, 0xe9b600ff, 0x95748502, 0x5858b1cc, 0x006ecd8b, 0x552eb782, 0xe703ebff, 0x1e004e04, 0x13b24600, + 0xb788201f, 0x1b2f1324, 0x417413b1, 0xeba6180c, 0x0b05220f, 0x222d8213, 0x701013b0, 0x302f0bb7, 0x36362531, 0x33273437, 0x06060716, 0x66002223, + 0x9e6e06bd, 0x15360805, 0x02161415, 0x0245515a, 0x021deb13, 0xe7b5d204, 0xe27ce2fe, 0x2e60bb92, 0x8b728a63, 0x4302af94, 0x8c677747, 0x01b0a052, + 0x971ef831, 0xbd428bfa, 0x20a4bd3a, 0xa582bf9a, 0xe7ff212c, 0xb0055a05, 0x4f001900, 0x6e1805b2, 0x452107eb, 0x8fdc1858, 0x8216200d, 0x821620b2, + 0x4cb020a5, 0xb0280d7b, 0x05b0d004, 0x1016b0d0, 0x0b656618, 0x160eb223, 0x06c54302, 0x15213523, 0x09574121, 0x2a059644, 0x01272606, 0x043efee3, + 0x423efe80, 0x200806ed, 0x032b1bf5, 0x8ce27d02, 0x0409c3bb, 0xfccdcde3, 0x02605487, 0xd8bba3b6, 0xa867ca62, 0xc00485f9, 0x28a582c3, 0x04e3ff44, + 0x003a04cb, 0x21a58317, 0x214d1918, 0x106a590d, 0x1520a594, 0x1520a58e, 0x3308a598, 0x04230606, 0xfe890103, 0xfe8b03bb, 0x5e4552ad, 0x40040363, + 0x01192ceb, 0xfec2f104, 0x77031389, 0xf0fdc3c3, 0x84026454, 0x7c9e9374, 0xf2cc377e, 0x00840108, 0x812ea382, 0xff04ebff, 0x2800c505, 0x26b27600, + 0xa3882a29, 0x1b2f1623, 0x5a7818b1, 0x820b2008, 0x100b210c, 0x0d556b18, 0x1624b223, 0x2b2d820b, 0x2f24b07c, 0x2473b218, 0x60b25d01, 0x3f590482, + 0x06b2230b, 0x21822503, 0x2510b223, 0x053e5424, 0x0be54c18, 0x241bb223, 0x0570411e, 0x33161435, 0x33353632, 0x23040614, 0x34352420, 0x35262625, + 0x68212434, 0x63080ae0, 0x15332114, 0x01062223, 0x8699b77f, 0xfe8dfcae, 0xf3fea0fd, 0x0e01bffe, 0x2f018276, 0xfa970901, 0x7ca3fd8b, 0x3301aa90, + 0xa39dbfb6, 0x7e659801, 0xbe825e81, 0xfdc4e969, 0x62a63157, 0xba69dbc5, 0x73755977, 0x70c8d963, 0x2d00ffff, 0xfc054bfe, 0x2600b005, 0x0000dd00, + 0x54020700, 0x00006e04, 0x2100ffff, 0x06221782, 0x17823a04, 0x1785f220, 0x82780321, 0x00023907, 0x026f0467, 0x00d705d6, 0x000d0005, 0x0bb00023, + 0xd004b02f, 0xb02f04b0, 0x07377f18, 0x68100b21, 0x3108059a, 0xb0d001b0, 0x31302f01, 0x15331301, 0x33012303, 0x07171615, 0x93013526, 0x5de6d370, + 0x03b1d4fe, 0x04b0504c, 0x153f0198, 0x5401c1fe, 0x48467b5f, 0x7583be5a, 0x0902472a, 0xcd025402, 0x11000600, 0x0f8f8584, 0x6d029e2f, 0x31039804, + 0xaf014600, 0xcd4c00e0, 0x24338340, 0x056d0282, 0x2d1385d0, 0x66660085, 0x02000040, 0x60fe0300, 0xaf829903, 0x0700032a, 0xb2000800, 0x2b030502, + 0x29057658, 0x21352135, 0x6afc9903, 0x03839603, 0x9d60fe2f, 0x00009c67, 0x04630001, 0x06960120, 0x232b821a, 0x0908b21d, 0x09077718, 0x1b2f0027, + 0x3e2200b1, 0x82e48559, 0x06173842, 0x35231507, 0x1a013636, 0xd5035b7c, 0x1a066701, 0x9890854d, 0x83d1608a, 0x04332645, 0x06650100, 0x18459000, + 0x3c09278b, 0x2f00b0d0, 0x27133130, 0x33353736, 0xaf061415, 0xd5035a7c, 0x4d000469, 0x8a9e9283, 0x26438467, 0x01d6fe32, 0x82ca0064, 0x88192043, + 0x2f092189, 0x0bdc9418, 0x06313f88, 0x557bad06, 0x6601da03, 0x7f4ed6fe, 0x5d859394, 0x20c982d0, 0x2083824a, 0x2083847c, 0x0ae84d16, 0x3808c28b, + 0x07171615, 0x35352626, 0x5a031f01, 0x06694d7c, 0x868f9e00, 0x67d13e4d, 0x00ffff8a, 0x0220046c, 0x001a06ef, 0x09840126, 0x01070000, 0x00590184, + 0x00ffff00, 0x02000440, 0x235582c0, 0x0d850126, 0x24081783, 0x005b0185, 0x00020000, 0x02c2fe32, 0x00ff00aa, 0x00120009, 0x130bb222, 0x39121114, + 0xb0100bb0, 0xb000d005, 0x22b58c13, 0x89d00eb0, 0x060722b8, 0x07024117, 0x837fb121, 0x31373ac2, 0x04587ff8, 0xc2fe66da, 0xc99d894e, 0x64726cba, + 0x968e4e41, 0xdd63b6cb, 0x2ad38200, 0x04000040, 0x00b0051e, 0x4e4c000b, 0x062412bc, 0x06b11b2f, 0x0c5c4f18, 0x2010a364, 0x0d97490a, 0x18d00421, + 0x3a0ce750, 0x21113311, 0x88fe1e04, 0x018dfef3, 0x7801f373, 0x8efc7203, 0x01c87203, 0x838afe76, 0xfe5c247d, 0x82390460, 0x0013227d, 0x0a2e497e, + 0x870cbd61, 0x334d1870, 0x6902200c, 0xb020060b, 0x4808f059, 0x04200770, 0x18069165, 0x200cbe5b, 0x0d2c4a0e, 0xb0d0093a, 0x11b0d010, 0x1006b0d0, + 0xb0d012b0, 0x3130d013, 0x23112121, 0x21352111, 0xb3820384, 0x09821520, 0x83390421, 0x018e23b7, 0x0382fe72, 0xfe2bbb82, 0xfe780188, 0xc2a00160, + 0x83c4b402, 0xfdc422c0, 0x38c3834c, 0x02060288, 0x00db0344, 0xb217000d, 0x110f0e03, 0xb0003912, 0x0ab02f03, 0xb7a018b0, 0x3233210b, 0x077f9f18, + 0x88272d08, 0x78676479, 0x79636777, 0x5f030302, 0x25627979, 0x5d73775e, 0x8a00ffff, 0x6f03f5ff, 0x26000001, 0x00031200, 0x12000700, 0x0000cd01, + 0x05211785, 0x20178828, 0x83178527, 0x6103201f, 0x5a2e0583, 0x6d01eb01, 0x0b00ed02, 0x03b21900, 0x7f860d0c, 0x0d09b122, 0x2108315d, 0x2c6b3130, + 0x14330806, 0x26222306, 0x4241485a, 0x41424848, 0x386b0248, 0x37384a4a, 0x00004949, 0xff4a0006, 0x055f07ec, 0x001500c4, 0x00270023, 0x00410034, + 0xb2bc004e, 0x82504f28, 0x28b0254f, 0xd002b010, 0x1b200583, 0x26200584, 0x35200584, 0x472d0584, 0x24b000d0, 0x2f26b02f, 0x584500b0, 0x0c084ab0, + 0x28086855, 0x03b0d003, 0x0305b22f, 0x314b8312, 0x07b0d007, 0x1012b02f, 0xb0d00eb0, 0x10b22f0e, 0x6b500312, 0xd0202306, 0x188320b0, 0x022bb122, + 0xb024b988, 0x32b11003, 0x2b290e8a, 0xd038b010, 0xb01032b0, 0x222c823f, 0x8a45b110, 0x1019231a, 0x0e894cb1, 0x01313023, 0x97b91834, 0x15152107, + 0x2720f783, 0x3520fb83, 0x8a411584, 0x01352507, 0x03170127, 0x26051146, 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, 0x3b5f0507, 0x37e98205, 0x35012313, 0x3c013301, + 0xe0fea7f7, 0x02a72001, 0x0171fe19, 0x86011386, 0x54203783, 0x1b203782, 0x00233787, 0x7e03b22f, 0x033d0540, 0x1331302f, 0x23011501, 0x01fb0313, + 0xa7e0fe20, 0xa903f7f7, 0xfe137afe, 0x018f017a, 0x306f8290, 0x036d002d, 0x00270571, 0x00090003, 0xb02f00b0, 0x24308202, 0x17012737, 0x20ea83aa, + 0x34b5836d, 0x00ffff00, 0x029b0235, 0x03b005be, 0x00200207, 0x009b0200, 0x355a1813, 0x3e20270a, 0xd00db059, 0x85833130, 0x8c02692e, 0xba05ff02, + 0x54000f00, 0x11100ab2, 0x4c08f747, 0x63580c45, 0x2f0d250c, 0x140db11b, 0x2006114e, 0x200c8207, 0x230c8207, 0x0d0301b2, 0xb0243b82, 0x0ab11003, + 0x2e091060, 0x17013130, 0x11203336, 0x26112311, 0x82072223, 0x01013b06, 0x01904b20, 0x7d05c503, 0x05c52763, 0xfe8779ac, 0x0109fec9, 0xfd59adda, + 0xa88203d2, 0x5f000130, 0x7c040000, 0x2700c305, 0x1fb29200, 0x8f882928, 0x6e181720, 0x06200b9d, 0x06270c82, 0xb2593e10, 0x82170627, 0x27b02421, + 0x420db12f, 0xb0240961, 0x06b0d001, 0x0d267718, 0xb0d00926, 0x10b01027, 0x232f0584, 0x2f23b0d0, 0x1f230fb6, 0x03232f23, 0x8a25b15d, 0x82112038, + 0xb010251a, 0x17b0d014, 0x0c895518, 0x231bb223, 0x05a3481e, 0x18172121, 0x220ec8b0, 0x18333523, 0x080fccb0, 0x21172137, 0xd0fe3203, 0xb8024002, + 0x52e7fb01, 0xa5022b27, 0x979c04a0, 0x9601fa05, 0x5f69f5e8, 0x01066758, 0x05c6fe3f, 0xd4013501, 0xca55872e, 0x5b6f09ca, 0x90799137, 0xdbb018a1, + 0x90a13c07, 0x00050079, 0x06000021, 0x00b0054f, 0x001f001b, 0x00260023, 0xb2bf0029, 0x822b2a0a, 0x0ab02586, 0xd01fb010, 0x21200583, 0x26200584, + 0x28210584, 0x638118d0, 0x0c344112, 0x42180c20, 0x09200bbf, 0x09270c82, 0xb2593e10, 0x5f1a0905, 0x012b0670, 0x2f01b0d0, 0x01010fb2, 0x4103b15d, + 0xb02409c2, 0x07b11005, 0x25200e8a, 0xd0236d82, 0x82d00eb0, 0x1db02317, 0x8282b0d0, 0xb0d0112c, 0x1eb01003, 0xd022b0d0, 0x438212b0, 0x19b0103c, + 0xd027b0d0, 0xb0d015b0, 0x24b01009, 0x1017b0d0, 0x30d029b0, 0x15330131, 0x03821523, 0x0123112a, 0x11231121, 0x35333523, 0x11210382, 0x210d8233, + 0x0b820133, 0x2733052c, 0x23350123, 0x05273301, 0x0082d877, 0xc9fefd26, 0xd3fcadfe, 0xfc3e0082, 0x57013501, 0x9471fefb, 0xee67fef3, 0x8c028f5f, + 0x2ba3fd2f, 0xa0c5032b, 0x12fea097, 0x0383ee01, 0x22080a82, 0x15feeb01, 0xdefceb01, 0xfe979797, 0xd7014b7e, 0x00020044, 0x06ecff98, 0x00b0053a, + 0x0025001e, 0x7921b2a6, 0x212105f1, 0x080d6d10, 0x240cac65, 0xb11b2f19, 0x9f921819, 0x0c456914, 0x2008d365, 0x0d5f471d, 0x72420a20, 0x1000320d, + 0xb0d00db0, 0x20b2d00e, 0x12111513, 0x2f20b039, 0x0b7476b1, 0xb0101d29, 0x1cb0d01c, 0x7b15b02f, 0x30220c1b, 0x79180131, 0x232d0cc1, 0x23070606, + 0x21112311, 0x33171632, 0x08018211, 0x3233015c, 0x23273411, 0x32bf3306, 0x532f263f, 0x78e8fe4d, 0x9ecaf41c, 0xd48c01fa, 0xf27518fd, 0x925ffbbf, + 0x03a0e6f4, 0x3da4fd86, 0x17bc0a38, 0x65023501, 0xfd03bbad, 0xc3b005e5, 0xfe0701b3, 0x01adfef9, 0x0006f700, 0x9400ffff, 0x3c08ecff, 0x2600b005, + 0x00003600, 0x57000700, 0x07827204, 0x21000626, 0x07060000, 0x1f301782, 0x27002300, 0x2e002b00, 0xec003100, 0x33322ab2, 0x2a21c583, 0x20d28210, + 0x210582b0, 0x0583d022, 0x05842720, 0x05842d20, 0x6f183120, 0x744213ab, 0x0800670c, 0x0c020822, 0x08204c83, 0x2409464b, 0xb11004b0, 0x0a664206, + 0x47440820, 0x3073830c, 0x12b0100a, 0x1008b0d0, 0xb0d014b0, 0x16b01006, 0x273282d0, 0xb0d018b0, 0x1ab01002, 0x1c200b84, 0x1e200b84, 0x20202384, + 0x22202384, 0x24200b84, 0x26200b84, 0x28230b84, 0x842ab2d0, 0x2cb2217b, 0xb0270684, 0x2db0100a, 0x882fb2d0, 0xd0302c0c, 0x33013130, 0x33033313, + 0x82072315, 0x23032103, 0x35240185, 0x35232733, 0x13201582, 0x01241b82, 0x05233733, 0x07200382, 0x01201382, 0x41080a82, 0xc2032337, 0x50fc3ed3, + 0xc921a888, 0x5ef976ea, 0x77f9607c, 0xa221c3e3, 0x3ffb4f81, 0xfee13dd9, 0xa61a723d, 0x1a6d4e02, 0x1a48eda1, 0x1ff2fe13, 0x1d51023f, 0x012a043b, + 0xa07afe86, 0xb8fda0a2, 0x03834802, 0x11830a82, 0xfd860124, 0x0083a238, 0xc5f9fd3e, 0x0000bbbb, 0x007c0002, 0x04100600, 0x000d003a, 0xb26d001b, + 0x111d1c08, 0x08b03912, 0x2409c342, 0xb11b2f00, 0x07b64200, 0x0c821620, 0x9e4f1620, 0x00b0240f, 0x56b05845, 0x8542082b, 0x4e00200b, 0x05220d56, + 0x5c820911, 0x0910b223, 0x05ee4411, 0x17163229, 0x34112311, 0x82212326, 0x11012706, 0x32211133, 0x06823736, 0x06064508, 0xbb0c0323, 0x5af302ae, + 0xf3aefe69, 0x01f39901, 0x01596a50, 0xdcef01f4, 0xcbc03a04, 0x4201b5fe, 0x8afc636d, 0xc6fb3a04, 0xedfdd602, 0xae026861, 0xd5bc57fd, 0x5e000100, + 0x3004edff, 0x2300c305, 0x15b28e00, 0x0a6d4b18, 0x440c654e, 0x2321089b, 0x248e8316, 0xb12f23b0, 0x0aa44500, 0xeb640920, 0xb010280e, 0x23b0d00c, + 0x840eb010, 0xd0132f05, 0xb62f13b0, 0x131f130f, 0x5d03132f, 0x388a10b1, 0xfb561620, 0x13b0300c, 0xd01eb010, 0xb01010b0, 0x3130d020, 0x62162101, + 0x23230561, 0x44030020, 0x3621069a, 0x083f7f00, 0x82152121, 0x03550801, 0x069cfe6a, 0x5f6e98a3, 0xff80781c, 0x08dafe00, 0xadacacac, 0xfd2c010d, + 0x661c856a, 0x09a29765, 0x9cfe6301, 0x0f026401, 0xcc21acae, 0x0120011d, 0x8d808d02, 0x1f1b01ff, 0xa4ac22cd, 0x0000808d, 0x00210004, 0x05d40500, + 0x001a00b0, 0x0024001f, 0xb2e70029, 0x05d3450c, 0xb0100c25, 0x82b0d01c, 0x84232005, 0x07cd4505, 0x1b2f0b24, 0x8a180bb1, 0x0b20108e, 0x820c3244, + 0x20b038bf, 0x0013402f, 0x20201020, 0x40203020, 0x60205020, 0x80207020, 0x835d0920, 0x2f1e3ae1, 0xc01eb0b6, 0x031ed01e, 0x000b405d, 0x201e101e, + 0x401e301e, 0xb15d051e, 0x0a704326, 0xb0d02735, 0x0f402f27, 0x27402730, 0x27602750, 0x27802770, 0x6c072790, 0x26320dce, 0xd003b010, 0xb0101eb0, + 0x20b0d006, 0xd00fb010, 0x418a12b1, 0x1d23bf82, 0x8407b0d0, 0x840a201a, 0xd0142226, 0x213282b0, 0xe972d017, 0x06554105, 0x32211129, 0x15331704, + 0x82071723, 0x06062d04, 0x21270123, 0x21252115, 0x01212726, 0x32240882, 0xb8fdd601, 0x53080082, 0x01ad2d02, 0xbde43c01, 0xe1bc0102, 0x01bdfa36, + 0xbefd0315, 0xbdfd4302, 0x7246f001, 0xf401c8fe, 0x31010cfe, 0xfd1d027b, 0xa01f03e3, 0x0901a048, 0x26a08188, 0x857da022, 0x4828c201, 0xfe023be8, + 0x0100373b, 0x00002800, 0xb0050c04, 0x70001a00, 0x1c1b16b2, 0x4b084b48, 0xa1440c0b, 0x34a41808, 0xd001250e, 0xb01019b0, 0x1421c282, 0x21f5832f, + 0x42181014, 0x06240ca7, 0x1014b0d0, 0x2105284b, 0xc95709b1, 0x0db22209, 0x062f6209, 0x17162336, 0x06230733, 0x15010706, 0x33270121, 0x21373632, + 0x23262137, 0x34080482, 0x33dad903, 0x9732ca0f, 0x01c9dc16, 0xfee1fed2, 0x70fd0103, 0xe6fd1683, 0x31e30133, 0x36f3fed8, 0xf904ae03, 0xa5b6654b, + 0xdffd11af, 0x9951020d, 0x9bb64c5d, 0x24cd82cc, 0x04ecff21, 0x24cd8251, 0xb294001e, 0x0a91531b, 0x560c4675, 0xb22307ba, 0x82051113, 0x13b02def, + 0xd017b02f, 0xb22f17b0, 0x5d011700, 0x270b9053, 0xb0d019b0, 0x09b0d008, 0x102b1c82, 0xb0d016b0, 0x0ab0d00b, 0x6713b0d0, 0x15260d71, 0xd00cb0d0, + 0x17830db0, 0xd012b025, 0x83d00fb0, 0x5d0520f1, 0xb2220c0a, 0x2c44051e, 0x06152b06, 0x22230402, 0x35071127, 0x03823537, 0x15331125, 0x83071537, + 0x36112e03, 0x04353536, 0xfe960251, 0x8c6bb2ed, 0x210082dc, 0x0082e1fc, 0xb2aa2208, 0xd259ff02, 0x14abc3fe, 0xc7575d02, 0xc8578957, 0xd73b0157, + 0x895ac85a, 0xfd59c85a, 0xf8fc02fb, 0x28f5824d, 0x0500004f, 0x003a040f, 0xff8a1817, 0x0ca66c0e, 0x08ab4118, 0x82180020, 0x0f410fe4, 0x0b152808, + 0x39121117, 0x182f15b0, 0x2217ff8a, 0x68130016, 0x2324064a, 0x15060611, 0x37080b82, 0x35370012, 0xe0280333, 0xf3040301, 0xf3728101, 0x03f38271, + 0xf3df0401, 0xfe296a03, 0xbfecfe92, 0x2aefc5b8, 0x95026afd, 0xb1c7f32a, 0x011401ba, 0x00d12b70, 0x28000200, 0x332cb182, 0x1600b005, 0x7b001f00, + 0x212018b2, 0x18217783, 0x614c1810, 0x0c7b6f08, 0x1b2f0229, 0x3e1002b1, 0x4606b259, 0x06200582, 0x0c9b6e18, 0x2a05c94a, 0xb0d00ab0, 0x0fb22f0a, + 0x185d010a, 0x470c107b, 0x15200508, 0x10251c82, 0xb0d017b0, 0x7872180c, 0x3130230c, 0xc3822125, 0x290a7443, 0x07041415, 0x01211521, 0x67763221, + 0x33032505, 0xcdfcbefe, 0x43080082, 0x01f12d02, 0xf4eefe20, 0x4201c4fe, 0x2d01befe, 0x7c8d9088, 0xe7e7c4fe, 0xcb6bcbe7, 0xd0fbc802, 0x6b03f1d4, + 0x7d7e3601, 0x00038e70, 0x70000400, 0x8905ecff, 0x1900c505, 0x34002600, 0x98003800, 0x3a391ab2, 0x1a25e383, 0xd000b010, 0x200582b0, 0x27058427, + 0xb000d037, 0x37b02f35, 0x2012de5b, 0x20f58224, 0x23f58224, 0xb01009b0, 0x2205824e, 0x8303090d, 0x10092142, 0x230cb145, 0x17b11003, 0x2309c045, + 0x090319b2, 0x242c2483, 0xd01db010, 0xb02f1db0, 0x2ab11024, 0xb0241e89, 0x31b1101d, 0x200c674e, 0x19b81814, 0x4efe8214, 0x2021096b, 0xc1ee1826, + 0x2349080a, 0x05150622, 0x02170127, 0x00ff9fb1, 0x80829ea2, 0x3641aaa1, 0x6a434234, 0xae180140, 0xa7ad8887, 0xaaabe8fe, 0x49403e4f, 0x4d3e3d4e, + 0x027efbfd, 0x25047ec7, 0x8aa79273, 0x94ab8247, 0x54403573, 0x55454a4a, 0x40fd3143, 0xa7ee1886, 0x00023217, 0x03ebff4c, 0x00f90590, 0x00210017, + 0x2201b25d, 0x23d18323, 0x18b01001, 0x09736818, 0x1b2f002b, 0x3e1000b1, 0x0c06b259, 0x211d8300, 0xc0182f06, 0xb0210b89, 0x10416913, 0x3e830620, + 0x3a10ff41, 0x35262205, 0x32352306, 0x36361137, 0x15163233, 0x07021415, 0x33161415, 0x6d363603, 0x4d08056a, 0xe1db0207, 0x616061ed, 0x9ab20360, + 0xb2d7ac88, 0x4dd46c68, 0x56202b57, 0xe5eb1503, 0x0118bb13, 0xb4d6bfe9, 0xfead269b, 0x8e4d67a9, 0x4b44027a, 0x3f2966cc, 0x0400b240, 0x00009000, + 0xc005c207, 0x0f000300, 0x27001d00, 0x1eb2a900, 0xa9832928, 0xb0101e25, 0x82b0d001, 0x05eb6905, 0x20077378, 0x20d08226, 0x07c54626, 0x0c645418, + 0x200cb277, 0x20268221, 0x072d5221, 0x82086a5c, 0xd00d31dc, 0xb02f0db0, 0x02b0d002, 0x0200b22f, 0x01b15d01, 0x2409e641, 0xb1100db0, 0x230e8a13, + 0x1ab11006, 0xb2230e89, 0x82212420, 0x25b22398, 0xd557261f, 0x34012808, 0x15162036, 0x41061415, 0x012510fb, 0x23110121, 0x08048211, 0x97073343, + 0x61029ffd, 0x01be76fd, 0xfebabf38, 0x5cafbdc2, 0x5c5b4f51, 0xfe5c4f50, 0xfef4fec7, 0x0b01f40d, 0x01f2f601, 0x2f02959c, 0xa6c0c19f, 0xc2c29c4e, + 0x6c6006a2, 0x5f51636c, 0xfb626d6d, 0xfb0a04a3, 0x63db18f6, 0x036d2c08, 0x05570494, 0x000c00b0, 0x756e0014, 0xf85e1209, 0x2f132b0c, 0x2013b11b, + 0x01b2593e, 0xb1820615, 0x8201b021, 0x010921f1, 0xb2220982, 0x10840103, 0xb2d00425, 0x84090108, 0xb010281a, 0x06b0d00b, 0x520db010, 0xb03407cf, + 0x0fb01001, 0x100db0d0, 0xb0d011b0, 0x3130d012, 0x03230301, 0x3327d182, 0x11331313, 0x82230123, 0x233b080a, 0xe8032135, 0x6f7c3e7c, 0x85858189, + 0x8a11fe6f, 0x8c018d75, 0x8bfe0905, 0x8cfe7401, 0x83fe1c02, 0xe4fd7d01, 0x45febd01, 0x005fbb01, 0xff960002, 0x049104ec, 0x0015004e, 0x1865001c, + 0x210a456c, 0xc885d016, 0x23142375, 0x020a19b2, 0x1923a083, 0x180fb12f, 0x25097999, 0xb11002b0, 0x3f520c13, 0x15b22108, 0x0a232485, 0x8916b110, + 0x30660824, 0x23062531, 0x35022622, 0x33361234, 0x17161632, 0x16112115, 0x01373233, 0x21110722, 0x14042611, 0xf491bbb7, 0x84f89087, 0x0384e385, + 0x9a7700fd, 0x90feacc4, 0x1c027a97, 0x9d725e73, 0x8f930101, 0x8b9f0301, 0xfe3e90f3, 0x037a6eb8, 0xebfe7a2a, 0x00711e01, 0x5900ffff, 0xcb05f5ff, + 0x27009905, 0xd9ffc601, 0x07828602, 0xfb00942e, 0x07010000, 0x21032402, 0x10000000, 0x210d9741, 0x33823130, 0xf5ff542e, 0xb4056806, 0x1f022700, + 0x94021d00, 0x01213383, 0x203386a8, 0x273389be, 0xb11b2f0d, 0x593e200d, 0x5b203384, 0x5c223382, 0x3382a805, 0x0c002124, 0x33849302, 0x33868c20, + 0x3389b220, 0x84072665, 0x82582033, 0x051a2233, 0x243382a3, 0x02220023, 0x2033848e, 0x20338633, 0xa3b31870, 0x02003e13, 0xebff6200, 0xf5054304, + 0x26001900, 0x13b25e00, 0x12112827, 0x1013b039, 0x00d020b0, 0x06b566b0, 0x52181320, 0x8f5b08a1, 0x2f002305, 0x098502b2, 0xa84e0b20, 0xae49180f, + 0x6c13200c, 0x01270e84, 0x26261732, 0x18072223, 0x5b0935a2, 0x122106bf, 0x06e66317, 0x35364808, 0x02262635, 0x1a77ae38, 0x8b7c84c5, 0x8f6e3c1d, + 0x27010d01, 0xe394e37a, 0xf4fef3fe, 0x7a84857b, 0x8b168579, 0xc27d0404, 0x19b735e5, 0xfe4efe2c, 0xfec13572, 0x2401a7d3, 0x01df0df7, 0xa4a7c212, + 0xc5d0b09a, 0x825f4c55, 0xa6002ef4, 0xf4041bff, 0x0700b005, 0xb0002800, 0x053b4604, 0x21082544, 0x11471004, 0x0bef6205, 0x05313026, 0x11211123, + 0x042e0382, 0x99fdf4f4, 0xe54e04f3, 0x2cfad405, 0x4d839506, 0xf3fe4024, 0x4d82c104, 0x37000c25, 0x7103b000, 0x03210ecf, 0x25478b10, 0xb0d005b0, + 0x95181008, 0x94180b65, 0x2f08129a, 0x03eefd8f, 0x027ffb44, 0x04b1fd4f, 0x02f6fc47, 0xfd430212, 0x0297c373, 0x98c602c8, 0x0073fdc3, 0x029e0001, + 0x03ef036d, 0x00030031, 0x02b00012, 0x2e0cba78, 0x21013130, 0xef032135, 0x5103affc, 0x83c46d02, 0x003b249f, 0x82920400, 0x0008229f, 0x8990183d, + 0x06477608, 0x211c4a67, 0x45571007, 0x3d58820b, 0x23013301, 0x21352303, 0x78014102, 0xc517fed9, 0x6701d1d8, 0x85042b01, 0x410250fa, 0x8d8200c5, + 0xecff5e3b, 0x4e04df07, 0x2a001a00, 0x74003900, 0x3b3a07b2, 0xb0391211, 0x22b01007, 0x200583d0, 0x06d14332, 0x0ca65618, 0x08a47918, 0xb010042b, + 0x16b0d016, 0x1607b22f, 0x26368304, 0x12b0d012, 0x8514b22f, 0x5316200c, 0xb0240c2c, 0x27b11004, 0x2809fe73, 0xb0d02eb0, 0x37b0101e, 0x08a482d0, + 0x06061429, 0x27262223, 0x26222102, 0x34353526, 0x20333612, 0x32211213, 0x07171616, 0x22232634, 0x15070607, 0x33161716, 0x55353632, 0x372405ed, + 0x27263537, 0x76081882, 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, 0x7c02b23f, 0x3c4f06fd, 0x0c656708, 0x593e1222, 0x0c8a7318, + 0x18100e21, 0x220bc35b, 0x6d053130, 0x37230835, 0x4e363411, 0x2d080648, 0xb6900115, 0x123f42aa, 0x028a252c, 0x593fb2c0, 0xa3322a19, 0x13b6b04f, + 0x049d0dbd, 0x15c3b3f4, 0x00b80bb9, 0x65000200, 0x15040101, 0x8582fa03, 0x7c002b24, 0xf36710b2, 0x10103305, 0x00d01cb0, 0xb02f19b0, 0x03b0d003, + 0xd008b02f, 0x0b8208b0, 0x0ab01022, 0xd2600882, 0x03b0210c, 0x280c7263, 0xb0100db0, 0x19b0d015, 0x050c4e10, 0x20230883, 0x181eb0d0, 0x200d5c6a, + 0x0ce36719, 0x1023b03e, 0x30d02bb0, 0x36361331, 0x17173633, 0x37323316, 0x22230615, 0x07262727, 0x15070622, 0x3a081594, 0x42843065, 0x469c4c52, + 0x66658451, 0x9846517f, 0x8742544f, 0x42803030, 0x46984f54, 0x66658751, 0x9c465183, 0x8442524c, 0x328e0330, 0x4e220238, 0x6ad97e20, 0x02244c20, + 0x82cb3c42, 0x4c24210f, 0x4e210f84, 0x310f8222, 0x91000100, 0xef038000, 0x1300c304, 0xb0003900, 0xbf612f13, 0xd004260c, 0xb01013b0, 0x24058407, + 0x0fb0d00f, 0x0b697e2f, 0x8208b021, 0xb0102211, 0x29bc820b, 0x27072101, 0x21352337, 0x03822137, 0x07174908, 0x07211533, 0xfdef0321, 0x5d6d80e2, + 0x7e2101b0, 0x100261fe, 0xbd636e86, 0x017dd1fe, 0xe46401ac, 0xdfc9a63e, 0xaf3eedca, 0xffffdfca, 0x14003c00, 0x6b048d03, 0x20006700, 0x8b000000, + 0x9a390040, 0xaf010700, 0xa7fd9eff, 0x80201d82, 0xe0201d82, 0x22201d84, 0xe23b1d8c, 0x0200a7fd, 0x00002400, 0xb005eb03, 0x09000500, 0x06b23800, + 0x12110b0a, 0x1806b039, 0x490e4565, 0x236b070d, 0x00062208, 0x21278203, 0x068408b2, 0x31302b08, 0x01013301, 0x03010123, 0xa4011313, 0xfe8301c4, + 0x7efec580, 0xf2ede101, 0xfdb005ec, 0x0229fd27, 0xfed601d7, 0x0129fe2a, 0x8f8200d7, 0xab00a130, 0x0705bc01, 0x12002700, 0xb6001a00, 0x07830700, + 0x82070421, 0x0263288b, 0x043e027f, 0x82030039, 0xb2342413, 0x82090800, 0x05b02163, 0x2006ea43, 0x5c621802, 0x8206200b, 0x1c06230c, 0x2482593e, + 0xac6b0220, 0xd0042106, 0x23238782, 0x83013311, 0x9d003c03, 0x9d3e019d, 0x017f029d, 0x0146feba, 0x000100ba, 0x0167ff45, 0x0006015a, 0x450c0008, + 0xd02505a9, 0x302f00b0, 0x06e35c31, 0xc5060630, 0xc9034980, 0x4d995301, 0x4f647b73, 0xa782ba5d, 0x00002d32, 0x15061a05, 0x4a002600, 0x07000000, + 0x44024a00, 0x02260782, 0x00001800, 0x17821704, 0x1b001726, 0x09b27500, 0x2105e152, 0xb56b1009, 0x82092008, 0x4309209b, 0x1464077d, 0x0cca780c, + 0x7f181720, 0xef5a07d1, 0x3e102808, 0x1004b059, 0x72d013b0, 0xb0240b80, 0x09b0d001, 0x0e3a4118, 0x23113337, 0x3e353335, 0x16323302, 0x23260717, + 0x15150622, 0x11231533, 0x08f98221, 0xa5a5bd2a, 0x88c26a01, 0x254f9350, 0x646f728a, 0x6702d5d5, 0x8603f3f3, 0xb67f4ab4, 0xc91a225c, 0x44616130, + 0x047afcb4, 0x0001003a, 0x0421df82, 0x24c7822c, 0xb2650016, 0x0a517612, 0x98821220, 0xbf871220, 0x180c2d5d, 0x620c6687, 0x122008a7, 0x260d9846, + 0x05b0100e, 0x6b0eb0d0, 0xb0250cb1, 0x3130d008, 0x85a98201, 0x842320a8, 0x36362ebf, 0x11053233, 0x66390323, 0xdcdcc44a, 0x2ab882f3, 0x017ac4d7, + 0x3f05f344, 0x825bb80e, 0x27b582a4, 0x30c3b761, 0x02001bfa, 0x0621ab83, 0x2fab8293, 0x002c0028, 0x2d14b2b8, 0x3912112e, 0xb01014b0, 0x1807576c, + 0x840c83d9, 0x20c08799, 0x20cd822b, 0x0762542b, 0x0c822120, 0x0c872120, 0x410c6e73, 0x28200ca7, 0x28202682, 0x2007da4b, 0x200c8225, 0x200c8725, + 0x200c822a, 0x200c832a, 0x0d746c21, 0xb0d02623, 0x10d84401, 0x44181620, 0xb6410e6f, 0x095e4505, 0x41211521, 0x232911c3, 0x21112111, 0xd2331123, + 0xf7d918a5, 0x74012108, 0x3806d141, 0x6f738826, 0xf3d5d564, 0xce048cfe, 0x8603f3f3, 0xc4b463b4, 0xb308be12, 0x0ddc4160, 0xfc860326, 0x003a047a, + 0x2905e141, 0x15069306, 0xa8002700, 0x9d5a13b2, 0xe7aa180a, 0x0c3a410c, 0x180c0641, 0x200c7c45, 0x20f9821f, 0x073a411f, 0x0c822720, 0x9b182720, + 0xc842100d, 0xb27d180e, 0x4508200c, 0x15200df3, 0x2a0c1a41, 0xb01001b0, 0x22b0d026, 0x413130d0, 0x27421223, 0x42112006, 0x21210a3e, 0x0d1f4111, + 0x42053842, 0xfe210547, 0x0a19418c, 0x42054042, 0xfc320951, 0x0100007a, 0xecff2d00, 0x1506d104, 0x7d002400, 0xad6c13b2, 0x821b200a, 0x871b20d6, + 0x42f084e3, 0xec420745, 0x59e38308, 0x1b20085f, 0x260c3466, 0xb0d00eb0, 0x59b0d001, 0x1b260e58, 0xd00fb010, 0x6f471fb0, 0x0fb0240c, 0x4423b010, + 0x142005ae, 0x2606ad46, 0x23111120, 0x83353335, 0x431120e3, 0x342b051e, 0x16323336, 0x04331117, 0x5931bfcb, 0xb233063b, 0xa36c45b2, 0xc2a5a5f3, + 0x72f165b0, 0xfd8603bf, 0x59373ea4, 0xb4250635, 0xfbb920f8, 0x26f98267, 0x38c3b662, 0x828efe31, 0xff4b2ee5, 0x068006ec, 0x004c0018, 0x4d46b2c8, + 0x084f544e, 0xe5824720, 0xd8874720, 0x0c824020, 0xf2874020, 0x0c916918, 0x19824b20, 0x19874b20, 0x200cf943, 0x2519822c, 0x593e102c, 0x525a4bb0, + 0x11ea560d, 0xb0d00d27, 0x47b0d00e, 0x0bd46d10, 0x401db223, 0x248b822c, 0xb11040b0, 0x0a8a5420, 0x402c2622, 0xb2211582, 0x24068431, 0xb1102cb0, + 0x201c8a34, 0x2532843b, 0x23013130, 0xdd471411, 0x27263106, 0x33352311, 0x23263435, 0x14150622, 0x2315021e, 0x16220a86, 0x77181604, 0x16240904, + 0x36323316, 0x26282482, 0x34352627, 0x17323336, 0x16390685, 0x06331515, 0x2671bf79, 0x874d532f, 0xacac0190, 0x584f5860, 0xf41c211d, 0x4fd51868, + 0x6b240812, 0xecb653f8, 0x2d4d5bb6, 0xdec9aed9, 0xfd8603bf, 0xbc0a88b7, 0x02a2aa17, 0x6258b44e, 0x3a455469, 0x4d796669, 0x1168d518, 0x413b5608, + 0x58283444, 0x17bc8ca7, 0xa5814f6c, 0x004fc5ca, 0x59001600, 0xec0772fe, 0x0d00ae05, 0x28001a00, 0x3d003700, 0x49004300, 0x56004f00, 0x5e005a00, + 0x66006200, 0x6e006a00, 0x7a007600, 0x82007e00, 0x8a008600, 0xc8018e00, 0x908f10b2, 0xb0391211, 0x00b01010, 0x200583d0, 0x2005841b, 0x20058430, + 0x2005843c, 0x2005843e, 0x20058446, 0x2005844a, 0x20058450, 0x20058457, 0x2005845b, 0x20058461, 0x20058463, 0x20058467, 0x2005846d, 0x20058470, + 0x20058477, 0x2005847b, 0x2005847f, 0x20058484, 0x24058488, 0xb000d08c, 0x05904c3d, 0x1b2f462f, 0x3e2046b1, 0x447db259, 0x7cb22b03, 0x21048279, + 0x04828178, 0x82398021, 0x460a2204, 0x21a9833d, 0xf6492f0a, 0xd00e3106, 0xb02f0eb0, 0x0fb0100a, 0x2f0fb0d0, 0x0f0e6fb2, 0x7c271e82, 0x182f6fb0, + 0x4f0b50b1, 0x50210a5d, 0x2236846f, 0x891eb110, 0x03b02415, 0x8a25b110, 0x100f320e, 0xb0d029b0, 0x0eb02f29, 0xd02eb010, 0xb12f2eb0, 0x281d8a34, + 0x6bb0103d, 0xd067b0d0, 0x23e082b0, 0x3fb1d03e, 0x3609bb4f, 0xb0d065b0, 0x6db0d069, 0xd03cb0d0, 0xb01039b0, 0x46b0d041, 0x8a47b110, 0xd05b2620, + 0xb0d057b0, 0x3017834a, 0xb0d060b0, 0x58b0d05c, 0xd04bb0d0, 0xb01044b0, 0x22c0824e, 0x8a51b110, 0x10472368, 0xcc825fb0, 0x76b11022, 0x2108148a, + 0x84b01078, 0x1079b0d0, 0xb0d085b0, 0x88b0107c, 0x107db0d0, 0xb0d089b0, 0x8cb01080, 0x1081b0d0, 0x514c8db0, 0x22232405, 0x43352726, 0x132805d9, + 0x16323311, 0x16071415, 0x23210482, 0x05bc4201, 0x1614152b, 0x35363233, 0x14113301, 0x222a8206, 0x84143335, 0x1120080e, 0x15331533, 0x35333521, + 0x11011133, 0x15231521, 0x11213525, 0x15013523, 0x34353233, 0x21351327, 0x03851c82, 0x0b8a0120, 0x7f6f1320, 0x01232205, 0x06bb5e23, 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, + 0xa1531021, 0x02202806, 0x39121100, 0x552f20b0, 0x042806a5, 0x2f04b0d0, 0x02000db2, 0x0d211583, 0x0552592f, 0x0407b223, 0x230f8214, 0x041419b2, + 0x30290682, 0x05030931, 0x36373634, 0x057e4436, 0x54330721, 0x142c05b2, 0x15060607, 0x33152317, 0x23153303, 0x55080383, 0xbf031804, 0x44fc41fc, + 0x241e0f04, 0x95a75c4a, 0xcb02a090, 0x392b3a02, 0x2f5b5d38, 0x4bcacaca, 0x04020404, 0xfc520604, 0x0331fc31, 0x3a3af1cf, 0x4a872718, 0x7f8b9780, + 0x34403433, 0x5c413c5f, 0xfdaa5b4c, 0x9e0a044c, 0x00010004, 0x0200003c, 0x002003b2, 0xc9180017, 0x1a20129f, 0x5506df62, 0xb121078b, 0x0a545416, + 0x00160222, 0xb222b482, 0xe8840f03, 0xb1100f23, 0x221c8a08, 0x830f000c, 0x8415201c, 0x31302406, 0x18352121, 0x21289fc9, 0xc918017d, 0x8020119d, + 0x0226a582, 0x06001303, 0xa3523200, 0x2f052405, 0x8705b11b, 0x8471189e, 0x10052108, 0x2105ac69, 0x8a8903b1, 0x23317c82, 0x25350711, 0xb9020233, + 0x136f01c9, 0x92303a02, 0x254e8277, 0xf5ff4b00, 0xf982aa02, 0xfb820d20, 0x03b24824, 0xb9631918, 0x08156105, 0x62820a20, 0x62870a20, 0x08df5b18, + 0x9b570a20, 0x8b152010, 0x4301206b, 0x8b430560, 0x15400805, 0x22233427, 0x33141507, 0xaa023732, 0x9f92909e, 0xa090919e, 0x037275bb, 0x01046f77, + 0xaaaa9f3e, 0xae9d989e, 0xa90c9ead, 0x9aa9b89f, 0x4f000200, 0xb703f6ff, 0x14009d04, 0x60002100, 0x232215b2, 0x15239183, 0x7708b010, 0x1e200bb7, + 0x0f799e18, 0x44081521, 0x152205fc, 0xc951182f, 0xe56f180c, 0x4908200e, 0x30250c1a, 0x23060131, 0x08b54622, 0x0500102b, 0x36333523, 0x36322736, + 0x057c4237, 0x14154208, 0x64c10216, 0xf2cab391, 0xfee8cec0, 0x24c5fec0, 0xadc0c118, 0x6a186444, 0x69695859, 0xcf5bd501, 0xfeecb2b6, 0xc3fe41e5, + 0xc104befe, 0x3aed8c01, 0x7e6d592a, 0x705f5e7b, 0x00030000, 0x03f0ff58, 0x2ac982c3, 0x00220017, 0xb281002d, 0x582f2e09, 0xb02405d8, 0x09b0d020, + 0x09b34618, 0x1b2f1524, 0xd18715b1, 0x2208f15e, 0x8315092b, 0x2f2b282d, 0x012bcfb2, 0x833fb271, 0x2b5f2404, 0x18b17201, 0x230a5b82, 0x2b1b03b2, + 0xb2232482, 0x851b2b0f, 0x20b12159, 0x220a6e51, 0x18b11015, 0x220ed2c4, 0x47160706, 0x352406be, 0x26373634, 0x032af986, 0x22232634, 0x33161406, + 0x0a853632, 0x0a82f682, 0x515ca632, 0xc7ee6c5e, 0x5e6cf0c6, 0xb9de5c51, 0x6bd6e0ba, 0x3b08f583, 0x1c6a585a, 0x574d4e5a, 0x03589c58, 0x27835556, + 0x9b618f28, 0x629cb3b4, 0x8227288f, 0xaeaf9855, 0x564a63fd, 0x55559655, 0x4f424202, 0x5143444d, 0x00010051, 0x03000039, 0x008d04d0, 0x1487c918, + 0xc042f987, 0xaa99180a, 0x00b2230b, 0xdc820503, 0x31302f08, 0x01210101, 0x03213521, 0xfffefdd0, 0xfd020200, 0x04970369, 0x03fbfb05, 0x0200c4c9, + 0xf0ff6000, 0x9a04d703, 0x20001300, 0x1bb26500, 0x32822221, 0x101bb024, 0x5c180cb0, 0x69870bf7, 0xfe640c20, 0x4b102008, 0xb2230b47, 0x830c0006, + 0x2f062436, 0x830604b2, 0x14b12109, 0x200a4d41, 0x0c32600c, 0x15268e82, 0x36070622, 0x50413233, 0x10352407, 0x82032500, 0x06664612, 0x26343d08, + 0xd2da1303, 0xada16b11, 0xd0c4eec8, 0x014d01f5, 0x6c48c438, 0x595f6e1a, 0x9a04696d, 0x6d9d9dc7, 0xe1afb2d4, 0x0148def9, 0x04500137, 0x2d3daafd, + 0x7386742e, 0x006b5b59, 0x67000100, 0xd128cd82, 0x1d008d04, 0x1ab26d00, 0x200acf73, 0x20b88201, 0x20c58701, 0x260c820d, 0x593e100d, 0x411001b0, + 0x07220c2f, 0xc5830d01, 0x552f0721, 0xb2230bcb, 0x83071a05, 0x5d0d2015, 0xb2200cd5, 0x13e30119, 0x2721d48a, 0xe3011933, 0x073a0809, 0x02498807, + 0x2106fec3, 0xd6b96564, 0xfab5cbe9, 0x6c08ee07, 0x76685a54, 0x223c5e64, 0x52023b02, 0xcb2bf3c8, 0xbbdcb1b5, 0x6a444a95, 0x276d5d64, 0x02000017, + 0x00003000, 0xc982ec03, 0x0e000a28, 0x0eb25700, 0x8483100f, 0xb0100e23, 0x06974109, 0xc4820920, 0xd1870920, 0x166c0420, 0x01b22306, 0x27830409, + 0x432f0121, 0x06250ccb, 0x0608b2d0, 0x25188401, 0xd00bb010, 0x25840db2, 0x01313028, 0x15231533, 0x03193523, 0x2e080842, 0xf39a9a52, 0x020adbfd, + 0xd2fdf82a, 0x01143b01, 0xf8f8c4bc, 0xfdfa029b, 0x219a012f, 0x00010000, 0x03f0ff3e, 0x009d04bc, 0xb2a10026, 0x4b282720, 0x0e2008bb, 0x0e207e82, + 0x19208b87, 0x19270c82, 0xb2593e10, 0x84190e01, 0xb22f2772, 0x7101013f, 0x0483cfb2, 0x01015f25, 0x838fb272, 0x83ff2004, 0x820f200e, 0x6fb42f09, + 0x02017f01, 0x01afb471, 0x5d0201bf, 0x1282bfb2, 0x760eb021, 0xb2210c24, 0x2049860a, 0x0c117110, 0x83251421, 0x1db223d2, 0x66830e19, 0x72571920, + 0x05624b0f, 0x06222325, 0x42342315, 0x8218066d, 0x35230787, 0x84161433, 0x2347081e, 0x80670123, 0x59626569, 0xeff36852, 0x63e7cbba, 0xcafcd861, + 0x72f4f3c5, 0xe568635a, 0x57a9027d, 0x484d4746, 0xb1b4913a, 0x25864f9c, 0xb99dd33d, 0x53429eb9, 0x00a84858, 0x00420001, 0x04d70300, 0x0018009d, + 0x1808b25b, 0x200a9f47, 0x20fe820f, 0x070b410f, 0x2008f946, 0x090f4317, 0x1702b222, 0x8a0ff946, 0x460b201c, 0x2e0821f9, 0x05070706, 0xfcd70321, + 0xb1a90185, 0x6e634f60, 0xc5c9f7f4, 0x606652e2, 0x460200ff, 0x9c8e01a5, 0x6556476e, 0xbbdaa95b, 0x649a52a2, 0x8200d35b, 0x00962aab, 0x04c40200, + 0x0006008d, 0xcdcd1840, 0x20ab8f11, 0x090647b0, 0x0220978a, 0x37064b44, 0x05112321, 0x02332535, 0xc5fef3c4, 0x031c1202, 0xaec3536f, 0x59000200, + 0x4706b145, 0x69871c0d, 0x890c0d47, 0x03b02163, 0x080c3a7c, 0x01313045, 0x22230214, 0x34352726, 0x12323312, 0x23102717, 0x10110322, 0x03133233, + 0xccd1e3c3, 0xd2e203e7, 0xf401e4d1, 0xc405bdc2, 0xe10106ba, 0xf8fffef0, 0x01efd6ed, 0xef00ff03, 0xfe170114, 0xfefafef9, 0x820601e6, 0x004124fd, + 0x82f30300, 0x000922fd, 0x05fd4746, 0x1b2f0724, 0x8c8707b1, 0x3c600220, 0x0b1e5506, 0x1804b221, 0x322731f1, 0xfc7b0278, 0xfd6c024e, 0xc2a00395, + 0x3c038dc2, 0x82008ac4, 0x00052471, 0x82360400, 0x05f21871, 0x8c71870d, 0x08b9437e, 0x49010021, 0x012005c4, 0x3a05405d, 0x1d022101, 0x0b010e01, + 0xfef25dfe, 0x020b0164, 0xfd13027a, 0x016cfe07, 0x83ec02a1, 0x82152061, 0x824a2061, 0x000b2261, 0x44d38553, 0x0a200ce0, 0x0a20d382, 0x240f1b44, + 0x584500b0, 0x237b84b0, 0xb2593e10, 0x1dfdf218, 0x82211321, 0x03032186, 0x24080583, 0x01f22702, 0x0189fe1c, 0xffe0fe8c, 0x01e4fefa, 0x0188fe81, + 0x01fa021a, 0xfdbefd93, 0xfe9901b5, 0x024b0267, 0x24f38242, 0x05000028, 0x209182e5, 0xdd83180c, 0x2084870c, 0x20918208, 0x200c8708, 0x200c820b, + 0x100c420b, 0x06209e83, 0x2707936c, 0x11030100, 0x05b23912, 0x0a200685, 0x30270684, 0x33130131, 0x18032301, 0x3e0730e2, 0xfeecaf4a, 0xdbd8ebe6, + 0xece6feeb, 0x01d6d8b1, 0xfb62032b, 0xfc410373, 0xfc8d04bf, 0x8264039c, 0x00092493, 0x41720400, 0x03200b87, 0x03205f82, 0x62148741, 0x012008e3, + 0x3f06e842, 0x01371701, 0x01230121, 0x132a0221, 0x01220112, 0xf646fe01, 0x010147fe, 0x4b4d3801, 0x73fb5703, 0x6f465682, 0x1e042105, 0x0f250a82, + 0x0cb23600, 0x09f96d10, 0xe341ef8c, 0x18b12007, 0x240b5a77, 0x0fb01008, 0x24d282d0, 0x20041411, 0x27761824, 0x11373f07, 0xfffe1e04, 0x00ff4afe, + 0xe56c7ef1, 0xfd8d0404, 0xdde0be01, 0xfdff02c1, 0xd4687300, 0x71820703, 0xd3822420, 0x71821620, 0xf6180720, 0xcd420ccb, 0xcbf6180f, 0xfe162f1c, + 0x83fef37e, 0xc903f203, 0xc90337fc, 0xd94500c4, 0x04ef2806, 0x0025009d, 0x1809b266, 0x460acd74, 0x807d0c65, 0x1c032708, 0x39121109, 0x877d0db2, + 0x10092105, 0x430c3c58, 0xb2210dc5, 0x212b8421, 0x2a591cb0, 0x22f7820c, 0x49242634, 0x24510746, 0x51172009, 0x53080a24, 0x36322114, 0xfe680203, + 0xf653b0cf, 0xf3fed2c3, 0x6e5f6578, 0xc0dd8f71, 0xe58accf8, 0x0001f47e, 0x32016f61, 0x624c4f42, 0xbb925c83, 0x5d51a0c8, 0x4c3a404d, 0x8eb23623, + 0xaa5dae99, 0x004ac071, 0x76000200, 0x39040000, 0x0d008d04, 0x63001600, 0x181705b2, 0xb024b582, 0x0fb01005, 0x410ba75b, 0x0023103a, 0x18b05845, + 0x22083f55, 0x8304020e, 0x590e2034, 0xb2230c3e, 0x830e000a, 0x44042015, 0x3d080fb0, 0x11231123, 0x15163221, 0x15010714, 0x32330121, 0x26343536, + 0x48022323, 0xc801f3df, 0x01e1f0da, 0xfefcfe12, 0x6c6cd534, 0x01d56f69, 0x0457fea9, 0xebaab78d, 0x0b25fe5b, 0x4e5f6b02, 0xb1826051, 0x30ff4c2c, + 0x9d046c04, 0x22001400, 0xb4184800, 0x1f200a3f, 0x1124b186, 0x11b11b2f, 0x240c5443, 0xb0593e10, 0x0df15311, 0x100eb418, 0x07061424, 0x14600717, + 0x35272905, 0x33361234, 0x27110032, 0x080cdb4f, 0x6e6c043c, 0xfe9dcf63, 0x9a3432f6, 0x820184f2, 0x01ef9cf1, 0x8997f122, 0x88979786, 0x2c029589, + 0x9848f1a3, 0x8b09c988, 0x39aa0101, 0x8e0501ab, 0xf4fec8fe, 0xc3c0b708, 0xc9b033b6, 0x6941b6c3, 0x042c2c06, 0x000a008d, 0xb24f0013, 0x41151404, + 0x454a051e, 0x0c784308, 0xc4820120, 0xb7820120, 0x010bb223, 0x20278303, 0x0c5c410b, 0x680e795b, 0x212305f7, 0x82151632, 0x412720c5, 0x20080752, + 0x01f36901, 0xf1fdd4e5, 0x68f2fed4, 0xf3657977, 0x67fe9901, 0xadd58d04, 0xc403c6a9, 0x69575458, 0x30938200, 0x04f0ff4f, 0x009d046f, 0x001c000e, + 0x1d03b248, 0x06a14d1e, 0x4b411220, 0x15864406, 0xf75b0b20, 0x1003220d, 0x366218b1, 0x0010250d, 0x11002223, 0x08164541, 0xdffe6f3a, 0xdafeeced, + 0xf09bf085, 0x96f22001, 0x99988688, 0x02948887, 0xfef8fe2c, 0x013501cc, 0x01ac2e0c, 0xc7fe8b07, 0xb708f5fe, 0x35b7c0c0, 0xb6c3c7b2, 0x00010000, + 0x04000076, 0x0020be82, 0x086b9818, 0x1b2f0524, 0xe64105b1, 0x10a5470c, 0x0cef8f18, 0x00050222, 0x15b2fe18, 0xf2670433, 0xf3f3f4fd, 0x03f20c02, + 0x04e5fc1b, 0x03e4fc8d, 0x2b71861c, 0x8d048f05, 0x60000e00, 0x100f01b2, 0x430db172, 0x46460c11, 0x0f661814, 0x4c858308, 0xb2230714, 0x84040001, + 0x20068585, 0x2206840a, 0x18093130, 0x2f0dcfff, 0x015101b2, 0xf23e014e, 0xa8a0fe19, 0xf219a1fe, 0xb5309382, 0x73fb4b03, 0x3a023b01, 0x70038bfc, + 0xc5fecbfd, 0x24055b45, 0x03000076, 0x210a8294, 0x00190005, 0x9c8c0bc9, 0x300e367d, 0x21253130, 0x33112115, 0x2b026901, 0xc2f3e2fc, 0x413d82c2, + 0x6820055d, 0x0c220982, 0x2b474b00, 0x2f042405, 0x4104b11b, 0x0220145d, 0x20060c48, 0x20d783b0, 0x200c820b, 0x2161820b, 0x034406b2, 0x10062805, + 0xb2d001b0, 0x4d06010a, 0x07290554, 0x33112311, 0x21013711, 0x08028201, 0xf387f026, 0x4f016ef3, 0x43fe2c01, 0xdefed301, 0xfe83db01, 0xfd8d04a8, + 0x7d0186fd, 0x7cfdf7fd, 0x24000100, 0x6403f0ff, 0x0e248582, 0x05b22300, 0x200a7141, 0x20658205, 0x21658205, 0x09490bb1, 0x31302109, 0x350e6b53, + 0xe3f37102, 0xf4e1cab2, 0x04574bb7, 0xaee0fc8d, 0xadafc0cf, 0x55825d5e, 0x00008524, 0x55827701, 0x1d000322, 0x0ae15718, 0x220f2c42, 0x82213130, + 0x770123ab, 0x5941f2f2, 0x68042108, 0x0b220a82, 0x35858700, 0x84820620, 0x35870620, 0x180c3d48, 0x190c1d51, 0x2d11cb03, 0xbf09afb4, 0xb25d0209, + 0x7101093f, 0x0483cfb2, 0x72220982, 0x0983ffb2, 0x01090f2e, 0x096fb472, 0x7102097f, 0xef09dfb4, 0x5f202683, 0x1c221283, 0x0b822c09, 0x840ba04c, + 0x3a40189f, 0x68042208, 0x05b342f3, 0xdb01f32a, 0x8d0425fe, 0xef0111fe, 0x002ee682, 0x04f0ff54, 0x009d0448, 0xb25f001c, 0x40181d1a, 0xaf8c09e1, + 0x22080b5e, 0x550a030e, 0xab6f06bc, 0x1003220b, 0x0b8a4bb1, 0x24851b20, 0x182f1b21, 0x080d144b, 0x06072550, 0x11002221, 0x33001035, 0x23171632, + 0x20232626, 0x16141511, 0x23353720, 0x48042135, 0xd5fe9617, 0x01dcfef8, 0xfad7f416, 0x7912ed19, 0xa0e4fe6c, 0xf9462801, 0x1893eb01, 0x012e018b, + 0x09014109, 0xc0c32c01, 0x89fe5c64, 0x39bab740, 0xe343b1c8, 0x9e032705, 0x09008d04, 0x85424200, 0x07784212, 0x0919b220, 0xb021147a, 0x0faa6204, + 0x23112133, 0x21152111, 0x5b032111, 0x03f30efe, 0x01cbfd28, 0x052d41f2, 0xd5fec422, 0x3e2e6d82, 0xef0313ff, 0x2a007305, 0x13b27200, 0xdf432c2b, + 0x0ccf4708, 0x08df4718, 0x09220322, 0x22050551, 0x18d00cb0, 0x200f74c9, 0x0c235a09, 0x1810b223, 0x262a8313, 0x1fb01022, 0x6022b0d0, 0xb2230cf0, + 0x43280326, 0xdb47051a, 0x19372007, 0x470ef119, 0x191905de, 0xe04708f1, 0xa9cf2409, 0x47cba6a0, 0xc32408e1, 0xe3bda0ae, 0x270ce147, 0xd910b486, + 0x8dc015dc, 0x2909e547, 0xe111ac86, 0x9ac713e1, 0xed824ac0, 0x0000382e, 0x9d041a04, 0x71001f00, 0x21201bb2, 0x0d674118, 0x4307d642, 0xb2230768, + 0x8205131f, 0x1fb02121, 0x200d1171, 0x0c0b5005, 0xd007b034, 0xb0d008b0, 0x0cb01000, 0x101fb0d0, 0xb0d00eb0, 0x16501013, 0x1f17220c, 0x31ec851a, + 0x21071621, 0x33352107, 0x27273636, 0x27333523, 0x66183626, 0x39080908, 0x03211717, 0x0685fe47, 0x01980250, 0x290a65fc, 0xa001032b, 0xd806039b, + 0xf3d9c2bf, 0x574d5057, 0x80010405, 0x70b2e501, 0x930bc3c3, 0x6993077d, 0xbcd4eece, 0x797e6a61, 0xbd4a0069, 0x99032905, 0x18008d04, 0x00b26f00, + 0x4b0a614e, 0x7c450cea, 0x0c002208, 0x238f8201, 0x0c0108b2, 0xb02c0682, 0x03b02f08, 0x03b07cd0, 0x05b0182f, 0x2308d968, 0x0ab01008, 0xd1820c88, + 0x10330f82, 0x1005b0d0, 0xb0d013b0, 0x15b01003, 0x1001b0d0, 0x4bd017b0, 0x33250567, 0x15072115, 0x22018221, 0x82213523, 0x27320801, 0x01333521, + 0xc8d20121, 0xbffafeff, 0x010afffe, 0xf2f5fe0b, 0x0c01f4fe, 0xc6f8fe04, 0x0101fafe, 0xff018e02, 0x1793b7fd, 0xd9d99130, 0x93093e91, 0xc3834902, + 0x00007624, 0xc3829703, 0x33000526, 0x070601b2, 0x0d954418, 0x1810024c, 0x2a151062, 0xd2fd9703, 0x032103f3, 0x8237fcc9, 0x00022149, 0x2807d54b, + 0x00080003, 0x0905b23d, 0x06d5490a, 0x92610220, 0x0f02450b, 0x0005b223, 0x18278202, 0x3f0b2248, 0x21213130, 0x27033301, 0x04210307, 0x0197fb72, + 0x1269f6b9, 0xe301de13, 0xc9fe8d04, 0x6ffd4d4b, 0x0020ba82, 0x28074348, 0x00120003, 0xb2790020, 0x051f5307, 0xb0100725, 0x82b0d001, 0x07c36905, + 0x4d0cf54f, 0x03210864, 0x2ff1830f, 0x2f03b07c, 0x0360b418, 0x5d020370, 0x400330b4, 0xb2240682, 0x71010300, 0x210c9063, 0x5e61100f, 0x1007210c, + 0x0b69d918, 0x2005f466, 0x1b7a4805, 0xfe380327, 0x01a6015a, 0x14804837, 0xc3df0123, 0x1b824876, 0x53410120, 0x00082608, 0x0907b238, 0x08a7410a, + 0x1b2f0224, 0x4b4102b1, 0x00b0230f, 0x09195845, 0x072209d7, 0x2e820002, 0x08054c41, 0x01210125, 0x0a010727, 0xb901fffe, 0xfeba01f6, 0x12defeff, + 0xfb8d0413, 0x4b560373, 0x0003004d, 0x03000042, 0x828d0455, 0x00072809, 0xb261000b, 0x4a0d0c04, 0x00230627, 0x5604b0d0, 0xd14509a9, 0x0843510c, + 0x0af48e18, 0x0a07b222, 0xb0227483, 0x77182f07, 0xb0220b12, 0x4e66100a, 0x2692830b, 0x21032135, 0x82132135, 0x55032b03, 0x1303edfc, 0x027efd49, + 0x09834982, 0x3801c326, 0xc40a01c4, 0x21059945, 0x95826204, 0x40000726, 0x090801b2, 0x1447fb88, 0x0cd2670c, 0x20087055, 0x0c646206, 0x2808c646, + 0xf4620421, 0x03f3fbfd, 0x06b342ec, 0x44000122, 0xe620f982, 0x0c246382, 0x00b24d00, 0x0a07cd18, 0x180c274e, 0x4f13ecbd, 0x55690602, 0x20ff820e, + 0x2aa78208, 0x01013130, 0x35211521, 0x82350101, 0x01280806, 0xe6fe9002, 0x5efc7002, 0xc1fe3f01, 0xbafd7c03, 0x45021601, 0x98c47ffe, 0xa601b701, + 0x8ffec498, 0x50000300, 0x4d050000, 0x112a8782, 0x1c001600, 0x08b27100, 0x47821e1d, 0xb0225d82, 0x0583d014, 0x43431a20, 0x2f102406, 0x4910b11b, + 0x10250c22, 0x0fb2593e, 0x29758310, 0xb02f0fb0, 0x09b2d000, 0x3a831008, 0xb02f0926, 0x09b0d006, 0x210c1d55, 0x184d0fb0, 0x1ab0280c, 0x1014b0d0, + 0x82d01bb0, 0x165b08af, 0x04141504, 0x35231507, 0x34352426, 0x33353724, 0x11050201, 0x26340504, 0x03241127, 0x1401f049, 0xf3ede9fe, 0x01eafef0, + 0xfdf3ef17, 0x180104f9, 0x1903ecfe, 0x12018290, 0xf60f1504, 0x0ffad0ca, 0xf90f6c6d, 0x0df7cdd0, 0xfeb7fd78, 0x2a0215fd, 0x8185fb15, 0x15d6fd0a, + 0x84010000, 0x820320dd, 0x001822dd, 0x0c31454c, 0xcd821220, 0xcd871220, 0x22083145, 0x83120c16, 0x831620c0, 0x12b02acd, 0xd017b010, 0xb0d004b0, + 0x0d126216, 0xb4830a20, 0x3536362f, 0x06113311, 0x11070607, 0x02261123, 0x080c8203, 0x17161434, 0x23033311, 0x01f36e7f, 0xf3fa7d68, 0xf302fbe3, + 0x01f37d70, 0xa7c218dd, 0xcdfe2f01, 0x1daf93e3, 0x1701e8fe, 0x012a0116, 0xfe360100, 0x18c0a8d1, 0xa383af02, 0x00005f2c, 0x9d048404, 0x5e002300, + 0xbd7707b2, 0x8219200a, 0x591920a3, 0xb0240f9d, 0xb0584500, 0x2007a647, 0x0e9259b0, 0xb0d00e26, 0x19b0d000, 0x270c2a55, 0xb01011b0, 0x21b0d020, + 0x2520b582, 0x8c59b582, 0x82152006, 0x154b08ad, 0x26333521, 0x36343511, 0x00323336, 0x06141515, 0x21153307, 0x6c78ad02, 0x948a8d94, 0x30fe7476, + 0xf283bdb0, 0x2a01ea9c, 0xfeb65963, 0xc922c82f, 0xac9e2bb0, 0xb128a4a9, 0xc4c823c7, 0x1627019b, 0xfe84ec91, 0x8d19ede3, 0x83c44adf, 0xff242cc7, + 0x045205ec, 0x0019008d, 0x1816b26e, 0x870f3548, 0x820e20c7, 0x100e21d4, 0x2006725a, 0x200c8218, 0x42481818, 0x08b22e17, 0x12110e02, 0x2f08b039, + 0xb1100eb0, 0x0965610f, 0x4208b021, 0x0a450c4b, 0x21152205, 0x20c68215, 0x21c58216, 0x644f3523, 0x222a0805, 0x01231107, 0x03a6fe7e, 0x8aa0fead, + 0xf0f0da8d, 0x747673eb, 0xf3858175, 0xc4c4c903, 0xc6d427ee, 0x54bdc0bc, 0x26677269, 0xbd83e7fd, 0xf0ff4f2c, 0x9d044304, 0x92001d00, 0x275803b2, + 0x14134e0a, 0x0b0fb222, 0x4e05a74e, 0xb2210c1a, 0x2d158515, 0xffb22f15, 0xb2710115, 0x7201150f, 0x09833fb2, 0x0482cf20, 0x156fb42f, 0x7102157f, + 0xbf15afb4, 0xb25d0215, 0x201c835f, 0x4504828f, 0x03200ce5, 0x220d5248, 0x430b031d, 0x062105d4, 0x05634e04, 0xe4823620, 0x84180420, 0x49080fb5, + 0xfe114204, 0xfeecd9f7, 0x9cec7eec, 0x140401d6, 0x727d0cf3, 0x800116fb, 0x7e0a80fe, 0x0d7c7883, 0xd5bf8401, 0x0b012c01, 0x8affa944, 0x6970c2da, + 0x94c4cffe, 0x0070629f, 0x24000200, 0x15070000, 0x17008d04, 0x7a002000, 0xcb4604b2, 0x577b1805, 0x0c27430a, 0x0c839718, 0x0b4d0b20, 0x12b02106, + 0x200df76e, 0x6b4b180b, 0x14b2230c, 0xc1820312, 0x2f14b022, 0x4f0c2577, 0x14371043, 0x11210706, 0x02060321, 0x37232306, 0x37363637, 0x33112113, + 0x82251632, 0x36420804, 0x23263435, 0xcff91507, 0xa4fe15fe, 0xac580b0e, 0x26013491, 0x150c4e60, 0xdaec3b03, 0xf140fdfa, 0x66767567, 0xd2ab7f01, + 0xfec90302, 0xfffeef9c, 0x0702cd75, 0x2b02ed9f, 0x0cd06cfe, 0x536b8efe, 0xe9836351, 0xe9827620, 0xe9821820, 0x1c001324, 0xad18c400, 0x1320120b, + 0x1320cf82, 0x870c4a4e, 0x0c06770c, 0x22080652, 0x69131000, 0xb42d05d0, 0x00bf00af, 0x3fb25d02, 0xb2710100, 0x820483cf, 0xb2722709, 0x7201005f, + 0x0e83ffb2, 0x09820f20, 0x006fb42a, 0x7102007f, 0xef00dfb4, 0xb4232b82, 0x822f001f, 0x9fb22106, 0xad181982, 0x33213d45, 0x051f5332, 0x0845ad18, + 0x08060e51, 0x01690122, 0x8cf2f3fd, 0xd2ff6fd2, 0x03fe1ffe, 0xf002f3f3, 0x767567f1, 0x019e0266, 0x5f6cfeef, 0xd0af70ab, 0x21051c4c, 0x2241a8fd, + 0x00012e06, 0x05000024, 0x008d0452, 0xb2590015, 0x0aa56d12, 0x240ca951, 0xb11b2f14, 0x07bf4314, 0x2108365b, 0x75471003, 0xd000250c, 0x031408b2, + 0x7f05bc43, 0xaa430b9e, 0x06037d0c, 0x270ba643, 0xebde8e86, 0x7474f304, 0x2906a443, 0xcbcf26ed, 0x5a0198fe, 0xa343697c, 0xfe762406, 0x8261049f, + 0x000b23a1, 0x4518b250, 0x022007f9, 0x4705ed63, 0x2d480c9a, 0x48b02014, 0x15480ba3, 0x09b0220b, 0x0f4718d0, 0x33113307, 0x33112111, 0x8afe6104, + 0xf37efef3, 0xfef30502, 0x7082019f, 0x0336fc23, 0x064342ca, 0x84280421, 0x0014267f, 0x1508b261, 0x5de28416, 0x778c0919, 0x18081151, 0x230d3048, + 0x080a03b2, 0x03243683, 0x1008b02f, 0x6e0cff55, 0x3d080d5f, 0x21013130, 0x16163315, 0x21230610, 0x32012111, 0x26343536, 0x03112327, 0xfcb7fdb2, + 0xd9f8f4cf, 0x3c031ffe, 0x7368a8fe, 0x03f66670, 0xc403e0cb, 0x04cca8fe, 0x6336fc8d, 0x015d4f54, 0xad839cfe, 0xaffe2724, 0xad821505, 0x15000f28, + 0x13b25d00, 0x76831716, 0xb0101327, 0xb000d005, 0x0535410d, 0x430c5552, 0x854a07d1, 0x05f54c0c, 0x0f6f0d20, 0x10b02706, 0xd011b0d0, 0xf64405b0, + 0x3130250c, 0x37023e37, 0x10879f18, 0x4a823308, 0x0c052342, 0xf2963d03, 0x01f3f7fc, 0xf0017401, 0x0d07a1fe, 0xb48651c3, 0xfcc1017e, 0x01ecfd36, + 0x02affe51, 0xfc060314, 0x0100aefe, 0x00001a00, 0xad821f06, 0x9f001524, 0x7d4201b2, 0x0cdf540a, 0x410c565c, 0x68180c6d, 0xa8440cad, 0x2f153d0c, + 0x1015b11b, 0x0cb2593e, 0x12110e03, 0x2f0cb039, 0x010c3fb2, 0x0c5fb271, 0xcfb27201, 0xb4300982, 0x0cbf0caf, 0x8fb45d02, 0x020c9f0c, 0xd00fb072, + 0x250c106a, 0x08b2d004, 0x3882040f, 0x0113b223, 0x058c450f, 0x82112321, 0x21032101, 0x0da59f18, 0x5ff50338, 0xfefc60f3, 0xfe5c01d3, 0xf71e01c4, + 0xf754f354, 0xc2fe1e01, 0x12825e01, 0x2bfed523, 0x27038201, 0x39025402, 0xe00120fe, 0xfd230383, 0x82a3fdd0, 0xff422cf5, 0x04e703f0, 0x0027009d, + 0x6a26b28d, 0xdb8c0af9, 0x2008d469, 0x0c914e0a, 0x0a06b223, 0x21908216, 0x068426b2, 0x2f26b025, 0x8226cfb2, 0x823f20d7, 0xafb42804, 0x0226bf26, + 0x82ffb25d, 0x0fb2220b, 0x20e88226, 0x1804825f, 0x220c4383, 0x83262310, 0x161c223c, 0x2006820a, 0x0d6c72b0, 0x65313021, 0x275d06e7, 0x1651080a, + 0x23041415, 0x26272622, 0x33163335, 0x34353632, 0x33352327, 0x70e20236, 0xf3665b6b, 0xf4d8c3f3, 0x6e6f5d6e, 0x5ddcfefe, 0xf37c3faf, 0x7477ca0b, + 0xc79a94e0, 0x4f464303, 0xb3943c46, 0x8a5b96a7, 0x5b912427, 0x2f2db59f, 0x57939f5b, 0xb003a648, 0x060d4e04, 0x046e042b, 0x0009008d, 0x0a00b24c, + 0x1575540b, 0x200c124b, 0x061d5305, 0xee54b020, 0x0304220c, 0x233b8200, 0x080509b2, 0x3c05a241, 0x11231133, 0x33112301, 0xf37b0311, 0xf3eefdf3, + 0xfb8d04f3, 0xfc230373, 0xfc8d04dd, 0x06e14be0, 0x77824020, 0x78000c22, 0x43197d4b, 0x08540c1d, 0x08314a0c, 0x05020622, 0x2a06e660, 0x7101063f, + 0x01065fb2, 0x82cfb272, 0xafb42d09, 0x0206bf06, 0x068fb45d, 0x7202069f, 0x200b5042, 0x082e54b2, 0xa3822320, 0x33113322, 0x3d052e54, 0xf3f36ad3, + 0x01380163, 0x0172fe1d, 0x01d1fead, 0x042bfed5, 0x0120fe8d, 0xfdc5fde0, 0xe55900ae, 0x82552006, 0x001026b1, 0x1104b24f, 0x15294112, 0x2008864c, + 0x1e911800, 0x00b0210a, 0x210c3642, 0x764409b0, 0x064d570c, 0x02060324, 0x7a470706, 0x04240806, 0xa4fef355, 0xaa570c0f, 0x27013a8c, 0x160c4a62, + 0x73fb8d04, 0x9ffec903, 0x78fefeed, 0x0b04cd01, 0x2b02e6a0, 0x1f249383, 0x3904ecff, 0x0f249382, 0x00b24400, 0x4e0aeb5a, 0x304e0cfb, 0x2f082b0c, + 0x1008b11b, 0x01b2593e, 0xc2820f08, 0x080ee254, 0x21131720, 0x23020e01, 0x32173727, 0x02210137, 0x01f31329, 0x3870fe0a, 0x665a7e5a, 0x33605701, + 0x1d825bfe, 0x02374b36, 0x7e7efc79, 0xc0053869, 0x7f036104, 0x76000100, 0x2405affe, 0x0b248582, 0x09b24300, 0x080f4c18, 0xdc5cb020, 0x14c55408, + 0x46420520, 0x0c084606, 0x30d00029, 0x03332531, 0x46211123, 0x62300608, 0xfcdd14c2, 0x0502f343, 0xecfdc3f4, 0x8d045101, 0x22050946, 0x5b410001, + 0x11240673, 0x04b24700, 0x0a476618, 0x4d0c4d53, 0xe2580c32, 0x7a0d2008, 0x0d200567, 0x200ca84e, 0x379d1830, 0x82272007, 0x14230879, 0x37323316, + 0x16043311, 0xea8186f3, 0x6ff301f0, 0xf3858279, 0xd226aa01, 0xfe6601d1, 0x266c779e, 0x42001f02, 0x062105c3, 0x22f7840e, 0x8607b242, 0x081443f7, + 0x470f0964, 0x03240c9f, 0xd006b010, 0x24055e4f, 0xb01006b0, 0x05ff460a, 0xf6873320, 0xfa0e062a, 0x5f01f368, 0xf36001f3, 0xf587f185, 0xaffe7624, + 0x7182d106, 0x42000f24, 0xef410bb2, 0x46032006, 0xc25e0549, 0x0c494614, 0xb0d00d26, 0x07b0d009, 0xb0216e83, 0x0e68410e, 0x06267983, 0xdd14c20f, + 0x788596fa, 0x850b6f41, 0x0002267d, 0x0500000a, 0x287d821b, 0x0015000c, 0x1608b261, 0x067d4717, 0xa14e1420, 0x46828c06, 0x07200802, 0x230c9e4a, + 0x03070ab2, 0x0a233683, 0x4d03b02f, 0xd5540ed6, 0x3130220c, 0x05924a01, 0x11213525, 0x47163233, 0x0533087e, 0xfecff91b, 0x02a2fe15, 0xf9dbeb52, + 0x756632fe, 0x4af96271, 0xc431067b, 0xfed06cfe, 0x4f536b9a, 0x8efe0263, 0x00ffff00, 0x20af8276, 0x2aaf82a9, 0x00080226, 0x01070000, 0x823204e3, + 0x05835c07, 0x22074548, 0x4803b24f, 0x03200545, 0x48094548, 0x60570cca, 0x04072208, 0x068a6406, 0x16581320, 0x04b02109, 0x840c654f, 0x822320b5, + 0x89b383b1, 0x28042ab4, 0x1ffed2ff, 0xd28cf2f3, 0x29b2886f, 0x8d04d0af, 0xab5f6cfe, 0xb187d4fe, 0x0001002d, 0x04f0ff3c, 0x009d0430, 0x4d8a001d, + 0x054c0c03, 0x1758180c, 0x1a002208, 0x65918212, 0x09220c2f, 0x01501a12, 0x08f95705, 0x57b47121, 0x165806ef, 0x08075806, 0x095fb224, 0x6e797201, + 0x12b0210b, 0x210c8a73, 0x4b840eb2, 0x162fd282, 0x36323316, 0x21352137, 0x06222302, 0x18362307, 0x080aa99b, 0x01272441, 0x787c0d2f, 0xfe0a8082, + 0x1680017f, 0x0c7d72fb, 0x040114f3, 0x1701e2d6, 0xea7b010c, 0xf8fedc9b, 0x7084010f, 0xc4949f62, 0x70693101, 0xe8fedac2, 0xffa975f0, 0x00bada88, + 0xff760002, 0x824106f0, 0x001326ed, 0xb2b20021, 0x051d6904, 0x1f750420, 0x0cbe4309, 0xa1600b20, 0x08d24418, 0x0b080d22, 0x2208fc83, 0xafb42f0d, + 0x020dbf0d, 0x0d6fb45d, 0x71020d7f, 0x010dffb2, 0x0d0fb271, 0x8fb47201, 0x020d9f0d, 0x825fb272, 0xcfb2210b, 0x3f201583, 0xb4230482, 0x822f0d1f, + 0x4110832d, 0x10200d0f, 0x210c9958, 0x0f7a03b0, 0x3130270c, 0x23001001, 0x67180022, 0x36210734, 0x11c25d00, 0xfe410630, 0xfedeeddf, 0xf2bc13e2, + 0x0114bcf2, 0x825cdc1d, 0xe2102a12, 0x8d041efe, 0x01e918fe, 0x0f855c0f, 0x43000226, 0x12040000, 0x22067143, 0x4306b25c, 0x06200571, 0x09234918, + 0x690c7143, 0x1128086d, 0x12110709, 0x2f11b039, 0x230bf57b, 0x110a01b2, 0x20095158, 0x0e404a07, 0x01334308, 0x36343526, 0x23112133, 0x13032311, + 0x33331614, 0x06222311, 0xd6160143, 0xcc01d3f0, 0x2ee6f1f3, 0xdddd6b61, 0x0a026b61, 0xb9a3d156, 0xbc0173fb, 0x220344fe, 0x4a01594a, 0x01000057, + 0x00000a00, 0xa782ff03, 0x52000d26, 0x0f0e01b2, 0x48081b47, 0x50590c38, 0x02072208, 0x06494308, 0x54500420, 0x0516750a, 0x280a725b, 0xb01007b0, + 0x3130d00c, 0x08938201, 0x35231120, 0x15211133, 0x02331121, 0xd4f3d6a7, 0xfd2103d4, 0xe601d6d2, 0xe6011afe, 0xc4fd01aa, 0x8583c7fe, 0xaffe1a24, + 0x85826d06, 0xa6001924, 0xff5008b2, 0x061d4506, 0x480cc44a, 0xb0720cc1, 0x085c4e0c, 0x11091722, 0x172da283, 0x173fb22f, 0x5fb27101, 0xb2720117, + 0x2d0982cf, 0xbf17afb4, 0xb45d0217, 0x179f178f, 0xba567202, 0x00b2230b, 0xf5561707, 0x0cbd4a05, 0x0b25c382, 0x170fb2d0, 0x2b4e8407, 0xd012b010, + 0xb01011b0, 0x18b0d014, 0x1322d983, 0xdc821133, 0xcf4a0320, 0xc1042611, 0xabd0beee, 0x12d14afd, 0xfe5d0228, 0x01edfd65, 0xd34a0151, 0x058b4712, + 0x047c0429, 0x0010008d, 0x4800b28a, 0x6e7e06a5, 0x2f0c2406, 0x520cb11b, 0xa76b0cce, 0x63b0200f, 0x0d220cf0, 0x4e430c09, 0x3fb22405, 0x4371010d, + 0x5d430934, 0x054c4307, 0x230bbf47, 0x0d0800b2, 0x06203283, 0x230c8a6a, 0x01013130, 0x0120e784, 0x28087049, 0x21019302, 0xfe9bd0c8, 0x077449c2, + 0xfe520223, 0x49d58770, 0x5f470576, 0xfe042105, 0x1426cb82, 0x05b28100, 0x55421615, 0x82142008, 0x871420c8, 0x0cac45bb, 0x19821120, 0x1c4f1120, + 0xc2781807, 0x11002208, 0x05295014, 0x28052250, 0x7201005f, 0x0100cfb2, 0x06385071, 0x008fb42b, 0x7202009f, 0xb0d004b0, 0x0d376300, 0xb2d00c25, + 0x4a000c08, 0x352306d0, 0x4a331533, 0x2323052a, 0x84352315, 0x012508ca, 0x37a34769, 0x1c013801, 0xae0172fe, 0xc2fed1fe, 0xf347a33e, 0xdead02f3, + 0xfde001de, 0x01affdc4, 0xfecbcbd5, 0x4fc1822b, 0x4e2005db, 0x0e240982, 0x09b28700, 0x430a6b5e, 0x744c0cc1, 0x0cef4a0c, 0x08487018, 0x07020822, + 0xb02a8f82, 0x3fb22f08, 0xb2710108, 0xcb83085f, 0xb42b0982, 0x08bf08af, 0x8fb45d02, 0x4a089f08, 0xb0210def, 0x0c1b5007, 0x180cb221, 0x27155978, + 0xf36ae102, 0x5302a0fe, 0x240e034b, 0xfec3ca03, 0x33cd8520, 0x4f000200, 0x9805ebff, 0x2300a504, 0x90002e00, 0x302f15b2, 0x2006cf6e, 0x06014824, + 0x1b2f1b24, 0x53661bb1, 0x0cac5714, 0x23073f58, 0x1b0402b2, 0x02234183, 0x4b0bb02f, 0xb0210c13, 0x0c0c4804, 0x6400b021, 0xb0270caa, 0x26b01002, + 0x191bb0d0, 0x380cfa00, 0x22053130, 0x20230627, 0x34350300, 0x22153300, 0x14151506, 0x37333316, 0x2d0f8226, 0x12323312, 0x07101517, 0x10013316, + 0x0f6f3617, 0x11560805, 0xaee39805, 0xdafea991, 0x0104acfe, 0x7f71db08, 0x1b1bc0cb, 0xbfdc02c0, 0xa301ddc6, 0x94fd5c5f, 0x5301a2be, 0x3910b35b, + 0x013c013e, 0x01fe3a18, 0xb1b4cc2e, 0x02cdcb26, 0x2c1e01aa, 0xfe0d01ea, 0xfe48ecfc, 0x010badff, 0x6ff4fed2, 0xa035f378, 0xffd2fe90, 0x676800ff, + 0x01263b07, 0x000000d3, 0x00260207, 0x00d5fe3b, 0xfe150001, 0x048b04af, 0x000f008d, 0x5418b25b, 0x0720078f, 0x5c05b949, 0xb94b0c3c, 0x08e2530c, + 0x260b4d4c, 0x0b0f00b2, 0x4a391211, 0xb2230b4f, 0x420f0b0a, 0x132105a5, 0x066b4321, 0x230d2968, 0x92cfc409, 0x250f2a68, 0xedfd77fe, 0x2e685101, + 0x24a38208, 0x06affe24, 0x22a3842e, 0x4a09b25e, 0xdd51065d, 0x0cc84506, 0x410c0450, 0x6a4a07d8, 0x5f08200c, 0xb0240c1c, 0x0bb0d00a, 0x2107b95d, + 0xe24bd00d, 0x38741808, 0x6a053d08, 0xfcde14c4, 0x03a4fe44, 0x02acfea2, 0xfdc3f206, 0x035101ec, 0xfcc4c4c9, 0x00ca03fa, 0xed4b9982, 0x00172607, + 0x1804b250, 0x08094419, 0x240cd244, 0xb11b2f16, 0x0f764b16, 0x5d10b221, 0x1021057d, 0x0bac452f, 0xd004b027, 0xb01010b0, 0x228b8213, 0x18112321, + 0x28086c73, 0x16141133, 0x15333517, 0x05fc4b36, 0x564c2208, 0x02cfcca3, 0xa35654f3, 0x01f3584a, 0xcc0a16aa, 0xbfd10dc8, 0x9ffe6a01, 0xf30c696b, + 0x021809f2, 0x06a5441f, 0x8d044b23, 0x0f894c00, 0x540cd641, 0xa8470cc2, 0x10042208, 0x24ca8201, 0xb12f04b0, 0x09524a0d, 0x1331302a, 0x33361133, + 0x11151632, 0x08d69f18, 0xf3763008, 0xefed8086, 0x817475f3, 0x8d04f385, 0xd62656fe, 0x019efed1, 0x26697c61, 0x0000e0fd, 0xff0a0002, 0x04a805f0, + 0x001b00a3, 0xb2670023, 0x8325240d, 0x100d2356, 0x97431db0, 0x0cb14106, 0x22087d43, 0x74000e20, 0xb12105d1, 0x2a7e8912, 0xb0d003b0, 0x0ab01020, + 0x5700b0d0, 0xb0210ce5, 0x0e6e720e, 0x20056808, 0x26262700, 0x16143335, 0x33023e17, 0x15110020, 0x32211221, 0x06173737, 0x06220306, 0x34352107, + 0xfec90326, 0x0cc0fefa, 0x54c1bfae, 0xf18f0958, 0x01000191, 0x12c0fc17, 0x73864f01, 0xc53b412f, 0x08a080a1, 0x10954c02, 0x0bea1101, 0x765dbbdd, + 0x7ee4920c, 0xf7fee5fe, 0x2bd0fe95, 0x2c21ba12, 0x8ca5ee03, 0x82958616, 0xff4f24df, 0x828104f0, 0x5b6e18df, 0x101b5b1c, 0x3a5b6e18, 0x14151725, + 0x18230606, 0x080b5b6e, 0x13363642, 0x21373632, 0x02161415, 0x010b0139, 0xf98c023b, 0xfefefe96, 0x073f03eb, 0x7686a6b3, 0xc940412d, 0x0a9e8198, + 0x0494b4fd, 0xf9dcfea3, 0x88f99b7a, 0x08011c01, 0x2c9a9695, 0x2b22ba11, 0x8ea312fc, 0x012ecb83, 0xecff4200, 0x8d04e803, 0x6c001900, 0xa55912b2, + 0x08f94317, 0x0d356118, 0x0204b22a, 0x39121100, 0x020b19b2, 0xb0270682, 0x05b02f19, 0x850fb2d0, 0x0e25670c, 0xb1101923, 0x095d4918, 0x01313023, + 0x556e1821, 0x7135200b, 0x2d08070c, 0x02352323, 0x03defd8d, 0xc6fe0152, 0x00ffc2a2, 0xf3f7d0df, 0x73657104, 0x037df173, 0xfe9bc4c9, 0x8bbf14c0, + 0xa1b9c0a8, 0x535a5049, 0x7f5fbbb0, 0x000e260b, 0x001c0015, 0x0ac56781, 0xb0d00f25, 0x5fb01003, 0xb04b077f, 0x20a58215, 0x096c420f, 0x0b13b223, + 0x2fc88203, 0x2f13b07c, 0x1360b418, 0x5d021370, 0x401330b4, 0xb2290682, 0x5d0113f0, 0x011300b2, 0x59538271, 0x13200ca1, 0x181dfe67, 0x200d2794, + 0x0cfe6704, 0x79f0fd30, 0x36020e94, 0x7978930e, 0xccfd0e91, 0x0668950f, 0x7f012b12, 0x9d95959d, 0x939ddbfc, 0xc7629d93, 0x0027240a, 0x5425b2b2, + 0x1d240a1f, 0x1db11b2f, 0x2210bf5c, 0x820c1d06, 0x06b03dce, 0x060fb22f, 0x01b05d01, 0x2f01b0d0, 0x0101cfb2, 0x1f09405d, 0x3f012f01, 0x04014f01, + 0x1082d582, 0x7602b121, 0xb0240964, 0x07b11006, 0x0c200e8a, 0x0dae4718, 0xb0d00e2a, 0x07b0d00f, 0xd011b010, 0xb0272982, 0x02b0d013, 0x8216b010, + 0xb010255a, 0x1db0d018, 0x0c345318, 0x2421b223, 0x2c818201, 0x01210cb2, 0x0131305d, 0x17211521, 0x2c048215, 0x07210706, 0x36333521, 0x33352337, + 0x11126335, 0x01c4012c, 0x0382fe83, 0x73fe7b01, 0x17632612, 0x343c0805, 0x03a19612, 0x0601999e, 0xd7c4bfd8, 0x4d5354f3, 0xba020557, 0x93164292, + 0xc3c33545, 0x0e936c0e, 0xce27924a, 0x5ab6d0ee, 0x00797e67, 0x46000100, 0xb003f0ff, 0x22009e04, 0x0ab2a400, 0x0a676918, 0x440c9445, 0x222208f8, + 0xa5820916, 0x2f22b02e, 0x01220fb2, 0x2210b45d, 0x5d022220, 0x210d5518, 0xb0102225, 0x82b0d00e, 0xd0133405, 0xb22f13b0, 0x5d0113cf, 0x2f131fb6, + 0x03133f13, 0x8200b25d, 0x654f180d, 0x7416200c, 0xb02a0ce4, 0x1db01013, 0x1010b0d0, 0x55181fb0, 0x22260c17, 0x35232724, 0x03823533, 0x3336362b, + 0x26071732, 0x21072223, 0x08018215, 0xfe4e0342, 0x6f7b1183, 0x761b7950, 0xfffed46e, 0x9292971a, 0xd3ff1a98, 0x5b167a6c, 0x0122d675, 0x017dfe7c, + 0x6a840183, 0x1fbf1c68, 0x5c92c4d0, 0x20d6c393, 0x93d61cbf, 0x0400005c, 0x00007600, 0x9e04c707, 0x08494e18, 0x4e18ad20, 0x4d422349, 0x2f242407, + 0x4a24b11b, 0x212014de, 0x4e181982, 0xb6281f49, 0x02100200, 0x5d030220, 0x394d4e18, 0x35212523, 0x4d4e1821, 0x05364911, 0x15062708, 0x11012301, + 0x01331123, 0x88073311, 0x3b02c5fd, 0x01bf8afd, 0xfebec036, 0x5aafc1ca, 0x02585053, 0x5d4e4f5d, 0xe36aa6fe, 0x95c83807, 0xb996f201, 0x96489cb8, + 0x059bb8b8, 0x54626557, 0x63645753, 0x6ab4fc5b, 0x02320afc, 0x00002800, 0x8d04aa04, 0x1e001500, 0x0db28f00, 0xbf46201f, 0x46172006, 0xe74706bf, + 0x084f680c, 0x43030621, 0xb121066d, 0x09524405, 0xd001b022, 0x31055253, 0xb62f0ab0, 0x0a1f0a0f, 0x5d030a2f, 0x9f0a8fb6, 0x0882af0a, 0x0f83b420, + 0x18710221, 0x200c6f52, 0x28308413, 0x0ab0d014, 0xd016b010, 0xc2db18b0, 0x1825200f, 0x240d6f52, 0x07061016, 0x0b496e21, 0xf5fef624, 0x0082d0f3, + 0xeb013408, 0xc8edf6d1, 0x0b01f6fe, 0x61f8f5fe, 0xf95e7573, 0xb6999999, 0x3a02b74d, 0xcdb4fed3, 0x04014d05, 0x65565567, 0x00010000, 0x02f5ff37, + 0x002003a9, 0x19820024, 0x20119904, 0x069a5f1a, 0x2f172708, 0x1017b11b, 0x00b2593e, 0x12110d17, 0x00b07c39, 0x50b4182f, 0x02006000, 0x0080b671, + 0x00a00090, 0x0db05d03, 0x0419b110, 0x0a220b9b, 0x2a820600, 0x1000b024, 0x4e4424b1, 0x12b22309, 0x7c4e0024, 0x1eb12105, 0x6618158a, 0x3321089f, + 0x06926032, 0x75076b58, 0x27261092, 0x510c0123, 0x04193684, 0x0123149b, 0x192361d2, 0x2a159b04, 0x00350002, 0x03be0200, 0x190a0015, 0x870e653a, + 0x073a4ae2, 0x890b2277, 0x06b02ba1, 0x1001b0d0, 0xb2d00bb0, 0xd6830b08, 0x08142277, 0x07353325, 0x5f5f5f02, 0x099afebb, 0xfebd6d01, 0x010eba8b, + 0xa3a3973a, 0xfef90179, 0x0016f225, 0xff4f0001, 0x82ae02f5, 0x001a2483, 0x180db26d, 0x240a2b57, 0xb11b2f02, 0x5d888702, 0x02210846, 0x0b687c10, + 0x0207b22b, 0x3912110d, 0xb12f07b0, 0x23978918, 0x071805b2, 0x18059e42, 0x230ba051, 0x181311b2, 0xb2231582, 0x8213181a, 0x31302606, 0x15211313, + 0x0d7d7821, 0x08066841, 0x3462072e, 0xacfeec01, 0x83473e14, 0x818ca38c, 0x05b902ad, 0x42437572, 0x7f013543, 0x94969601, 0x787a861b, 0x52638499, + 0x2844387d, 0x4d000200, 0xb92abf82, 0x13002203, 0x5e001e00, 0x194314b2, 0x7a142005, 0xc7870e0b, 0x8a0c0b7a, 0x0c0622b1, 0x05964600, 0x4614b121, + 0x52180d66, 0x047a0a52, 0x36342212, 0x05047a33, 0x32334108, 0x02343536, 0x0d899132, 0x87756b47, 0xab9386a8, 0x2d96def0, 0x357f0f42, 0x99220344, + 0x8e45625f, 0xa799777a, 0xe8d2319b, 0x172457fe, 0x36469124, 0x01000074, 0x00003600, 0x1503ae02, 0x33000600, 0x4e12e37d, 0x052308df, 0x8904b110, + 0x00b22296, 0x07227b04, 0x2101233a, 0xae022135, 0x01c4adfe, 0x024cfe53, 0xfdac0278, 0x967f0254, 0x4b000300, 0x2a06e97d, 0x001c0013, 0xb2990024, + 0x83262507, 0x100725e0, 0xb0d014b0, 0x22200582, 0x24063744, 0xb11b2f11, 0x071d4111, 0x22080368, 0x82110722, 0xb07c382d, 0xb6182f22, 0x22902280, + 0x5d0322a0, 0x602250b4, 0xb4710222, 0x83102200, 0x22402906, 0x5d022250, 0xe022d0b4, 0xb1210d82, 0x229e8a19, 0x82192202, 0x0cb2233c, 0x71852219, + 0x230c5241, 0x1fb11011, 0x430d3c7e, 0x3425084c, 0x34352637, 0x05ca5636, 0x26345d08, 0x16140622, 0x15223413, 0x36321614, 0x84719702, 0xa48c8ea1, + 0x819b7184, 0xe4fe9b82, 0x6a414035, 0xc4974040, 0x02316033, 0x3d377441, 0x797a6a80, 0x373d806b, 0x76766974, 0x5a33e0fd, 0x335a3030, 0x5656ab01, + 0x00303027, 0x46000200, 0xa302f7ff, 0x13002003, 0x63001f00, 0x212014b2, 0x14209783, 0x2409b967, 0xb11b2f08, 0x07034108, 0x2307874c, 0x081002b2, + 0x7c292782, 0x182f02b0, 0xb11010b0, 0x22b58911, 0x8c1002b0, 0x100821d3, 0x0b795418, 0x667e3020, 0x15172a0b, 0x23070614, 0x27363235, 0x071d4632, + 0x16143a08, 0x5a42e701, 0x84aa877e, 0xdc02a28b, 0x798f13e0, 0x42234e63, 0x3c413334, 0x8a393601, 0xa6a4787d, 0xd9d73b97, 0xac529301, 0x41484534, + 0x4437394e, 0x00010000, 0x03870290, 0x5d50182d, 0x0fb94a0b, 0xfd2d0333, 0x029d0263, 0x0000aa87, 0x04960003, 0x06a20248, 0x31098295, 0x001b000f, + 0x0db00050, 0xd019b02f, 0xb12f19b0, 0x44180907, 0xb022082a, 0xdc82d002, 0xd000b037, 0x402f00b0, 0x1f000f0f, 0x3f002f00, 0x5f004f00, 0x07006f00, + 0x25e4825d, 0x19d003b0, 0xfe8203b0, 0xb1100d23, 0x44921813, 0x0733240c, 0x7d340723, 0x3720090d, 0x0806997a, 0x2223262d, 0xe6bc0106, 0x6e8295f5, + 0x696c4c4e, 0x636b514f, 0x30242534, 0x34252430, 0xdec29506, 0x4d65644e, 0x4b62634a, 0x25313125, 0x4e333327, 0x03270519, 0x008d04b5, 0x6f51000b, + 0xfd4412d3, 0x060b2208, 0x12727304, 0xc7680420, 0x18b0200c, 0x260d7d72, 0x21013130, 0x86152111, 0x032e0803, 0x020afe5f, 0x03c1fc4c, 0x01b7fd3c, + 0xfef801f6, 0x8d04c2ca, 0x00f2fec4, 0x0a000300, 0x1b044afe, 0x29004e04, 0x43003600, 0x08b2a000, 0x6c834544, 0xb0100825, 0x82b0d030, 0x433a2005, + 0x26240629, 0x26b11b2f, 0x0c6d5f18, 0x593e122a, 0xb01026b0, 0x28b0d028, 0x0c190d19, 0x1608b223, 0x24428426, 0x160fb22f, 0x23098308, 0x35b12f0f, + 0x23098047, 0x0f351bb2, 0xb2221582, 0x2684081f, 0xb1101623, 0x821c8930, 0x3ab12172, 0x26230e8a, 0x7141b110, 0x23300c64, 0x14151516, 0x22230606, + 0x14150627, 0x16163317, 0x24240d85, 0x26373435, 0x262a0383, 0x36343535, 0x21173233, 0x20820601, 0x2106085f, 0x67180325, 0x7c080b38, 0x3a8a1b04, + 0x5180ce73, 0xc2732545, 0xfa8fcac3, 0xf5fed99a, 0x5a7532b6, 0x55c7fc64, 0xfd71014b, 0x88312430, 0x93ac8672, 0x7a40eafe, 0x75775859, 0xa00375b8, + 0x64166955, 0x23125fa9, 0x01034a2f, 0xa6588e9a, 0xa5799b62, 0x77483259, 0x5f9e3151, 0x14caa216, 0x4813e5fb, 0x5e4d4230, 0x02096b40, 0x664bb302, + 0x4a124e67, 0x004d6666, 0x56000200, 0x5f04ebff, 0x10004e04, 0x70001d00, 0x79a718b2, 0x0c157e09, 0x20075941, 0x49b8180c, 0x0ce1530b, 0x27089943, + 0x11020900, 0x0bb23912, 0xb0210684, 0x0c5f5a02, 0x4a09b021, 0x54080cd3, 0x06253130, 0x35022223, 0x33121035, 0x33371732, 0x01231303, 0x32331614, + 0x26353736, 0x06222326, 0xf26e6303, 0xc7e8e6c7, 0xdd1c71e9, 0xfddd736c, 0x60747cc7, 0x7d11177c, 0xc47f7363, 0xf42001d9, 0x010a010f, 0xfdc3d736, + 0x01e4fde2, 0xabaca0f9, 0xb9a52fa6, 0x2ed383c5, 0x0400009b, 0x00b005f2, 0x001e0016, 0x4618b263, 0x18200575, 0x09eb4f18, 0xc6820320, 0x48200321, + 0xf35e06a9, 0x820f200c, 0x100f2719, 0x17b2593e, 0xc6820103, 0x7617b021, 0xb2230c48, 0x83170009, 0x6d032015, 0x56080f4b, 0x21112311, 0x14151632, + 0x15131607, 0x21151714, 0x34352726, 0x21252326, 0x34353632, 0x97012121, 0xf52902fc, 0x05e5f7ff, 0x3bfcfe47, 0xfe707b04, 0x901401d3, 0xfef8fe81, + 0xfd5602e3, 0xd9b005aa, 0x4565e3cd, 0xa973f6fe, 0xb8311a3d, 0xca807479, 0x00e66d71, 0x82000100, 0x300521c7, 0x017bc782, 0x82042008, 0x8704209e, + 0x820820b8, 0x8708200c, 0x0c8c410c, 0x22106774, 0x181fb22f, 0x3d2401c0, 0xfcac4302, 0xac018bfc, 0x0cfe3601, 0xd0fe2002, 0x90fd7002, 0x9cfdb005, + 0x47fd6402, 0x918209fd, 0x0000812a, 0x00063504, 0x54000c00, 0x84051344, 0x644b1891, 0x42918407, 0x9195072b, 0x02080723, 0x05934811, 0x38430020, + 0x0ab22309, 0x1a630700, 0x08d36009, 0xf26fe23d, 0x0f0169f2, 0x9ffe1c01, 0xe6fe8f01, 0x27fed901, 0x9cfc0006, 0x11fe9e01, 0x4100b5fd, 0x1222061f, + 0x6d18b005, 0xd841098b, 0x0c96180c, 0x0ce5410c, 0x21095a57, 0x77820103, 0x8505b221, 0x00092106, 0x2206ba47, 0x88112311, 0xfc973b84, 0x190206fc, + 0xa5fd3801, 0xc8fe7f02, 0x66fd9a02, 0x7ffdb005, 0x35fd8102, 0x83831bfd, 0x00008128, 0x18062204, 0x6e180a00, 0xe618070f, 0x06230c40, 0x18b11b2f, + 0x8c080f6e, 0x084c4e83, 0x85060021, 0x20068583, 0x22838c08, 0x82012101, 0xf2733c02, 0x015901f2, 0x0150fe2a, 0x01dbfedc, 0x0615feeb, 0x0184fc18, + 0xfd0cfe9e, 0x5e0000ba, 0x2a2a050f, 0x0b008d04, 0x48001300, 0x297913b2, 0x10132305, 0x1b4502b0, 0x0cc95306, 0x21073d53, 0xb15601b0, 0x5e00200d, + 0x3f080ccd, 0x11333130, 0x16043221, 0x06141517, 0x11032304, 0x35132033, 0x01762510, 0x0301a47b, 0xfe8f0290, 0x8283a8f9, 0xfe064701, 0x8a8d04c9, + 0xa33d9ffb, 0xc9038bfe, 0x5c01f9fc, 0x08600143, 0x4f000100, 0x26060b6b, 0xb250001b, 0x541d1c03, 0x535108ef, 0x150b6b14, 0x210e3474, 0xc96a1bb2, + 0x11202219, 0x05354415, 0x2313c76a, 0x8786edfe, 0x3913c26a, 0xb5b9488e, 0x03007062, 0x00007600, 0x8d040a04, 0x16000e00, 0xa7001f00, 0x81481eb2, + 0x101e2505, 0xb0d002b0, 0x11200582, 0x231b4541, 0x000117b2, 0x5b052644, 0x6f2f0759, 0x02177f17, 0x17ffb271, 0x0fb27101, 0x5b720117, 0x825b066a, + 0x3fb22109, 0xb42e1a82, 0x172f171f, 0xbfb45d02, 0x0217cf17, 0x5252b172, 0x0f08210b, 0x27843e19, 0x14151622, 0x07444618, 0xe76a0320, 0x274a0805, + 0x36363327, 0x23263435, 0xaf017623, 0x5b59ebde, 0xdde27060, 0x6466e4e2, 0x5bd4fab4, 0xc6656763, 0x9ca58d04, 0x1723834f, 0xaba3638f, 0xc7fefb01, + 0x059e4155, 0x454802aa, 0x0200464f, 0x00000900, 0x8d049404, 0x0a000700, 0x51764700, 0x0d665b1a, 0x08145e76, 0x040ab239, 0x39121102, 0x21253130, + 0x33012307, 0x21012301, 0xfe3f0303, 0x01f55f1e, 0xd501dfd7, 0x0106fef6, 0xf9f9aa54, 0x73fb8d04, 0xba01b201, 0x00010000, 0x01690494, 0x182b06a9, + 0x1810af72, 0x3613f572, 0x34352307, 0x83260136, 0xd301023f, 0x532b0655, 0x85867c6d, 0x8200b659, 0x752a08c3, 0x0003d404, 0x0d007e06, 0x5e001100, + 0x2f03b000, 0xb0d006b0, 0x0b402f06, 0x061f060f, 0x063f062f, 0x5d05064f, 0xb11003b0, 0x6a49060a, 0xcb5e1809, 0x08088208, 0xb0d01167, 0x0eb02f11, + 0x2f0eb0d0, 0x0e0f0f40, 0x0e2f0e1f, 0x0e4f0e3f, 0x0e6f0e5f, 0x11b05d07, 0xd010b010, 0x2f10b019, 0x01313018, 0x22230614, 0x14333526, 0x36323316, + 0x17332535, 0xaf000323, 0xb1b19596, 0x4c47494c, 0x72b794fe, 0x61b10580, 0x34637a7c, 0xcd343c3c, 0xfc0200c0, 0xfebc049d, 0x008c06d6, 0x00170013, + 0x209b8a76, 0x239b890d, 0x5d06065f, 0xb0249d82, 0x09b0d009, 0x1023ba82, 0x89080db1, 0x20b582a6, 0x220e8a10, 0x4fb0100d, 0x280805fa, 0xb07cd016, + 0x40182f16, 0x1f160f09, 0x3f162f16, 0xb05d0416, 0x14b0d014, 0x143fb62f, 0x145f144f, 0x0fb45d03, 0x02141f14, 0x28b3875d, 0x15062223, 0x33363427, + 0x08b98432, 0x07332737, 0x5fd6fe23, 0x29833846, 0x5f672a1f, 0x2a8e2c46, 0xc3882c1d, 0x82058db6, 0x3246694c, 0x6d4b1c25, 0xec253146, 0x000200d4, + 0x04e7047a, 0x0090068b, 0x000a0006, 0x24c1845b, 0x05b0d005, 0x06a54a2f, 0xa54a0920, 0x2a7f8207, 0x02b01003, 0x02b019d0, 0x67b2182f, 0xb021055a, + 0x220e8206, 0x89182f06, 0xd00732dd, 0xb62f07b0, 0x071f070f, 0x5d03072f, 0xb01009b0, 0x2222820a, 0x82182f0a, 0x332b08a6, 0x07272305, 0x03330123, + 0xa19d0123, 0x9fd42301, 0x3303d59f, 0x059dd8de, 0x8e8efae1, 0xf5fea901, 0xff020000, 0x03da044c, 0x8a83065c, 0x8204208d, 0x82042040, 0x82002063, + 0x85002007, 0xd001236b, 0x044201b0, 0x41092007, 0x04250768, 0x0302b25d, 0x05c94706, 0xd008b027, 0xb02f08b0, 0x20328207, 0x20328207, 0x51868308, + 0x8d820b7b, 0x25208b83, 0x21089282, 0x5c033303, 0xd49f9fd5, 0xfea12301, 0xddd79d87, 0x8e8eda04, 0x0b015cfa, 0x75000200, 0x0a04e704, 0x8b82cb06, + 0x61001523, 0x25728300, 0x03b0d003, 0x9192b02f, 0xb0d0052e, 0x09402f05, 0x051f050f, 0x053f052f, 0x05208b84, 0x01218b83, 0x2c858210, 0xb02f07b0, + 0x0db0d00d, 0x0708b22f, 0x2115820d, 0xa8420eb1, 0x14b22209, 0x07264708, 0x23072726, 0x27173325, 0x0b5cf618, 0x03072708, 0xb2b3c15c, 0xbb1601c1, + 0x383f07b9, 0x8c890781, 0x04013849, 0xfaa2a2e7, 0x18057d74, 0x59693e1d, 0x0741374b, 0xad85003b, 0x065c0323, 0x22ad82d1, 0xb08f001a, 0x030521ad, + 0xb0249782, 0x0ab0d00a, 0x3f29c682, 0x5f0a4f0a, 0x040a6f0a, 0x39b6855d, 0x0d0f0f40, 0x0d2f0d1f, 0x0d4f0d3f, 0x0d6f0d5f, 0x0ab05d07, 0xd010b010, + 0xd78210b0, 0x14b11022, 0x1782cd89, 0x8a17b121, 0x1014240e, 0x41d01ab0, 0x3725086d, 0x22230614, 0x0da94226, 0x3208e086, 0x59ba932a, 0x247b313d, + 0x595a291b, 0x267f2a3c, 0xe7042c1a, 0xdfed8e8e, 0x2c425f3e, 0x6040181b, 0x001c2d41, 0x00760001, 0x05970300, 0x000700c4, 0x7503b233, 0x4a611783, + 0x0f767508, 0x11330137, 0x11231121, 0xf3a40221, 0x02f3d2fd, 0xfec4052e, 0x0437fc05, 0x053d418d, 0x6344d320, 0x050d413d, 0x27176344, 0x11b01010, + 0x11b019d0, 0x22116344, 0x44073327, 0x65250b63, 0x0580a9b6, 0x076244b0, 0x85c0ce21, 0x02d5289b, 0x000807f6, 0x431c000d, 0x072606a1, 0x2f07b0d0, + 0x67430b40, 0x073f2305, 0xff44074f, 0x10072111, 0x2005bb41, 0x840882b0, 0x053e4495, 0x0e0fb228, 0x39121114, 0x521815b1, 0xb2230941, 0x820f0e1b, + 0x0ffc4412, 0x88422720, 0x023b080d, 0x9291aff6, 0x4450adaf, 0x08df4d45, 0x07923f48, 0x444e9f9e, 0x62b00501, 0x34627979, 0x19333a39, 0x1a170276, + 0x44506036, 0x3a083a2f, 0x00ffff00, 0x028d024b, 0x03b805aa, 0x82c70107, 0x009822c4, 0x057d4613, 0x1b2f0a2c, 0x3e200ab1, 0xd010b059, 0x27833130, + 0x9802352a, 0xad05be02, 0x20020703, 0x0920278b, 0x09202782, 0x083d7318, 0x4f204f82, 0xae204f82, 0x21202784, 0x10202784, 0x01204f85, 0x01202782, + 0x30212782, 0x20238231, 0x2223824d, 0x82ba05b9, 0x8b22204b, 0x8200204b, 0x82002023, 0x14b02123, 0x36207386, 0x4b857382, 0x4b8b2320, 0x27820520, + 0x4b870520, 0x0221bf88, 0x20238424, 0x206f8519, 0x20238211, 0x24238211, 0xb0d019b0, 0x05b85711, 0x4624c583, 0xa3028f02, 0x0221ed83, 0x4b798b25, + 0x1a2008ce, 0x002f7983, 0xff6b0001, 0x052605eb, 0x001d00c5, 0x740cb242, 0x68180a51, 0xa7680ca9, 0x4be11808, 0x74b0200d, 0x30200d08, 0x150f4619, + 0x15024208, 0x33121415, 0x05373632, 0xd2fe1724, 0xdcfeb6f9, 0x019e01a0, 0x01fbb720, 0x16fd1734, 0xccac90a3, 0x9b91acd2, 0xe9da0116, 0x01b4fafe, + 0xd53cd245, 0xfeb44a01, 0x9298e9f3, 0x34efe6fe, 0x8fe4feeb, 0x26a78a96, 0xb2580020, 0x4922210c, 0xa79808ed, 0x5b0cae5d, 0xb2230c0e, 0x82030c20, + 0x20b0223f, 0x0dac7a2f, 0x04062535, 0x02242223, 0x12343527, 0x04323324, 0x21022317, 0x86070222, 0x115608bc, 0x05213521, 0xdcfe4626, 0xcefec0b0, + 0x019f02ad, 0x01f8b723, 0x2ef91f2b, 0xd3aae9fe, 0x64bce803, 0xddfe1f9b, 0x5fbc1f02, 0x4801b272, 0x01d931d1, 0xe3f0b64f, 0xe5fe0701, 0xfeec33e9, + 0x012430df, 0x0200c01b, 0x00009b00, 0xb0051705, 0x15000b00, 0x03b24800, 0x1e461716, 0x490f2006, 0x6d4d0bff, 0x2c454b07, 0x17123a08, 0x04021415, + 0x33110307, 0x35351232, 0x9b230234, 0x01c8be01, 0xb003b241, 0xc4ccc0fe, 0xf1f8dcae, 0xb1b005da, 0x38c8c3fe, 0xb2bffecc, 0xfbe40403, 0xf00e01e6, + 0x0c01ea26, 0x2a978200, 0x05ebff6b, 0x00c50572, 0x82200011, 0x09617597, 0x24071b5f, 0xb11b2f0d, 0x6297870d, 0xe11808a6, 0xb0210d32, 0x0fb04e04, + 0x0bcaf918, 0x04323325, 0x82071712, 0x02222697, 0x16141515, 0x08a68216, 0x72053740, 0xb4d8fea6, 0xaad8feb2, 0x2a01a501, 0x2601b2b4, 0xdcfb04a8, + 0x66dfa9ad, 0xd8a46eb6, 0xcec3020a, 0xbabab0fe, 0x31c94e01, 0xc04d01cb, 0xc6b9feb7, 0x2201e412, 0x25e8dbfe, 0x0186f193, 0xb985da09, 0xb9840320, + 0x23001422, 0x14774119, 0xb9821020, 0xcc4e1020, 0x3e10240c, 0x1810b059, 0x18107946, 0x290a4751, 0x14013130, 0x07170702, 0x0e420625, 0x90202008, + 0x053538bc, 0xef899772, 0x43d5fea5, 0xdafeb33e, 0x01a702aa, 0x01680128, 0x8201a827, 0xaa3008c0, 0x6fb566de, 0xc602d9ae, 0x62bdfeca, 0x0df594c0, + 0xcb4d01b7, 0x5201d02e, 0xaffeb7bb, 0x01ec05ce, 0xefddfe1f, 0x84f2971d, 0x00f52001, 0x97000100, 0xef22c882, 0x03568c04, 0x0fbe7c0e, 0x0004b223, + 0x06096105, 0xd54e0320, 0x31303509, 0x05112321, 0x02332535, 0x9bfef3ef, 0x031f3902, 0xd0cd7a69, 0x6e2c5583, 0x2c040000, 0x19009e04, 0x09b25b00, + 0x670a435f, 0xa57c0ce6, 0x89182008, 0x02b22352, 0x68820018, 0x0003b223, 0x21068211, 0x721811b0, 0x0c200d27, 0xb2221584, 0xf3651117, 0x21212305, + 0x0e4c0135, 0x06222505, 0x36342315, 0x08061254, 0x2101072e, 0x60fc2c04, 0x3946fb01, 0x7b675a69, 0x85d779f3, 0x6e57eaca, 0x4902b1fe, 0x3fba019f, + 0x5a484063, 0xbc736078, 0x5a9cb76a, 0xd6fe669f, 0x0f26af83, 0xf203a3fe, 0xaf828d04, 0xf35f5c20, 0x630c2008, 0x022005fd, 0x6306ce7d, 0xb2230b3f, + 0x82020004, 0x05b2229e, 0x2506830c, 0xb02f05b0, 0xc675100c, 0x05b0250b, 0x0317b110, 0x2208d84a, 0x4f1719b2, 0x21310677, 0x01152135, 0x14151616, + 0x22230406, 0x33163727, 0x05cd4c32, 0x02353c08, 0x03bafd9e, 0xab9dfe77, 0xf2fe90db, 0x39cec7b0, 0xc4a4ad9d, 0x0348b7aa, 0xfe8fc4c9, 0xb0f71a80, + 0x6784f3a3, 0x92b858b6, 0x007b9296, 0xfe350002, 0x048b04c4, 0x000a008c, 0x4553000e, 0x586f058b, 0x0c9a500c, 0xc1820620, 0x3e100623, 0x25c18b59, + 0xb01006b0, 0xb982d005, 0x0608b223, 0x05935a00, 0xd00cb025, 0x4c090db2, 0x330806d5, 0x11231533, 0x27211123, 0x21013301, 0xd5030711, 0xfdf2b6b6, + 0xa6020658, 0x0164fdfa, 0xc3c217aa, 0x3b01c5fe, 0xfcf90394, 0x2a800236, 0x66000100, 0x1e04a0fe, 0x1c268f82, 0x19b26000, 0x50821e1d, 0x0eb00022, + 0x6d0d3d65, 0x07220c06, 0x24510e01, 0x29481806, 0x05b2230a, 0x15831907, 0x0dd26418, 0x1311b222, 0xb2221583, 0xb859191c, 0x3603240a, 0x54123637, + 0x45410579, 0x22350809, 0x5a870706, 0x9afd2903, 0xcf86652d, 0xa5f585ed, 0x844ab5e4, 0x8eab8fbd, 0x1b665378, 0x17037501, 0x32aafed2, 0xf7fe0202, + 0x82f398e4, 0xb363b275, 0x35a28794, 0x24bd823b, 0x04c4fe43, 0x25bd8210, 0x00260006, 0xf87501b0, 0x18b68c0d, 0x36091d54, 0x35210123, 0xfd100421, + 0x3e02f3b6, 0xcd0332fd, 0xbefa0604, 0x48c30505, 0xd02a05a1, 0xdc06f702, 0x20000c00, 0xa14d7e00, 0x4d09201b, 0x0c260da1, 0x2f0cb0d0, 0x4b4a06b0, + 0xd0132807, 0x402f13b0, 0x5f130f0d, 0x4f330540, 0x06135f13, 0x1010b05d, 0xb0d016b0, 0x13b02f16, 0x4d1ab110, 0x10230a2b, 0x8a1db110, 0x101a2a0e, + 0x30d020b0, 0x06140131, 0x08c04d20, 0x704a1320, 0x02430812, 0xdefeb0f7, 0x464cafb0, 0x5f904a48, 0x2a813847, 0x61682a1f, 0x2c882f45, 0xb0052c1e, + 0x657b7b65, 0x333c3a35, 0x6b4b0f01, 0x1b253247, 0x32476c4d, 0x01000024, 0x9afe5c00, 0xb5004f01, 0x12000300, 0x1904b000, 0x820cf500, 0x11233c73, + 0xf34f0133, 0x029afef3, 0x0002001b, 0x06f0ff4f, 0x009d046d, 0x001e0014, 0x5416b296, 0x162305a9, 0x180bb010, 0x680bc96b, 0x82461491, 0x45002308, + 0xd042b058, 0x510b2008, 0xb2280cc6, 0x110b0010, 0x10b03912, 0x0de47818, 0x9d680020, 0x6502200d, 0x0a200d28, 0x240c8045, 0x21213130, 0x9e4a1805, + 0x57052007, 0x052308b3, 0x68271137, 0x063f05a3, 0xfe47fd6d, 0xdafeecad, 0x019bf085, 0xfdb80253, 0xfef601b7, 0xfb4c020a, 0x86cfcdf4, 0x18109998, + 0x3108a44a, 0xf2fec410, 0x0fcafec3, 0x09140308, 0xb235b7c0, 0xff8200c7, 0xb4fe732e, 0xa0045404, 0x24001800, 0x1fb25600, 0x2005075b, 0x051f5c1f, + 0x6a421420, 0x2f0c2105, 0x2106f76b, 0x64441014, 0x1419220c, 0x24db820c, 0x2f19b07c, 0x0c405f18, 0x0f707118, 0x36320532, 0x22230637, 0x36343502, + 0x00323336, 0x02141511, 0x20055d44, 0x0bf55913, 0x98e94e08, 0xaa7219bd, 0xda7bf7d1, 0x1401f187, 0xb2f3fe91, 0x7d2f849e, 0x8852b0d1, 0x8a876d7f, + 0x5abec889, 0x99e51201, 0xd1fe80ed, 0xe5cef6fe, 0x3cb2b2fe, 0xe9012fb6, 0xb4a5ac78, 0xb08a92b1, 0xb0ff0100, 0x8e014bfe, 0x0d00cd00, 0x03b22f00, + 0x05436e0e, 0x2006e343, 0x23c18205, 0x593e1205, 0x210bcf6e, 0x744b0eb0, 0x31302606, 0x07141125, 0x06ef4406, 0x11352908, 0x5b708e01, 0x0e384695, + 0xcd7c3d24, 0x62c8f7fe, 0x0cc6114f, 0xff0501b2, 0xfe3900ff, 0x041c04a3, 0x0206018d, 0x00002a4c, 0x2006d34a, 0x067f4502, 0x82313021, 0xfe6a2621, + 0x042204a0, 0x2121828c, 0x2188044e, 0x21820120, 0x3e1e0123, 0x24218459, 0x04c4fe2c, 0x22218482, 0x4b00f74d, 0x1b450767, 0x4a0d2008, 0x662606f3, + 0x24040000, 0x47829e04, 0x88f84b21, 0x079c4647, 0x63204784, 0x30204782, 0x4f214784, 0x84218820, 0x266987e7, 0x04ebff35, 0x82a00458, 0xd3652143, + 0x0a206988, 0x0a208b82, 0xb0212182, 0x2b698611, 0x04ecff6f, 0x03b70531, 0xfa1a0006, 0x834b2588, 0x86152008, 0xfe592425, 0x843a04b4, 0xe653214b, + 0x17422588, 0x861f2008, 0x82682025, 0x0522224b, 0x234b82c4, 0x0000001c, 0x2006834b, 0x2b718215, 0x593e2015, 0xb0d01bb0, 0x25b01015, 0xe33b2b86, + 0x3b030000, 0x06008c04, 0x004c4a02, 0xb5ffffff, 0x93014bfe, 0x06023a04, 0x92009c00, 0x8f002b0f, 0x82010000, 0x06003a04, 0x1f848d00, 0x5cfefb22, + 0x26200f84, 0x15820f83, 0x0ad2a424, 0x258dffff, 0x00010031, 0x04ebff76, 0x009c0416, 0xb2680021, 0x4b232201, 0x94840819, 0x2007d543, 0x21a1821f, + 0x8c58101f, 0x08686906, 0x3f5b1f20, 0x0ab2230c, 0x3d82151f, 0x2f0ab027, 0xb1d019b0, 0x093b4708, 0x7c69d382, 0x4725200d, 0x50080934, 0x22232613, + 0x11231115, 0x32333636, 0x16031716, 0x06141516, 0x01272223, 0x4d484beb, 0x54747c5c, 0xb15146ca, 0xcfd101ef, 0xf968cd78, 0xafd9aaa1, 0x31db6c7c, + 0x47585265, 0x390101a3, 0x021cfdf9, 0x61d5d7f0, 0x17d4fe6f, 0xcaaf81a4, 0x00020036, 0x2ccd8262, 0x00a00485, 0x001a000d, 0x1b03b248, 0x2291831c, + 0x62b01003, 0xfe6d07e5, 0x08974c0c, 0xfa470a20, 0x1803200d, 0x2b0c9546, 0x10013130, 0x26222300, 0x00103502, 0x1224a482, 0x20263407, 0x0805f96c, + 0x3736323f, 0xe3fe8504, 0x82f39ef3, 0x9ff21f01, 0x9bf281f2, 0x9a99f6fe, 0x02978586, 0xe9fe3e02, 0x018ec4fe, 0x1601c70c, 0xfe8e3e01, 0xc7b8a7f3, + 0xb52cbac8, 0x00b4c5cd, 0x003a0001, 0x05ea0300, 0x0eb149b0, 0x1810ec59, 0x200d9c49, 0x0eba46b2, 0xfdea0331, 0x2c02f4d4, 0xb00344fd, 0xd7fa2905, + 0x82c3ed04, 0xff7c27ff, 0x064604ec, 0x1a190000, 0x457c277d, 0x8754180c, 0x0c052708, 0x39121103, 0x06840ab2, 0xb54db020, 0x0aed4911, 0x31304f08, + 0x23021401, 0x23072722, 0x36113311, 0x11123233, 0x23263427, 0x16110722, 0x04363233, 0xc0c7f346, 0xf3d2116d, 0xf0ccb269, 0x9a7b8bf3, 0x7a994744, + 0xf411028a, 0x7a8ecffe, 0xd2fd0006, 0xfed6fe7c, 0xbba608fa, 0x8737fe85, 0x010000bc, 0xbf825000, 0x4e040028, 0x4d001d00, 0x4f4e17b2, 0xfe66180a, + 0x7908200c, 0x6a450660, 0x0803220c, 0x22b38310, 0x82081014, 0x6dac1806, 0x6fce180e, 0x4535200b, 0x16230563, 0x82262317, 0x063808a7, 0x16141515, + 0x7a5a4202, 0x7a04e406, 0xfee674ca, 0x98e17af2, 0xe406f4c3, 0x795c7807, 0x69ae8585, 0x64b0664f, 0x19fe2b01, 0xe487fb9e, 0xb3765fb4, 0xb0ad1bb2, + 0x4f000200, 0x172ca782, 0x11000006, 0x66001c00, 0x1e1d1ab2, 0x1a207483, 0x6e05bd5b, 0x67180673, 0x0d200cbe, 0x0d20b282, 0x59074043, 0x06220856, + 0x37820d04, 0x840bb221, 0x4db02006, 0x1a20110f, 0x370cb26c, 0x33363634, 0x33111732, 0x06272311, 0x26262223, 0x16143735, 0x11373233, 0x2e08c683, + 0x82cd704f, 0xd3f36aac, 0x7ebb6c11, 0x8df374cb, 0x4646947b, 0x028d7d92, 0x8cfd9f26, 0xfa290277, 0x8c897500, 0x9d019bfd, 0xd70181c2, 0x8300c17d, + 0x56fe2fc1, 0x4e041704, 0x26001b00, 0x1fb28600, 0x89822827, 0xd546b020, 0x45002306, 0xbe8cb058, 0xbe820720, 0x605d0720, 0x4412200c, 0x1820060c, + 0x18271982, 0xb2593e10, 0x83180406, 0x740c2041, 0xb2220cf5, 0x15831210, 0x8516b221, 0x1018231c, 0xd2891fb1, 0x6904b021, 0x30220c57, 0xe1851331, + 0x11333724, 0xe0820014, 0x2006164a, 0x8bec8435, 0xcd6d3eeb, 0x1069bf85, 0xeffbfed1, 0x3549b955, 0x838e9082, 0xcc7fae6a, 0x788ff372, 0x94454695, + 0x3bf5827c, 0x868dfba0, 0xf61cfc72, 0x2d2ff6fe, 0x9b9c4cb0, 0xfc8c7716, 0x81c09f9d, 0xc17bd901, 0x4c24fb82, 0x5504ecff, 0x0f24fb82, 0x45001900, + 0x0a371f19, 0x1d8bbe18, 0x230b1250, 0x17b11004, 0x20119c41, 0x06585f00, 0x35003608, 0x32161417, 0x26343536, 0x824c0622, 0x01e696eb, 0x98ed7f20, + 0xf2e1fee6, 0x9793fc95, 0x270295f8, 0xfe8bfd9f, 0x9d0dfccd, 0x31018dfc, 0xc4a009fe, 0xc59fb5c4, 0x249982c6, 0x0460fe7c, 0x2e998244, 0x001b0010, + 0x1c19b270, 0x3912111d, 0x181019b0, 0x1808017a, 0x240c53a0, 0xb11b2f0a, 0x0795410a, 0x0c820720, 0x95410720, 0x18042007, 0x2207195d, 0x82040d06, + 0x0bb22141, 0xb0210684, 0x0de95e0d, 0xbb4bc482, 0x3130330a, 0x06061401, 0x11272223, 0x17331123, 0x12323336, 0xca430717, 0x442d080a, 0xb181c86f, + 0x0ed9f36c, 0xefc1ba6c, 0x7c91f10a, 0x93454492, 0x11029378, 0x748afd9e, 0xda0500fe, 0xebfe8571, 0xc29f27ec, 0x7817fe78, 0x056142c3, 0x16046022, + 0x6d20cb86, 0x0420cb8a, 0x0b875618, 0x6818be8c, 0xcb870ce1, 0x6142f284, 0x0a2d4305, 0x5f18b120, 0xc88f0b6b, 0x21094842, 0xd1821123, 0x42270221, + 0x2c080b3d, 0xb786cd6f, 0xf3d2116b, 0xf6beaa6a, 0x7893f20b, 0x8c484690, 0x26028f7e, 0x828afca2, 0x0126fa6e, 0x1c0170fc, 0xc59e27e2, 0x73f40176, + 0x24c783c6, 0x04ecff53, 0x26c7820b, 0x001e0016, 0x4a08b27f, 0x082005ff, 0x5e095346, 0xf96f0c51, 0x081b3a08, 0x39121100, 0xb42f1bb0, 0x1bcf1bbf, + 0x5fb45d02, 0x021b6f1b, 0x1b1fb471, 0x2806822f, 0x011b8fb2, 0x1befb45d, 0x210b82ff, 0x8a630cb1, 0x0f1e7509, 0x67420820, 0x2205220e, 0x06c04400, + 0x15151228, 0x33161621, 0x0d703632, 0x023d080b, 0xcffef276, 0xdd8be27d, 0x0f3efdf1, 0x92558da9, 0xbd3f3a31, 0x107c66a7, 0x1473d001, 0x21f72801, + 0xfe8bf99e, 0x857bf7f4, 0xa6202f9d, 0x9f033932, 0x701a7c8d, 0x0002007f, 0x0456fe51, 0x26e38204, 0x00240019, 0x4a22b286, 0x222005e3, 0x1809e34b, + 0x5e0c3ba6, 0x0b240c30, 0x0bb11b2f, 0x6907ab41, 0x05220851, 0xfd831703, 0x58470b20, 0x0fb2220c, 0x21158311, 0x1c8515b2, 0xf0511720, 0x3a9a180c, + 0x3130230e, 0x71613413, 0x100c4405, 0xcd410220, 0x5162080a, 0x6bbdc3e7, 0xfafed011, 0x37af57ed, 0x8e837535, 0xbeae6a82, 0x7381f2ea, 0x94444397, + 0x26028076, 0x862b01fd, 0xf210fc72, 0x212efefe, 0x94963fb0, 0x2f017622, 0x85b7a8f6, 0xb57fd101, 0x5b00ffff, 0xb2020000, 0x0600b505, 0x00b31500, + 0x5d000300, 0xb704efff, 0x1d009d04, 0x32002600, 0x2cb26c00, 0xc7833433, 0xb0102c25, 0x82b0d013, 0x421f2005, 0x0d2006bb, 0x0d20f582, 0x240f6251, + 0x584500b0, 0x083a7cb0, 0x1a0d1422, 0x2a06954f, 0x2b0ab01e, 0xdc1bd858, 0x8421b259, 0x2ab22113, 0xb0240684, 0x30b0100d, 0x302a1a87, 0x26220531, + 0x37363435, 0x06832737, 0x32338908, 0x07141516, 0x35361707, 0x17071433, 0x27062721, 0x07033732, 0x16141506, 0x17161403, 0x34353637, 0x06222326, + 0xe4bafb01, 0x40327252, 0x9994be5c, 0xe8489dbb, 0xc980d43a, 0x9b4af4fe, 0xfd5874bf, 0x175c4245, 0x493f2a39, 0x3f333742, 0x5585aa11, 0x45224e86, + 0x9a797369, 0x6c927ba0, 0x8663f032, 0x4ccfa0dc, 0x012dc35d, 0x48303004, 0xc3024a3f, 0x2b2a4a29, 0x3a2c4135, 0x0001003c, 0x03000003, 0x008d049e, + 0xb23e000d, 0x490b6b7a, 0x95740c3d, 0x45022008, 0xb2230908, 0x82040a06, 0x0cb221f4, 0x33080684, 0x07013130, 0x21152111, 0x37350711, 0x37113311, + 0x02fa6d02, 0x7de2fc2b, 0x02faf37d, 0x71fe4c9d, 0x260802c2, 0xf2012693, 0x004c57fe, 0xf1ff0200, 0x03060000, 0x0f287582, 0x8a001200, 0x141305b2, + 0xb0234982, 0x5eb01005, 0x7d9407dd, 0x4500b025, 0x4808b058, 0xb2210610, 0x2477840f, 0x2f0fb07c, 0x0c2a5118, 0x210de965, 0x268411b2, 0x2f11b022, + 0x200c9b7d, 0x0c6d600a, 0x8412b221, 0x21c38224, 0xc3821321, 0x2b190320, 0x30080814, 0x05032105, 0x0c45fe98, 0xfdfc1a02, 0x8382fe0a, 0x6d02fcfe, + 0xf6fd7703, 0xfcc2010b, 0x14160140, 0xc2fefe01, 0xfe0701c0, 0xc18d04f9, 0x02f9f4fe, 0x25db8205, 0x00007600, 0xdb82d203, 0x15000c26, 0x09b25900, + 0x2005b955, 0x935b1809, 0x82002009, 0x4f0020c1, 0x10240c43, 0x02b2593e, 0x23051a4f, 0x0fb22f02, 0x0f210985, 0x0c566d2f, 0x494f0220, 0x3057080c, + 0x15331331, 0x15163233, 0x23070614, 0x11132315, 0x35363233, 0x76272634, 0xfdd795f3, 0xf39cd7f6, 0x736b99f3, 0x8d046376, 0xaeaad0b7, 0x03e301ca, + 0x5f94fe12, 0x01655255, 0x4f000300, 0x6f04c9ff, 0x1600ba04, 0x28001f00, 0x06b26a00, 0x12112a29, 0x1006b039, 0x83d01cb0, 0x42252005, 0x257f06f7, + 0x082f4a0c, 0x06121922, 0xb2212d82, 0x2106841a, 0xc57412b0, 0x22b2210c, 0xb2231584, 0x85120623, 0xcd621851, 0x31302c0b, 0x15171601, 0x22230010, + 0x78230727, 0x36330547, 0x37173233, 0x17140133, 0x22232601, 0x34211506, 0x83160127, 0x036008c8, 0xfe0487e4, 0x7a9eeddf, 0x9087a44c, 0x9bf08501, + 0xa4487ba3, 0x0128d8fc, 0x8662439b, 0x243c0298, 0x5f4267fe, 0xfb039488, 0xfe41f49a, 0x47ccfef8, 0x019bc36e, 0x01ac3404, 0x694c8b07, 0x598172fd, + 0xc0345202, 0xfd5977b7, 0xb6c330b2, 0x31000200, 0xd7040000, 0x13008d04, 0x8d001700, 0x191805b2, 0x18066d42, 0x6f076941, 0x267f0c0f, 0x1499530c, + 0x5413b221, 0x13290548, 0x130fb22f, 0x00b15d01, 0x093b540e, 0x1a851520, 0x43181520, 0xb02a0c0d, 0x08b01000, 0x1013b0d0, 0x05840ab0, 0x83d00e21, + 0xd0162911, 0x23013130, 0x21112311, 0x23260382, 0x33353335, 0x03822115, 0x01332408, 0x04213521, 0xfdf25ad7, 0x5a5af3f3, 0xf20d02f3, 0x02a7fc5a, + 0x03f3fd0d, 0x01b1fc4f, 0x0325fedb, 0x8294aa4f, 0xa5fe2b00, 0x010000b1, 0x4bfe7600, 0xdb846704, 0x02b25b24, 0xed581514, 0x149e7c0d, 0x1b2f0024, + 0xc54500b1, 0x820a2007, 0x100a230c, 0x9082593e, 0x230bb550, 0x000c09b2, 0xb2214a82, 0x8206840e, 0x05fe54a7, 0x01353522, 0x5108ab82, 0x33110133, + 0x03060611, 0x0e384707, 0xfd7c3e24, 0x02f3f3f5, 0xb801f20c, 0xc6114bfe, 0x0339b20c, 0x04e5fc1a, 0x03e4fc8d, 0xb232fb1c, 0xffff00c2, 0x09024700, + 0xcd025402, 0x11000602, 0x02000000, 0x0000f7ff, 0xb005f004, 0x1d000f00, 0x10b28500, 0xc64b1f1e, 0x06b02105, 0x20067942, 0x20948205, 0x0fdb5805, + 0x5603b221, 0x032d05d4, 0x03cfb22f, 0x3fb25d01, 0xb2710103, 0x2004836f, 0x2004831f, 0x2513839f, 0x7201030f, 0x624702b1, 0xd011210a, 0xcd49d883, + 0x6705200b, 0xb0280cf2, 0x1db01003, 0x333130d0, 0x3305117f, 0x15120432, 0x04021415, 0x11231323, 0x35363233, 0x23263435, 0x2e080982, 0x01bbbbb2, + 0x2b01c1ae, 0xcffea5a4, 0xa3e53fc5, 0xc4ced5cb, 0x8c02e5b1, 0xac7a02aa, 0x49ccc4fe, 0xaac6fecf, 0x3efe8c02, 0xed46f0fd, 0x4052fefa, 0x0135e2e1, + 0x0000d4ff, 0x00061604, 0x76001800, 0x1a190cb2, 0x00391211, 0xb1d918b0, 0x152f2529, 0x0fb25d01, 0x18220483, 0x3b82150f, 0xd918b020, 0x0f2010ac, + 0x04201583, 0x210ca645, 0xd91800b0, 0x23260cac, 0x20333611, 0xd5791113, 0x43112008, 0x2b080543, 0xe7710233, 0x5a01b677, 0x5e61f305, 0xc3f34892, + 0x04e7f3c3, 0x8afdfec7, 0x3dfd75fe, 0x5d70ba02, 0x04fbfc82, 0x8f8faac7, 0x2d000100, 0xb026c382, 0x0f00b005, 0xe15d4e00, 0x0bc4540e, 0x0a0fb223, + 0x208c8302, 0x4fda180f, 0x04b0280c, 0x100fb0d0, 0x18d006b0, 0x180e9355, 0x080e6341, 0x15213530, 0x03331121, 0xd3fbcfb9, 0x043efed3, 0xcf3afe83, + 0xeefc1203, 0x01aa1203, 0xfecccc28, 0xff0100d8, 0x02ecffe8, 0x00410585, 0xb275001c, 0x8d571d00, 0x247f8305, 0xb11b2f1b, 0x3477181b, 0x3e10280c, + 0x101bb059, 0x82d001b0, 0x7f501805, 0x8304200c, 0x17b02511, 0x2f17b0d0, 0x22052758, 0x181017b0, 0x240bfb73, 0xb0d008b0, 0x0d4b4111, 0xb0101b2f, + 0x1cb0d01c, 0x0131302f, 0x23153311, 0x19038215, 0x200b390a, 0x05c47523, 0x01114208, 0xd8bfbfad, 0x2a3f31d8, 0xfe4d532b, 0xb2d2d2e8, 0xfe4105b2, + 0xaaa5b4f9, 0x373ef3fe, 0x0117bc0a, 0xaa160135, 0x0701b4a5, 0x00ffff00, 0x05000012, 0x02360742, 0x00250026, 0x00070100, 0x01230144, 0x07d55336, + 0x21082b6a, 0x3d5fdc0c, 0x222d8f05, 0x89c20175, 0x0802442d, 0x2d8c0d20, 0x5b883720, 0xc3009e22, 0x0f205b92, 0x2c202d8c, 0xa52c2d88, 0x3701c500, + 0xb0000900, 0x16b02f04, 0x0220238c, 0x6a222388, 0x5182ee00, 0x09421620, 0x26ad8805, 0x1bb0dc12, 0x883130d0, 0x889420dd, 0x01a3262f, 0x006a0158, + 0x2353840c, 0x15b0dc10, 0xb120258b, 0x00272585, 0x01270207, 0x821c015e, 0xfe66263d, 0x05eb043c, 0x2a1782c4, 0x00000027, 0x01790007, 0x82fbffc9, + 0x00942617, 0x074c0400, 0x2017823d, 0x05334129, 0x01e80023, 0x0733413d, 0x1b2f0624, 0xbf1806b1, 0x2d8f0b6f, 0x87017522, 0x0e202d92, 0x2d85e186, + 0x5b883e20, 0x88009e22, 0x10202d92, 0x09202d8c, 0x6a222d88, 0x2d82b300, 0x88060f41, 0xdc132389, 0xe9841cb0, 0x82c8ff21, 0x84a020af, 0x852d20b9, + 0x97ff21b9, 0x02205d89, 0x0220b982, 0x0520b983, 0xa3245d86, 0x7d020000, 0x75222d8a, 0x2d893500, 0x2008276b, 0x212d8506, 0x2d82cbff, 0x83077a21, + 0x225b85b9, 0x9237ff9e, 0x8608205b, 0x82bf202d, 0x0785212d, 0x2d85b983, 0x62ff6a22, 0x8988b989, 0xb0dc0b23, 0x27b98414, 0x00009400, 0x2c071705, + 0x3220e982, 0xa522b984, 0x1d42ee00, 0x2f052305, 0x538515b0, 0xff660027, 0x071e05ec, 0x20238236, 0x22238433, 0x423a0144, 0x0c20096f, 0x0c20dd82, + 0x2020dd83, 0x75222d96, 0x2d89d901, 0x125f0d20, 0x8c212007, 0x8837202d, 0x009e225b, 0x205b92da, 0x832d8c23, 0x228985ad, 0x82dc00a5, 0x421320ad, + 0x5b8805a7, 0x2d8c2220, 0x5b880220, 0x05016a22, 0x8809d542, 0xdc2623b7, 0x0b412fb0, 0xff7d2405, 0x84bd04ec, 0x863920e7, 0x891120e7, 0x08c9628b, + 0x5d861220, 0x75222d8f, 0x2d82b001, 0x8b820920, 0x13b02f22, 0xdd83238c, 0x9e225185, 0x5192b100, 0x85076741, 0x85af8351, 0x826a202d, 0x003621dd, + 0x88067542, 0xdc18237f, 0xaf8521b0, 0x00000724, 0xaf84d604, 0xaf843d20, 0x87017522, 0x01295d89, 0x01b11b2f, 0xb0593e20, 0x2a8b860b, 0x03ecff5a, + 0x020006fb, 0x84450026, 0x0044242d, 0x430000ad, 0x1720075d, 0x17212d82, 0x202d821c, 0x222d962b, 0x824c0175, 0x23dd822d, 0x2cb02f17, 0x0120238c, + 0x06235186, 0x914d9e00, 0x8b2e204f, 0xf605212b, 0xa5222b88, 0x7b90014f, 0x2b8c2d20, 0x2b88cc20, 0x00786a22, 0x88070541, 0xdc3123a7, 0x05413ab0, + 0x20d78505, 0x24d7885e, 0x00e200a3, 0x232f9034, 0x37b0dc2f, 0x7c202f8b, 0x00312f85, 0x00270207, 0xffe7ffe8, 0xfe4f00ff, 0x04f5033c, 0x2017824e, + 0x26e98247, 0x01790007, 0x82fbff3d, 0xff532617, 0x060b04ec, 0x20178200, 0x06374149, 0x3741a120, 0x08045109, 0xbb861f20, 0x75222d8f, 0x37414001, + 0x2f082205, 0x072143b0, 0x01202385, 0x06235186, 0x41419e00, 0x4f880837, 0x8407c342, 0xcc05212b, 0x6a212b88, 0x080b416c, 0x25232b88, 0x842eb0dc, + 0xb4ff21db, 0x8c22a182, 0x2d82f905, 0x09828d20, 0x44000624, 0x6541f983, 0x18022007, 0x4407bb80, 0x8f240785, 0x69020000, 0x75212b8a, 0x502b8821, + 0x834408f6, 0x82b72007, 0x0566222b, 0x255786fa, 0xff9e0007, 0x2d88ff23, 0x83445988, 0x82ab2007, 0x0571222d, 0x222d88c5, 0x824eff6a, 0x06c7422d, + 0x83442d88, 0x00792609, 0x05f80300, 0x202f82f6, 0x2ab58452, 0x000155a5, 0x03b00009, 0x411cb02f, 0x4f260655, 0x3d04ecff, 0x21820006, 0x83415320, + 0x41b62006, 0xb2550983, 0x222d9708, 0x82550175, 0x05f1462d, 0x518c1d20, 0x51860120, 0x9e000623, 0x08834156, 0xd3414f88, 0x847d8407, 0x237d839f, + 0x58a50006, 0x04239f84, 0x8b26b02f, 0xcc05214d, 0x6a229f88, 0x71828100, 0x320b3f47, 0xb0593e1c, 0x2bb0dc22, 0xff3130d0, 0xff7700ff, 0x84f703ec, + 0x865920cf, 0x89af20cf, 0x087556cf, 0x8f076944, 0x0175222d, 0x20cf854e, 0x09694406, 0xcf832385, 0xcf825183, 0xcf884f20, 0x67444f88, 0x842b8407, + 0x212b85ad, 0x53427a6a, 0x442b8808, 0x0c240965, 0xd6034bfe, 0x5d20ab84, 0x7522ab84, 0x7d851601, 0xb02f0122, 0x2384a187, 0x23835184, 0x6a000623, + 0x18518842, 0x2308d07d, 0x20b0dc17, 0x210a1748, 0x3d48e406, 0x00702408, 0x493a01be, 0x5a26181b, 0xfb03ecff, 0x0d44ae05, 0x48702308, 0x87440004, + 0x482a2005, 0x1c200cbd, 0xa1224f88, 0x0f49f600, 0x07094812, 0xe6204f85, 0x22082f44, 0x458000a1, 0x2d201207, 0x00335b83, 0xfe120002, 0x05420552, + 0x001600b0, 0xb2760019, 0x561b1a19, 0x42180699, 0x1620078b, 0x0beda318, 0x59181420, 0x52720b41, 0x820c200c, 0x120c2319, 0x9a18593e, 0x012b0c19, + 0xd011b010, 0xb22f11b0, 0x70161417, 0xb12005aa, 0x0a005018, 0x1619b223, 0x38158214, 0x01013130, 0x15060623, 0x37323314, 0x22230617, 0x37343526, + 0x21032103, 0x08048201, 0x021b0335, 0x4a573e27, 0x152e2c47, 0x745f5c49, 0xccfd7395, 0x02f9fe76, 0xa6016226, 0xfab005d3, 0x315e3850, 0x2c8e1744, + 0x628d5b6e, 0xadfe4901, 0x6ffcb005, 0x82005c02, 0xfe5a30d5, 0x04fb0352, 0x002d004e, 0xb2aa0038, 0x843a3917, 0xb010227e, 0x06754e2f, 0x24086645, + 0xb0584500, 0x20bb8229, 0x0f625729, 0x1983b020, 0x19821e20, 0x3e101e2d, 0xd000b059, 0xb22f00b0, 0x82041702, 0x0bb22147, 0xb0240684, 0x17b02f0b, + 0x0c348418, 0x0b12b223, 0x301f820f, 0x120c0940, 0x122c121c, 0x5d04123c, 0xb11029b0, 0x0a325d24, 0xb1100423, 0x0956532e, 0x100bb024, 0x0e8932b1, + 0x25313024, 0x01412726, 0x33242205, 0x050a5433, 0x24073c65, 0x17141117, 0x0e264115, 0x36320331, 0x22233537, 0x16141506, 0x0d0bff02, 0x19a3a874, + 0x20108c60, 0x093c412a, 0x7f48763e, 0x88878320, 0x4519075d, 0xad89ba79, 0x655447b9, 0x9b594053, 0xfeadbf58, 0x11579218, 0x33084a41, 0x4608018c, + 0x565ecc3b, 0xffff5346, 0xecff6600, 0x4b07eb04, 0x2c05c94a, 0x75000701, 0x4b01c001, 0xb0000900, 0x09ed450c, 0xecff4f26, 0x0006f503, 0x84055746, + 0x00292923, 0x00090000, 0xb02f0fb0, 0x85076144, 0x884c2047, 0x009e2247, 0x204782c1, 0x05d74813, 0x85106149, 0x86012051, 0x00062351, 0xeb432a9e, + 0x086d4308, 0x2920598d, 0xa2245988, 0x5401a701, 0x88076b43, 0x0ac74459, 0x05f50323, 0x22ab88de, 0x821001a2, 0x888786a9, 0x4925205b, 0xfd82095f, + 0x9f22b589, 0xfd88d800, 0x8f07bf46, 0x419f21ab, 0x014afb87, 0x00942607, 0x07d20400, 0x2a73823e, 0x01000028, 0x009f0007, 0x823d0167, 0x01b02475, + 0x451ab02f, 0x0527095f, 0x0002065b, 0x83480026, 0xba012d23, 0xfc040104, 0xb0000600, 0x31302f1e, 0x2107394c, 0xaf4beb06, 0x00702408, 0x4c410183, + 0x53471839, 0x47ae2005, 0x70220853, 0x6f83043c, 0xb02f0823, 0x0cff4b1e, 0x4f882320, 0xbb00a122, 0x4b09734b, 0x614d08ff, 0x204f8507, 0x214f88e6, + 0xcf4774a1, 0x22ed8b11, 0x881b074c, 0x01a22459, 0x9046016e, 0x481420a9, 0x05210b4d, 0x087b48de, 0x2701a222, 0x47098f41, 0x262008ff, 0x002f2d83, + 0xfe940001, 0x054c0452, 0x001b00b0, 0x7511b284, 0xa3440adb, 0x2f0f240c, 0x430fb11b, 0xbd4414cd, 0x1ab22107, 0x20058e44, 0x8b8d181a, 0x14b0230c, + 0xf256b110, 0x03b0240a, 0x180fb0d0, 0x200d729c, 0x0e9d6416, 0x11210123, 0x0f934321, 0x13833720, 0x03260382, 0x02aafde7, 0x7e436fbb, 0xfd872d09, + 0xfdb10393, 0x0256024c, 0xca40fe8a, 0x08086d43, 0x055f8623, 0x6efeccb0, 0x00020000, 0x046dfe53, 0x004e040b, 0x002b0023, 0x2c11b2a9, 0x3912112d, + 0xb01011b0, 0x06b34424, 0xd8821920, 0xac5d1920, 0x82112014, 0x10112719, 0x02b2593e, 0xac5d1911, 0xa09f1806, 0x28b2230a, 0x15831119, 0xb42f2838, + 0x282f281f, 0xbfb47102, 0x0228cf28, 0x288fb25d, 0x5fb45d01, 0x12836f28, 0xff28ef22, 0xb1210682, 0x0b4f531d, 0x0cb0fe18, 0x8523b221, 0x5d192045, + 0x25220edc, 0xbc450706, 0x0026220e, 0x058b5f27, 0xbc181220, 0x012b079d, 0x21070622, 0x03262635, 0x417149fa, 0x50240911, 0x06fbfecf, 0x3105d45a, + 0x779d0b3d, 0xc5fe69a7, 0x01117b64, 0xb87208cf, 0x2041336a, 0x52663808, 0xd713010d, 0x8effa23a, 0xfefee6fe, 0x879c8662, 0x7d8c5602, 0x4f7d7a12, + 0xf34e084f, 0x009f2209, 0x12c5429f, 0xb94a1120, 0x09954a0c, 0x00589f22, 0x43061543, 0x6a3207cb, 0xf004ecff, 0x26024c07, 0x00002b00, 0x9e000701, + 0xa544be00, 0x180b2009, 0x4207789b, 0x522507e9, 0x0c0456fe, 0x204f8306, 0x232d824b, 0x409e0006, 0x4a081543, 0x2720085f, 0x59857b86, 0x59883120, + 0xf100a122, 0x87875992, 0x05215984, 0x852d82e6, 0x73a12159, 0x28205991, 0x2920598c, 0xa2225988, 0xff44a401, 0x87b38809, 0x20598587, 0x245986de, + 0x01a20007, 0x096f4326, 0x2d20b588, 0xfd255b87, 0x05f004f3, 0x2a5b85c4, 0xba010700, 0x8cfee301, 0x8400ffff, 0xa9062145, 0x02254587, 0x00270134, + 0x06d14a7e, 0x61442920, 0x18052309, 0x23823e07, 0x41002c21, 0xe220054b, 0x28099b41, 0xb11b2f07, 0x593e2007, 0x078f50b0, 0x00007926, 0x5e07f803, + 0x4c202d82, 0x17222d86, 0x51835d01, 0x014a1020, 0xb3ff2708, 0x90020000, 0x23823307, 0x2405f94f, 0x0139ffa5, 0x0759443e, 0x20085550, 0x217f8507, + 0x2d829fff, 0xef057c22, 0x2408a34b, 0xff25ffa5, 0x225183fa, 0x44b02f02, 0xff2106d7, 0x212383cd, 0x5188eb06, 0x32ff7022, 0x50095545, 0xff210fd5, + 0x222d82b9, 0x88a70568, 0xff702451, 0x4cfdff1e, 0xff21177d, 0x222d82df, 0x88230765, 0xffa1225b, 0x88ff896a, 0x20ad875b, 0x222d82cb, 0x88df0551, + 0xffa1225b, 0x127f4c56, 0x00272d86, 0x0158fe17, 0x85b0059f, 0x06002f5b, 0x06eea400, 0x0000ffff, 0x900152fe, 0x1582d505, 0x00004d28, 0xa4000600, + 0x158200d7, 0x00009d26, 0x1b07a301, 0xa2228788, 0x8f451c00, 0x53878809, 0xa32a07a7, 0x2606ecff, 0x2600b005, 0x43822d00, 0x2e000725, 0x83004202, + 0xfe7d2345, 0x5b82034b, 0x5b831782, 0x4e000724, 0x17840b02, 0xecff2d2a, 0x3707ab04, 0x2e002602, 0x2105b741, 0x994a6801, 0x084b6709, 0x2506ed45, + 0x4bfeb5ff, 0xe5846b02, 0x2d859c20, 0xff28ff23, 0x0cab47de, 0x593e1c23, 0x07af43b0, 0x44fe9424, 0xe5841805, 0x8b832f20, 0x01ba012f, 0xffddfe9d, + 0xfe7d00ff, 0x0636042f, 0x20738200, 0x2217864f, 0x44c8fe2d, 0x2622060d, 0x17823607, 0x5d843020, 0x29007522, 0x63548b89, 0x06c34d08, 0x008a0027, + 0x07620200, 0x202d8291, 0x222d8650, 0x4291011a, 0x22200c4d, 0x1f4e8b82, 0x94002506, 0x260403fe, 0x5b828b84, 0x82070021, 0xfe6d228b, 0x2473829c, + 0x0103fe55, 0x828b847f, 0x21178345, 0x17841000, 0x00009426, 0xb1052604, 0x01258b87, 0x040a02ba, 0x073769ab, 0x5b740a20, 0x31302106, 0x8c204182, + 0xe7258782, 0x26000206, 0x82878400, 0x048d2259, 0x202987fc, 0x20298208, 0x48878208, 0x838a0803, 0x01a20025, 0x86d4fdca, 0x06eb2241, 0x21418500, + 0x17820700, 0xaffd6422, 0x23050f41, 0x36071705, 0x2208f952, 0x41eb0175, 0xf173090f, 0x07f94108, 0x00007926, 0x0006f803, 0x2406a34e, 0x01750007, + 0x05054d52, 0x81430320, 0x94002708, 0x1705fffd, 0x5185b005, 0x0123ed83, 0x8298fedc, 0xfe792669, 0x04f80303, 0x843b854e, 0x41412017, 0x81820705, + 0x81883720, 0x03019f22, 0x65488189, 0x20818510, 0x08254f01, 0x006a9f22, 0x4d065344, 0xff2206d7, 0xa38300a5, 0x21860320, 0xba010726, 0xfd0460ff, + 0x24072b41, 0xb11b2f15, 0x072b4115, 0xecff6626, 0xe4061e05, 0x22081953, 0x4dd50070, 0x6f4a0981, 0x3d042313, 0x2b4fae05, 0x51702208, 0x063f5604, + 0x69531b20, 0x881c200c, 0x01a1224f, 0x88c9890d, 0x0a134a4f, 0xe6204f82, 0x22082d4f, 0x4f8900a1, 0x8b4912cd, 0x21ab8407, 0x5b883507, 0x6301a622, + 0x5309c553, 0x212308f3, 0x4e25b0dc, 0xad4f055d, 0x88ff2005, 0x00a6225d, 0x128b4fdf, 0x45531d20, 0x00942608, 0x07de0400, 0x202f8236, 0x05e94236, + 0x82710121, 0x052d505f, 0x23077f4a, 0x0200007c, 0x2005c34b, 0x21238556, 0x5382ad00, 0x0b212382, 0x08a3452f, 0x03fe9426, 0xb005de04, 0x00314785, + 0x01ba0107, 0xff9cfe6e, 0xfe4f00ff, 0x04b40203, 0x8217824e, 0x2117833b, 0x03430a00, 0x07de2208, 0x22778837, 0x8889009f, 0x411c2077, 0x38200657, + 0xfa227782, 0x3b850106, 0x00060126, 0x0000c69f, 0x12207585, 0x4a242186, 0x8a04ecff, 0x3720bd84, 0x01219985, 0x2345858e, 0x2ab02f09, 0x4b262386, + 0xca03ecff, 0x45820006, 0x23865720, 0xbd853a20, 0x8f462382, 0x83478507, 0x2247858d, 0x548f009e, 0x518d12a9, 0x51839783, 0x9e000623, 0x0db16c3b, + 0x593e1c23, 0x255988b0, 0x8a0441fe, 0x7d82c405, 0x00315982, 0x01790007, 0xff00009d, 0xfe4b00ff, 0x04ca0338, 0x8495854e, 0xff442217, 0x221782f7, + 0x8bf9fd4a, 0xba01252f, 0x92fe8901, 0x4b221782, 0x2f8beffd, 0x30221782, 0x178288fe, 0x9f22b98f, 0x0141a600, 0x07a95408, 0x89050141, 0x529f26af, + 0x00090000, 0x54ff82b0, 0x2d2607ef, 0xb004fcfd, 0x8d82b005, 0x00003824, 0x5d820700, 0x95fe7722, 0x08265d82, 0x7202f9fd, 0x17824105, 0x17855820, + 0x84c80021, 0xfe2d228d, 0x822f8b44, 0x008b22d5, 0x232f8303, 0xa50241fe, 0x00232f89, 0x84dc0079, 0x002d26ed, 0x07b00400, 0x255f8537, 0x9f000701, + 0xeb439800, 0x410d2012, 0x082906b1, 0x2703ecff, 0x26008306, 0x39758600, 0x7d05cd01, 0x7d00ffff, 0xbd04ecff, 0x26022c07, 0x00003900, 0xa5000701, + 0xff56b300, 0x75102009, 0x4f4607b4, 0x05655206, 0x82f60521, 0x05e7512d, 0x5551a521, 0x0d200873, 0x0d242b82, 0xb0593e1c, 0x59842b87, 0x88e40621, + 0x00702559, 0x003a01ac, 0x4605cd56, 0x37520771, 0x88ae2005, 0x4a70224f, 0x0cb94c04, 0x1d574f83, 0x881c200d, 0x00a1224f, 0x124f42e4, 0xe620a98d, + 0x07245986, 0x8200a100, 0x8c120f53, 0x940721ab, 0xa3225b88, 0x7d5a4601, 0x2f002305, 0xa35a16b0, 0x21ad8408, 0x53885e06, 0xe400a329, 0x0c003400, + 0x8b06b000, 0x21f78425, 0x4b883507, 0x3a01a622, 0x41095d44, 0x13230851, 0x5317b0dc, 0x042308b9, 0x88ff052e, 0x00a62255, 0x85a982d8, 0x20258255, + 0x30258215, 0x7d000100, 0xbd0489fe, 0x1f00b005, 0x1cb25900, 0xa3761820, 0x2f182409, 0x5f18b11b, 0xd01807cd, 0x0e200cea, 0x0e2c1982, 0xb2593e18, + 0x11181304, 0x09b13912, 0x200a1551, 0x0c596213, 0x7a18b021, 0x012205af, 0x5b4c1411, 0x00203110, 0x11331135, 0x20331614, 0xbd041111, 0x4f3d7e85, + 0x33071b52, 0xfe00ff36, 0x9094fcdb, 0xb0052401, 0xe49832fc, 0x3759293d, 0x27051b52, 0x0c014555, 0xfccd03eb, 0x076e7619, 0x77000128, 0xf70352fe, + 0xbd823a04, 0x1ab26822, 0x1552bd8a, 0x8212200c, 0x101221b0, 0x6f060e6b, 0x37190c28, 0xb02b13de, 0x0fb0101f, 0x2f0fb0d0, 0x181012b0, 0x210b5977, + 0x746017b0, 0x4d212005, 0x27240e24, 0x26222306, 0x3322cb84, 0xd2823732, 0x4de20321, 0x922a0918, 0xb0c56b05, 0xb1abf3b5, 0x064df33e, 0x8c250808, + 0xce7e6261, 0xfdbd02c3, 0x037fce46, 0xffc6fb09, 0x003000ff, 0x07e50600, 0x00260237, 0x0100003b, 0x019e0007, 0x129346a8, 0x2706eb4a, 0x00002100, + 0x0106cc05, 0x5b202d82, 0x0a202d86, 0x18098142, 0x43080cd0, 0x79590709, 0x595b8305, 0x9e220579, 0x79598800, 0xfe0c241a, 0x84d6034b, 0x051d555b, + 0x51179e21, 0xdb4211af, 0x20598507, 0x85878202, 0x006a2259, 0x098f42b3, 0x23089548, 0x19b0dc10, 0x26058f42, 0x04000050, 0x8236078c, 0x843e202f, + 0x017522b7, 0x4c898983, 0xc5480847, 0x00522607, 0x06c00300, 0x202d8200, 0x202d865e, 0x1267431b, 0x5b852d87, 0x5b881420, 0x6a01a224, 0xf1433f01, + 0x435b8807, 0x5b8407f1, 0x88de0521, 0x01a2225b, 0x093b4d02, 0x8510d356, 0x8837205b, 0x009f225b, 0x05b5459b, 0xb02f0723, 0x0605450e, 0x06215184, + 0x24518601, 0x339f0006, 0x20518200, 0x272189b0, 0x0000f6ff, 0x42075707, 0x81202182, 0x0223cf85, 0x444201bb, 0x20220c93, 0xc75c593e, 0xff482408, + 0x848406ec, 0x8686204f, 0x0071222d, 0x064b5601, 0x73863f20, 0xa1ff692a, 0x80072205, 0x83002602, 0x01232385, 0x878001e0, 0x080f4451, 0x26075746, + 0x0477ff4f, 0x82fe053d, 0x8689202d, 0xff30222d, 0x0cc956fe, 0x7f821c20, 0x2b068b4e, 0x0000a6ff, 0x8d042a04, 0x30022602, 0x022f2d83, 0xff16ff26, + 0x0046006e, 0x01171fb2, 0x836fb271, 0x9c461804, 0xafb62908, 0xcf17bf17, 0xb2720317, 0x72261282, 0x01175fb2, 0x1083b672, 0x0317df25, 0x823fb271, + 0xdfb42a2a, 0x0217ef17, 0x171fb45d, 0x2306822f, 0xffff3130, 0x00215fdf, 0x20bf8224, 0x21bf8316, 0xbf82d801, 0x2602062c, 0x0800be32, 0x0b00b200, + 0x7f835d01, 0x82090021, 0x0694221f, 0x20df821e, 0x261f8233, 0x00440007, 0x411e00c7, 0x1e230c0d, 0x42b0593e, 0x2d8f075d, 0x66017522, 0x05242d89, + 0x05b11b2f, 0x11472d83, 0x202d8507, 0x235b861f, 0x679e0006, 0xcb435991, 0x202b8507, 0x222b8814, 0x601f69a5, 0x21840eef, 0x88ea0521, 0x006a22a9, + 0x597b8292, 0x7b830baf, 0x8409ef60, 0x7c06212f, 0xa3252f88, 0x5200fc00, 0x232f8f00, 0x18b0dc10, 0x85059543, 0x8599202f, 0x0700312f, 0x02012702, + 0xffff0400, 0x41fe4f00, 0x9d044304, 0x31341782, 0x07000000, 0x6b017900, 0xffff0000, 0x00007600, 0x1e06b503, 0x03551782, 0x00442205, 0x090b4196, + 0x08876218, 0x8f070b41, 0x0175222d, 0x242d8935, 0xb11b2f07, 0x43bd8307, 0x2d850745, 0x5b861f20, 0x9e000623, 0x08394136, 0x67505988, 0x212b8407, + 0x2b88ea05, 0x1e616a22, 0x2b88e587, 0x2409f560, 0x010000a6, 0x21b5837e, 0xef41e301, 0x75ff2105, 0x6c188789, 0x0520081b, 0x24065943, 0x02000083, + 0x232d885b, 0x13750006, 0x03208788, 0x0320b382, 0x4f4eb383, 0xa9ff2106, 0x58212b82, 0x86b38206, 0xff9e2259, 0x4e599215, 0xff2106ab, 0x212d829d, + 0xb5820563, 0x6a222d86, 0xcd4140ff, 0x5c878809, 0x762a096f, 0x67040000, 0x26021406, 0xb784de01, 0x8800a528, 0x09001f00, 0xf360b000, 0xff4f240a, + 0x846f04f0, 0x84dd20ad, 0x00442223, 0x208189d5, 0x20af820b, 0x4caf830b, 0x2d8f07a3, 0x74017522, 0xa94b2d82, 0x09455c05, 0xd3835183, 0x06235183, + 0x88759e00, 0x204f88ff, 0x08ef5621, 0xa1832b83, 0xa5212b85, 0x229f8477, 0x44b02f0b, 0x0020064b, 0xf3847184, 0x6a229f85, 0xf389a000, 0x24234f88, + 0x422db0dc, 0x67200591, 0x1e20cf82, 0xd720cf84, 0xb520cf86, 0x0820cf89, 0x07b08918, 0x8f07df46, 0x0175222d, 0x182d8954, 0x45084862, 0x2d8507f9, + 0x5b83d983, 0x5520d982, 0x5988d988, 0x8407df46, 0x85b7842b, 0x006a2287, 0x88b78980, 0x092b5c2d, 0x00000524, 0xb7843604, 0x794dd320, 0x2d012105, + 0x01208989, 0x60063f79, 0x092008e3, 0x94222d82, 0xf943cc05, 0x62702208, 0x1e7f4422, 0xd3430420, 0x00a12208, 0x1859899a, 0x34083584, 0x3130dc0e, + 0x00020000, 0x0452fe09, 0x008d0494, 0x00190016, 0x12075c73, 0x5c0cc96c, 0xb2233307, 0x5c001417, 0x00201304, 0x2c17045c, 0x23072127, 0x03210301, + 0xd501bf02, 0x091d4936, 0xfe599d2f, 0x01f55f1e, 0x54013cd7, 0xfb8d04aa, 0x08224973, 0xeb619234, 0xfd8d04f9, 0x00ba0125, 0x4f00ffff, 0x4304f0ff, + 0x89441e06, 0x07012505, 0x63017500, 0x4208b142, 0x43220bd5, 0x23861f06, 0x9e000623, 0x11b14264, 0xb1422020, 0x0543220a, 0x244f88fc, 0x004a01a2, + 0x077b4127, 0x210a8f42, 0x7d893130, 0x9f225989, 0xd74e1e7b, 0x244f8706, 0x0400006a, 0x277b842a, 0x01000030, 0xf89f0006, 0x01232184, 0x8618b02f, + 0x05ab4471, 0xab44cc20, 0x31702108, 0x4508eb41, 0x04201631, 0xa1212b88, 0x88c98869, 0x073d462b, 0xc9835785, 0x22058b45, 0x891c01a2, 0x202d88c9, + 0x29858314, 0x76000100, 0xb50352fe, 0x73598d04, 0x4b1e2015, 0x7359061e, 0x161b2222, 0x05377304, 0x590cc06f, 0x5f254d73, 0x4c020afe, 0x092a425e, + 0xfbfd8722, 0x0ad85518, 0x26082842, 0x8d045f86, 0x46f2fec4, 0x3b460997, 0x4d9f2109, 0x44113741, 0x54250733, 0x4804f0ff, 0x282b8206, 0x0000e501, + 0x9e000601, 0x702b8868, 0xdf4408c2, 0x222b8507, 0x84260204, 0x0007242b, 0x439b00a1, 0x2d88097b, 0x84070b42, 0xfc05212d, 0xa2222d88, 0x91414e01, + 0x5c2d8809, 0x54260795, 0x4804f9fd, 0x2d859d04, 0x01070027, 0xfe6a01ba, 0x05634792, 0x84680421, 0x85e4209f, 0x887b209f, 0x0833479f, 0x5b421020, + 0x91ff2705, 0x6e020000, 0x43821406, 0x2205d946, 0x4617ffa5, 0x1d570521, 0x82ab200a, 0x055a2223, 0x232388cc, 0x0010ff70, 0x46088142, 0xff210ffd, + 0x212d82bd, 0xf1830643, 0xa1225185, 0xf18948ff, 0xc1562d88, 0xfe152607, 0x048d0152, 0x295b858d, 0xa4000600, 0xffff00ec, 0xb7827c00, 0xfc058222, + 0x01241585, 0xfba20006, 0x88086143, 0x075d4941, 0xf0ff2424, 0xed843704, 0x3582e220, 0x9e000724, 0x6f89f400, 0x2008ac44, 0x25ef8513, 0x00fe7600, + 0x6f846804, 0x0000e12a, 0xba010700, 0x99fe1201, 0x23053341, 0x1e069403, 0xe0207182, 0x06234582, 0x410a7500, 0xa1490833, 0x06854708, 0x01224382, + 0x43849403, 0x43842b82, 0x9afe1022, 0x04214387, 0x83438690, 0x0395225b, 0x0ceb558a, 0x593e1e24, 0x29883130, 0x4184f583, 0x01a20025, 0x8546fd72, + 0x67042117, 0xaf478584, 0x01752205, 0x12bb4685, 0x7624f987, 0x6704f9fd, 0x2d828784, 0x78208784, 0x2208ff41, 0x471f0667, 0x9f2208f5, 0x45899d00, + 0x47100544, 0xcc20055f, 0x81472d82, 0x70702205, 0x06a14422, 0xa3471d20, 0x8604200c, 0x00072421, 0x48a800a1, 0x1f451221, 0x066f220b, 0x222d881d, + 0x82fe00a6, 0x000c262d, 0xb02f0bb0, 0x088b541f, 0x00007624, 0xe9843904, 0x0000da28, 0x75000701, 0x95451701, 0x2f042305, 0xab4119b0, 0x04012208, + 0x82df8439, 0x20df8423, 0x07674118, 0x1f203b82, 0x17826182, 0x00060125, 0x551e2f9f, 0x3e240ea5, 0xef03f0ff, 0xd9205d84, 0x41205d86, 0x09205d85, + 0x85095748, 0x83458323, 0x00062323, 0xf141429e, 0x8b401808, 0x07055408, 0x41fe3e26, 0x9d04ef03, 0x2b827182, 0x0007002a, 0x004f0179, 0x00ffff00, + 0x9f21438f, 0x54898459, 0x24230a91, 0x4c04fffd, 0xc3840849, 0x98fe2522, 0x24203982, 0x1621ff82, 0x207d8306, 0x82a182d8, 0x444720c3, 0x054b116f, + 0xfe242207, 0x82438b47, 0x0039227d, 0x26438206, 0x04f0ff67, 0x8214061e, 0x058d4895, 0x1f57a522, 0x48078746, 0xf74208b9, 0x212b8407, 0x2b88cc05, + 0x22507022, 0x4406f352, 0x00200609, 0x06212184, 0x24218604, 0x00a10007, 0x09e54188, 0x8c08af48, 0x7c06214f, 0xa32f2d88, 0x5200ea00, 0xb0000c00, + 0x15b02f00, 0x491ab0dc, 0x3422098b, 0x25881d06, 0xde00a622, 0x82050b42, 0x6b122025, 0x00290599, 0xfe670001, 0x041e0482, 0x2119828d, 0xb618b263, + 0x17240bbd, 0x17b11b2f, 0x870c8377, 0x820d200c, 0x180d2119, 0x51067346, 0xb229079f, 0x11001204, 0x0db03912, 0x9c401810, 0x7112200c, 0x30260cfb, + 0x06110131, 0x65640706, 0x2626220d, 0x054c5227, 0x11373228, 0x7d011e04, 0x4c527f77, 0xcd403107, 0x7ef102f2, 0x0404e56c, 0x81fcfc8d, 0x5a5632bd, + 0x37054a52, 0xd606495d, 0xfd0503bb, 0xd4687300, 0xffff0703, 0x00002800, 0x1f06e505, 0xd528e982, 0x07010000, 0x19019e00, 0x4712bd49, 0xeb490779, + 0x202d8305, 0x232d82d3, 0x2e9e0006, 0x4108fd41, 0xfd410869, 0x212b8407, 0x5982ea05, 0x6a212b85, 0x08a94c59, 0x25512b88, 0x00412609, 0x06f30300, + 0x202d821e, 0x245982d2, 0x01750007, 0x12c54130, 0x84074144, 0xfc05212d, 0xa2222d88, 0x6f461701, 0x082b4609, 0x8407fd4a, 0x83e3842d, 0x0006235b, + 0x5746489f, 0x26e18711, 0x05000012, 0x66410642, 0x002d05a9, 0xbfae0006, 0xfeffff00, 0x040000e7, 0x2915844c, 0x00000029, 0xfeae0007, 0x17830021, + 0x2d82f020, 0x17841820, 0x17862c20, 0x17842a20, 0xc382f320, 0x43069f22, 0x2d204582, 0x2d311786, 0xffff0200, 0xecffa7ff, 0x41063205, 0x33002600, + 0x20478514, 0x822f84e1, 0x3a052105, 0x3d211784, 0x20178564, 0x2117831b, 0x7782b2ff, 0x1784f120, 0x2f86ba20, 0x1784ec20, 0xf4ff872a, 0x9a06da02, + 0xc3002602, 0x07286982, 0x20ffaf00, 0x1c00ebff, 0x2b0a8d64, 0xb0593e1c, 0x10b0dc18, 0x1018b0d0, 0x84078d6c, 0xb00525db, 0x25000602, 0x00254583, + 0x04000094, 0x200f84a3, 0x200f8826, 0x820f844c, 0xffff23e5, 0x1f825000, 0x0f848c20, 0x1f873e20, 0x84180521, 0x23ed820f, 0xa300ffff, 0x9f207b82, + 0xe5820f84, 0x8506af5b, 0x872f201f, 0x6a06212f, 0x31201f84, 0x17203f88, 0x32200f84, 0x66260f84, 0x1e05ecff, 0x8f82c405, 0x7f883320, 0x1f84d420, + 0x0f843420, 0x7f822d20, 0x0f84b020, 0x0f843820, 0x0f820720, 0x0f84d620, 0x0f843d20, 0x0421a582, 0x200f84e9, 0x200f833c, 0x2f596fff, 0x2a2fc953, + 0x04ebff56, 0x02410679, 0x82bb0026, 0x00072ef9, 0x005001ae, 0x00090000, 0xb02f13b0, 0x06fb4524, 0xecff6024, 0x23840c04, 0x01208d82, 0x19202383, + 0x4508c959, 0x7e240795, 0x060461fe, 0xc1202384, 0x23204786, 0x03212385, 0x08ed572f, 0xf4ffa926, 0x2c066102, 0x2406e141, 0x0fae0006, 0x06f744eb, + 0x2007a942, 0x228d8280, 0x82a20608, 0x82cb2021, 0x00062445, 0x42f31daf, 0x00320701, 0x00b11b2f, 0xb0593e1c, 0x15b0dc1e, 0x101eb0d0, 0xd74427b0, + 0x008e2905, 0x046b0400, 0x0006023a, 0xff230982, 0x824f00ff, 0x043d22ad, 0x2a0f824e, 0xff000053, 0xfe9200ff, 0x841f0460, 0x8476201f, 0x0016240f, + 0x84da0300, 0x825a200f, 0x000128a1, 0x0449fe3e, 0x824a0465, 0xb26a2367, 0xfd731d13, 0xafbf1809, 0x8205200c, 0x6305207d, 0x584b07e6, 0x8214200c, + 0x12142c19, 0x04b2593e, 0x12110f00, 0x180fb039, 0x200d7478, 0x20158513, 0xd5501800, 0x3069080c, 0x16321331, 0x33131317, 0x17161301, 0x06073717, + 0x27272627, 0x01230303, 0x07232603, 0x66c13627, 0xe172328d, 0xc69ffef5, 0x28294c35, 0x9a362a28, 0xf87e1b5b, 0xa67c01f8, 0x02437042, 0x684a0442, + 0x01fefe74, 0xfe28fdce, 0x01087b3e, 0x0510c603, 0x0138b407, 0x0300fe1f, 0x987e010c, 0xff13ba05, 0xffccffff, 0x059202f4, 0x084d43b7, 0x6fff6a24, + 0x5551ebff, 0xb55f1807, 0xdc142308, 0x45411db0, 0xff802605, 0x050804eb, 0x087941bf, 0xf36c6a22, 0x08412d87, 0xdc1a2308, 0xed5c23b0, 0x4106210a, + 0x2408ed5c, 0x002201ae, 0x06f74700, 0x8407a948, 0x34062151, 0x07265186, 0x0d01ae00, 0xef41f3ff, 0x0ae37106, 0x062d0623, 0x20238232, 0x053542ce, + 0xff2c0223, 0x202386f1, 0x0c156723, 0x27281573, 0x00009b00, 0x3d073704, 0xb1205382, 0x75225384, 0xe3618201, 0x08557409, 0x494d0820, 0xff4a2c06, + 0x058a04ec, 0x002700c4, 0x1811b266, 0x200a0f6d, 0x42541809, 0x45002407, 0x821db058, 0x101d2e0c, 0x02b2593e, 0x1211091d, 0x090eb239, 0x2106821d, + 0x707f09b0, 0x02b0210c, 0x0c3e4018, 0x8422b221, 0x1db0222b, 0x0e837b10, 0x2426342c, 0x34352627, 0x16323324, 0xa9181516, 0x26080dbb, 0x24222304, + 0x14333526, 0x36323316, 0xfe878d03, 0x01c768a0, 0xee98e51f, 0x858ffc88, 0x0194897c, 0xfe60ce54, 0x199eefe9, 0x44269590, 0x4d4411cd, 0xff2d3430, + 0x05e403ec, 0x000602b0, 0xff00002e, 0x009b00ff, 0x83300500, 0x4502200f, 0x9420052d, 0x18260f82, 0x26023607, 0x6b412f00, 0x586e2006, 0xdd610907, + 0x07dd4308, 0xebff3926, 0x2307dd04, 0x514b2d82, 0x00a12205, 0x099941d9, 0x1b2f0f28, 0x3e200fb1, 0xd548b059, 0x1fd94507, 0x04218b82, 0x209b8437, + 0x14e945b1, 0x0d209b83, 0xdc206d84, 0xa1229b84, 0x6d891d01, 0x4708d358, 0x2d8207d9, 0x4610d745, 0xd7450b17, 0x217d820f, 0x7d841405, 0xe745b620, + 0x272f8214, 0xc405eb04, 0x27000602, 0x4514f745, 0x00270ee7, 0x03ecff5a, 0x824e04fb, 0x8445202f, 0xff53242f, 0x840b04ec, 0x8449200f, 0x00862a0f, + 0x05120400, 0x002602d9, 0x23cd85f0, 0xf3ff9700, 0x6907614a, 0xcd870893, 0x240f0345, 0x0460fe7c, 0x214d8430, 0x3e820054, 0x1f820020, 0x04f50327, + 0x001c004e, 0x0cf1784d, 0x7f086c6b, 0x47180be8, 0x0f270ef9, 0xb2391211, 0x44080f13, 0x162006ec, 0x080c2a6d, 0x3736323d, 0x23020e33, 0x35110022, + 0x32330034, 0x26231716, 0x06222326, 0x16141507, 0x785b3902, 0x7604e504, 0xfee375ca, 0xe40801f6, 0xe506f3c1, 0x765c7704, 0xae7f0180, 0xaf654e6a, + 0x19260166, 0x370f218c, 0x0c00ffff, 0xd6034bfe, 0x06023a04, 0x00005d00, 0x1f00ffff, 0xe8030000, 0x5c200f84, 0x72092741, 0x002127a9, 0x2e3d8285, + 0x02f3054d, 0x00ec0026, 0x00070100, 0x41c20075, 0x04290945, 0x04b11b2f, 0xb0593e1c, 0x0bc16008, 0x824e0421, 0x8457207b, 0x827d206b, 0x05902233, + 0x200f82d5, 0x200f834d, 0x2e7172ff, 0xfeb5ff25, 0x8485014b, 0x844e203f, 0x008f264f, 0x05650400, 0x208d82f2, 0x825982f1, 0x4401238d, 0x3954f2ff, + 0x438d830c, 0x0c26073d, 0xd6034bfe, 0x2d82e605, 0x2105cf5b, 0xcf5b4aa1, 0x073b4311, 0x2005855c, 0x08855c36, 0x08024422, 0x68099743, 0x0e20087f, + 0x855ce786, 0x5c002005, 0x44220885, 0x9f5b6a01, 0x08855c09, 0x5b8f2d87, 0xa7027522, 0x75635b89, 0x0de15c08, 0x75225b89, 0x5b890902, 0x87088746, + 0x205b852d, 0x22b78802, 0x82d3016a, 0x06f1585b, 0xb546b788, 0x21b98409, 0xb988cc05, 0x35016a22, 0x88097563, 0x492f89b9, 0x3620051d, 0x2208e75c, + 0x89e80044, 0x081344bb, 0x17410a20, 0x0d837206, 0x44000623, 0x11714177, 0x2b861120, 0xfc03522a, 0x00060b01, 0x0b000603, 0x270ef763, 0xb0593e22, + 0x01b0d001, 0x2405336e, 0x02f40365, 0x20278440, 0x20278206, 0x8b54182c, 0x1827830a, 0x83080b4a, 0x1009270c, 0xb0d006b0, 0x3d8a2f06, 0xf2ff8f2a, + 0xb005c803, 0x05002600, 0x072e3d82, 0x25020500, 0xffff0000, 0x4bfeb1ff, 0xc3677302, 0xff9f240a, 0x61deff3f, 0x332a0e47, 0x65010004, 0x06020006, + 0xc94a8501, 0x36072509, 0x31002602, 0x21057d42, 0x0b419002, 0x08836809, 0x7c24df87, 0x79060000, 0x26223d82, 0x2d865100, 0xdf49a020, 0x076d5008, + 0x6dfe1226, 0xb0054205, 0x3006674c, 0x01a70007, 0xff03007a, 0xfe5a00ff, 0x04fb0371, 0x2017824e, 0x24b58445, 0x00ad00a7, 0x33797b07, 0x070d0523, + 0x4545823d, 0x442205cf, 0xcf454a01, 0x07777812, 0x210f1177, 0x3f770044, 0x055d451b, 0x5d45f320, 0x00442208, 0x125d45c4, 0x44245b87, 0x5c050000, + 0x0632e782, 0x0000b900, 0x4f00ffff, 0x7e0522fe, 0x06023a04, 0x0f84cd00, 0x00001034, 0xfc06f304, 0x19012602, 0x07010000, 0x4904ac00, 0x4d490e01, + 0x08e74607, 0xb17c1120, 0xf1ff2107, 0x18222f82, 0x2f82d005, 0x2f851a20, 0xffe50323, 0x282f87e2, 0xb11b2f11, 0x593e1c11, 0x090d62b0, 0x4bfe4f31, + 0x4e046408, 0x53002600, 0x07000000, 0x4a045d00, 0x662605f9, 0x5c094bfe, 0x1782c405, 0x17853320, 0xd7820520, 0x00ffff2d, 0x043afe49, 0x02c3057f, + 0x83db0026, 0x51022517, 0xa0ff9201, 0x4d261782, 0xc4033bfe, 0x17824d04, 0x1786ef20, 0xa1ff3922, 0x66231782, 0x7d043efe, 0x2f820a29, 0xa4ffd622, + 0x3e20e784, 0x820bab78, 0x844a2017, 0x0fc34c17, 0x5ffe2022, 0x3a262782, 0xbd000602, 0x85480000, 0x24d98211, 0x079b0700, 0x20778223, 0x21ef84da, + 0x994702a1, 0x2f0d250a, 0x200db11b, 0x7952ef82, 0x001e2607, 0x055c0600, 0x202d82d9, 0x212d85ee, 0x9b418701, 0x202d8409, 0x4d2d8a1c, 0x12250fbf, + 0x42050000, 0x52a57507, 0x7e088f7e, 0x5a2529bf, 0xfb03ecff, 0x26617a05, 0x00f6ff37, 0x05570700, 0x000602b0, 0xff000081, 0xff4800ff, 0x048406ec, + 0x410f8250, 0x942605d5, 0x4c040000, 0x2d722307, 0xff513452, 0x061e05eb, 0x012602db, 0x01000058, 0x006a0007, 0x4c0f01c2, 0x20230c0d, 0x7cb0593e, + 0x592009c1, 0xf822d782, 0x99824f04, 0x84056367, 0xcd05210f, 0x0f829982, 0x00060125, 0x8c01696a, 0x8c1c203d, 0x8216203d, 0x079b22e7, 0x080d4209, + 0x15026a22, 0x42093b7e, 0x1d23080d, 0x4c26b0dc, 0x0f42057b, 0x42bf2005, 0x6a23080f, 0x4cff7f01, 0x0f4208ab, 0x262f8908, 0x04edff49, 0x4217077f, + 0xcd8405fd, 0x4b01a322, 0x53468f87, 0x09d97b08, 0xcd824d20, 0xcc05c422, 0x83051543, 0x784e20bd, 0x25240855, 0x25b11b2f, 0x2f23bd83, 0x8538b0dc, + 0x0094268d, 0x060d0500, 0x089544eb, 0xe5007022, 0x4609ad6e, 0x39440851, 0x05674407, 0x2d82a120, 0x0000f028, 0x70000601, 0xd962f75f, 0x875b830c, + 0x2159842b, 0x59880907, 0x41016a21, 0x59880a17, 0xdf531120, 0x205b8508, 0x08c344bf, 0x8f006a22, 0x4a091741, 0x2f890821, 0xecff6625, 0x7e071e05, + 0x4f2429a7, 0x3d04ecff, 0x202a6d7a, 0x285f825f, 0x02c40517, 0x00170106, 0x0b974f00, 0x84180121, 0x231f840f, 0x26020607, 0x01271f83, 0x016a0007, + 0x4e3a0113, 0x65420ca1, 0x837f880d, 0x0601243f, 0x41736a00, 0xb9490897, 0x08937c08, 0x826b0021, 0x07f127ad, 0x00260218, 0xc34200e7, 0x01e32205, + 0x245d874c, 0xb11b2f13, 0x235d8313, 0x30b0dc27, 0x2405c741, 0x03ecff51, 0x20dd84e8, 0x822f82ff, 0x8859205d, 0x083b415d, 0xb0dc2823, 0x262d8531, + 0x04ebff39, 0x4ceb06dd, 0x702408c9, 0x4101a100, 0x55063d76, 0x0c2607c3, 0xd6034bfe, 0xaf49ae05, 0x12702208, 0x84218e04, 0x09072145, 0x6a224588, + 0xf942d100, 0x08274609, 0x7a09955e, 0x5d852def, 0x5d883c20, 0x2f01a622, 0x16235d92, 0x8512b0dc, 0x225d83d3, 0x86ff05f6, 0x000724af, 0x48a000a6, + 0x184c09c9, 0x242f8908, 0x0400008e, 0x20bd84ee, 0x056141e1, 0x890f0121, 0xa963185f, 0xdc192308, 0x5f8522b0, 0x00005f26, 0xbf05e003, 0xf9205f82, + 0x20056141, 0x08b54367, 0x1b2f0924, 0xc54509b1, 0x322d8705, 0x0600009b, 0x000a0758, 0x0be60026, 0x00270000, 0x82b9042d, 0x00072635, 0x01c2016a, + 0x10bd433e, 0xb0dc2023, 0x26658529, 0x0500008f, 0x82bf05c9, 0x82fe2037, 0x002724bd, 0x8647048d, 0x43742037, 0x194a090d, 0xdc1f2308, 0x378528b0, + 0xecff4f32, 0x00060304, 0x48000602, 0xffff0000, 0x97fe1200, 0x220ccb48, 0x480d05ad, 0x9b2006cb, 0x240ccb48, 0x004004ad, 0x080b4607, 0xfb48bb20, + 0x07012705, 0x0505ab00, 0x11513c01, 0x07d14306, 0xecff5a26, 0x8506fb03, 0x2408037c, 0x008f04ab, 0x06096606, 0x20074753, 0x22bf8212, 0x87b1074a, + 0x37022747, 0x2101bf00, 0x274a1700, 0x07514f05, 0x090eb125, 0x8214b0f4, 0x82a983b8, 0xd4042355, 0x55867c06, 0x37020624, 0x4018ec49, 0x2d231087, + 0x8533b0dc, 0x821020e7, 0x0742225f, 0x245f88ae, 0x01c40038, 0x275f872b, 0xb11b2f04, 0x593e2004, 0x13205f84, 0xff215f85, 0x20b5849a, 0x225f8879, + 0x93f64e38, 0x7d32205f, 0x07210a65, 0x245f88de, 0x01c30039, 0x0cb36413, 0xb0215f82, 0x0875420e, 0x5722bd83, 0x5d88a906, 0xde4d3922, 0x2b205d90, + 0x47087743, 0xd62005cd, 0x3a205d88, 0x0520bd82, 0x6f502f87, 0x490c2008, 0x554f0759, 0xa1062105, 0x3a225d88, 0x5d93d04e, 0xbb863420, 0x0597fe25, + 0x85370742, 0x2700235d, 0xbb829e00, 0x07013628, 0x0d05ad00, 0xa7450300, 0x4f658807, 0x5a26076b, 0xfb039bfe, 0x63850106, 0x00260025, 0x83004d9e, + 0x40042333, 0x33870700, 0x2008c26a, 0x0c3b7e2e, 0x2c098541, 0x01ef003c, 0x000c0030, 0xb02f04b0, 0x0865690e, 0x41052f42, 0x3c220979, 0x2383fb79, + 0xb02f1723, 0x087f462d, 0x89051141, 0xa4352049, 0x97352049, 0x3e082149, 0x24085b41, 0x01ee003d, 0x21939536, 0x51410807, 0x783d2208, 0x21939500, + 0x49881808, 0xf1005024, 0x03423c01, 0x181b2013, 0x200b1b43, 0x225388e2, 0x41067b50, 0x2c2010a5, 0x08794318, 0x97fe1222, 0x2609d149, 0xa1002700, + 0x4101f600, 0xe75310a5, 0x087f7f08, 0x039bfe25, 0x85e605fb, 0x21358463, 0xa7410080, 0x412c2019, 0x942606a7, 0x4c049efe, 0x6349b005, 0x07003105, + 0xcb04ad00, 0xffff0a00, 0x94fe5300, 0x4e040b04, 0x49221782, 0x17840000, 0x05528f20, 0x074c2208, 0x089349c2, 0xca04ab2a, 0x09004301, 0x2f06b000, + 0x26088168, 0x04ecff53, 0x8585060b, 0x0701253b, 0x8304ab00, 0x7c050544, 0x33201009, 0xa5244788, 0x3e018a00, 0x17204786, 0x210b3979, 0x4786f605, + 0xa5000624, 0x39790143, 0x0bed7706, 0xb8070f22, 0x02254587, 0x01840037, 0x07eb4328, 0x1b2f072d, 0x3e2007b1, 0x090fb159, 0x4315b0f4, 0x002005eb, + 0xc8229b83, 0x53877c06, 0x3d370222, 0x47084b44, 0x21210805, 0x067957dc, 0x00d5ff27, 0x074c0400, 0x245f88b5, 0x01890038, 0x205f8732, 0x205f8206, + 0x445f8706, 0xff2106ab, 0x20fb848e, 0x215f8879, 0x4b444238, 0x495f8b08, 0x942006e9, 0x92225f82, 0x5f88e507, 0x88003924, 0x19681a01, 0x245f820c, + 0xb0dc0fb0, 0x05474213, 0x4b22bd83, 0x5d88a906, 0x44413921, 0x5d88084b, 0xb1731f20, 0x053f4b08, 0x5d88dd20, 0xbd823a20, 0x5d930c20, 0x5d891620, + 0xa1060b22, 0x3a215d88, 0x084b4442, 0x21205d88, 0x26084f46, 0x049efe94, 0x853e074c, 0x2700235d, 0xbb829e00, 0x42013d21, 0x2b6c0641, 0x07334810, + 0x94fe5326, 0x01060b04, 0x00246385, 0x419e0026, 0x2005a342, 0x0933518f, 0x22206b88, 0x0ad74918, 0xc2071122, 0x22084b78, 0x427803ab, 0x02230573, + 0x8604b02f, 0x233f8223, 0x7e06fd01, 0x2808c978, 0xff6403ab, 0x000900ff, 0x24238ab0, 0x019afe94, 0x08bf78a7, 0x0323a982, 0x82060078, 0xfe782225, + 0x0ac1789e, 0x5c221783, 0x17820a00, 0x94fe6626, 0xc4051e05, 0x6d4e5382, 0x05ad2e05, 0xff00001d, 0xfe4f00ff, 0x043d0492, 0x4e17824e, 0xad24059d, + 0xfeff9d04, 0x6f4a1782, 0x75bb2005, 0xab240851, 0x3c011c05, 0x230c6778, 0xb0593e20, 0x0cfd4418, 0x58850621, 0xab220861, 0x25439804, 0x2f042305, + 0xff751bb0, 0x0761220a, 0x255187b1, 0xd6003702, 0x414a2101, 0x48242010, 0x4f26081b, 0xdd04ecff, 0x53867c06, 0x37020623, 0x08dd4252, 0x2308414a, + 0x24b0dc1e, 0x2605ef41, 0x05ecff27, 0x88ae071e, 0x0038245d, 0x872b01db, 0x08974c5d, 0x0d432220, 0x82a32008, 0x063d225d, 0x215d8879, 0xdb425738, + 0x595d8b08, 0x0d410641, 0x88de2005, 0x0039225d, 0x092747da, 0x20084553, 0x08f54c20, 0x6022bb83, 0x5d88a906, 0x42563921, 0x5d8808db, 0x6b491c20, + 0x205d8508, 0x205d88d6, 0x47bb823a, 0x5d8b0827, 0x83063549, 0x063d225d, 0x215d88a1, 0xdb42573a, 0x205d8b08, 0x05194125, 0x94fe6626, 0x37071e05, + 0x00235d85, 0x829e0027, 0x058145bb, 0xa7421d20, 0x20658809, 0x06ad4123, 0x92fe4f26, 0x01063d04, 0x00246385, 0x569e0026, 0x2005db42, 0x12bb6e9d, + 0x33861d20, 0xecff582b, 0x3307aa05, 0x98002602, 0x242d8300, 0x01d30175, 0x07334233, 0x44088341, 0xc58307ef, 0x0006bb22, 0x99202d82, 0x58202d86, + 0xc7888f89, 0x5b962520, 0x34014422, 0xf96a5b92, 0x04ec2109, 0x44225b8b, 0x5b92b900, 0x8507315d, 0x88b820b7, 0x05ab24b7, 0x90390116, 0x633520b7, + 0x5b8308d3, 0xb7888520, 0x9b04ab24, 0x07560600, 0x07474110, 0x29205b85, 0xa5245b88, 0x3401d600, 0x2a205b90, 0x05215b8b, 0x245b86f6, 0x5ba50006, + 0x20599001, 0x262b8626, 0x0594fe58, 0x852e06aa, 0x07002559, 0x0605ad00, 0x2406d143, 0x04bb048b, 0x834385a8, 0x9a042d17, 0xfffff7ff, 0x94fe7d00, + 0xb005bd04, 0x8405c574, 0x84f22017, 0xfe77262f, 0x04f70394, 0x2117823a, 0x1d470059, 0x84422005, 0x05f57417, 0x2f85bb20, 0x00070127, 0x01f304ab, + 0x0ea5543c, 0x20053f75, 0x843b8585, 0x43912023, 0x062105f7, 0x08837c2f, 0x06234782, 0x8242073d, 0x009a2123, 0x20051542, 0x097f71d7, 0x4408ec74, + 0x51820725, 0x05280523, 0x202d82ec, 0x222d869b, 0x41ecff57, 0x13270703, 0x13b11b2f, 0x18593e1c, 0x8f08f349, 0x0144225b, 0x185b8938, 0x2008bf6f, + 0x0631411a, 0x44225b8f, 0x5b89b800, 0x87088b50, 0x205b8589, 0x24b788c7, 0x011a05ab, 0x88898748, 0x8b2720b7, 0x7106215b, 0xab22b788, 0x1d589a04, + 0x42b78809, 0x5b85079f, 0x5b883820, 0xda00a524, 0x5b904301, 0xb78c1c20, 0x5b86e220, 0xa5000624, 0x1141ed5a, 0x07834310, 0x8bfe7d23, 0x05b74306, + 0xcd419a20, 0x19052d05, 0xfffff7ff, 0x94fe7700, 0x93042805, 0x00234385, 0x54ad0007, 0x07260685, 0xd604a4fe, 0x6357b005, 0x22178405, 0x821000c6, + 0xfe0c262f, 0x04d6030f, 0x055f4e3a, 0x05231783, 0x827bff46, 0x00072617, 0x07d60400, 0x252f85bb, 0xab000701, 0x1542ca04, 0x2f012305, 0x895709b0, + 0x4e85200c, 0xab22089b, 0x15425904, 0x47238205, 0x4785073b, 0x47882c20, 0x8a00a524, 0x714f3701, 0x8b142006, 0xf6052147, 0x2208934f, 0x860119a5, + 0x07a34121, 0xaefe4f2a, 0x0006b204, 0x48002600, 0x2726ed82, 0x85012602, 0x95824202, 0x99004333, 0x12006dff, 0x1c2fb200, 0x1fb25d01, 0xb271011c, + 0x2109829f, 0xc1823130, 0x9afe2d22, 0x2d0b9579, 0x4d025102, 0xffff0000, 0x9afe2300, 0xf184d003, 0x5f55f620, 0x84e62006, 0x828e2017, 0x05ee262f, + 0x002602b0, 0x211785e1, 0x1784cf02, 0x2f825f20, 0x3b04e022, 0xf9201782, 0x01211785, 0x201784c6, 0x202f829b, 0x202f8437, 0x821786b1, 0xffff23eb, + 0x2f828500, 0x5f844d20, 0x1785ec20, 0x07820020, 0x16261782, 0xbc0543fe, 0xbb82c405, 0x17854c20, 0xffed022d, 0xffffffa9, 0x0446fecb, 0x824e048b, + 0x279f8217, 0x51020700, 0xacfff501, 0xe37d2f82, 0x02002305, 0x2f830006, 0xd0ff0236, 0xc1040000, 0x1300b005, 0x71001c00, 0x1e1d00b2, 0xb0391211, + 0x077a4a18, 0x2f088d74, 0xb0584500, 0xb11b2f0a, 0x593e100a, 0x0a1013b2, 0x13202483, 0x0ca15518, 0x8502b221, 0x2f022d15, 0xb01000b0, 0x13b0d00c, + 0xd00eb010, 0x0f028018, 0x6a180a20, 0x30250c6d, 0x15230131, 0x71471921, 0x23400808, 0x33353335, 0x11033315, 0x35363221, 0x02272634, 0x2a01e06d, + 0xfe7ceea0, 0xd3fdefeb, 0xe0fdc0c0, 0x802901e0, 0x047c8c8f, 0xca6ec447, 0x02f8cc85, 0xbfaa4704, 0xfec7fdbf, 0x6e738b12, 0x00000280, 0x2acdcd40, + 0x00f0ff01, 0x05370400, 0x180d00b0, 0x180769b4, 0x2814f47f, 0x02080db2, 0xb0391211, 0x0c8f410d, 0xd004b027, 0xb0100db0, 0x40d51806, 0x9298180f, + 0xf68d3f10, 0x03ababfc, 0xf660fd9c, 0x61fd9f02, 0x02aa9f02, 0x65fecc67, 0xe2ff0100, 0x4d030000, 0x7d8e3a04, 0x27071763, 0xb11b2f02, 0x593e1002, + 0x21297db0, 0x23112311, 0x21113335, 0x38018215, 0xf8fe7f02, 0x02a3a3f2, 0x012afec8, 0xfed10108, 0xaad1012f, 0xfbc4bf01, 0x247f8200, 0x050000e3, + 0x22fd8244, 0x51760014, 0xfd8c0511, 0x180c9a42, 0x200c385c, 0x20998213, 0x20998313, 0x0517410e, 0xb12f0e23, 0x09b75e01, 0x8507b221, 0xeaad1815, + 0x1007310e, 0xb0d00ab0, 0x0cb01004, 0x0112b2d0, 0x3912110e, 0x36092841, 0x33153335, 0x33152315, 0x01012101, 0xac570221, 0xfcccccfc, 0x188bd5d5, + 0x2c0d2881, 0xc7aa3f04, 0x02f3aac7, 0xfd47fd64, 0x27bd8209, 0x040000ae, 0x00000649, 0x2220bd8d, 0x0be96918, 0x240f4a41, 0x584500b0, 0x21bd89b0, + 0x85820210, 0xbd90b020, 0x15831020, 0x4818bd83, 0xbda10a28, 0xbd851120, 0x6ff6012a, 0xf2e7e7f2, 0x0169c4c4, 0x0c598118, 0xaabb0427, 0xfdaa9b9b, + 0x5d8118e1, 0x82072009, 0x05d629bf, 0x000e00b0, 0x0f0ab257, 0x84417483, 0x08515712, 0x0cc15918, 0x08020622, 0x0621a383, 0x22dd182f, 0xd001230c, + 0x7a410ab2, 0x10062405, 0x41d00eb0, 0x0122095e, 0x02820121, 0xc303332c, 0x7acafed5, 0x190167fe, 0x01824f01, 0x67fe1835, 0xfd040286, 0xaa0402fc, + 0x4efd0203, 0xfefcb202, 0x5a000100, 0x9582066d, 0x95916420, 0x53074f41, 0x958808f1, 0x76411220, 0x366f1806, 0x6661180c, 0x41062008, 0xb2230949, + 0x83000b0a, 0xd00d21bb, 0x0521a284, 0x05ac4223, 0x33012308, 0x01331313, 0xdc600333, 0xfea2cef3, 0xecf3fbbb, 0xafbcfefb, 0x0160fe01, 0x9103aaa0, + 0xff0201fd, 0x9d826ffc, 0x2306e761, 0x64001100, 0x41052c41, 0x0e240c1f, 0x0eb11b2f, 0x14b18318, 0x19820520, 0x3e100527, 0x0b11b259, 0x207d8302, + 0x0cc94311, 0x8504b221, 0xd0072915, 0xb01011b0, 0x0db2d009, 0x30230f84, 0x41230131, 0x2321053a, 0x06dc4135, 0xdb033337, 0xfe950187, 0xfec7fed9, + 0x01dafec6, 0xfe738196, 0x01240182, 0x37018232, 0x7983fe24, 0x6bfd9502, 0xeafd1602, 0x02aa9502, 0x02f2fd71, 0x008ffd0e, 0x6561b582, 0x41b58e06, + 0xd318074c, 0x67430c1a, 0x20b5890c, 0x85b5940e, 0x84b58915, 0x23b5850f, 0x01210303, 0x4108b584, 0x01211313, 0x95570333, 0xf4fe2601, 0xf2fed7d8, + 0x828a2501, 0x0c01effe, 0x0e01ceca, 0x018ceefe, 0x0129fed7, 0x018efe72, 0xb901aad7, 0x64019cfe, 0xff0047fe, 0xff6000ff, 0x040c04ec, 0x0006024d, + 0x0f8300bf, 0x00000239, 0xb0053104, 0x2a002602, 0x07000000, 0x72ff2602, 0xffff69fe, 0x18028200, 0x820e8ff3, 0x82512013, 0x0540222b, 0x203b82c4, + 0x08a95816, 0x0f841520, 0x2005b958, 0x201f8234, 0x224b8258, 0x84180006, 0x8281201f, 0x843a206b, 0x8419200f, 0x8289200f, 0x054b270f, 0x000600b7, + 0x7b83141a, 0x0f827c20, 0xc4053622, 0x1c200f82, 0x5d240f84, 0x1204faff, 0x1d200f84, 0x8508074b, 0x8414201f, 0x826a201f, 0x07f0222f, 0x2d4a184b, + 0x01752408, 0x6f4b01bd, 0x4a1806f7, 0x00200dd7, 0x4b212382, 0x05f34a00, 0x7f5f3f20, 0x07314a08, 0x00009423, 0x5b461805, 0x0144220b, 0x09d15f4c, + 0x08d94518, 0x18078d56, 0x220f5b46, 0x82b30044, 0x42132051, 0xf36705a5, 0x54122008, 0x21200cb1, 0x2408df56, 0x017704ac, 0x10d35333, 0xb0dc0c23, + 0x05234e10, 0xecff0d26, 0xec05fb03, 0x2408eb56, 0xff0104ac, 0x10d553fe, 0x59182b20, 0x48260805, 0x4c040000, 0xf1522807, 0x04ac2208, 0x090d5a3c, + 0x0d23bb88, 0x8511b0dc, 0xff01245f, 0x840b04ec, 0x0049285f, 0x00070100, 0x89f503ac, 0x0823515f, 0xb1681f20, 0xf6fe2507, 0x1e020000, 0x2d205f84, + 0x02212f85, 0x605f89ea, 0x052308ed, 0x8409b0dc, 0xe2fe215f, 0x0a222f82, 0x8f82e405, 0x2f868d20, 0x4fffd621, 0x561808cf, 0x2f88084d, 0x714f0020, + 0x50212005, 0xac2208dd, 0x1f418e04, 0x080b4f09, 0x5d502020, 0x82162008, 0x843d20bf, 0x855320bf, 0x0a04215f, 0xab4ebf89, 0x181c2008, 0x2508bd54, + 0x04000032, 0x5f8307de, 0x2f863620, 0x7f412620, 0x69192012, 0xff2107cf, 0x20bf826e, 0x205f84b4, 0x212f8556, 0x5f896203, 0x5308177f, 0x7120093b, + 0xbd208f82, 0x39205f84, 0x04212f85, 0x205f8965, 0x070c6909, 0xb0dc1222, 0x24060d53, 0x03ecff0f, 0x205f84f7, 0x202f8659, 0x885f9203, 0xacfe322f, + 0x02050000, 0x26004106, 0x0064d000, 0xae000700, 0x050b4bfd, 0x9efe942b, 0xb005a304, 0x26002602, 0x32178300, 0x00b904ad, 0x00ffff0a, 0x048bfe7c, + 0x02000632, 0x86460026, 0xffcb2217, 0x831782f7, 0x84d2202f, 0x8628202f, 0x84942017, 0xfe4f242f, 0x84030494, 0x8648202f, 0x00b42217, 0x212f8400, + 0x2f8a0403, 0x01ba0125, 0x829cfe48, 0xfd4f2217, 0x212f89f9, 0x17820701, 0x92fe6830, 0xb6000c00, 0x1e401e30, 0x5d031e50, 0x3d843130, 0x18059e22, + 0x2c206d84, 0x05215585, 0x246d8426, 0x039efe79, 0x206d84f8, 0x2117854c, 0x1784a104, 0x23150f69, 0x04b00009, 0x08df4c18, 0x007d0027, 0x07360400, + 0x21d9823d, 0xc943004f, 0x016b2305, 0x238d003d, 0xdffe9422, 0x2f207786, 0xe9225f86, 0x8f824b00, 0xcafe7d22, 0x0b654b18, 0x04ad0025, 0x85360079, + 0x094b18a7, 0x4117820b, 0x78240545, 0x8b019efe, 0x5020a784, 0x03204785, 0x2405bb53, 0x069efe94, 0x20d7846a, 0x21178531, 0xbf84d605, 0x17827c20, + 0x4e047922, 0x51209b82, 0xd9201786, 0x94221784, 0x4a189afe, 0x00250b63, 0x002805ad, 0x22778206, 0x189efe79, 0x820b634a, 0x848d2077, 0x050d432f, + 0x7f52df20, 0x05362408, 0x53530105, 0x22231099, 0x5f35b0dc, 0x04230845, 0x824207d4, 0x4134202f, 0x72270613, 0x09004201, 0x1803b000, 0x26092d60, + 0x0460fe7c, 0x82f70530, 0x86542023, 0xff9d2223, 0x222383f7, 0x4eb02f0c, 0xd78207ab, 0x0b0d4918, 0xba208f82, 0x72228f84, 0x49189efe, 0x00230b0d, + 0x845603ad, 0xfe4a2217, 0x25481894, 0x04ad2a0c, 0xff0000d5, 0xfe4b00ff, 0xf547188b, 0x2247820b, 0x82f7ff7c, 0xfe2d2217, 0x0be94d97, 0xc3221782, + 0x17820300, 0x94fe0822, 0x0baf4718, 0x14201782, 0x2208e945, 0x82df07bd, 0x833920b3, 0x360226b3, 0x5301dc04, 0x05997300, 0x89561a20, 0x00122608, + 0x071d0500, 0x20258238, 0x22d9843a, 0x55b000a5, 0x581805c1, 0x16260aeb, 0xda030000, 0x2382ed05, 0x23825a20, 0xa5000624, 0xb94ef818, 0x08a14506, + 0x059efe25, 0x85b0051d, 0x07002145, 0xef208382, 0x1626e384, 0xda039efe, 0x39853a04, 0x57201784, 0x30241784, 0xe5069efe, 0x3b202f84, 0x2006eb41, + 0x201784e6, 0x20478221, 0x202f84cc, 0x2017865b, 0x2417844e, 0x049efe50, 0x202f848c, 0x2117853e, 0x1784c104, 0x5f825220, 0x2f84c020, 0x17865e20, + 0x17836320, 0xff1cfe37, 0x056405ec, 0x002600d7, 0x00004633, 0xfd710107, 0xff0000b5, 0x28b582ff, 0x05940400, 0x0226021e, 0x282f8433, 0xfe76ffae, + 0xffffffdd, 0x27e1822a, 0x002105f1, 0x3c280226, 0x00252f82, 0xfe64feae, 0x2a1782e0, 0x04000037, 0x001c05a4, 0x86e40126, 0xfe712217, 0x241782db, + 0x01000039, 0x212f83b3, 0x1786e301, 0x2f847320, 0xf0ff9326, 0x1e057904, 0xdd212f82, 0x2047850a, 0x215f83cd, 0x4782e8fe, 0x17847220, 0x2f86d320, + 0x77842220, 0x1782a420, 0x17848e20, 0x2f86f320, 0x1783de20, 0x0423a785, 0x8306028d, 0x060f78a7, 0x0f840a20, 0xc7843220, 0xaf827620, 0x0f84b520, + 0x0f842820, 0x0f824120, 0x0f83f320, 0x84d20121, 0x211f820f, 0x0f846804, 0x0f84e420, 0xaf828520, 0x0f847720, 0x1f8ee320, 0x0f87e120, 0x848f0521, + 0x88df201f, 0x8467201f, 0x84de200f, 0x824f200f, 0x046f26d7, 0x0106029d, 0x201f88dd, 0x201f842c, 0x200f84dc, 0x20c78224, 0x200f8416, 0x200f84d8, + 0x200f8205, 0x200f8436, 0x200f84d3, 0x200f8215, 0x200f844a, 0x180f83d4, 0x7430bf40, 0x41182dfb, 0x00202cd3, 0x97272d83, 0x26021e06, 0x4500ea01, + 0x23220513, 0x13451e00, 0x078d6b06, 0xf0ff3e24, 0xff84ef03, 0x4f41d920, 0x20cfb013, 0x264f8224, 0x028d0464, 0x41e20106, 0x6820084f, 0xe1208384, + 0x20100579, 0x0605490f, 0xecff1f2a, 0x04063904, 0x01022602, 0x06242382, 0x1e7aa100, 0x2418e577, 0x04000009, 0x1e3f4294, 0x7f849720, 0x5f42f382, + 0x42032005, 0x76200b4f, 0x6e203f82, 0x01216b83, 0x228f84fe, 0x76ba00a1, 0x0d20123d, 0x2d829986, 0x42103d42, 0x3d420b7d, 0x84622013, 0x42ef207d, + 0x2f83144d, 0x9d044325, 0x74020602, 0x5d4205e7, 0x0c4d420f, 0x00010039, 0x0339fe42, 0x009d04e7, 0xb2a70028, 0x112a2927, 0xb0003912, 0x52b02f17, + 0x2d780824, 0x2f192807, 0x1019b11b, 0x18b0593e, 0x20107ab2, 0x23338219, 0x0a1927b2, 0xb02e0682, 0x5fb22f27, 0xb2720127, 0x7101273f, 0x0483cfb2, + 0x0483ff20, 0x13820f20, 0x276fb42f, 0x7102277f, 0xbf27afb4, 0xb25d0227, 0x2112828f, 0x0482bfb2, 0x4f24b121, 0x10220ad0, 0x5d182724, 0xb2210831, + 0x2053851d, 0x0f751819, 0x3130280c, 0x23263401, 0x18150622, 0x250d91b2, 0x23110706, 0xb2182611, 0xbb241c92, 0xb09bf3ac, 0x1890b218, 0xae862208, + 0x0141fe18, 0x87ac18c2, 0xa6485793, 0x0004b003, 0xfe760001, 0x042c059a, 0x000f008d, 0x1003b2aa, 0x216c1811, 0x08e77a15, 0x58450028, 0x1b2f01b0, + 0x537901b1, 0x82062007, 0x1006210c, 0x2006ae4e, 0x200c8203, 0x230c8203, 0x09060ab2, 0xb0304882, 0xafb42f0a, 0x020abf0a, 0x0a3fb25d, 0xcfb27101, + 0x09820483, 0xffb27222, 0x0f2e0983, 0xb472010a, 0x0a7f0a6f, 0xdfb47102, 0x2682ef0a, 0x0a1fb423, 0x2106822f, 0x19825fb2, 0x0b6f6c18, 0x1003b024, + 0x96180eb1, 0x6d180ca5, 0x33380718, 0x33112111, 0x2c053311, 0xf4fdc4f3, 0x0c02f3f3, 0x9afec4f3, 0xdb016601, 0x0738c518, 0x8228fc21, 0xfe4f2ae3, + 0x04430443, 0x001e009d, 0x0c377a60, 0x0ca9a318, 0xbc820420, 0x784f0420, 0x0d791807, 0xd0062508, 0x030e12b2, 0x0e20cc83, 0x830c0a54, 0x411b2092, + 0x1e220ad4, 0x83510e03, 0x41062005, 0x022e05a5, 0x36343527, 0x04323336, 0x26262317, 0x8f182023, 0x0c2609f4, 0xb5f3a9c6, 0xba1801cf, 0xfe200abc, + 0x07f48f18, 0x1bd09f39, 0xb90149fe, 0xdd1f0124, 0x8affa94f, 0x6970c2da, 0xb9488efe, 0x187062b5, 0x2209eba6, 0x45010602, 0x0a340531, 0xa8053afe, + 0x2602a304, 0x00001702, 0x51020700, 0xa0ffe602, 0x2505a943, 0xcc056e04, 0x99432602, 0x00702c06, 0x00220082, 0x00b00009, 0x440ab02f, 0x23830b29, + 0x21062944, 0x21844270, 0x51180220, 0x502609b9, 0x4d050000, 0x6d828d04, 0x0000f130, 0x8500ffff, 0x6005f0ff, 0x26008d04, 0x6d83e301, 0x01e20123, + 0x201783fc, 0x231d82ff, 0x00060306, 0x73208582, 0x00231783, 0x83830275, 0x4f002717, 0x6f04c9ff, 0x17821e06, 0x17857520, 0x0074012b, 0x00ffff1e, + 0x03f9fd3e, 0x091f7def, 0x01ba0125, 0x7b92fe3b, 0x2f820815, 0x84d50121, 0x0144222f, 0x202f8479, 0x20878228, 0x864783e5, 0x02752217, 0x23178918, + 0x2602ea05, 0x6a221786, 0x17844401, 0x0c1b4518, 0x00070025, 0x848e0044, 0xfe122217, 0x0c316555, 0x8201a424, 0x77820300, 0x59fe5a22, 0x240c3165, + 0x00b500a4, 0x22178207, 0x615cfe94, 0xa4240c5b, 0x0a004001, 0x53221782, 0x5b6152fe, 0x01a4220c, 0x20ef8404, 0x22178209, 0x488d0494, 0xa4220837, + 0x17842301, 0x5afe7624, 0x1784b503, 0x8f82c982, 0xee00a424, 0xb75e0800, 0x048b2206, 0x05c14d3a, 0xad261782, 0x0a005c03, 0xed820100, 0x8f000e28, + 0x4e001600, 0x0d830500, 0x0000002b, 0x0200000e, 0x00300200, 0x210f8406, 0x01870060, 0x009bd80a, 0x014201c5, 0x025d02c2, 0x031403fa, 0x036f0340, + 0x03c803a2, 0x040104ea, 0x043f0428, 0x05c20494, 0x05880514, 0x063306cc, 0x07c9069c, 0x07b30748, 0x07cb07bf, 0x081208ea, 0x09980831, 0x09870946, + 0x0a470af3, 0x0bd30a91, 0x0b6b0b0a, 0x0bc40ba9, 0x0c3f0cf8, 0x0cbc0c63, 0x0d530df8, 0x0e000e9f, 0x0ec90e5a, 0x0f330ff4, 0x0fb30f64, 0x102f10fe, + 0x108d1068, 0x10ca10a4, 0x110c11f1, 0x12ae112d, 0x1264120f, 0x133713c2, 0x14fd1381, 0x1477143d, 0x150a15c3, 0x15911525, 0x162916da, 0x17ef168e, + 0x179c172d, 0x182f18e8, 0x18ad185f, 0x193719f6, 0x19b31970, 0x1a0c1aca, 0x1a8f1a51, 0x1b571bf2, 0x1c1b1cb9, 0x1dd71c3a, 0x1eac1d09, 0x1e381e2c, + 0x1f081f56, 0x1f621f22, 0x20fa1fa6, 0x208d206d, 0x210b21df, 0x2162212c, 0x21dc2191, 0x220222e8, 0x2236221c, 0x230623a0, 0x24c02344, 0x257f2412, + 0x26b92540, 0x26842611, 0x276027e4, 0x28da27bf, 0x28712827, 0x290729af, 0x2ae92963, 0x2bb72a86, 0x2b842b1c, 0x2c572cf2, 0x2d072dac, 0x2d9c2d38, + 0x2efb2dd3, 0x2e322e03, 0x2e8e2e55, 0x2fff2ebb, 0x2f792f34, 0x2fb92f99, 0x30f32fc2, 0x30413025, 0x30a0305a, 0x30cf30a8, 0x317831fd, 0x32e831a6, + 0x32543217, 0x332333c9, 0x3402348d, 0x35a63473, 0x359b351c, 0x364036f6, 0x37e236b4, 0x37ac373b, 0x385838fe, 0x390d39b6, 0x39923952, 0x3a523aff, + 0x3b2c3bb3, 0x3cf23b7c, 0x3dc53c55, 0x3eb23d3c, 0x3e413e04, 0x3ff73e9a, 0x40e33f63, 0x4066401c, 0x411f41ad, 0x41964155, 0x421d42d4, 0x43dc4277, + 0x44a04329, 0x447b4420, 0x455045e4, 0x46cd4577, 0x46ba463a, 0x474447f3, 0x48d6478c, 0x485f4830, 0x4916498b, 0x498e494c, 0x4a114acc, 0x4bc94a66, + 0x4b864b14, 0x4c594cff, 0x4d424dd3, 0x4e294eb8, 0x4fca4e8e, 0x4f8a4f2a, 0x507950f3, 0x514851fb, 0x52035297, 0x53e45271, 0x54e05356, 0x55095569, + 0x560c569d, 0x57bc5677, 0x576f5703, 0x599958d7, 0x5acd5953, 0x5aa35a4d, 0x5b2c5bf7, 0x5b7c5b48, 0x5ca85b92, 0x5dea5c7c, 0x5d205d05, 0x5ee15d89, + 0x5e815e51, 0x5f015faa, 0x5f595f4d, 0x5f715f65, 0x60d35f7d, 0x60776026, 0x60d960cd, 0x614561e5, 0x62f46194, 0x63dc624b, 0x63746368, 0x64c76380, + 0x6417640b, 0x64766423, 0x650865c5, 0x66f96579, 0x66af665a, 0x67c766bb, 0x67826726, 0x679a678e, 0x68b267a6, 0x687d681a, 0x68e868d9, 0x690469f8, + 0x69606910, 0x6a526ac9, 0x6b306bc5, 0x6cfd6b98, 0x6dd66c6a, 0x6ea96d3b, 0x6e586e05, 0x6ffd6eab, 0x6f806f74, 0x9abb6f8c, 0xc3f00901, 0xd56fcb6f, + 0xf76fdf6f, 0x3c701a70, 0x7b705c70, 0x93708770, 0x0571c670, 0x8b716771, 0xa7719771, 0x9a72ca71, 0xd272b672, 0xf972e572, 0xc5734173, 0xf6746874, + 0xca750275, 0xb0763076, 0xce776777, 0xa2784978, 0xb1791279, 0xaa7a137a, 0x6c7b087b, 0xa07b867b, 0xd47bba7b, 0x687c417c, 0xb87ca17c, 0x807ded7c, + 0x447ec37d, 0x937e847e, 0xdb7ea27e, 0x167fe87e, 0x3b7f2f7f, 0xf57f9f7f, 0x1c819080, 0x59828f81, 0x0d845982, 0xc9847684, 0x3c85f384, 0x2686a185, + 0xbe865786, 0x6d872387, 0x4988f387, 0xc8887a88, 0x32890189, 0xc5897b89, 0x2f8af689, 0xc58a5a8a, 0x7a8b1e8b, 0x198cc48b, 0xa48c528c, 0x0b8dc88c, + 0x518d368d, 0x0b8eac8d, 0xb98e428e, 0x868f248f, 0xe68fb08f, 0x8d905a90, 0x0a91d890, 0xbd914e91, 0x73920f92, 0x4d93d292, 0x5394c293, 0xe494a494, + 0x92953b95, 0x8d960d96, 0x2297c996, 0xaf976c97, 0x2b98e997, 0xa3986498, 0x0799fb98, 0xcb995499, 0xb09a5c9a, 0x759bf39a, 0x419cdb9b, 0x359da49c, + 0x939d419d, 0x2e9ee09d, 0xe09e709e, 0xa69f469f, 0xb1a01da0, 0xd0a138a1, 0xbba247a2, 0x5da3fda2, 0xe8a3bba3, 0xd0a46ea4, 0x3ba5e7a4, 0x2ea67da5, + 0xfca698a6, 0x8ca745a7, 0x0fa8cea7, 0xaea858a8, 0x72a933a9, 0xe3a995a9, 0x8baa44aa, 0x28abd1aa, 0xc7ab9aab, 0x70ac15ac, 0x98ac84ac, 0xbeacaaac, + 0xe7acd0ac, 0x4fadfbac, 0xfeadb2ad, 0xbdae5bae, 0x40afe8ae, 0xe0af98af, 0x66b03fb0, 0xedb0d7b0, 0xd2b16db1, 0x14b203b2, 0x38b225b2, 0x5ab249b2, + 0x80b26db2, 0xa9b293b2, 0xb9b2b1b2, 0xc9b2c1b2, 0xdcb2d4b2, 0x96b343b3, 0x23b4c3b3, 0xd8b477b4, 0xa3b556b5, 0x6db609b6, 0x5bb7dfb6, 0xe6b763b7, + 0x8fb821b8, 0x58b9dfb8, 0x18bac6b9, 0x2c0d0182, 0xbb91ba20, 0xbb64bb02, 0xbc0cbca7, 0xbc3abc23, 0xbc63bc51, 0xbc8ebc7b, 0xbca6bc9a, 0xbcd4bcbd, + 0xbd03bdeb, 0xbd31bd1a, 0xbd60bd48, 0xbd89bd72, 0xbdb7bda0, 0xbde6bdce, 0xbe0fbefd, 0xbe3ebe26, 0xbe6cbe55, 0xbe94be7e, 0xbec1beaa, 0xbee5bed9, + 0xbf08bff1, 0xbf30bf1a, 0xbf5dbf47, 0xbf8abf73, 0xbfb3bfa2, 0xbfdcbfca, 0xc003c0f2, 0xc032c01b, 0xc05ac044, 0xc083c071, 0xc0b1c09a, 0xc0d9c0c2, + 0xc15bc1f0, 0xc211c2ff, 0xc23ac223, 0xc267c250, 0xc290c27e, 0xc2b3c2a1, 0xc2dac2c3, 0xc302c3eb, 0xc32fc318, 0xc4b5c346, 0xc465c44e, 0xc48dc476, + 0xc4bac4a3, 0xc4e7c4d0, 0xc50ac5fe, 0xc533c51c, 0xc55cc545, 0xc585c56e, 0xc5b3c59c, 0xc5d5c5ca, 0xc6f7c5e0, 0xc60fc603, 0xc63dc626, 0xc655c649, + 0xc683c66c, 0xc69bc68f, 0xc6c5c6b0, 0xc6ddc6d1, 0xc706c7f4, 0xc71ec712, 0xc746c735, 0xc772c75b, 0xc79ac783, 0xc7c9c7b1, 0xc8f3c7e1, 0xc811c805, + 0xc82fc81d, 0xc852c840, 0xc87bc864, 0xc89dc891, 0xc8b5c8a9, 0xc8d3c8c1, 0xc8f0c8e4, 0xc908c9fc, 0xc92bc914, 0xc94ec937, 0xc976c964, 0xc9a3c98c, + 0xc9cdc9ba, 0xcaf8c9e0, 0xca6aca0b, 0xcae4cacd, 0xcb12cbfb, 0xcb40cb28, 0xcb6ecb57, 0xcb9ccb85, 0xcbbfcbae, 0xcbe8cbd6, 0xcc16ccff, 0xcc76cc46, + 0xcc9dcc86, 0xcccaccb4, 0xcdf3ccdb, 0xcd17cd0b, 0xcd3acd23, 0xcd67cd51, 0xcd95cd7e, 0xcdc2cdab, 0xceeccdda, 0xce15ce03, 0xce3cce2b, 0xce6bce54, + 0xce98ce82, 0xcec7ceb0, 0xcff4cedd, 0xcf6ecf5c, 0xcf9bcf84, 0xcfbdcfac, 0xd0e9cfd3, 0xd06fd000, 0xd09bd085, 0xd0c9d0b2, 0xd0ebd0d5, 0xd114d1fd, + 0xd136d12b, 0xd163d14c, 0xd185d16f, 0xd1a6d191, 0xd1c9d1b2, 0xd1ecd1d5, 0xd214d2fd, 0xd239d227, 0xd256d245, 0xd27ed268, 0xd29bd28a, 0xd2bdd2a7, + 0xd2dfd2c9, 0xd307d3f0, 0xd32dd31a, 0xd3a6d38f, 0xd3d3d3bc, 0xd401d4ea, 0xd422d417, 0xd43ad42e, 0xd452d446, 0xd46ad45e, 0xd48dd485, 0xd49dd495, + 0xd4add4a5, 0xd4bdd4b5, 0xd4cdd4c5, 0xd4ddd4d5, 0xd4edd4e5, 0xd50dd5f5, 0xd537d525, 0xd55bd549, 0xd586d56c, 0xd596d58e, 0xd6a6d59e, 0xd629d611, + 0xd652d640, 0xd676d664, 0xd7a5d68e, 0xd71cd714, 0xd73cd734, 0xd75bd744, 0xd77ad772, 0xd78ad782, 0xd7a9d792, 0xd7b9d7b1, 0xd7c9d7c1, 0xd7d9d7d1, + 0xd7e9d7e1, 0xd8f9d7f1, 0xd818d810, 0xd875d820, 0xd885d87d, 0xd8b3d89c, 0xd8c3d8bb, 0xd8e3d8db, 0xd910d9fa, 0xd93ed927, 0xd96cd955, 0xd99cd984, + 0xd9c9d9b3, 0xdafcd9dd, 0xda1ada08, 0xda39da22, 0xda57da4b, 0xda7ada63, 0xdaa8da91, 0xdac7dabf, 0xdae7dacf, 0xdb0bdbff, 0xdb23db17, 0xdb3bdb2f, + 0xdb4fdb47, 0xdb5fdb57, 0xdb8ddb76, 0xdbacdb95, 0xdbdbdbc3, 0xdcfadbf2, 0xdc19dc02, 0xdc47dc2f, 0xdc66dc4f, 0xdc96dc7e, 0xdcc5dcae, 0xddf2dcdc, + 0xdd22dd0a, 0xdd52dd3a, 0xdd62dd5a, 0xdd91dd7a, 0xddc0dda9, 0xdde3ddd2, 0xde12defb, 0xde42de2a, 0xde71de5a, 0xdea9de8d, 0xdebddeb1, 0xdedbdec9, + 0xdf06dfed, 0xdf36df1d, 0xdf65df4d, 0xdf94df7c, 0xdfc6dfab, 0xe0f3dfe0, 0xe018e005, 0xe03de02a, 0xe067e04f, 0xe099e07e, 0xe0c0e0b4, 0xe0dee0cc, + 0xe102e1f0, 0xe12ce113, 0xe15ce143, 0xe18be173, 0xe1bae1a2, 0xe2ece1d1, 0xe218e206, 0xe236e22a, 0xe24ee242, 0xe271e25a, 0xe29be283, 0xe2cae2b2, + 0xe3f9e2e1, 0xe328e310, 0xe35ae33f, 0xe38be374, 0xe3b9e3a2, 0xe3e7e3d0, 0xe415e4fe, 0xe437e42b, 0xe44fe443, 0xe46de45b, 0xe496e47f, 0xe4c4e4ad, + 0xe5f2e4db, 0xe520e509, 0xe542e536, 0xe55ae54e, 0xe578e566, 0xe59ce58a, 0xe5c7e5ad, 0xe5dfe5d3, 0xe6f7e5eb, 0xe60fe603, 0xe627e61b, 0xe696e62f, + 0xe73ce7fd, 0xe8dbe77c, 0xe886e83b, 0xe930e9d5, 0xe991e989, 0xe9a7e99d, 0xe9b7e9af, 0xe9c7e9bf, 0xe9d7e9cf, 0xe9e7e9df, 0xea0beaf9, 0xea39ea22, + 0xea69ea51, 0xea99ea81, 0xeac9eab1, 0xebf9eae1, 0xeb29eb11, 0xeb59eb41, 0xeb71eb65, 0xeb89eb7d, 0xeba1eb95, 0xebc0ebb4, 0xebdeebcc, 0xecfcebf0, + 0xec14ec08, 0xec2cec20, 0xec44ec38, 0xec68ec50, 0xec8cec7a, 0xeca4ec98, 0xecbcecb0, 0xecd4ecc8, 0xedf9ece7, 0xed16ed0a, 0xed2eed22, 0xed46ed3a, + 0xed5eed52, 0xed76ed6a, 0xed8eed82, 0xeda6ed9a, 0xedbaedb2, 0xedcaedc2, 0xeddaedd2, 0xedeaede2, 0xeefaedf2, 0xee0aee02, 0xee1aee12, 0xee3aee22, + 0xee68ee51, 0xee82ee7a, 0xeea2ee8a, 0xeebceeaa, 0xeedaeed2, 0xeeeaeee2, 0xef09eff2, 0xef19ef11, 0xef29ef21, 0xef39ef31, 0xef49ef41, 0xf049f0d7, + 0xf0b3f0ab, 0xf0d1f0bf, 0xf0eaf0e2, 0xf102f1f6, 0xf11af10e, 0xf132f126, 0xf14af13e, 0xf162f156, 0xf17af16e, 0xf192f186, 0x0000009e, 0x2e038201, + 0xac122302, 0x5ff0c8ff, 0x00f53c0f, 0x83000819, 0xf0c42300, 0x07832e11, 0x5201d52b, 0xfd24faec, 0x085c09d5, 0x230f8273, 0x00020009, 0x03230084, + 0x8464008c, 0x24048208, 0x0000fe01, 0x2c038201, 0x8f002502, 0x65009802, 0x6000e204, 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, + 0x051b3408, 0x02750051, 0x0486001e, 0x0464007d, 0x055e00b5, 0x045d009d, 0x010b0040, 0x048800fc, 0x035a00f8, 0x065d0085, 0x03570044, 0x038d0091, + 0x045700e2, 0x847f006d, 0x00db2e0f, 0x000a039b, 0x004a047f, 0x00f6025f, 0x3403823c, 0x009b0237, 0x00bb0470, 0x00ed0392, 0x00420245, 0x0010028e, + 0x2217826d, 0x82a70380, 0xe2340887, 0xd0055d00, 0x2b065900, 0x57065000, 0xe4036700, 0x85074200, 0x4404f6ff, 0x84054d00, 0xca046900, 0xe7049400, + 0xc1068800, 0xa7044800, 0x91046700, 0x88044300, 0x973ed782, 0xed048200, 0xb0054f00, 0x1a021f00, 0x98048f00, 0x64048e00, 0x4f022200, 0x93052100, + 0x23829000, 0xb4077e3a, 0x3a076400, 0x0c025b00, 0x88058b00, 0xd0025100, 0x8a05e4ff, 0x9e045800, 0xa4383782, 0xf2047d00, 0x26027700, 0x3c04b5ff, + 0xe6035900, 0xb0039400, 0xdc037200, 0x7c20bf82, 0x0b3efb82, 0xb2028100, 0x4d027800, 0xd8032900, 0x1f037a00, 0x6c024900, 0x00008200, 0x00008efc, + 0x07825efd, 0x07827320, 0x07823e20, 0x07820c20, 0x5d021c24, 0x4782c600, 0xdf836720, 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, 0x4d260382, 0x94002a06, 0x97821b05, 0x05338782, 0x04940013, 0x047c0086, 0x038f006a, 0x047e00a1, + 0x829b00f2, 0x087e2a73, 0x0616001c, 0x051e00d3, 0x340f82cc, 0x058f00fa, 0x0490002c, 0x068e00ab, 0x05340095, 0x063d00a4, 0x24438228, 0x0786000d, + 0x2a0782d0, 0x087e00aa, 0x069b0047, 0x827e00f5, 0x8267205b, 0x612e087b, 0x29003905, 0x1f004604, 0x2d003107, 0x26007005, 0x8e00fa05, 0x5f00dc04, + 0x80007405, 0x74007304, 0x84008605, 0x16002406, 0xcbffc304, 0x5b822105, 0x5b827820, 0x2b822820, 0x21001d24, 0x7382af05, 0x4b828820, 0x5b823520, + 0x63821a20, 0x94007e24, 0x83827806, 0x51008826, 0x5b00a604, 0x5d260382, 0x3400c704, 0x2f82af03, 0x67826720, 0x00742808, 0x0007051f, 0x00f10652, + 0x00dd0668, 0x0053065e, 0x0028053c, 0x007b042f, 0x003e0448, 0x00be0774, 0x009d0642, 0x82fd0740, 0x009e2c47, 0x00040577, 0x002c045d, 0x82aa0555, + 0x001d286b, 0x00550544, 0x82490681, 0x003e2e4b, 0x002c0321, 0x00140467, 0x00290800, 0x29078700, 0x0000b902, 0x00000a02, 0x13825c01, 0x00007f24, + 0x0b823002, 0x0382a220, 0x00820020, 0x0382d120, 0x02230282, 0x834700a1, 0x054b0803, 0x069d0029, 0x03810030, 0x0103009c, 0x016300c0, 0x013300bc, + 0x013200ce, 0x034a00a8, 0x036c0014, 0x0340001b, 0x04320008, 0x0440005d, 0x025c0099, 0x038800cb, 0x058a00fa, 0x018a00a6, 0x075a00c8, 0x024a00a7, + 0x026c0072, 0x82540069, 0x022d3643, 0x033500f6, 0x0469005c, 0x065f00b5, 0x06210070, 0x089800b8, 0x20c78293, 0x300b8228, 0x047c008c, 0x055e008c, + 0x042100f5, 0x04280034, 0x08cf82a2, 0x4f005e34, 0x28007d05, 0x7000e405, 0x4c00e203, 0x90002e08, 0x6d000905, 0x96001405, 0x59003506, 0x5400dd06, + 0x5b00d106, 0x5800a206, 0x62009104, 0xa6009605, 0x8b82d904, 0x00832808, 0x00b2049e, 0x0045083b, 0xff2d025e, 0x008e04af, 0x007a0465, 0x00110491, + 0x002a043c, 0x000c0480, 0x005b0224, 0x829802a1, 0x00f130d3, 0x001b0545, 0x00a8042d, 0x00bc0418, 0x8523072d, 0x11052803, 0xb7062d00, 0x82004b00, + 0x30082500, 0x35085900, 0x4745df82, 0x82802005, 0x044b24c7, 0x824f001d, 0x82582003, 0x04392403, 0x8260001c, 0x82672007, 0x82302003, 0x823e2003, + 0x82422003, 0x82962003, 0x82592003, 0x04412a6f, 0x0405003c, 0x0615005e, 0x2ad78207, 0x0409007b, 0x04670084, 0x8224003b, 0x043e2ae7, 0x0476005c, + 0x044c00c0, 0x2a07846d, 0x00dd044f, 0x00060676, 0x82b90376, 0x825b200f, 0x00d52807, 0x00fc0124, 0x82de0485, 0x00a6240f, 0x82c50354, 0x00342a07, + 0x0066043e, 0x00a40338, 0x83278409, 0x82c02053, 0x2507828f, 0x42009803, 0x2382d804, 0x44001930, 0x50009d05, 0x50005405, 0x5f00e404, 0x6f829105, + 0x4f00802c, 0x24005407, 0x76005707, 0x0f829705, 0x2782d720, 0x0b827120, 0x27005928, 0x1a003a06, 0x3b824604, 0x1382e420, 0xcb209383, 0x46241f82, + 0x5d051f00, 0x8c280f82, 0x84064100, 0x0a077600, 0x5a242b82, 0x20060a00, 0x67201382, 0x80240382, 0x92063c00, 0x88240782, 0x22044300, 0x92201782, + 0x9d204382, 0x1a202382, 0x6e240382, 0xf0052400, 0x5a249382, 0xc4040500, 0x9520fb82, 0x47824f82, 0x828c0421, 0x00fe241b, 0x82d2040a, 0x836f831b, + 0x24cb83b7, 0x084600f7, 0x264b8236, 0x022800eb, 0x823700f6, 0x82352003, 0x824f2003, 0x824d2003, 0x82362003, 0x824b2003, 0x82462003, 0x029026ef, + 0x039600b2, 0x202b82e0, 0x3047823b, 0x055600bb, 0x059b0044, 0x049b0028, 0x05810030, 0x24078239, 0x0481002d, 0x229f847a, 0x8260044f, 0x009e3607, + 0x00050209, 0x00a10394, 0xfc000075, 0x000b049d, 0xff0b047a, 0x2007824c, 0x82038375, 0x83762053, 0x8603831b, 0x257b9467, 0x6b007a05, 0x0382a205, + 0x6f828620, 0x0782e020, 0x6b00e23a, 0x97001b04, 0x6e008204, 0x0f005704, 0x3500be04, 0x66006b04, 0x43002e04, 0x01254b83, 0x065c00b3, 0x26e78298, + 0x027300b4, 0x82b0ff10, 0x823920fb, 0x826a2003, 0x822c2003, 0x82662003, 0x82632003, 0x82352003, 0x826f2003, 0x49592003, 0xe3240603, 0xb5ff2602, + 0x1b270384, 0x1b028f00, 0x8202fbff, 0x2fc78407, 0x046200eb, 0x043a0033, 0x047c0088, 0x0450003d, 0x93205b83, 0xa1245f82, 0x94044c00, 0x9f201382, + 0x4b380b82, 0x89045300, 0xa4035100, 0x03055b00, 0xc4035d00, 0x46060300, 0x0904f1ff, 0x33055f42, 0x31000905, 0x7600dd04, 0x0000fe01, 0x4700a002, + 0xf7ff5805, 0x042f0383, 0x04d4ff8f, 0x022d00db, 0x05e8ffa9, 0x98120053, 0x82392003, 0x008623df, 0x038a0494, 0xff420227, 0x004202c8, 0x200782a3, + 0x280382cb, 0x00ae05bf, 0x00860594, 0x23039066, 0x057d0037, 0x0427038a, 0x040700e0, 0x985a0054, 0x86302003, 0x86d383cf, 0x1a022703, 0x1a02b4ff, + 0x07828f00, 0x0382b720, 0x4904ab21, 0x8e20075f, 0x038b2b82, 0x77007223, 0x23038a04, 0x0c00e503, 0xd7830383, 0x07906f83, 0x6f82d783, 0x07970520, + 0xd3823a20, 0x63821a20, 0x8b83f783, 0x0527079e, 0x046a0072, 0x98520089, 0x00af2a07, 0x00710494, 0xff420279, 0x20c782b3, 0x2007829f, 0x200782cd, + 0x200782b9, 0x340782df, 0x004202cb, 0x000b0217, 0x00420200, 0x00b3069d, 0x000c04a3, 0x262f827d, 0xff26022d, 0x820b05b5, 0x822d203b, 0x0054220f, + 0x20238294, 0x83cf828a, 0x84552007, 0x00a12207, 0x2407848c, 0x058c00e7, 0x222782ae, 0x8f790073, 0x73042b07, 0x8605a5ff, 0x8e046600, 0x078f4f00, + 0x82fe0421, 0x00d02253, 0x2007867c, 0x2807864f, 0x00d40438, 0x0021044a, 0x2607a04b, 0x022d00db, 0x420800a9, 0x0786054b, 0x0800d124, 0xaf823705, + 0x77007222, 0x072f07a7, 0x0530000a, 0x042100f2, 0x030700e0, 0x830c00e5, 0xd1042707, 0x06045000, 0x078f5200, 0xff850733, 0x00c106f6, 0x00840548, + 0x00880469, 0xff7a044f, 0x260384a6, 0x0424003b, 0x9809009e, 0x00802603, 0x00e0034f, 0x27038b76, 0xa6fffc01, 0x8300fc01, 0xa9200782, 0x9d220382, + 0x3743dd04, 0xc0042105, 0x038b5782, 0x67008423, 0x22038b04, 0x8c05003c, 0x205b8267, 0x22038b04, 0x8f6a007a, 0x230f836b, 0x5400a604, 0xde22038c, + 0x77827600, 0x03829120, 0x0382ab20, 0x8b82bd20, 0x03821520, 0xd5037c22, 0x5b20cb82, 0x21051746, 0x0789b903, 0xa3839f84, 0x5c20a78f, 0x8306c745, + 0x00342307, 0x038b043e, 0x4b823b20, 0xc78f0387, 0x06240f86, 0x04280007, 0x0383d383, 0x41002a23, 0x3f038604, 0x12005305, 0xe7fe8604, 0xf0feaf05, + 0xf3fe4202, 0xa7ff9a05, 0xe1fe4405, 0xb2ff6f05, 0x87ffaa02, 0x05211f83, 0x061f440c, 0x5000d122, 0x2107974d, 0x8f4d0b05, 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, + 0x2308cb4d, 0x034f0030, 0x2005af4d, 0x371b831f, 0x85005a03, 0x4b002104, 0x7d000b02, 0xabff1a02, 0xb5ff0102, 0x8f006e04, 0xcb422383, 0x42078f07, + 0x013b07db, 0x0252005a, 0x04650098, 0x028f004a, 0x01b1ff26, 0x073300bc, 0x06940001, 0x837c00f6, 0x867f84af, 0x258787ab, 0x4400aa05, 0x434bc905, + 0xf1ff2707, 0x4f007308, 0xb3826b09, 0x4900d626, 0x4d001604, 0x8307c744, 0x0e042f63, 0x42022000, 0xa207a300, 0x76061600, 0x0b831e00, 0x430fff44, + 0x04200743, 0x2706d744, 0x51008805, 0x59003c04, 0x37870383, 0x5b870420, 0x9400a827, 0x86009804, 0x44078705, 0xd74b074b, 0x22078707, 0x826b0050, + 0x0551283f, 0x0339000a, 0x900c00e5, 0x00893007, 0x0066048e, 0x00f9065f, 0x006f069b, 0x8284048f, 0x005322cf, 0x149f4512, 0x10005326, 0x9aff5404, + 0x0fafb78f, 0x0799df87, 0x04d5ff25, 0x978eff4b, 0x4202271f, 0x1a02a300, 0x07828f00, 0x0b029424, 0x3f457800, 0x240f8a0f, 0xff8e0427, 0x4e1f98a3, + 0x079f07ff, 0x4f0f3745, 0x0520062f, 0x3745079e, 0x4503200b, 0x0784063f, 0x4f00a22b, 0x2d00db04, 0x2300f503, 0x067f4105, 0x00750427, 0x005a039b, + 0x07c34c85, 0x00710427, 0xff070579, 0x2f0383d0, 0xf0ff7504, 0xe2ff5a03, 0xe3ff3c05, 0xaeff4404, 0x33074f42, 0x29001005, 0x1f000604, 0x60006004, + 0x02006504, 0x81003006, 0x2a10db51, 0x048900a0, 0x047c00b4, 0x825d00a0, 0x477d2007, 0x9746080b, 0x05eb4107, 0x86040d30, 0x4b044800, 0x42020100, + 0x1a02f6fe, 0x3341e2fe, 0x04163e06, 0x023200fe, 0x056effd0, 0x04710037, 0x040f0072, 0x05acfedf, 0x0494000c, 0x057c0081, 0x2207823a, 0x884f0084, + 0x064f4707, 0x47071b47, 0x78200e23, 0x87084f43, 0x0086247b, 0x851d0566, 0x2467824b, 0x00d00294, 0x08db4672, 0x8206c346, 0x057d2877, 0x0312002d, + 0x871600f5, 0x08974607, 0x3f068b46, 0x1cfecc05, 0x09009e04, 0x2aff1c04, 0x37ff1a05, 0x39ff3802, 0x93ffca04, 0xe8fe7804, 0xa4ffee04, 0x60201b84, + 0x2d056346, 0x41002a04, 0x7600de04, 0x8500fc01, 0xe74b5b04, 0x085f4605, 0x76006d27, 0x24003b04, 0x062b4c04, 0xfffc0123, 0x210b839d, 0xeb45e003, + 0x34042305, 0x37833e00, 0x0b461783, 0x46042307, 0x5f881f00, 0x6386b920, 0x5786e420, 0x04256782, 0x044f00c0, 0x835782d8, 0x8280205b, 0x225f830b, + 0x8215005e, 0x83422037, 0x83042087, 0x246f8213, 0x0a00fe05, 0x82378204, 0x051f2c17, 0x0550009d, 0x068500d1, 0x84f1ff46, 0x2377823f, 0x28000706, + 0x93830387, 0x230b9344, 0x53004b04, 0xa7838383, 0x001a0235, 0x00010078, 0xfe6c0700, 0x0900000c, 0xfe24fa6b, 0x835c0941, 0x8a002011, 0x0e053300, + 0x98040300, 0x0500f401, 0x9a050000, 0x00003305, 0x07851f01, 0x00d10326, 0x00000266, 0x2a078254, 0xe0000000, 0x50ff0200, 0x825b2000, 0x8220200a, + 0x47003803, 0x00474f4f, 0xff000040, 0xfe0006fd, 0x07660000, 0x2000029a, 0x839f0100, 0x3a04231b, 0x0c82b005, 0x03002022, 0x01200d82, 0x10325b82, + 0x00040b09, 0x02020200, 0x07050603, 0x03030206, 0x04840504, 0x00870520, 0x82020221, 0x08042209, 0x27008206, 0x06060505, 0x05060503, 0x06200c84, + 0x08200d83, 0x02250582, 0x04040204, 0x822e8403, 0x02022405, 0x83080205, 0x05032c0c, 0x07040503, 0x03050405, 0x82060302, 0x05062a43, 0x07040602, + 0x07050404, 0x201a8204, 0x821c8203, 0x04042618, 0x04070707, 0x20538208, 0x20348406, 0x82298306, 0x08092389, 0x06820602, 0x0e820620, 0x00820420, + 0x04219183, 0x82b18203, 0x82032002, 0x06062257, 0x20328206, 0x84058207, 0x82052076, 0x830f8212, 0x264e820b, 0x07070505, 0x820a0a06, 0x0907221d, + 0x82298205, 0x0909220d, 0x20b38207, 0x22ac8208, 0x84070604, 0x83052026, 0x8205209b, 0x05072215, 0x26028205, 0x05080805, 0x82070805, 0x27dd8202, + 0x0a070807, 0x06040509, 0x0d855282, 0x78820982, 0x07200282, 0x39820982, 0x0905062d, 0x06060708, 0x07060705, 0x85060906, 0x0608230b, 0x1d820507, + 0x1a850483, 0x05202182, 0x06212b84, 0x230a8408, 0x07090709, 0x06202082, 0x04333382, 0x09050905, 0x05020203, 0x01010202, 0x06030300, 0x82020407, + 0x04032200, 0x24c98203, 0x09020604, 0x2a0a8203, 0x08070504, 0x0507070a, 0x82050507, 0x09042133, 0x48820482, 0x0922e684, 0x00830502, 0x02030322, + 0x0825d182, 0x00080608, 0x82328209, 0x08b4413c, 0xd4840520, 0x07270e85, 0x02040504, 0x82040505, 0x83038202, 0x82062007, 0x82052000, 0x20598237, + 0x20508407, 0x09094106, 0x06211082, 0x823e8407, 0x22328205, 0x85030609, 0x03042100, 0xf4823d82, 0x83050621, 0x04022200, 0x22068300, 0x85040404, + 0x8203201d, 0x84072052, 0x22338231, 0x85050702, 0x822a85a1, 0x840220da, 0x820e8466, 0x0406231f, 0x10820507, 0x82030221, 0x8205204e, 0x823b8204, + 0x20d28502, 0x410f8803, 0x468809dd, 0x0420df89, 0x41069e41, 0x058205a4, 0x1b890620, 0x05221388, 0x01860203, 0x05050823, 0x20218202, 0x20978202, + 0x21718203, 0x01820605, 0x08820484, 0x82060321, 0x203d8901, 0x87208205, 0x23498522, 0x04050708, 0x08211f86, 0x21678a08, 0xfe820505, 0xdd840420, + 0x0a863e8a, 0x35851a83, 0x02212083, 0x912b8404, 0x068c4226, 0x89840682, 0x8b820620, 0x05050622, 0x08220582, 0x08840606, 0x91821982, 0x04200582, + 0x07260684, 0x03050505, 0x1c820503, 0x89431e84, 0x21948606, 0xa8820504, 0x05236e82, 0x83070804, 0x04052601, 0x02050302, 0x05e94102, 0x07285582, + 0x0b0a0506, 0x05060505, 0x09224382, 0x71820307, 0x08080522, 0x09210f84, 0x41068307, 0x06210938, 0x20018404, 0x8afa8205, 0x07314114, 0xcb8f0784, + 0x03020323, 0x842b9702, 0x83b38417, 0x20a48204, 0x21038204, 0x88820405, 0x82070421, 0x84062078, 0x4297840a, 0x8d870642, 0x5483a882, 0x7b8daa82, + 0x0620d384, 0x03215682, 0x20228205, 0x82ac8306, 0x070521aa, 0x11823782, 0x05225783, 0x03430205, 0x05022707, 0x02050404, 0xb0420402, 0x05004405, + 0x0728bd86, 0x07060506, 0x07050507, 0x06200482, 0x5a451f84, 0x00032807, 0x00140000, 0x84010003, 0x06042207, 0x2607826e, 0x008000f4, 0x82740006, + 0x02f10809, 0x7e000d00, 0xac00a000, 0xbf00ad00, 0xcf00c600, 0xef00e600, 0x0f01fe00, 0x25011101, 0x30012701, 0x5f015301, 0x7e016701, 0x8f017f01, + 0xa1019201, 0xf001b001, 0x1b02ff01, 0x59023702, 0xc702bc02, 0xdd02c902, 0x0103f302, 0x09030303, 0x23030f03, 0x8c038a03, 0xa1039203, 0xb903b003, + 0xce03c903, 0xd603d203, 0x2f042504, 0x4f044504, 0x6f046204, 0x86047904, 0xa9049f04, 0xba04b104, 0xd704ce04, 0xf504e104, 0x10050105, 0x011e1305, + 0x851e3f1e, 0xf31ef11e, 0x4d1ff91e, 0x0b200920, 0x15201120, 0x22201e20, 0x30202720, 0x3a203320, 0x44203c20, 0x7f207420, 0xaa20a420, 0xb120ac20, + 0xbd20ba20, 0x13210521, 0x22211621, 0x2e212621, 0x02225e21, 0x0f220622, 0x1a221222, 0x2b221e22, 0x60224822, 0xca256522, 0xc3f602ee, 0xfffe04fb, + 0xfffffdff, 0x83008300, 0x822020f5, 0x82a120f5, 0x00ae3cf5, 0x00c700c0, 0x00e700d0, 0x01ff00f0, 0x01120110, 0x01280126, 0x01540131, 0x86680160, + 0x01a022f5, 0x22f582af, 0x861802fa, 0x82c620f5, 0x82d820f5, 0x880020f5, 0x828420f5, 0x038e2cf5, 0x03a30393, 0x03ba03b1, 0x82d103ca, 0x003008f5, + 0x30042604, 0x50044604, 0x70046304, 0x88047a04, 0xaa04a004, 0xbb04b204, 0xd804cf04, 0xf604e204, 0x11050205, 0x3e1e001e, 0xa01e801e, 0xf41ef21e, + 0x002cf582, 0x10200a20, 0x17201320, 0x25202020, 0x3222f582, 0xf5883920, 0xa620a324, 0xf582ab20, 0xbc20b922, 0x5b20f58c, 0x1120f586, 0x6420f58a, + 0x0120f582, 0x0120f582, 0xfc20f582, 0x0132f582, 0xf6ff0000, 0xd801e4ff, 0xcc01c2ff, 0x0000c1ff, 0x0382bf01, 0x0382ba20, 0x0382b620, 0x0382b420, + 0x0382b220, 0x0382aa20, 0x16ffac2d, 0x05ff07ff, 0xebfef8fe, 0x8200ee01, 0x65fe3700, 0x230144fe, 0xd7fdd8fd, 0xb4fdc9fd, 0xa7fda8fd, 0x9dfda2fd, + 0x51828afd, 0xfdfffe22, 0x00222082, 0x0b820afd, 0xfefcde27, 0x0000fbfc, 0x205382fc, 0x214b82fc, 0x0b82a7fc, 0x0382a120, 0x03829920, 0x1f829120, + 0x03822820, 0x0b822520, 0x005e3008, 0xe5e2e500, 0xe553e5a2, 0xe5e7e47e, 0xe17de57c, 0xe173e172, 0xe100006f, 0xe16be16c, 0xe361e169, 0xe359e1a9, + 0xe150e1a1, 0x0017e121, 0x82f2e000, 0xed330803, 0xe5e0e6e0, 0x91e09ee0, 0x84e08fe0, 0x79e094df, 0xaadf4de0, 0x9edfacde, 0x96df9ddf, 0x87df93df, + 0x54df6bdf, 0xeddb51df, 0xf70ab713, 0xc302bb06, 0x8200c701, 0x8a9b83f1, 0x82e42003, 0x82ee200b, 0x821820e1, 0x8a322003, 0x82742003, 0x23028a17, + 0x7e017401, 0x0a8c0e8a, 0x836c0121, 0x2421820e, 0x01000090, 0x820b83a8, 0x00c02807, 0x00080200, 0x82300200, 0x82522003, 0x82622003, 0x828e2003, + 0x829a2003, 0x82be2003, 0x82ce2003, 0x85e22003, 0x21058d2b, 0x0f8dd202, 0x02210d85, 0x822f82c2, 0xad0d8503, 0x02da0a05, 0x0280027f, 0x02820281, + 0x00840283, 0x027b0281, 0x0290028f, 0x02920291, 0x00940293, 0x02830082, 0x02960295, 0x02980297, 0x00840099, 0x029a0285, 0x029c029b, 0x029e029d, + 0x0086009f, 0x02aa0287, 0x02ac02ab, 0x02ae02ad, 0x008800af, 0x02b00289, 0x02b202b1, 0x00b402b3, 0x007a028a, 0x028c008b, 0x028d007c, 0x02e402e3, + 0x02e602e5, 0x00e802e7, 0x02e9028e, 0x02eb02ea, 0x02ed02ec, 0x02ef02ee, 0x008f00f0, 0x02f10290, 0x02f302f2, 0x02f502f4, 0x00f702f6, 0x02920091, + 0x02f902f8, 0x02fb02fa, 0x00fd02fc, 0x03940093, 0x030d030c, 0x03110310, 0x02130312, 0x027e027d, 0x03a00285, 0x032c032b, 0x032e032d, 0x030b030a, + 0x000f030e, 0x03af00ae, 0x03b00086, 0x03880387, 0x00b10089, 0x039003b2, 0x00920391, 0x039303b3, 0x03b40094, 0x00960395, 0x009703b5, 0x009803b6, + 0x039903b7, 0x03b8009a, 0x00b9009b, 0x039c03ba, 0x039e039d, 0x03a0039f, 0x03a203a1, 0x03c400a3, 0x00a603a5, 0x00a403c5, 0x00c700c6, 0x00c900c8, + 0x00cb00ca, 0x00a703cc, 0x03ce00cd, 0x00ad03e4, 0x00ae03d2, 0x03af03d3, 0x03b103b0, 0x00d400b2, 0x03d600d5, 0x03e503b4, 0x03d700b5, 0x03d800b6, + 0x00b803b7, 0x00b903d9, 0x00db00da, 0x03ba03dc, 0x03dd00b3, 0x03bc03bb, 0x03be03bd, 0x03c003bf, 0x00de00c1, 0x03c203df, 0x00ea00c3, 0x00ec00eb, + 0x00c403ed, 0x00ef00ee, 0x00c503f0, 0x00f200f1, 0x03f400f3, 0x03f500c6, 0x00c803c7, 0x00c903f6, 0x03ca03f7, 0x01cb03e6, 0x01cc0302, 0x03cd0303, + 0x03cf03ce, 0x010401d0, 0x03060105, 0x03e703d1, 0x010701d2, 0x04090108, 0x03e80381, 0x011701e9, 0x01190118, 0x03ea031a, 0x03ed03eb, 0x012801ec, + 0x012a0129, 0x0180042b, 0x012d012c, 0x012f012e, 0x04820430, 0x01310183, 0x01330132, 0x03ee0334, 0x013501ef, 0x01370136, 0x04840438, 0x03f00385, + 0x047704f1, 0x03f20378, 0x048604f3, 0x017f0487, 0x044d014c, 0x037e047d, 0x03f503f4, 0x014e01f6, 0x0150014f, 0x01520151, 0x01540153, 0x04790455, + 0x0156017a, 0x04580157, 0x04000401, 0x04030402, 0x04050404, 0x01590106, 0x047b045a, 0x041b047c, 0x015b011c, 0x015d015c, 0x0488045e, 0x045f0189, + 0x018a041d, 0x0170016f, 0x04820181, 0x018b048c, 0x01760497, 0xb000009d, 0xb04b2c00, 0xb1585009, 0x598e0101, 0x85ff01b8, 0xb11d44b0, 0x5e5f0309, + 0x2c01b02d, 0x69452020, 0x6001b044, 0x2c02b02d, 0x212a01b0, 0x2c03b02d, 0x03b04620, 0x58524625, 0x8a205923, 0x64498a20, 0x2046208a, 0xb0646168, + 0x07842504, 0x65291882, 0x202f598a, 0x585300b0, 0x26058269, 0xb0215854, 0x881b5940, 0x5965260a, 0xb02d3a59, 0x82468304, 0x212d8231, 0x4082598a, + 0x40866a20, 0x12840782, 0xfd2f2908, 0x2c05b02d, 0x03b0204b, 0x51585026, 0x4480b058, 0x4440b01b, 0x21211b59, 0xc0b04520, 0xc0b05850, 0x59211b44, + 0x06b02d59, 0xab82a388, 0x18697d22, 0x0727ad85, 0x2a06b02c, 0x8508b02d, 0x58532941, 0xb01b40b0, 0x8a8a5900, 0x53294f83, 0xb0212358, 0x1b8a8a80, + 0x82c1828a, 0x200f845f, 0x220f8dc0, 0x8f0001b8, 0x8b402010, 0x03b02710, 0x01b84525, 0x4a825080, 0x23220682, 0x10831b21, 0x23212323, 0x29a18221, + 0xb02d4459, 0x534b2c09, 0xa2824558, 0xa2822120, 0xb02c0a2a, 0xb02d452c, 0x2db02c0b, 0x0c3f0682, 0x0127b12c, 0x538a2088, 0x0040b958, 0xb8630004, + 0x54880008, 0x2c00b958, 0x5970e803, 0x8223b01b, 0x882024ac, 0x880010b8, 0x34e58313, 0x40b02c0d, 0x0020b888, 0x2db1585a, 0xb91b4400, 0xe8032d00, + 0x2e5a8244, 0x00b02b0c, 0x01b2002b, 0x012b020e, 0x82010fb2, 0x0fb73105, 0x1b25303a, 0x2b080010, 0x3801b700, 0x111a242e, 0xb7260a82, 0x32404e02, + 0x09831523, 0x3b480325, 0x8314212e, 0x88042009, 0x30052513, 0x0e161f28, 0x06251383, 0x2d3f5163, 0x2209831b, 0x86344007, 0x5b08253b, 0x19293a4a, + 0x09251383, 0x3a4e6483, 0x25098323, 0x4c62770a, 0x09832136, 0x77910b23, 0x2513855c, 0x4b60760c, 0x13831d36, 0x242c0d25, 0x830c141c, 0x430e2509, + 0x121f2b37, 0x00240982, 0x070e10b2, 0x202cac82, 0x18697d45, 0x1480b244, 0xb0b27301, 0x50230483, 0x83740114, 0xb274230e, 0x13821c3f, 0x04835f20, + 0x04837f20, 0x821c2f21, 0x834f2018, 0x836f2004, 0x838f2004, 0x83af2004, 0x83ff2004, 0x1c1f2304, 0x31837501, 0x82b27521, 0xb2752131, 0x75233182, + 0x82200fb2, 0x206f2140, 0x7f201882, 0xef200983, 0x1f210483, 0x20458220, 0x2004835f, 0x2004838f, 0x200483cf, 0x200483ff, 0x2127833f, 0x3183222f, + 0x2f210483, 0x2009822a, 0x2804823f, 0x002a0000, 0x009100cc, 0x0803829e, 0x7200ec4b, 0x7d00b200, 0x5f005600, 0x60004e00, 0xaa000401, 0x0000c400, + 0x60fe1400, 0x9b021400, 0x39ff1000, 0x97fe0d00, 0x21031200, 0x3a040b00, 0x8d041400, 0xb0051000, 0x18061400, 0xc0061500, 0x5b021000, 0x04071200, + 0xde060500, 0x07eb4600, 0xba000f28, 0x01000300, 0x47820904, 0x03825e20, 0x01240b85, 0x5e001a00, 0x02241786, 0x78000e00, 0x03200b86, 0x0420178a, + 0x05240b8a, 0x86002600, 0x06202386, 0xac201782, 0x07240b86, 0xc6004000, 0x09240b86, 0x06010c00, 0x0b240b86, 0x12011400, 0x0c240b86, 0x26012600, + 0x0d240b86, 0x4c015c00, 0x0e240b86, 0xa8015400, 0x10200b86, 0xfc203b82, 0x113e0b86, 0x08020c00, 0x6f004300, 0x79007000, 0x69007200, 0x68006700, + 0x20007400, 0x30003200, 0x01823100, 0x47002022, 0x6f201d82, 0x6c221782, 0x17826500, 0x6e004926, 0x2e006300, 0x41220982, 0x01826c00, 0x52002022, + 0x73203588, 0x52201582, 0x73202582, 0x72220382, 0x05827600, 0x29826420, 0x3f825220, 0x03826220, 0x03827420, 0x4d002022, 0x69241584, 0x6d007500, + 0x65203982, 0x75205782, 0x61204582, 0x56207b82, 0x73203584, 0x6f204d82, 0x81836382, 0x7f822e20, 0x37003324, 0x8f883b00, 0x33823720, 0x87006f21, + 0x8e2d204d, 0x2019894d, 0x83458220, 0x8261208d, 0x82742039, 0x0061225b, 0x215d8264, 0x6783006d, 0x13826b20, 0x66006f22, 0xd98b0582, 0xe78c2e20, + 0x6320198d, 0x6d24b982, 0x68004300, 0x69244982, 0x74007300, 0x61205d82, 0xdb85a384, 0x17826520, 0x17827420, 0x4c20b783, 0x63201b82, 0x6e206b82, + 0x65200f82, 0x20207582, 0x6e20e982, 0x72207d84, 0x68208b84, 0x20241b82, 0x70004100, 0x63208b82, 0x65205182, 0x338d1582, 0x11822c20, 0x20130b41, + 0x202d8230, 0x247b8274, 0x003a0070, 0x2101822f, 0x01830077, 0x47822e20, 0x2e204b89, 0x7222a982, 0x1d826700, 0x878c6c20, 0x11827320, 0x49004c22, + 0x452ec382, 0x53004e00, 0x2d004500, 0x2e003200, 0x4f413000, 0x0b9b410c, 0x51000021, 0xff210627, 0x20bd826a, 0x2b009200, 0x00020001, 0xff020008, + 0x000f00ff, 0x0e200b83, 0x02212385, 0x24178228, 0x00250059, 0x2215823e, 0x825e0045, 0x00792205, 0x22058279, 0x82810081, 0x00832205, 0x22058283, + 0x82860086, 0x00892205, 0x22058289, 0x8296008b, 0x00982205, 0x2205829d, 0x82a400a4, 0x00a82205, 0x227d82ad, 0x82b100b1, 0x00ba220b, 0x220582bb, + 0x82bf00bf, 0x00c12205, 0x220582c1, 0x82c300c3, 0x00c72205, 0x220582c7, 0x82cb00cb, 0x00cd2205, 0x220582ce, 0x82d100d0, 0x00d32205, 0x220582d3, + 0x82de00da, 0x00e12205, 0x220582e1, 0x82e500e5, 0x00e72205, 0x220582e9, 0x82fb00eb, 0x00fd2205, 0x280582fd, 0x000101ff, 0x01030101, 0x22058203, + 0x82090108, 0x01162205, 0x2205821a, 0x821c011c, 0x01202205, 0x28058222, 0x00250124, 0x012a0103, 0x220b822b, 0x82340133, 0x01362205, 0x22058236, + 0x823c013b, 0x01412205, 0x22058244, 0x82480147, 0x014b2205, 0x2205824d, 0x82510151, 0x01542205, 0x21058258, 0xfb82015d, 0x01620123, 0x220b8262, + 0x82640164, 0x01682205, 0x22058268, 0x826c016a, 0x016e2205, 0x2205826e, 0x82700170, 0x01ba2205, 0x286582ba, 0x00c101bb, 0x01d20102, 0x221182e6, + 0x82ea01ea, 0x01f32205, 0x220582f3, 0x82f501f5, 0x01fc2505, 0x020100fe, 0x05822082, 0x82020321, 0x070223b3, 0x0b820702, 0x0b020922, 0x11220582, + 0x05821102, 0x18021622, 0x1a220582, 0x05821a02, 0x28022822, 0x2b210582, 0x23b98202, 0x2d022d02, 0x30220b82, 0x05823302, 0x63025f22, 0x7a220582, + 0x0582e202, 0x8b03e528, 0x8d030100, 0x0582a403, 0xb203a622, 0xb4220582, 0x0582bd03, 0xda03bf22, 0xde220582, 0x0582de03, 0xe703e022, 0xe9220582, + 0x0582eb03, 0xf203ee22, 0xf4280582, 0x01007c04, 0x7f047f04, 0x82220582, 0x05828304, 0x86048522, 0x88210582, 0x234d8204, 0xd0049504, 0xd2220b82, + 0x0582f104, 0xfa04f322, 0xfc2a0582, 0x0100fd04, 0x0d050705, 0x01820100, 0x00000224, 0x03820c00, 0x0b822c20, 0xa8000e22, 0xa9240182, 0xaa00a900, + 0xab2e0182, 0xac00ab00, 0x2401ac00, 0x26012501, 0x1f822701, 0x7900052a, 0xad00a400, 0xba01ad00, 0x01203182, 0x20080382, 0x0032000a, 0x4404004c, + 0x00544c46, 0x7279631a, 0x671a006c, 0x006b6572, 0x74616c1a, 0x001a006e, 0x36238204, 0x00ffff00, 0x00000002, 0x63020001, 0x00707370, 0x72656b0e, + 0x8414006e, 0x20048211, 0x22858500, 0x82100206, 0x82002009, 0x82082003, 0x000a2603, 0x00240005, 0x24098248, 0x000800fa, 0x082d820a, 0x1600152a, + 0x18001700, 0x1a001900, 0x1c001b00, 0x25001d00, 0x27002600, 0x29002800, 0x2b002a00, 0x2d002c00, 0x2f002e00, 0x31003000, 0x40089382, 0x00340033, + 0x00360035, 0x00380037, 0x003a0039, 0x003c003b, 0x003e003d, 0x00670065, 0x00830081, 0x008c0084, 0x0091008f, 0x00b10093, 0x00b300b2, 0x00b500b4, + 0x00b700b6, 0x00b900b8, 0x00d200ba, 0x05f34ad3, 0x00d70025, 0x4ad900d8, 0x430805e5, 0xde00dd00, 0xe000df00, 0xe200e100, 0xe400e300, 0xe600e500, + 0xe800e700, 0x2f01e900, 0x35013301, 0x39013701, 0x41013b01, 0x45014301, 0x4b014901, 0x58014c01, 0x97015901, 0xa2019d01, 0x7a02a501, 0x7d027b02, + 0x330b8f4c, 0x86028502, 0x88028702, 0x8a028902, 0x8c028b02, 0x8e028d02, 0x4c0b9f4c, 0x7b08099b, 0xb802b602, 0xbc02ba02, 0xc002be02, 0xc402c202, + 0xc802c602, 0xcc02ca02, 0xd002ce02, 0xd402d202, 0xd802d602, 0xdc02da02, 0xe002de02, 0xe302e202, 0xe702e502, 0xeb02e902, 0xef02ed02, 0xf302f102, + 0xf802f502, 0xfc02fa02, 0x0003fe02, 0x04030203, 0x08030603, 0x0c030a03, 0x10030e03, 0x14031203, 0x18031603, 0x1c031a03, 0x20031e03, 0x24032203, + 0x27032503, 0x2b032903, 0x86032d03, 0x29056d4c, 0x8b038a03, 0x8e038c03, 0x734c8f03, 0x93033a05, 0x95039403, 0x97039603, 0x99039803, 0x9b039a03, + 0x9d039c03, 0xae03ad03, 0x06334c03, 0x03b3032f, 0x03b503b4, 0x03b703b6, 0x03b903b8, 0x0d1d4cba, 0xc2034b08, 0xd503d303, 0xd903d703, 0xf003ee03, + 0x0704f203, 0x13040d04, 0x82047d04, 0x07058604, 0x02000905, 0x02000000, 0x7a410a00, 0xee030100, 0x00000400, 0xd007f201, 0x183c183c, 0x6008fe07, + 0x083f503e, 0x2e411e3c, 0x6608d43e, 0x0182763f, 0x603f1222, 0x34080582, 0x3f2e4176, 0x0c040ca2, 0x40ec3fd2, 0x3cf640be, 0x41da3d30, 0x3e480d14, + 0x3cc03fb2, 0x0e8e0dda, 0x3fce0ec4, 0x3e983f98, 0x3fc03fe2, 0x40d00fda, 0x3c3610dc, 0x2a05828a, 0x41c03f50, 0x3d96102e, 0x82503e18, 0x50360853, + 0x16121811, 0xfa131813, 0xdc409c14, 0x983fa214, 0x7a198817, 0xb21a981a, 0xbe1ab81a, 0xbe1db81d, 0x2e1ef81d, 0x4220b81e, 0xe2230c22, 0x3025763f, + 0x303cda26, 0x7f833c29, 0x84903c21, 0x7638088d, 0xc02b122a, 0xee3c763f, 0x702daa2c, 0x642e022e, 0xe43c4a2f, 0x8a3cdc2f, 0xdc30b230, 0xc03fb632, + 0x7e364036, 0x8a39bc37, 0x4638c03f, 0xfe38d438, 0x8a395439, 0xe23e503e, 0xdc2eb582, 0xc03fb039, 0xe43c183d, 0x8a3c303c, 0x0184123f, 0x0b847620, + 0x4121e782, 0x2517852e, 0xda39183c, 0x0183183c, 0x3b6a412f, 0x41b23b64, 0x410e3c64, 0x4152414c, 0x20038264, 0x8209824c, 0x003c2703, 0x1e3c5241, + 0x01852e41, 0x82ec3f21, 0x8950205f, 0x1e3c2303, 0x0185d43e, 0x3d41b185, 0x252b8505, 0xda3d2e41, 0x018bb23e, 0x85da3c21, 0x983f2301, 0x0187e23e, + 0x40dc4023, 0x204f82dc, 0x210387b2, 0x01851e3c, 0x3e2e4125, 0x8fda3cd4, 0x205f8203, 0x82698998, 0x3f6021d5, 0x76210185, 0x8517833f, 0x82982003, + 0x87e2203b, 0xda3f2103, 0xec210184, 0x2901823f, 0xda3df640, 0xda3ddc40, 0x01841441, 0xe7826420, 0xe9826a20, 0x038a5220, 0x03851383, 0x64241585, + 0x0e3c4c41, 0x2d820185, 0xa9823184, 0xe785d420, 0x5026df82, 0xd43e083f, 0x93841441, 0x15851220, 0x3fa23f2b, 0x3cda3dec, 0x3d763f30, 0x82e983da, + 0x3ee224df, 0x86183dd4, 0x3c122323, 0x35823e90, 0x3e183d22, 0x3f294586, 0x3f1e3ca2, 0x3e303cec, 0x2eef82b2, 0x40c03fe2, 0x3c8a3cdc, 0x40e43cda, + 0x83f640dc, 0x41b38301, 0x418205a5, 0x7d829820, 0xd43eb226, 0xbe40da3c, 0x1e202782, 0x3f201b83, 0x4106d741, 0x1d820845, 0x81823f82, 0x418a3c26, + 0x3ee23e2e, 0x3c215382, 0x862d8290, 0x21278803, 0x75413e50, 0x41139c08, 0x97411287, 0x20f5850b, 0x0871413e, 0x850b7d41, 0x0575417f, 0x84dc4021, + 0x3dec2ead, 0x3fe43c18, 0x3dee3c98, 0x3d123f18, 0x21d389da, 0x2d83763f, 0x3fda3f29, 0x41c03f08, 0x832e412e, 0x123f2119, 0x60200182, 0x76220984, + 0x1382983f, 0xc03fa222, 0xec202182, 0x0384fd83, 0x1441f622, 0xb1422b82, 0x426a2007, 0x6a2606bd, 0xa5000200, 0x01820400, 0x06000022, 0x01240182, + 0x0c000b00, 0x13221382, 0x13821300, 0x2a002528, 0x2c000500, 0x15822d00, 0x36002f26, 0x38000d00, 0x15340182, 0x3f003a00, 0x45001600, 0x1c004600, + 0x4a004900, 0x4c001e00, 0x20220182, 0x01824f00, 0x51002128, 0x22005400, 0x01825600, 0x58002622, 0x27280182, 0x5d005a00, 0x5f002800, 0x2c220182, + 0x01828a00, 0x96002d22, 0x2e220182, 0x01829d00, 0xb1002f2e, 0x3000b500, 0xb900b700, 0xbb003500, 0x38220182, 0x0182bd00, 0xc0003924, 0x6982c100, + 0xc300c326, 0xc5003c00, 0x3d280182, 0xce00c700, 0xd2003e00, 0x462e0182, 0xde00d400, 0xe0004700, 0x5200ef00, 0x0182f100, 0x00625109, 0x00f800f6, + 0x00fb0063, 0x006600fc, 0x000001fe, 0x01030168, 0x016b0005, 0x000a010a, 0x010d016e, 0x016f000d, 0x001a0118, 0x01220170, 0x01730022, 0x0030012e, + 0x01330174, 0x01770035, 0x00370137, 0x0139017a, 0x017b0039, 0x003b013b, 0x0143017c, 0x017d0044, 0x00540154, 0x0156017f, 0x01800056, 0x00580158, + 0x015c0181, 0x0182005e, 0x00850184, 0x01870185, 0x01870089, 0x00d801d8, 0x01da018a, 0x018b00db, 0x00dd01dd, 0x01e0018d, 0x018e00e1, 0x00ed01eb, + 0x01ff0190, 0x029300ff, 0x0010020e, 0x02300294, 0x02970030, 0x00330233, 0x02450298, 0x02990045, 0x00480247, 0x027a029a, 0x029c007b, 0x007d027d, + 0x027f029e, 0x029f0094, 0x00a00299, 0x02a202b5, 0x02bd00a5, 0x00af02aa, 0x02b402c1, 0x02c700bc, 0x00be02be, 0x02c002d0, 0x02d100c0, 0x00c202c2, + 0x02c402d2, 0x02d300c4, 0x00cf02c6, 0x02d802d4, 0x02de00da, 0x00dc02dc, 0x02de02e1, 0x02e200de, 0x00e002e0, 0x02e202e3, 0x02e400e2, 0x00e702e7, + 0x02e902e5, 0x02e600e9, 0x00eb02eb, 0x02ed02e7, 0x02e800ed, 0x00ef02ef, 0x02f102e9, 0x02ea00fd, 0x00ff02ff, 0x030103f7, 0x03f80001, 0xcb090082, + 0x0e03f900, 0xfa000e03, 0x10031003, 0x1203fb00, 0xfc001203, 0x20032003, 0x2203fd00, 0xfe002503, 0x27032703, 0x29030201, 0x03012903, 0x38032f03, + 0x43030401, 0x0e014703, 0x4f034d03, 0x54031301, 0x16015403, 0x69036503, 0x6d031701, 0x1c016f03, 0x78037803, 0x86031f01, 0x20018b03, 0x9d038e03, + 0xa0032601, 0x3601a003, 0xa403a403, 0xa6033701, 0x3801a603, 0xaa03aa03, 0xad033901, 0x3a01ae03, 0xb103b003, 0xb3033c01, 0x3e01b903, 0xbd03bb03, + 0xbf034501, 0x4801c403, 0xc703c603, 0xc9034e01, 0x5001cc03, 0xd303d203, 0xd5035401, 0x5601d503, 0xd703d703, 0xd9035701, 0x5801dc03, 0xe403df03, + 0xe6035c01, 0x6201e603, 0xeb03ea03, 0xf0036301, 0x6501f003, 0xfb03f203, 0xfe036601, 0x7001ff03, 0x04040104, 0x0b047201, 0x76010c04, 0x10041004, + 0x12047801, 0x79011804, 0x46041e04, 0x48048001, 0xa9014804, 0x57044a04, 0x5f04aa01, 0xb8015f04, 0x75047004, 0x7704b901, 0xbf017704, 0x7c047b04, + 0x7f04c001, 0xc2017f04, 0x82048104, 0x8404c301, 0xc5018404, 0x86048604, 0x9704c601, 0xc7019b04, 0x9d049d04, 0x9f04cc01, 0xcd01a004, 0xa204a204, + 0xa604cf01, 0xd001a804, 0xaa04aa04, 0xac04d301, 0xd401ae04, 0xb004b004, 0xb204d701, 0xd801b204, 0xba04b404, 0xbc04d901, 0xe001bc04, 0xbf04bf04, + 0xc204e101, 0xe201c604, 0xc804c804, 0xca04e701, 0xe801cb04, 0xcf04cf04, 0xd204ea01, 0xeb01d204, 0xd804d804, 0xdd04ec01, 0xed01dd04, 0xe804e804, + 0xea04ee01, 0xef01ea04, 0xf104f104, 0xf504f001, 0xf101f504, 0x38000b00, 0xd200c4ff, 0xd6240382, 0x3901c4ff, 0x45240382, 0x0e03c4ff, 0x10200382, + 0x12200382, 0xc1240382, 0x7704c4ff, 0xbf200382, 0x183a2382, 0x14003a00, 0x26003b00, 0x16003d00, 0x14001901, 0x16009902, 0x26002003, 0x07822203, + 0x03822420, 0x03828b20, 0x03829a20, 0x03829d20, 0x1782d320, 0x0382d520, 0x0382d720, 0x0f82d920, 0x1400ea28, 0x1600f203, 0x03827004, 0x03827220, + 0x03827420, 0x03828620, 0x1400c224, 0x0382c404, 0x5782c620, 0x1300012c, 0xe70008ff, 0xeefe1000, 0x03821200, 0x40ff2528, 0x30ff2e00, 0x77823800, + 0xdeff4528, 0xebff4700, 0x03824800, 0x03824920, 0x03824b20, 0x03825320, 0x03825520, 0xe6ff562c, 0xeaff5900, 0xe8ff5a00, 0x03825d00, 0x13829420, + 0x03829920, 0x13829b20, 0x4382b220, 0x0382b420, 0x0f82bb20, 0x1b82bd20, 0x0782c820, 0x0382c920, 0x1b82cb20, 0x5782d220, 0x0382d620, 0xebfff724, + 0x03820301, 0x40ff0d24, 0x07821801, 0xe8ff1a24, 0x07821e01, 0x03822220, 0x14003924, 0x07824201, 0x07824520, 0x07826020, 0x03826120, 0x03826b20, + 0xeefe8624, 0x03828a01, 0x03828e20, 0x03828f20, 0xc0ffeb28, 0xc0ffed01, 0x03823302, 0x40ff7f24, 0x03828002, 0x03828120, 0x03828220, 0x03828320, + 0x03828420, 0x03828520, 0xdeff9a24, 0x03829b02, 0x03829c20, 0x03829d20, 0x03829e20, 0x03829f20, 0x0382a020, 0xebffa124, 0x0382a202, 0x0382a320, + 0x0382a420, 0x0382a520, 0x0382ab20, 0x0382ac20, 0x0382ad20, 0x0382ae20, 0x0382af20, 0xeaffb024, 0x0382b102, 0x0382b220, 0x0382b320, 0xe8ffb424, + 0x0382b502, 0x5f82b620, 0x4782b720, 0x0782b820, 0x0782b920, 0x0782ba20, 0x0782bb20, 0x3382bd20, 0x0382bf20, 0x0382c120, 0x0382c320, 0x0382c520, + 0x0382c720, 0x0382c920, 0x0382cb20, 0x0382cd20, 0x0382cf20, 0x0382d120, 0x0382d320, 0x0382d520, 0x0382d720, 0x30ffe524, 0x0782f902, 0x0382fb20, + 0xebfffd28, 0x14000e03, 0x03821003, 0x03821220, 0xeaff1524, 0x03821703, 0x03821920, 0x03821b20, 0x03821d20, 0x03821f20, 0xe8ff2328, 0xc0ff3203, + 0x03823303, 0x03823420, 0x03823520, 0x03823620, 0x03823720, 0x03823820, 0x03824d20, 0x03824e20, 0x03824f20, 0x40ff8624, 0x03828e03, 0x5b829e20, + 0x3b82a220, 0x0321f382, 0x203f82a6, 0x200b82a9, 0x201382aa, 0x230782ab, 0x0330ffb2, 0x0321d782, 0x247382c1, 0x03deffc3, 0x201782c4, 0x200382c6, + 0x200382c8, 0x202b82c9, 0x200782cb, 0x200782d2, 0x200382da, 0x204b82e2, 0x202382e3, 0x201382e6, 0x200f82eb, 0x200782ec, 0x200382f1, 0x200b82f3, + 0x201b82f8, 0x201b82f9, 0x200782fa, 0x240782fb, 0x04ebffff, 0x20038201, 0x20038202, 0x2003820c, 0x2003820e, 0x24038210, 0x04e8ff14, 0x20038216, + 0x20038218, 0x280f821d, 0x0440ff1e, 0x04deff1f, 0x20078220, 0x20078221, 0x20078222, 0x20078223, 0x20078224, 0x20078225, 0x20078226, 0x20078227, + 0x20078228, 0x20078229, 0x2007822a, 0x2007822b, 0x2007822c, 0x2007822d, 0x2007822e, 0x2007822f, 0x20078230, 0x20078231, 0x20078232, 0x20078233, + 0x20078234, 0x20078235, 0x20638237, 0x20038239, 0x2003823b, 0x2003823d, 0x2003823f, 0x20038241, 0x20038243, 0x20038245, 0x2003824b, 0x2003824d, + 0x2003824f, 0x20038251, 0x20038253, 0x20038255, 0x20038257, 0x20038259, 0x2003825b, 0x2003825d, 0x2003825f, 0x24038261, 0x04eaff63, 0x20038265, + 0x20038267, 0x20038269, 0x2003826b, 0x2003826d, 0x2003826f, 0x20d38271, 0x20038273, 0x24038275, 0x04140077, 0x20838299, 0x2083829a, 0x2037829c, + 0x200382a0, 0x202382a4, 0x200782a9, 0x200382ab, 0x201f82bf, 0x202782c3, 0x240382c5, 0x04c0ffcb, 0x360382d2, 0x00c0ffea, 0xff380033, 0xff3a00df, + 0xff3b00e4, 0xff3d00ec, 0x82d200dd, 0xffd6280f, 0xff1901df, 0x823901e4, 0x82452007, 0x00eb2803, 0x00ed010e, 0x8233020e, 0xff992803, 0xff0e03dd, + 0x821003df, 0x82122003, 0xff202403, 0x822203ec, 0x82242013, 0x00322303, 0x2382030e, 0x82340321, 0x82352007, 0x82362003, 0x82372003, 0x82382003, + 0x824d2003, 0x824e2003, 0x824f2003, 0x828b2003, 0x829a202b, 0x829d2003, 0x82c12003, 0x82d32043, 0x82d52043, 0x82d72003, 0x82d92003, 0xffea2813, + 0xfff203e4, 0x827004dd, 0x82722003, 0x82742003, 0xff772403, 0x828604df, 0x82bf2007, 0xffc22407, 0x82c404e4, 0xffc62803, 0x00cb04ec, 0x82d2040e, + 0x00ea2403, 0x821d000e, 0x82ce20cd, 0x82ed20cd, 0x82d020c9, 0x00ce24c9, 0x82ceffd6, 0x82ed20c9, 0x01ce28c9, 0x02ceff45, 0x82d0ff99, 0x82ce20bd, + 0x03ce24bd, 0x82ceff12, 0x03d022b9, 0x20138224, 0x2003828b, 0x2003829a, 0x2003829d, 0x201782c1, 0x220782d9, 0x82edffea, 0x82d02085, 0x04d02685, + 0x04d0ff72, 0x22038274, 0x82ceff77, 0x04d02285, 0x220782bf, 0x82edffc2, 0x00ed2c85, 0xff2e0011, 0xff3900ee, 0x829502ee, 0x82962003, 0x82972003, + 0x82982003, 0xffe52403, 0x821403ee, 0x82162003, 0x82182003, 0x821a2003, 0x821c2003, 0x821e2003, 0xffb22403, 0x826204ee, 0x82642003, 0x82c12003, + 0x004d263f, 0x00100006, 0x2c03820b, 0x0014000d, 0x00120041, 0x00e8ff47, 0x20038248, 0x20038249, 0x2003824b, 0x24038255, 0x00130061, 0x20078294, + 0x20038299, 0x200382bb, 0x200382c8, 0x240382c9, 0x01e8fff7, 0x20038203, 0x2003821e, 0x20038222, 0x20038242, 0x20038260, 0x20038261, 0x2403826b, + 0x01100084, 0x20038285, 0x20038287, 0x28038288, 0x02100089, 0x02e8ffa1, 0x200382a2, 0x200382a3, 0x200382a4, 0x200382a5, 0x200382bd, 0x200382bf, + 0x200382c1, 0x200382c3, 0x200382c5, 0x200382c7, 0x200382c9, 0x200382cb, 0x200382cd, 0x200382cf, 0x200382d1, 0x200382d3, 0x240382d5, 0x03e8ffd7, + 0x2003829e, 0x820382c4, 0xcb03218f, 0xdb240782, 0xdc031000, 0xdf200382, 0xe6200382, 0xec200f82, 0xf1200382, 0xff240382, 0x0104e8ff, 0x02200382, + 0x0e200382, 0x1d200382, 0x37200382, 0x39200382, 0x3b200382, 0x3d200382, 0x3f200382, 0x41200382, 0x43200382, 0x45200382, 0x59200382, 0x5b200382, + 0x5d200382, 0xcf820382, 0x829c0421, 0x82a92007, 0x82ab2003, 0x000230f7, 0x01d6fff6, 0x0098ff85, 0xff470040, 0x824800ec, 0x82492003, 0x824b2003, + 0x82552003, 0x82942003, 0x82992003, 0x82bb2003, 0x82c82003, 0x82c92003, 0xfff72403, 0x820301ec, 0x821e2003, 0x82222003, 0x82422003, 0x82602003, + 0x82612003, 0xff6b2403, 0x82a102ec, 0x82a22003, 0x82a32003, 0x82a42003, 0x82a52003, 0x82bd2003, 0x82bf2003, 0x82c12003, 0x82c32003, 0x82c52003, + 0x82c72003, 0x82c92003, 0x82cb2003, 0x82cd2003, 0x82cf2003, 0x82d12003, 0x82d32003, 0x82d52003, 0xffd72403, 0x829e03ec, 0x82c42003, 0x217b8203, + 0x0782cb03, 0x0382e620, 0x0382ec20, 0x0382f120, 0xecffff24, 0x03820104, 0x03820220, 0x03820e20, 0x03821d20, 0x03823720, 0x03823920, 0x03823b20, + 0x03823d20, 0x03823f20, 0x03824120, 0x03824320, 0x03824520, 0x03825920, 0x03825b20, 0x03825d20, 0x0421af82, 0x2007829c, 0x200382a9, 0x26d782ab, + 0xff530019, 0x821801e2, 0x00852803, 0xffab0218, 0x82ac02e2, 0x82ad2003, 0x82ae2003, 0x82af2003, 0x82f92003, 0x82fb2003, 0xfffd2403, 0x82a403e2, + 0x82aa2003, 0xffc62403, 0x820c04e2, 0x82102003, 0x824b2003, 0x824d2003, 0x824f2003, 0x82512003, 0x214f8203, 0x07825504, 0x03825720, 0x03825f20, + 0xe2ffa02e, 0x10000600, 0x120084ff, 0x860184ff, 0x8a200382, 0x8e200382, 0x8f200382, 0x11221382, 0x85822e00, 0xf9823920, 0x03829520, 0x03829620, + 0x03829720, 0x03829820, 0xed82e520, 0x03821420, 0x03821620, 0x03821820, 0x03821a20, 0x03821c20, 0x03821e20, 0xbd82b220, 0x03826220, 0x03826420, + 0x3f82c120, 0x06002026, 0x0b00f2ff, 0x5a240382, 0x5d00f3ff, 0xbd200382, 0xf62c0382, 0x1a01f5ff, 0x8401f3ff, 0x8501f2ff, 0x87200382, 0x88200382, + 0x892c0382, 0xb402f2ff, 0xb502f3ff, 0x2303f3ff, 0xa6200382, 0xc9200382, 0xd2200382, 0xda200382, 0xdb240382, 0xdc03f2ff, 0xdf200382, 0xeb200382, + 0xf3240f82, 0x1404f3ff, 0x16200382, 0x18200382, 0x71200382, 0x73200382, 0x75200382, 0xc3200382, 0xc5200382, 0x3f226b82, 0x05822700, 0x03822b20, + 0x03823320, 0x03823520, 0x03828320, 0x03829320, 0x03829820, 0x0382b320, 0x0d00c424, 0x8d82d300, 0x03820820, 0x03821720, 0x03821b20, 0x03821d20, + 0x03821f20, 0x03822120, 0x03824120, 0x95826a20, 0x03824520, 0x03824620, 0x03824820, 0x03824920, 0x03828620, 0x03829020, 0x03829120, 0x03829220, + 0x02215382, 0x20078294, 0x200382bc, 0x200382be, 0x200382c0, 0x200382c2, 0x820382d0, 0xd40221c1, 0xd6200782, 0xf8200382, 0xfa200382, 0xfc200382, + 0x2d20c182, 0x8a200382, 0x97200382, 0xbd200382, 0x33820382, 0x82ed0321, 0x82f02007, 0x820b20bd, 0x820d2003, 0x820f2003, 0x824a2003, 0x824c2003, + 0x824e2003, 0x82502003, 0x82522003, 0x82542003, 0x82562003, 0x82582003, 0x825a2003, 0x825c2003, 0x825e2003, 0x82602003, 0x829f2003, 0x82b82003, + 0x824020db, 0x00e626fd, 0x00e6ff2b, 0x20038233, 0x20038235, 0x20038283, 0x20038293, 0x20038298, 0x2c0382b3, 0x00c2ffb8, 0x001000c4, 0x01e6ffd3, + 0x20038208, 0x20038217, 0x2003821b, 0x2003821d, 0x2003821f, 0x20038221, 0x24038241, 0x02e6ff6a, 0x20038245, 0x20038246, 0x20038248, 0x20038249, + 0x20038286, 0x20038290, 0x20038291, 0x82038292, 0x94022157, 0xbc200782, 0xbe200382, 0xc0200382, 0xc2200382, 0xd0200382, 0xd2200382, 0xd4200382, + 0xd6200382, 0xf8200382, 0xfa200382, 0xfc240382, 0x2d03e6ff, 0x8a200382, 0x97200382, 0xbd200382, 0x33820382, 0x82ed0321, 0xfff02407, 0x820b04e6, + 0x820d2003, 0x820f2003, 0x824a2003, 0x824c2003, 0x824e2003, 0x82502003, 0x82522003, 0x82542003, 0x82562003, 0x82582003, 0x825a2003, 0x825c2003, + 0x825e2003, 0x82602003, 0x829f2003, 0x82b82003, 0x00382edf, 0x00e4ff25, 0x00d2ff3c, 0x00d3ff3d, 0x200b82b2, 0x2c0382b4, 0x00e2ffc4, 0x01d2ffda, + 0x01e4ff0d, 0x20078233, 0x28038243, 0x02d2ff5d, 0x02e4ff7f, 0x20038280, 0x20038281, 0x20038282, 0x20038283, 0x20038284, 0x24038285, 0x02d3ff99, + 0x200782b6, 0x280382b8, 0x03e4ffba, 0x03d3ff22, 0x20038224, 0x200b8286, 0x2007828b, 0x2007828e, 0x2407829a, 0x03d2ff9b, 0x2007829d, 0x200f82b6, + 0x200b82c2, 0x200b82d9, 0x200b82e2, 0x200782f2, 0x200f82f5, 0x280b82f8, 0x04e4fffa, 0x04d2ff03, 0x2007821e, 0x20038220, 0x20038222, 0x20038224, + 0x20038226, 0x20038228, 0x2003822a, 0x2003822c, 0x2003822e, 0x20038230, 0x20038232, 0x24038234, 0x04d3ff70, 0x20038272, 0x20038274, 0x20038286, + 0x26cb8299, 0xff100028, 0x82120046, 0xff252203, 0x22e182cd, 0x82b400cd, 0xffc72207, 0x26dd82f2, 0xff8601cd, 0x828a0146, 0x828e2003, 0xff8f2203, + 0x20e18246, 0x26e182cd, 0xff8102cd, 0x828202cd, 0x82832003, 0x82842003, 0x82852003, 0x82b62003, 0x82b82003, 0xffba2403, 0x828603cd, 0x828e2003, + 0x82b62003, 0x82e22003, 0x82f82003, 0xfffa2203, 0x22b182cd, 0x822004cd, 0x82222007, 0x82242003, 0x82262003, 0x82282003, 0x822a2003, 0x822c2003, + 0x822e2003, 0x82302003, 0x82322003, 0x82342003, 0x82992003, 0x00012c8b, 0x000e00c4, 0xff4700b9, 0x824800dc, 0x82492003, 0x824b2003, 0xff512403, + 0x825200c1, 0xff532403, 0x825400d6, 0x82552007, 0xff592813, 0xff5a00dd, 0x825d00e1, 0x82942003, 0x8299200f, 0x829b2003, 0x82bb2013, 0x82bd2007, + 0xffbf2413, 0x82c100e6, 0xffc2302b, 0xffc300eb, 0xffc500e9, 0xffc600f0, 0x82c800e7, 0x82c9201f, 0xffca2403, 0x82cb00e3, 0xffcc2c2f, 0xffcd00ce, + 0xffce00d4, 0x82ec00db, 0x82f0202f, 0x82f12003, 0x82f32003, 0x82f42003, 0x82f52003, 0x82f72003, 0x82f8202f, 0x82fa2007, 0x82fb2003, 0xfffe2403, + 0x820001c1, 0xff032403, 0x820501dc, 0xff182807, 0xff1a01d6, 0x821e01e1, 0x8222200f, 0x822b2003, 0x82362013, 0x823c2003, 0x823e2003, 0x82422003, + 0x82532013, 0x82552007, 0x82572003, 0x825c2003, 0x82602003, 0x82612013, 0xff6b2403, 0x82a102dc, 0x82a22003, 0x82a32003, 0x82a42003, 0x82a52003, + 0xffaa2803, 0xffab02c1, 0x82ac02d6, 0x82ad2003, 0x82ae2003, 0x82af2003, 0xffb02403, 0x82b102dd, 0x82b22003, 0x82b32003, 0xffb42403, 0x82b502e1, + 0x82bd2003, 0x82bf2033, 0x82c12003, 0x82c32003, 0x82c52003, 0x82c72003, 0x82c92003, 0x82cb2003, 0x82cd2003, 0x82cf2003, 0x82d12003, 0x82d32003, + 0x82d52003, 0x82d72003, 0x82f22003, 0x82f42067, 0x82f62003, 0x82f72003, 0x82f92003, 0x82fb2063, 0xfffd2803, 0xff1503d6, 0x821703dd, 0x82192003, + 0x821b2003, 0x821d2003, 0x821f2003, 0xff232c03, 0xff9e03e1, 0xffa003dc, 0x82a203c1, 0x82a4200f, 0x82a6202b, 0x82a92013, 0x82aa200b, 0x82ab200b, + 0x82c42007, 0x82c5201f, 0x82c6201f, 0x82c7200f, 0x82c82007, 0x82c9200f, 0x82cb2023, 0x82cc2007, 0x82d1200f, 0x82d22003, 0x82da200f, 0x82e12003, + 0x82e6200b, 0x82e72017, 0x82eb2007, 0x82ec200f, 0x82f1200b, 0x82f32003, 0xffff240b, 0x820104dc, 0x82022003, 0xff082403, 0x820a04c1, 0xff0c2403, + 0x820e04d6, 0x8210200f, 0xff142407, 0x821604e1, 0x82182003, 0x821c2003, 0x821d201b, 0x82372017, 0x82392003, 0x823b2003, 0x823d2003, 0x823f2003, + 0x82412003, 0x82432003, 0x82452003, 0x824b2003, 0x824d2037, 0x824f2003, 0x82512003, 0x82532003, 0x82552003, 0x82572003, 0x82592003, 0x825b201f, + 0x825d2003, 0x825f2003, 0x8261200f, 0xff632407, 0x826504dd, 0x82672003, 0x82692003, 0x826b2003, 0x826d2003, 0x826f2003, 0x82712003, 0x82732077, + 0x82752003, 0x827c2003, 0x8298207f, 0x829c2003, 0x82a02033, 0x82a4203b, 0x82a9201f, 0x82ab200b, 0x82b52003, 0x82b72017, 0x82c32003, 0xffc52a27, + 0x007c00e1, 0x00daff06, 0x2403820b, 0x00f0ff47, 0x20038248, 0x20038249, 0x2003824b, 0x27038255, 0x00efff59, 0x00dcff5a, 0x00218582, 0x200f8294, + 0x20038299, 0x2013829b, 0x200782bb, 0x2c1782bd, 0x00ecffc2, 0x000f00c4, 0x00eaffc6, 0x201382c8, 0x240382c9, 0x00ceffca, 0x282382cb, 0x00e7ffcc, + 0x01f0fff7, 0x24038203, 0x01dcff1a, 0x2007821e, 0x20038222, 0x20038242, 0x20038260, 0x20038261, 0x2403826b, 0x01daff84, 0x20038285, 0x20038287, + 0x28038288, 0x02daff89, 0x02f0ffa1, 0x200382a2, 0x200382a3, 0x200382a4, 0x240382a5, 0x02efffb0, 0x200382b1, 0x200382b2, 0x240382b3, 0x02dcffb4, + 0x200382b5, 0x201b82bd, 0x200382bf, 0x200382c1, 0x200382c3, 0x200382c5, 0x200382c7, 0x200382c9, 0x200382cb, 0x200382cd, 0x200382cf, 0x200382d1, + 0x200382d3, 0x280382d5, 0x03f0ffd7, 0x03efff15, 0x20038217, 0x20038219, 0x2003821b, 0x2003821d, 0x2403821f, 0x03dcff23, 0x201f829e, 0x200b82a2, + 0x200b82a6, 0x200782a9, 0x200382ab, 0x821382c4, 0xc90321e3, 0xcb201382, 0xd2200b82, 0xda200782, 0xdb240382, 0xdc03daff, 0xdf200382, 0xe6200382, + 0xeb201782, 0xec201382, 0xf1200782, 0xf3200382, 0xff240b82, 0x0104f0ff, 0x02200382, 0x0e200382, 0x14240382, 0x1604dcff, 0x18200382, 0x1d200382, + 0x37200f82, 0x39200382, 0x3b200382, 0x3d200382, 0x3f200382, 0x41200382, 0x43200382, 0x45200382, 0x59200382, 0x5b200382, 0x5d200382, 0x61200382, + 0x63240382, 0x6504efff, 0x67200382, 0x69200382, 0x6b200382, 0x6d200382, 0x6f200382, 0x71200382, 0x73205382, 0x75200382, 0x9c200382, 0xa4202b82, + 0xa9201382, 0xab200782, 0xc3200382, 0xc52a1382, 0x4700dcff, 0x0c001000, 0x03821200, 0xe7ff4724, 0x03824800, 0x03824920, 0x03824b20, 0x03825520, + 0x03829420, 0x03829920, 0x0382bb20, 0x0f00c424, 0x0782c800, 0x0382c920, 0xe7fff724, 0x03820301, 0x03821e20, 0x03822220, 0x03824220, 0x03826020, + 0x03826120, 0x03826b20, 0x0c008624, 0x03828a01, 0x03828e20, 0x0c008f28, 0xe7ffa102, 0x0382a202, 0x0382a320, 0x0382a420, 0x0382a520, 0x0382bd20, + 0x0382bf20, 0x0382c120, 0x0382c320, 0x0382c520, 0x0382c720, 0x0382c920, 0x0382cb20, 0x0382cd20, 0x0382cf20, 0x0382d120, 0x0382d320, 0x0382d520, + 0xe7ffd724, 0x03829e03, 0x0382c420, 0x03218b82, 0x200782cb, 0x200382e6, 0x200382ec, 0x240382f1, 0x04e7ffff, 0x20038201, 0x20038202, 0x2003820e, + 0x2003821d, 0x20038237, 0x20038239, 0x2003823b, 0x2003823d, 0x2003823f, 0x20038241, 0x20038243, 0x20038245, 0x20038259, 0x2003825b, 0x8203825d, + 0x9c0421bf, 0xa9200782, 0xab200382, 0x063ae782, 0xeaffca00, 0xeeffed00, 0xd5fff600, 0xedfffe00, 0xecff3a01, 0xecff6d01, 0x11820100, 0x0582c020, + 0x2000ca2a, 0x0600be00, 0x0b000c00, 0x274d0382, 0x824a200b, 0xff4b240f, 0x825300e8, 0x82552041, 0x825a2007, 0x825d2021, 0x0b334d03, 0x0f82bd20, + 0x90ffc424, 0x0782c600, 0x2382c820, 0x0382c920, 0x3782ca20, 0x2707434d, 0x01eaff18, 0x010b001a, 0x26194b4d, 0x0085010c, 0x8287010c, 0x82882003, + 0x82892003, 0x00d32403, 0x82d6010d, 0x00d82803, 0xffd9010e, 0x82db01f5, 0x82dd20b1, 0x82e520b9, 0xffeb2407, 0x82ec01bf, 0x82ed200b, 0x82f42007, + 0x82f5201f, 0x00f8240b, 0x8210020e, 0xff112803, 0x001202ed, 0x8214020d, 0x821a200b, 0xff31260b, 0xff3302ee, 0x149b4dbf, 0xeaffab24, 0x0382ac02, + 0x0382ad20, 0x0382ae20, 0x0382af20, 0x0b00b424, 0x0382b502, 0x2136b74d, 0x4382f902, 0x0382fb20, 0xeafffd2b, 0x0b002303, 0xbfff3203, 0x217f8203, + 0x07823403, 0x03823520, 0x03823620, 0x03823720, 0x03823820, 0xedff3924, 0x03824303, 0x03824420, 0x03824520, 0x03824620, 0x03824720, 0x0d004c24, + 0x1f824d03, 0x03824e20, 0x03824f20, 0x13825020, 0x03825120, 0x03825220, 0x03825320, 0x03825a20, 0x03825b20, 0x03825c20, 0x03825d20, 0x03826d20, + 0x03826e20, 0x03826f20, 0xf5ff7324, 0x03827403, 0x03827520, 0x03827620, 0x0e007824, 0x4f828103, 0x03828220, 0xe8ff9e24, 0x9782a403, 0x9782a620, + 0x0782aa20, 0x0f82c420, 0x0782c620, 0x0782c820, 0x1382c920, 0x0782cb20, 0x0782d220, 0x0382da20, 0x0c00db24, 0x0382dc03, 0x0382df20, 0x1782e620, + 0x1382eb20, 0x2007734e, 0x4e0b82f3, 0x0c280b77, 0x0e04eaff, 0x1004e8ff, 0x14240782, 0x16040b00, 0x18200382, 0x8b4e0382, 0x824b2023, 0x824d2033, + 0x824f2003, 0x82512003, 0x82532003, 0x82552003, 0x82572003, 0x0ba74e03, 0x0f825f20, 0x63826120, 0x57827120, 0x03827320, 0x03827520, 0x0f829c20, + 0x1782a020, 0x2106bb4e, 0x1382c304, 0x0382c520, 0xbfffcb2c, 0xedffcf04, 0x0d00d004, 0x0b82d204, 0x0782de20, 0x0382e120, 0x0b82ea20, 0x1782f120, + 0x0382f420, 0x0e00f524, 0x0782f904, 0x0d00fa30, 0xf6000100, 0x0e00e2ff, 0xedff5c00, 0x03825e00, 0x0382ee20, 0xc0fff628, 0xedff3401, 0x03824401, + 0x03251382, 0x03edff26, 0x20038228, 0x2003822a, 0x200382ca, 0x203b82f6, 0x20038204, 0x202b82c9, 0x2039820d, 0x243982f2, 0xffee00f2, 0x203582f2, + 0x243582f2, 0xff5e01f2, 0x203582f2, 0x223582f2, 0x822a03f2, 0x82ca200b, 0xfff62403, 0x820404f2, 0xffc92803, 0x002200f2, 0x84f4ff5a, 0x825d2039, + 0xff5e2407, 0x82bd00f3, 0x22418307, 0x8bf4ff1a, 0xb4022945, 0xb502f4ff, 0x2303f4ff, 0x26220382, 0x5182f3ff, 0x5182f320, 0xa603f322, 0xc9200f82, + 0x59830382, 0x0782d220, 0x0382da20, 0x0382eb20, 0x0382f320, 0x14246987, 0x1604f4ff, 0x18200382, 0x71200382, 0x73200382, 0x75200382, 0xc3200382, + 0xc5200382, 0xc9200382, 0x62267782, 0xcaff0600, 0x03820b00, 0xd2ff3828, 0xd4ff3a00, 0x89823c00, 0xd3ff3d22, 0xe620a182, 0xef24a182, 0xe6ff5d00, + 0xe6229d82, 0x1f82d200, 0x0382d620, 0x00216982, 0x24f982de, 0x00e1ffe1, 0x3c2f82e6, 0x00efffee, 0x00c9fff6, 0x01d1fffe, 0x01e5ff09, 0x01d4ff19, + 0x01e6ff1a, 0x01e3ff20, 0x2acd8433, 0xff3901ef, 0xff3a01d2, 0x824301c4, 0xff44240f, 0x824501ef, 0xff47240f, 0x824901e1, 0x825d2003, 0x825e2013, + 0x82622013, 0xff633437, 0xff6401f5, 0xff6c01e7, 0xff6d0164, 0xff8401c9, 0x828501ca, 0x82872003, 0x82882003, 0xff893403, 0xff9902ca, 0xffb402d3, + 0xffb502e6, 0xff0e03e6, 0x821003d2, 0x82122003, 0xff222403, 0x822303d3, 0x82242013, 0x828b2007, 0x829a2003, 0xff9b2403, 0x829d03f4, 0x82a62007, + 0xffb52417, 0x82c103ed, 0x82c22027, 0x82c92013, 0xffca240f, 0x82d203ef, 0x82d92007, 0x82da201f, 0xffdb2407, 0x82dc03ca, 0x82df2003, 0xffea2403, + 0x82eb03d4, 0x82f22013, 0x82f3201b, 0x82f52007, 0xfff62833, 0xff0304ef, 0x820404f4, 0xff132807, 0xff1404ed, 0x821504e6, 0x82162007, 0x82172007, + 0x82182007, 0xff192807, 0xff7004e1, 0x827104d3, 0x8272200b, 0x82732007, 0x82742007, 0x82752007, 0xff772407, 0x827904d2, 0x8286201f, 0x82bf200f, + 0xffc2240b, 0x82c304d4, 0x82c42017, 0xffc52a07, 0x007200e6, 0x00c0ff06, 0x3403820b, 0x009dff38, 0x00c7ff3a, 0x00f0ff3c, 0x00abff3d, 0x00d2ff51, + 0x20038252, 0x20038254, 0x200382c1, 0x241f82d2, 0x00f5ffd4, 0x200782d6, 0x202382da, 0x2c0b82dd, 0x00eaffde, 0x00e5ffe1, 0x00c1ffe6, 0x202382ec, + 0x200382f0, 0x200382f1, 0x200382f3, 0x200382f4, 0x240382f5, 0x00cdfff6, 0x200782f8, 0x200382fa, 0x240382fb, 0x01d2fffe, 0x20038200, 0x24038205, + 0x01c7ff19, 0x2407822b, 0x01f0ff33, 0x28078236, 0x019dff39, 0x01ccff3a, 0x200b823c, 0x2003823e, 0x20178243, 0x24138245, 0x01e5ff47, 0x28038249, + 0x01dfff4c, 0x01f5ff50, 0x201b8253, 0x20038255, 0x20038257, 0x2003825c, 0x2827825d, 0x01ceff62, 0x01eaff64, 0x241f8266, 0x019eff6c, 0x200f826d, + 0x240b826f, 0x01c0ff84, 0x20038285, 0x20038287, 0x2c038288, 0x02c0ff89, 0x02abff99, 0x02d2ffaa, 0x200382f2, 0x200382f4, 0x280382f6, 0x03d2fff7, + 0x039dff0e, 0x20038210, 0x24038212, 0x03abff22, 0x20038224, 0x2003828b, 0x2403829a, 0x03f0ff9b, 0x2007829d, 0x242782a0, 0x03eaffb5, 0x202382c1, + 0x201382c2, 0x200f82c5, 0x200382c7, 0x200382cc, 0x200382d1, 0x242382d9, 0x03c0ffdb, 0x200382dc, 0x200382df, 0x201382e1, 0x240382e7, 0x03c7ffea, + 0x241b82f2, 0x04f0fff5, 0x24038203, 0x04d2ff08, 0x2403820a, 0x04eaff13, 0x20038215, 0x24038217, 0x04e5ff19, 0x2413821c, 0x04abff70, 0x20038272, + 0x24038274, 0x049dff77, 0x20178279, 0x2017827c, 0x200f8286, 0x20078298, 0x200382b5, 0x200382b7, 0x2e1b82bf, 0x04c7ffc2, 0x00c7ffc4, 0xff060075, + 0x820b00b1, 0xff383403, 0xff3a009e, 0xff3c00c5, 0xff3d00f2, 0xff5100a8, 0x825200cf, 0x82542003, 0xff5c2403, 0x82c100ef, 0x82d22007, 0x82d62023, + 0x82da2003, 0xffde2323, 0x574300ec, 0x00c22205, 0x201b82ec, 0x202382ee, 0x200782f0, 0x200382f1, 0x200382f3, 0x200382f4, 0x240382f5, 0x00c6fff6, + 0x200782f8, 0x200382fa, 0x240382fb, 0x01cffffe, 0x20038200, 0x24038205, 0x01c5ff19, 0x2807822b, 0x01f2ff33, 0x01efff34, 0x280b8236, 0x019eff39, + 0x01c0ff3a, 0x200b823c, 0x2003823e, 0x431b8243, 0x9e230587, 0x43ff4701, 0x4c240587, 0x5301dfff, 0x55201b82, 0x57200382, 0x5c200382, 0x5d200382, + 0x9b432782, 0x01cd3205, 0x01e8ff64, 0x019fff6c, 0x01c6ff6d, 0x01b1ff84, 0x20038285, 0x20038287, 0x2c038288, 0x02b1ff89, 0x02a8ff99, 0x02cfffaa, + 0x200382f2, 0x200382f4, 0x280382f6, 0x03cffff7, 0x039eff0e, 0x20038210, 0x24038212, 0x03a8ff22, 0x20038224, 0x2003828b, 0x2403829a, 0x03f2ff9b, + 0x2007829d, 0x242782a0, 0x03ecffb5, 0x202382c1, 0x201382c2, 0x200f82c5, 0x240382c7, 0x03efffca, 0x200782cc, 0x200382d1, 0x242782d9, 0x03b1ffdb, + 0x200382dc, 0x200382df, 0x201382e1, 0x240382e7, 0x03c5ffea, 0x201b82f2, 0x433782f5, 0xf22a05a3, 0xefff0404, 0xcfff0804, 0x03820a04, 0xecff1324, + 0x03821504, 0x03821720, 0xe1ff1924, 0x13821c04, 0xa8ff7024, 0x03827204, 0x03827420, 0x9eff7724, 0x17827904, 0x17827c20, 0x0f828620, 0x07829820, + 0x0382b520, 0x0382b720, 0x1b82bf20, 0xc5ffc232, 0xc5ffc404, 0x38005300, 0x5100beff, 0x5200e1ff, 0x54200382, 0x5a240382, 0x5d00efff, 0xbd200382, + 0xc1200382, 0xd2200f82, 0xd6201f82, 0xe6240382, 0xec00c9ff, 0xf0200f82, 0xf1200382, 0xf3200382, 0xf4200382, 0xf5200382, 0xf6240382, 0xf800dfff, + 0xfa200782, 0xfb200382, 0xfe240382, 0x0001e1ff, 0x05200382, 0x092c0382, 0x1a01edff, 0x2001efff, 0x2b01ebff, 0x36200f82, 0x39280382, 0x3a01beff, + 0x3c01dfff, 0x3e200b82, 0x45200382, 0x4c240f82, 0x5301e9ff, 0x55200b82, 0x57200382, 0x5c200382, 0x63300382, 0x6d01f5ff, 0xaa02e0ff, 0xb402e1ff, + 0xb502efff, 0xf2200382, 0xf4200b82, 0xf6200382, 0xf7280382, 0x0e03e1ff, 0x1003beff, 0x12200382, 0x23240382, 0xa003efff, 0xa6201382, 0xc1200782, + 0xc5200f82, 0xc7200b82, 0xc9200382, 0xcc200f82, 0xd1200782, 0xd2200382, 0xda200b82, 0xe1200382, 0xe7200b82, 0xeb200382, 0xf3280b82, 0x0804efff, + 0x0a04e1ff, 0x14200382, 0x16200b82, 0x18200382, 0x1c200382, 0x71200f82, 0x73200782, 0x75200382, 0x77240382, 0x7c04beff, 0x98201382, 0xb5200382, + 0xb7200382, 0xbf200382, 0xc3201382, 0xc52c1b82, 0x6a00efff, 0xe6ff3800, 0xe7ff3a00, 0x26061b43, 0xff5100e7, 0x825200d6, 0x82542003, 0xff5c2403, + 0x82c100f1, 0x82d22007, 0x82d62023, 0x051b4303, 0xe100ee26, 0xe600e8ff, 0xec200f82, 0xee201b82, 0xf0202382, 0xf1200782, 0xf3200382, 0xf4200382, + 0xf5200382, 0xf6240382, 0xf800d0ff, 0xfa200782, 0xfb200382, 0xfe240382, 0x0001d6ff, 0x05200382, 0x19240382, 0x2b01e7ff, 0x1b430782, 0x01f12205, + 0x280b8236, 0x01e6ff39, 0x01ceff3a, 0x200b823c, 0x4303823e, 0xf122051b, 0x17824501, 0xe8ff4724, 0x03824901, 0x17825320, 0x03825520, 0x03825720, + 0x03825c20, 0x22051743, 0x826201f1, 0xff64244f, 0x826c01ed, 0xff6d2c2b, 0xff9902d0, 0xffaa02e7, 0x82f202d6, 0x82f42003, 0x82f62003, 0xfff72803, + 0xff0e03d6, 0x821003e6, 0x82122003, 0xff222403, 0x822403e7, 0x828b2003, 0x829a2003, 0x05034303, 0xa003e722, 0xb5242782, 0xc103eeff, 0x03432382, + 0x03d62205, 0x241382c7, 0x03f1ffca, 0x200782cc, 0x200382d1, 0x202f82d9, 0x200782e1, 0x200382e7, 0x200b82ea, 0x420382f2, 0xf12e05f7, 0xf2ff0304, + 0xf1ff0404, 0xd6ff0804, 0x03820a04, 0xeeff1324, 0x03821504, 0x03821720, 0xe8ff1924, 0x13821c04, 0xe7ff7024, 0x03827204, 0x03827420, 0xe6ff7724, + 0x17827904, 0x17827c20, 0x0f828620, 0x07829820, 0x0382b520, 0x0382b720, 0x1b82bf20, 0x1382c220, 0xe7ffc42e, 0x25009800, 0x27001000, 0x2b00e8ff, + 0x33200382, 0x35200382, 0x38240382, 0x3a00e0ff, 0x3d240382, 0x8300dfff, 0x93200f82, 0x98200382, 0xb2200382, 0xb3202b82, 0xb4200782, 0xd2200782, + 0xd3201f82, 0xd4200b82, 0xd6200b82, 0xd9240b82, 0xdd001400, 0xe1440b82, 0x00e02605, 0x001300ed, 0x2c0f82f2, 0x01e0fff9, 0x01100004, 0x01e8ff08, + 0x2007820d, 0x20078217, 0x20138219, 0x2007821b, 0x2003821d, 0x2003821f, 0x20038221, 0x20138239, 0x20078241, 0x24078245, 0x01e1ff47, 0x20078248, + 0x20078249, 0x2007824a, 0x2007824d, 0x203b8250, 0x2c038251, 0x01e9ff58, 0x01dfff62, 0x01deff64, 0x200f8266, 0x2033826a, 0x240f826c, 0x01f2ff6e, + 0x280f826f, 0x02100070, 0x02e8ff45, 0x20038246, 0x20038248, 0x20038249, 0x2013827f, 0x20038280, 0x20038281, 0x20038282, 0x20038283, 0x20038284, + 0x20038285, 0x201f8286, 0x20038290, 0x20038291, 0x82038292, 0x940221eb, 0x99240782, 0xb602dfff, 0xb8201f82, 0xba200382, 0xbc200382, 0xbe201382, + 0xc0200382, 0xc2200382, 0xd0200382, 0xd2200382, 0xd4200382, 0xd6200382, 0xf8200382, 0xfa200382, 0xfc280382, 0x0e03e8ff, 0x1003e0ff, 0x12200382, + 0x22240382, 0x2403dfff, 0x2d200382, 0x86241782, 0x8a031000, 0x8b200782, 0x8e200f82, 0x97200b82, 0x9a200b82, 0x9d200b82, 0x6b820382, 0x82bd0321, + 0x215f820f, 0x3782c103, 0x1382d920, 0x2382e220, 0x0b82ea20, 0x1782ed20, 0x0382f020, 0x1382f220, 0x1382f820, 0x1000fa28, 0xe8ff0b04, 0x03820d04, + 0x03820f20, 0xe1ff1928, 0xe0ff1a04, 0x17821e04, 0x03822020, 0x03822220, 0x03822420, 0x03822620, 0x03822820, 0x03822a20, 0x03822c20, 0x03822e20, + 0x03823020, 0x03823220, 0x03823420, 0x3b824a20, 0x03824c20, 0x03824e20, 0x03825020, 0x03825220, 0x03825420, 0x03825620, 0x03825820, 0x03825a20, + 0x03825c20, 0x03825e20, 0x03826020, 0xdfff7024, 0x03827204, 0x03827420, 0x6f827720, 0x77827920, 0x07827a20, 0x0f828620, 0x4f829920, 0x23829f20, + 0x0382b820, 0x1382bf20, 0x0382c220, 0xe0ffc430, 0x1b003500, 0x3800f2ff, 0x3a00f1ff, 0x7f4af4ff, 0x00f02206, 0x480f82d2, 0xf12205e5, 0x1782da00, + 0x2a05e548, 0xffe600f3, 0xff1901f1, 0x823301f4, 0x82392003, 0x8243200b, 0x82452007, 0xff502407, 0x825d01f5, 0xff62240b, 0x826401f2, 0x057d4803, + 0x6f01f22e, 0x9902f5ff, 0x0e03f0ff, 0x1003f1ff, 0x12200382, 0x22200382, 0x24200f82, 0x8b200382, 0x9a200382, 0x274a0382, 0x03f02605, 0x03f3ffb5, + 0x241f82c1, 0x03f4ffc2, 0x201782d9, 0x200782ea, 0x240782f2, 0x04f4fff5, 0x24038203, 0x04f3ff13, 0x20038215, 0x22038217, 0x82f0ff70, 0x04f022e9, + 0x24078274, 0x04f1ff77, 0x20078286, 0x820782bf, 0xc404213b, 0x6b24af82, 0x0f002500, 0xe620d582, 0xe62ad582, 0x0e003c00, 0xe6ff3d00, 0x1382b200, + 0x0382b420, 0x0b82d220, 0x1382d420, 0x0782d620, 0x1300d924, 0x0b82da00, 0x0382dd20, 0x0b00de22, 0x2a06c749, 0xffe700e6, 0x00ed00f4, 0x82f20012, + 0xfff6302f, 0xfff900e7, 0xfffe00e8, 0x000401e7, 0x820d010f, 0xff192703, 0x003301e6, 0xc144010e, 0x01e72205, 0x440b8243, 0xe52a05b5, 0xe8ff4801, + 0xe5ff4901, 0x07824a01, 0xe4ff4c24, 0x1b825001, 0x33825120, 0x07825d20, 0x37826220, 0x03826420, 0x0b826620, 0x2205b944, 0x826f01e7, 0x0070240b, + 0x827f020f, 0x82802003, 0x82812003, 0x82822003, 0x82832003, 0x82842003, 0x82852003, 0xff992403, 0x82b602e6, 0x82b82007, 0x00ba2203, 0x0ed5440f, + 0x2403e626, 0x8603e6ff, 0x8b201782, 0x8e200782, 0x9a200782, 0x9b240782, 0x9d030e00, 0xb5230782, 0x82030b00, 0x05dd443b, 0xd9201382, 0xe2201382, + 0xea202382, 0xf2200782, 0xf5200382, 0xf8201382, 0xfa2c0f82, 0x03040f00, 0x13040e00, 0x15040b00, 0x17200382, 0x19280382, 0x1a04e5ff, 0x1e04e8ff, + 0x20201b82, 0x22200382, 0x24200382, 0x26200382, 0x28200382, 0x2a200382, 0x2c200382, 0x2e200382, 0x30200382, 0x32200382, 0x34200382, 0x70240382, + 0x7204e6ff, 0x74200382, 0xed440382, 0x04e52205, 0x2047827a, 0x200f8286, 0x441f8299, 0xe62c05e5, 0xe6ffc404, 0x06003a00, 0x0b00bfff, 0x382c0382, + 0x3a009fff, 0x3d00c9ff, 0xd200adff, 0xd6200b82, 0x97490382, 0x00e63a05, 0x00c4ffe6, 0x00cdfff6, 0x01d5fffe, 0x01c9ff19, 0x019fff39, 0x01ccff3a, + 0x24078245, 0x01e6ff47, 0x38038249, 0x01dfff4c, 0x01d1ff62, 0x01ecff64, 0x01a1ff6c, 0x01cfff6d, 0x01bfff84, 0x20038285, 0x20038287, 0x30038288, + 0x02bfff89, 0x03adff99, 0x039fff0e, 0x039fff10, 0x20038212, 0x200f8222, 0x20038224, 0x2003828b, 0x2003829a, 0x2403829d, 0x03ecffb5, 0x201b82c1, + 0x240b82d9, 0x03bfffdb, 0x200382dc, 0x270382df, 0x03c9ffea, 0x04adfff2, 0x220ddb48, 0x827004e6, 0x82722013, 0x82742003, 0xff772403, 0x8279049f, + 0x828620e9, 0x82bf200b, 0xffc2220b, 0x2ae982c9, 0x003100c9, 0x00e3ff38, 0x82e5ff3c, 0x82e420e1, 0x00e322e1, 0x200b82d4, 0x241382d6, 0x00e2ffd9, + 0x200b82da, 0x280382dd, 0x00e9ffde, 0x01eafff2, 0x22038204, 0x82e5ff33, 0x01e322e9, 0x24078243, 0x01e3ff45, 0x20078250, 0x20178251, 0x2007825d, + 0x24038266, 0x01e4ff6c, 0x2207826f, 0x82eaff70, 0x82e420d5, 0x82e320d5, 0x82e320d5, 0x03e326d5, 0x03e4ff22, 0x20038224, 0x2003828b, 0x2403829a, + 0x03e5ff9b, 0x2207829d, 0x82e9ffb5, 0x03e322d9, 0x200f82c2, 0x200f82d9, 0x240382f2, 0x04e5fff5, 0x24038203, 0x04e9ff13, 0x20038215, 0x24038217, + 0x04e4ff70, 0x20038272, 0x24038274, 0x04e3ff77, 0x20078286, 0x20ab82bf, 0x20c58224, 0x83c582e2, 0x82e220c1, 0x00e428c1, 0x00e2ffd6, 0x82e1ffd9, + 0x00e426c1, 0x00e4ffdd, 0x20c182de, 0x220782ed, 0x82ebfff2, 0x01eb22c5, 0x22a58233, 0x82e2ff39, 0x01e422c5, 0x20078245, 0x200f8250, 0x201b8251, + 0x2007825d, 0x24c18466, 0xff7001e4, 0x20bd82eb, 0x20bd82e2, 0x22bd82e2, 0x889b03e2, 0x82e220a9, 0x03e422a9, 0x207d82f5, 0x8b038203, 0xff7724a1, + 0x82bf04e2, 0x8218207b, 0x00eb2891, 0x00f3ff3d, 0x82ebffd2, 0x01eb228d, 0x265d8239, 0x02ebff45, 0x82f3ff99, 0x82eb2055, 0x82eb2055, 0x03eb2255, + 0x200f8222, 0x20038224, 0x2003828b, 0x2003829a, 0x2003829d, 0x207982c1, 0x240782d9, 0x04f3fff2, 0x20038270, 0x20038272, 0x22038274, 0x82ebff77, + 0x82f320f3, 0x00eb2861, 0xff510039, 0x825200ef, 0x82542003, 0xff5c2403, 0x82c100f0, 0x82ec2007, 0xffed2403, 0x82ee00ee, 0x82f0200f, 0x82f1200b, + 0x82f32003, 0x82f42003, 0x82f52003, 0x82f62003, 0x82f8201b, 0x82fa2007, 0x82fb2003, 0xfffe2403, 0x820001ef, 0x82052003, 0xff092803, 0xff2001f4, + 0x822b01f1, 0xff34240b, 0x823601f0, 0x823a2007, 0x823c2003, 0x823e2003, 0x82442003, 0x82532013, 0x82552007, 0x82572003, 0x825c2003, 0x825e2003, + 0xff6d2413, 0x82aa02ef, 0x82f22003, 0x82f42003, 0x82f62003, 0xfff72403, 0x82a003ef, 0x82c52003, 0x82c72003, 0xffca2403, 0x82cc03f0, 0x82d12007, + 0x82e12003, 0x82e72003, 0xfff62403, 0x820404f0, 0xff082403, 0x820a04ef, 0x821c2003, 0x827c2003, 0x82982003, 0x82b52003, 0x82b72003, 0x0024219f, + 0x2609b35e, 0xff5d00f5, 0x82bd00f5, 0xfff62403, 0x82fe00f4, 0xff0924ad, 0x821a01f5, 0x823a2003, 0x826d2003, 0x15c35e03, 0xb502f526, 0x2303f5ff, + 0xa6200382, 0xc9200382, 0xd2200382, 0xda200382, 0xc35e0382, 0x03f5260d, 0x04f5fff3, 0x20038214, 0x20038216, 0x20038218, 0x20038271, 0x20038273, + 0x20038275, 0x200382c3, 0x267b82c5, 0xff510035, 0x825200ee, 0x82542003, 0x82c12003, 0x82ec2003, 0x00ed2403, 0x82f00014, 0x82f12007, 0x82f32003, + 0x82f42003, 0x82f52003, 0xfff62403, 0x82f800ed, 0x82f92007, 0x82fa2007, 0x82fb2007, 0xfffc2203, 0x26bd82d0, 0xff0001ee, 0x820501ee, 0x822b2003, + 0x82362003, 0xff3a2403, 0x823c01ed, 0x823e2007, 0x82482003, 0x824a200b, 0x82532003, 0x8255200b, 0x82572003, 0x825c2003, 0xff6d2803, 0xffaa02ed, + 0x82f202ee, 0x82f42003, 0x82f62003, 0xfff72403, 0x82a003ee, 0x82c52003, 0x82c72003, 0x82cc2003, 0x82d12003, 0x82e12003, 0xffe72403, 0x820804ee, + 0x820a2003, 0xff1a2403, 0x821c04ed, 0x827a2007, 0x827c2007, 0x82982007, 0x82b52003, 0x82b72003, 0x000a2293, 0x24db8206, 0x01f5ff0b, 0x20038284, + 0x20038285, 0x20038287, 0x24038288, 0x03f5ff89, 0x200382db, 0x200382dc, 0x212382df, 0x4b590076, 0xff53260f, 0xff5500c7, 0x084359f0, 0x0b82bb20, + 0x0382c820, 0x0382c920, 0x26072359, 0x01c7ff18, 0x59ebff1c, 0xdb201827, 0xdd201b82, 0xe5240382, 0xec01e9ff, 0xf5240782, 0x1102ebff, 0x1a200382, + 0x31200382, 0x33590382, 0xffab2413, 0x82ac02c7, 0x82ad2003, 0x82ae2003, 0x82af2003, 0x362f5903, 0x82f90221, 0x82fb203b, 0xfffd2803, 0xff3903c7, + 0x824303eb, 0x82442003, 0x82452003, 0x82462003, 0x82472003, 0x82502003, 0x82512003, 0x82522003, 0x82532003, 0x825a2003, 0x825b2003, 0x825c2003, + 0x825d2003, 0x826d2003, 0x826e2003, 0x826f2003, 0xff9e2403, 0x82a403f0, 0x82aa204b, 0x82c42003, 0x82c6200b, 0x82c82007, 0x82cb2007, 0x82e62003, + 0x82ec2003, 0x82f12003, 0x0b3f5903, 0xc7ff0c28, 0xf0ff0e04, 0x07821004, 0x20233b59, 0x2027824b, 0x2003824d, 0x2003824f, 0x20038251, 0x20038253, + 0x20038255, 0x59038257, 0x5f200b57, 0x61200f82, 0x9c205782, 0xa0200382, 0x33590b82, 0xffcf2407, 0x82f104eb, 0x82f42003, 0xfff92a03, 0x00e200eb, + 0x000d0006, 0x2803820b, 0x00f0ff45, 0x00c0ff47, 0x20038248, 0x20038249, 0x2013824a, 0x2407824b, 0x00e2ff53, 0x57078255, 0xc02209fb, 0x0f829900, + 0x0382bb20, 0x3982bd20, 0xd6ffc724, 0x0b82c800, 0x0382c920, 0xd5ffcc30, 0xc8ffed00, 0xd7fff200, 0xc0fff700, 0x03820301, 0xd7ff0430, 0xe2ff1801, + 0x0b001a01, 0xecff1c01, 0x13821e01, 0x0c002024, 0x07822201, 0x03824220, 0x1f825120, 0x07826020, 0x03826120, 0x23826320, 0x03826520, 0x0b826b20, + 0x17827020, 0x0d008424, 0x03828501, 0x03828720, 0x03828820, 0x03828920, 0x244f1b58, 0x02f0ff9a, 0x2003829b, 0x2003829c, 0x2003829d, 0x2003829e, + 0x2003829f, 0x240382a0, 0x02c0ffa1, 0x200382a2, 0x200382a3, 0x200382a4, 0x640382a5, 0x37581309, 0x82b72007, 0x82b92033, 0x82bb2003, 0x82bd2003, + 0x82bf202b, 0x82c12003, 0x82c32003, 0x82c52003, 0x82c72003, 0x82c92003, 0x82cb2003, 0x82cd2003, 0x82cf2003, 0x82d12003, 0x82d32003, 0x82d52003, + 0x82d72003, 0x0b556403, 0x25914358, 0xffa403c0, 0x435803e2, 0x03e22a05, 0x03f0ffc3, 0x03c0ffc4, 0x201382c6, 0x240782c8, 0x030b00c9, 0x580782cb, + 0x0d260947, 0x0d00dc03, 0x0382df03, 0x2b82e320, 0x1b82e620, 0x2382eb20, 0x0782ec20, 0x0382f120, 0x0b82f320, 0x1782f920, 0x0382fb20, 0xc0ffff24, + 0x03820104, 0x03820220, 0xe2ff0c24, 0x07820e04, 0x07821020, 0x260d5358, 0xff1f04c0, 0x822104f0, 0x82232003, 0x82252003, 0x82272003, 0x82292003, + 0x822b2003, 0x822d2003, 0x822f2003, 0x82312003, 0x82332003, 0x82352003, 0x82372003, 0x82392047, 0x823b2003, 0x823d2003, 0x823f2003, 0x82412003, + 0x82432003, 0x82452003, 0x1ba56503, 0x1f825920, 0x03825b20, 0x03825d20, 0x8b825f20, 0x07826120, 0x200b8358, 0x205f829a, 0x2013829c, 0x201b82a0, + 0x200782a9, 0x580382ab, 0x0f2e3787, 0x1400ed00, 0x1000f200, 0xf0fff600, 0x0382f900, 0xf0fffe30, 0x16000101, 0x10000401, 0xe6ff3a01, 0x0f824801, + 0xdcff4a24, 0x0f825101, 0x0b826d20, 0x10007024, 0x81821a04, 0x2b827a20, 0x47004f26, 0x4800eeff, 0x49200382, 0x4b200382, 0x55200382, 0x94200382, + 0x99200382, 0xbb200382, 0xc8200382, 0xc9200382, 0x4f4c0382, 0x820e2005, 0x00e32265, 0x2e0f82f7, 0x00e3fff9, 0x00b8fffc, 0x01e3fffe, 0x82eeff03, + 0x010e226d, 0x2007821e, 0x24038222, 0x01baff3a, 0x20078242, 0x221b8248, 0x82d9ff4a, 0x010e2279, 0x200f8260, 0x20038261, 0x2003826b, 0x2817826d, + 0x020e0070, 0x02eeffa1, 0x200382a2, 0x200382a3, 0x200382a4, 0x200382a5, 0x200382bd, 0x200382bf, 0x200382c1, 0x200382c3, 0x200382c5, 0x200382c7, + 0x200382c9, 0x200382cb, 0x200382cd, 0x200382cf, 0x200382d1, 0x200382d3, 0x240382d5, 0x03eeffd7, 0x2003829e, 0x820382c4, 0xcb0321af, 0xe6200782, + 0xec200382, 0xf1200382, 0xff240382, 0x0104eeff, 0x02200382, 0x0e200382, 0x1a240382, 0x1d04e3ff, 0x37200782, 0x39200382, 0x3b200382, 0x3d200382, + 0x3f200382, 0x41200382, 0x43200382, 0x45200382, 0x59200382, 0x5b200382, 0x5d200382, 0xbb820382, 0x827a0421, 0x829c2037, 0x82a9200b, 0xffab2a03, + 0x002200ee, 0x00c0ff5a, 0x2003825d, 0x240382bd, 0x0080fff6, 0x341582f9, 0x01f0fffe, 0x01dbff09, 0x01c0ff1a, 0x01dcff20, 0x0147ff3a, 0x20f58248, + 0x3403824a, 0x01070063, 0x01f4ff65, 0x027fff6d, 0x02c0ffb4, 0x03c0ffb5, 0x20038223, 0x200382a6, 0x200382c9, 0x200382d2, 0x200382da, 0x240382eb, + 0x04c0fff3, 0x20038214, 0x20038216, 0x20038218, 0x2075821a, 0x20078271, 0x20038273, 0x20038275, 0x200f827a, 0x200782c3, 0x207b82c5, 0x24898223, + 0xff5c00f4, 0x2a8d82f0, 0xffbd00f4, 0xffed00f4, 0x82ee00ef, 0xfff2240f, 0x82fe00f3, 0xff042279, 0x229182f3, 0x823401f4, 0x8244209d, 0x82512003, + 0x825e200f, 0xff702207, 0x0c2b5af3, 0x21091f5a, 0x1f5a03f0, 0x04f02411, 0x82f0ff04, 0x1c1f5a95, 0x000a002b, 0x00d6ff06, 0x01d6ff0b, 0x20038284, + 0x20038285, 0x20038287, 0x24038288, 0x03d6ff89, 0x200382db, 0x200382dc, 0x202382df, 0x20b38215, 0x28a782e0, 0xfff600e0, 0xfff90076, 0x32ab82c2, + 0xff0901d3, 0xff2001d9, 0xff3401db, 0xff3a01e0, 0x8244011e, 0xff482807, 0xff4a01c2, 0x825e01ed, 0x8263200b, 0xff652eb7, 0xff6d01f2, 0xffca0356, + 0xfff603e0, 0x269782e0, 0xff1a04e0, 0x827a04c2, 0x820d2043, 0x8264204d, 0x82d2204d, 0x88d9204d, 0x2249834d, 0x84d2ff48, 0x82418a45, 0x82d22035, + 0x00d22235, 0x20358209, 0x2031826a, 0x83318cc6, 0x842d8a73, 0x82d720db, 0x82d720db, 0x01d726db, 0x01d7ff85, 0x20038287, 0x22038288, 0x82d7ff89, + 0x03d722db, 0x2a0782dc, 0x00d7ffdf, 0xff470062, 0x82480098, 0x82492003, 0x824b2003, 0xff532403, 0x82550070, 0xff572807, 0x005b0018, 0x8294000b, + 0x8299200b, 0x82bb2003, 0x82c82003, 0x82c92003, 0xfff72403, 0x82030198, 0xff182403, 0x821e0170, 0x82222007, 0x82422003, 0x82602003, 0x82612003, + 0x826b2003, 0xffc12803, 0xffa10218, 0x82a20298, 0x82a32003, 0x82a42003, 0x82a52003, 0xffab2403, 0x82ac0270, 0x82ad2003, 0x82ae2003, 0x82af2003, + 0x82bd2003, 0x82bf2017, 0x82c12003, 0x82c32003, 0x82c52003, 0x82c72003, 0x82c92003, 0x82cb2003, 0x82cd2003, 0x82cf2003, 0x82d12003, 0x82d32003, + 0x82d52003, 0x82d72003, 0x82f92003, 0x82fb203b, 0xfffd2803, 0xff050370, 0x82070318, 0x82092003, 0x820b2003, 0x820d2003, 0xff9e2403, 0x82a40398, + 0x82aa201b, 0x82c42003, 0x82c6200b, 0x21c38207, 0x0b82cb03, 0x1f82cd20, 0x0782e620, 0x0382ec20, 0x0382f120, 0x98ffff24, 0x03820104, 0x03820220, + 0x70ff0c24, 0x07820e04, 0x07821020, 0x07821d20, 0x03823720, 0x03823920, 0x03823b20, 0x03823d20, 0x03823f20, 0x03824120, 0x03824320, 0x03824520, + 0x27824b20, 0x03824d20, 0x03824f20, 0x03825120, 0x03825320, 0x03825520, 0x03825720, 0x1f825920, 0x03825b20, 0x03825d20, 0x0f825f20, 0x07826120, + 0x03829c20, 0x0b82a020, 0x0782a920, 0x0382ab20, 0x18ffbe36, 0xd3011300, 0xd501eeff, 0xd601f5ff, 0xd801f1ff, 0xf401f2ff, 0xf8240382, 0x1002f2ff, + 0x122c0382, 0x1402eeff, 0x4c03f2ff, 0x7803eeff, 0x80240782, 0x8103f5ff, 0x82240b82, 0xd004eeff, 0xde200382, 0xe1200382, 0xf5260382, 0xfa04f2ff, + 0x4d84eeff, 0x4d82e520, 0x4d82f120, 0x4d82eb20, 0x4d82e920, 0xf801e924, 0x4d82e9ff, 0x1202e924, 0x4d82e5ff, 0x4d82e920, 0x4d82e520, 0x8003e924, + 0x4d82f1ff, 0x8203e524, 0x4d82e5ff, 0xde04e522, 0xe1200782, 0xf5220382, 0x4d82e9ff, 0x0300e522, 0xee209786, 0xf5222982, 0x53820200, 0x01b72408, + 0x00f0ffdb, 0x005b0001, 0x0004000b, 0x00e6ff0d, 0x00f4ff41, 0x01efff61, 0x00edff4d, 0xffb80016, 0x82c200d4, 0x00c43009, 0xffca0011, 0xffcc00e0, + 0xffcd00e7, 0x82ce00e5, 0x00d92c9b, 0xffea0012, 0xfff600e9, 0x823a01d7, 0xff4a3803, 0xff4c01d3, 0xff4d01d6, 0xff5801c5, 0x006201e7, 0x0064010d, + 0x826d010c, 0xff6e2213, 0x266982f2, 0xffe501e9, 0x823102e7, 0x01012433, 0x82f1ff1c, 0xffd9243f, 0x82e600ae, 0x82eb2007, 0xffed325b, 0xffef00ad, + 0xfffd00d6, 0xff0101df, 0xff0701d2, 0x2a2582e0, 0xff2e01ce, 0xff3001dd, 0x823801e2, 0x8240200f, 0xff4a2203, 0x266382e9, 0xff5f01da, 0x826901bd, + 0x826c202b, 0x8202209b, 0x01f52a85, 0x00c0ff85, 0xffed0002, 0x26378268, 0x000a00ee, 0x82c3ffe6, 0x00cf2417, 0x82d4fffe, 0x01ce22a1, 0x50958249, + 0x3c080df9, 0xff6d01a0, 0x003000d1, 0x007eff56, 0x009dff5b, 0x00f1fe6d, 0x00f4fe7c, 0x00abfe81, 0x005eff86, 0x004bff89, 0x0072ffb8, 0x000fffbf, + 0x000affc3, 0x0041ffc6, 0x0007ffc7, 0x0068ffca, 0x2a1382cc, 0x000effcd, 0x000cffce, 0x8263ffd9, 0x00052cc7, 0x00bdffea, 0x0049ffeb, 0x82fefeed, + 0x821320cb, 0x8268207d, 0x000e22cf, 0x222f82fe, 0x8213ffff, 0x010724d7, 0x82300002, 0x010e2cdb, 0x0111ff09, 0x01e7fe1c, 0x82acff20, 0x821520e3, + 0x013c24e3, 0x820eff38, 0x6a2008a9, 0x49ff4001, 0x0cff4a01, 0x3fff4c01, 0xf1fe4d01, 0xc0ff5801, 0xeffe5f01, 0x31ff6301, 0x5fff6501, 0x0a24f782, + 0x05006c01, 0x303abd82, 0xd5ff6e01, 0x0a001d00, 0x0d00e2ff, 0x0e001400, 0x4100cfff, 0x4a001200, 0xd582eaff, 0x5800d822, 0x612e0782, 0x6d001300, + 0x7c00aeff, 0x8100cdff, 0xd982a0ff, 0x8900c12a, 0xb800c0ff, 0xbc00d0ff, 0xbf241f82, 0xc000c6ff, 0xc2223d82, 0xe582e9ff, 0xe582d620, 0xe582e820, + 0xca00ba22, 0xcc260f82, 0xcd00cbff, 0xe582daff, 0x8d01c72e, 0xdb01d3ff, 0xe501cbff, 0x3102cbff, 0x18244b82, 0xafff2300, 0xef286182, 0xdfff5b00, + 0xeeff9a00, 0xe5255182, 0xd1ffb900, 0x052f4200, 0xd900c822, 0xe62a7982, 0xf600c5ff, 0xfe00caff, 0xdb82d0ff, 0x49018128, 0x4a0165ff, 0xdb8285ff, + 0x4d016624, 0xdb82ddff, 0x6201f22c, 0x6401b1ff, 0x6c01caff, 0xd382a9ff, 0xd601c824, 0x6582cdff, 0x0800f522, 0xf0203982, 0xf0283982, 0xf1ff0901, + 0xf3ff2001, 0xf1224182, 0x07826301, 0x03826520, 0xf1ff6d24, 0xe9820300, 0x7f82ee20, 0x3382ea20, 0x0900f022, 0x20064964, 0x203782b8, 0x203382e2, + 0x203382f0, 0x203382f1, 0x203382eb, 0x2a5982f5, 0xff8501ec, 0x01020090, 0x820b0011, 0x82e6206b, 0xff5b229d, 0x20b582c1, 0x243782c5, 0xffea00b4, + 0x203782d7, 0x206f82b9, 0x243b82e9, 0xff1c01b2, 0x203f82d2, 0x243f82c8, 0xff4a01a0, 0x20a982c5, 0x244782e4, 0xff6501cc, 0x284b82cc, 0xff6e01cb, + 0xffdb01ef, 0x28a982e7, 0xff3102e6, 0x000500e8, 0x2619825b, 0x01b8ffd6, 0x82f2ffdb, 0x82f12015, 0x82f32015, 0x00d926c3, 0x00ed0015, 0x20f98215, + 0x204782e4, 0x20f982e5, 0x20f182e4, 0x20f182e3, 0x228582e2, 0x820200e4, 0x82d62075, 0x88200899, 0x58000700, 0x81000e00, 0xc400d7fe, 0xc70098ff, + 0xd900c7ff, 0xed0012ff, 0x5f0152ff, 0x0600cfff, 0x200a2765, 0x0c2765d6, 0x4a000424, 0x3b821400, 0x00322a08, 0x0111005b, 0x00100085, 0xff040034, + 0xff5600c4, 0xff5b00bf, 0xff6d00d1, 0xff7c006c, 0xff81006e, 0xff860043, 0xff8900ac, 0x2cf582a1, 0xffbf00b8, 0xffc3007e, 0xffc6007b, 0x206d829b, + 0x225f8279, 0x82cc00b2, 0xffcd2613, 0xffce007d, 0x2c7d827c, 0x00e600af, 0xffea000f, 0xffeb00e4, 0x248982a0, 0xffef0074, 0x22af8280, 0x82fd00b2, + 0xfe280823, 0xff00b2ff, 0x010180ff, 0x020179ff, 0x07012800, 0x09017dff, 0x1c017fff, 0x200166ff, 0x2e01daff, 0x300181ff, 0x380198ff, 0x3a361782, + 0x4001b3ff, 0x4a01a0ff, 0x4c017cff, 0x4d019aff, 0x58016cff, 0xd982e6ff, 0x63016b35, 0x650192ff, 0x6901adff, 0x6c017bff, 0x6d010f00, 0x440191ff, + 0xb92b0533, 0xb9ffe501, 0xb9ff3102, 0x73000700, 0x11200527, 0xe228d582, 0x13006100, 0xd9ffdb01, 0xd9201d82, 0xd9241d82, 0x4a000600, 0xc6221f82, + 0xc7820b00, 0xca00ea28, 0xed000c00, 0x8782c8ff, 0x3784f120, 0x41000f22, 0x56221182, 0x3782ebff, 0xb3410e20, 0x05894406, 0x5b000630, 0xb800e5ff, + 0xcd00cbff, 0xdb01e4ff, 0x5182ecff, 0x5182eb20, 0x3782ed20, 0xdfff8130, 0xf3ffb500, 0xf0ffb700, 0xeaffc400, 0x0f82d900, 0xe0ffe628, 0xe0ff6c01, + 0x2b820100, 0x0400eb26, 0xc7ffd601, 0xf2200982, 0xf2203582, 0xf2203582, 0xd6221782, 0x0583f1ff, 0x022f8d82, 0x04000c0b, 0xac0e0000, 0x26006817, + 0x8b002500, 0x87122000, 0xe3ff230c, 0x0b87e4ff, 0x88110021, 0x20088509, 0x88068211, 0xe4ff2113, 0x1082a982, 0xd382028d, 0xff251086, 0xffd5ffab, + 0x250c85ed, 0x0000eaff, 0x0b85e9ff, 0xff270583, 0x0086ffe1, 0x83f5ff00, 0x8b0f8317, 0xebff2703, 0xf4ffd0ff, 0x1383f5ff, 0xce262182, 0x88ffefff, + 0x0d836aff, 0x840c0021, 0x00f12413, 0x8288ff00, 0xffd92403, 0x84c7ffc4, 0x21bd82a3, 0x1b84b3ff, 0xdfffc922, 0xdd200784, 0x038d0583, 0x3782ff20, + 0xff211187, 0x200988f0, 0x21b189a8, 0x17890000, 0x07a91f87, 0xa1b0ff21, 0x050f412b, 0xffedff23, 0x212b85ef, 0x0782e6ff, 0x03821420, 0x8b990292, + 0x328d4585, 0x1989dd8b, 0x11896787, 0x794109a1, 0x89278505, 0xe3ff2155, 0x00230b89, 0x85f2ff00, 0x21059d1f, 0x1f93f3ff, 0x39853ba3, 0xd9957185, + 0x0f205984, 0x04840584, 0xff59ff23, 0x980884d7, 0x0d6b4204, 0x980bf541, 0x23188c32, 0xe1ffe6ff, 0xe520f982, 0x2305c742, 0xd8ffe7ff, 0x0c9c1e8c, + 0x825cff21, 0x87a32039, 0xbfff2522, 0xd8ffe3ff, 0xd9380582, 0xc1ff6aff, 0xecffcbff, 0x1100a0ff, 0xabff1200, 0xe2ffc6ff, 0x0d00f0ff, 0xff212985, + 0x261582e9, 0x00f3ff00, 0x8219ff00, 0x00ef2203, 0x20058212, 0x201b8668, 0x155d41a0, 0x05931d85, 0xffeaff23, 0x211785ee, 0x0785ecff, 0xff23058b, + 0x82e4ffa7, 0x82302003, 0xff882695, 0xffb9ff58, 0x281d82ae, 0xff100010, 0xffb4ffaf, 0x098b42c4, 0x00b3ff2f, 0xff00000f, 0xfecbfff1, 0xff7efffe, + 0x222182ed, 0x82f0febc, 0x827c2011, 0x41282003, 0xed4111ab, 0x827f8913, 0x82c0206d, 0x21029267, 0x4f82d8ff, 0x93435782, 0x2758873d, 0xe6ffebff, + 0xebff0000, 0x0d20af82, 0xec200782, 0x4108b944, 0x27870669, 0xff2307a1, 0x82e7ffe6, 0x42eb2041, 0xff23053f, 0x9ee1ffe7, 0x07334533, 0x35820e20, + 0x03826420, 0x2f9bd120, 0x9be3ff21, 0x411b971d, 0x8f42054f, 0x2049982b, 0x211983ed, 0x0584dcff, 0x0582e220, 0x82081746, 0x2002890b, 0x210a8910, + 0x0b8953ff, 0x9d42098b, 0x23058305, 0xf5ff4eff, 0xab431982, 0x80ff2106, 0x02820b82, 0x00cdff23, 0x82678500, 0x2502820c, 0x6cfe6fff, 0x0882a7ff, + 0xff21028a, 0x9e0c8a48, 0x0bb5440a, 0xff212a99, 0x2f1b83c0, 0x1300f2ff, 0xf2ff0000, 0xe8ff85ff, 0xe9fe33ff, 0x17830d83, 0xee241382, 0xe0fe0000, + 0xa3240782, 0xbdffb7ff, 0x00231385, 0x8732ff00, 0x25078309, 0x0000d7ff, 0x0382c5ff, 0xa5ffec22, 0x88220582, 0x1583ceff, 0xff210387, 0x230987a4, + 0xdbff0000, 0x09970b89, 0x4306bb41, 0x31971291, 0x79445782, 0x05894214, 0xffe1ff29, 0xffd5ffed, 0x84e7ffdf, 0x820e203f, 0x84cb202d, 0x21049209, + 0x148771ff, 0x87c4ff21, 0x23079709, 0xc9ffe5ff, 0x45881b97, 0x0988e820, 0x2206f945, 0x82ffd4ff, 0xd2ff2509, 0xb5ffe4ff, 0xd9200582, 0x2107a541, + 0x2987b4ff, 0xff21078f, 0x20438829, 0x91098763, 0x31bd4507, 0x67884391, 0x0987b520, 0xff21078b, 0x43639779, 0xff231da3, 0x8badff9f, 0x00002347, + 0x3941c0ff, 0xc8ff210f, 0xff232183, 0x970000e7, 0x911f8363, 0x44fe2003, 0xff23221d, 0x82bdff55, 0xff662603, 0xff33ff7e, 0x2061825f, 0x22478261, + 0x82070007, 0xff6b2309, 0x7d44ff86, 0x6aff2308, 0x19820500, 0x92ff0026, 0x0fff36fe, 0x07280982, 0x1efe0000, 0x0cff0000, 0x02b10b82, 0x482a4745, + 0x05431393, 0x23768305, 0xbbffb4ff, 0x03910783, 0x00d5ff2b, 0xffbdff00, 0xffaeffe9, 0x220982bd, 0x86afffa5, 0x00122223, 0x200f8212, 0x8c0d86d2, + 0xcaff2306, 0x4f8777fe, 0x4a39ff21, 0x02240a83, 0x06009a00, 0x00220182, 0x01820b00, 0x10000122, 0x02200182, 0x12324782, 0x25000300, 0x04002900, + 0x34002c00, 0x38000900, 0x15823e00, 0x47004526, 0x49001900, 0x1c220182, 0x01824c00, 0x51001d28, 0x1e005400, 0x01825600, 0x5a002222, 0x23280182, + 0x5e005c00, 0x8a002400, 0x27220182, 0x01829600, 0xb1002824, 0x4982b400, 0xbd00bd26, 0xc1002d00, 0x2e220182, 0x0182c700, 0xd4002f28, 0x3000d500, + 0x0182d700, 0xda003222, 0x33240182, 0xde00dc00, 0xe0266d82, 0x3700e600, 0x0182ec00, 0xee003e22, 0x3f220182, 0x0182f700, 0xfc004022, 0x43080182, + 0x00fe0041, 0x014200ff, 0x00050104, 0x010a0144, 0x0146000a, 0x000d010d, 0x01180147, 0x0148001a, 0x0030012e, 0x0133014b, 0x014e0035, 0x00370137, + 0x01390151, 0x01520039, 0x003b013b, 0x01430153, 0x01540044, 0x00220182, 0x01820156, 0x5700ce08, 0x58015801, 0x5c015800, 0x59005e01, 0x8a018401, + 0x8e015c00, 0x63008f01, 0xd801d801, 0xdd016500, 0x6600dd01, 0xe101e001, 0xeb016700, 0x6900ed01, 0xff01ff01, 0x0e026c00, 0x6d001002, 0x30023002, + 0x33027000, 0x71003302, 0x45024502, 0x47027200, 0x73004802, 0x7b027a02, 0x7d027500, 0x77007d02, 0xa5027f02, 0xaa027800, 0x9f00af02, 0xc402b402, + 0xc602a500, 0xb600cf02, 0xda02d802, 0xdc02c000, 0xc300dc02, 0xde02de02, 0xe002c400, 0xc500e002, 0xe202e202, 0xe502c600, 0xc700e502, 0xe702e702, + 0xe902c800, 0xc900e902, 0xeb02eb02, 0xed02ca00, 0xcb00ed02, 0xef02ef02, 0xf102cc00, 0xcd00fd02, 0xff02ff02, 0x0103da00, 0xdb000103, 0x09008203, + 0x03dc00d5, 0x000e030e, 0x031003dd, 0x03de0010, 0x00120312, 0x031403df, 0x03e00014, 0x00160316, 0x031803e1, 0x03e20018, 0x001a031a, 0x031c03e3, + 0x03e4001c, 0x001e031e, 0x032003e5, 0x03e60020, 0x002a0322, 0x032f03e7, 0x03f00038, 0x00470343, 0x034d03fa, 0x03ff004f, 0x01540354, 0x03650302, + 0x03030169, 0x016f036d, 0x03780308, 0x030b0178, 0x018b0386, 0x038e030c, 0x0312019d, 0x01a003a0, 0x03a40322, 0x032301a4, 0x01a603a6, 0x03aa0324, + 0x032501aa, 0x01ae03ad, 0x03b00326, 0x032801b9, 0x01bd03bb, 0x03bf0332, 0x033501c4, 0x01cc03c6, 0x03d2033b, 0x034201d3, 0x01d503d5, 0x03d70344, + 0x034501d7, 0x01dc03d9, 0x03df0346, 0x034a01e4, 0x01e603e6, 0x03ea0350, 0x035101eb, 0x01fb03f0, 0x03fe0353, 0x045f01ff, 0x01040401, 0x040b0461, + 0x0465010c, 0x01100410, 0x04120467, 0x04680118, 0x0146041e, 0x0448046f, 0x04980148, 0x0157044a, 0x045f0499, 0x04a7015f, 0x01620462, 0x046404a8, + 0x04a90164, 0x01750470, 0x047704aa, 0x04b00177, 0x017c047b, 0x047f04b1, 0x04b3017f, 0x01820481, 0x048404b4, 0x04b60184, 0x01860486, 0x049704b7, + 0x04b8019b, 0x019d049d, 0x049f04bd, 0x04be01a0, 0x01a204a2, 0x04a604c0, 0x04c101a8, 0x01aa04aa, 0x04ac04c4, 0x04c501ae, 0x01b004b0, 0x04b204c8, + 0x04c901b2, 0x01ba04b4, 0x04bc04ca, 0x04d101bc, 0x01bf04bf, 0x04c104d2, 0x04d301c6, 0x01cb04c8, 0x04cf04d9, 0x04dd01cf, 0x01d204d2, 0x04d804de, + 0x04df01d8, 0x01dd04dd, 0x04e804e0, 0x04e101e8, 0x01ea04ea, 0x04f104e2, 0x04e301f1, 0x01f504f5, 0x010200e4, 0x82060074, 0x00192201, 0x2201820b, + 0x82100019, 0x00212201, 0x22018212, 0x82250021, 0x00022201, 0x22018226, 0x8227001c, 0x00132201, 0x22018228, 0x82290001, 0x00052201, 0x2201822e, + 0x822f000a, 0x000b2201, 0x22018230, 0x82330018, 0x00012201, 0x22018234, 0x82380016, 0x000e2201, 0x22018239, 0x823a000a, 0x001d2201, 0x2201823b, + 0x823c001b, 0x00122201, 0x2201823d, 0x823e000c, 0x00112201, 0x22018245, 0x82460006, 0x00072201, 0x22018247, 0x82490017, 0x00082201, 0x2801824c, + 0x00510004, 0x00040052, 0x22018253, 0x82540003, 0x00072201, 0x22018256, 0x825a0015, 0x00092201, 0x2201825c, 0x825d0014, 0x00092201, 0x2201825e, + 0x828a0010, 0x00072201, 0x22018296, 0x82b10001, 0x00222201, 0x220182b2, 0x82b30002, 0x00012201, 0x220182b4, 0x82bd0002, 0x00092201, 0x220182c1, + 0x82c70004, 0x00072801, 0x00d500d4, 0x82da0020, 0x00122201, 0x220182de, 0x82e40025, 0x00202201, 0x220182e6, 0x82ec0020, 0x001a2201, 0x220182ee, + 0x82f70014, 0x00072201, 0x220182fc, 0x82fe001f, 0x001f2201, 0x2a0182ff, 0x01040107, 0x011f0005, 0x820a010a, 0x0d3e0805, 0x02000d01, 0x18011801, + 0x19010300, 0x1d001901, 0x1a011a01, 0x2e010900, 0x07002e01, 0x2f012f01, 0x30012200, 0x1a003001, 0x33013301, 0x34011200, 0x14003401, 0x35013501, + 0x37010b00, 0x05823701, 0x39013922, 0x43220582, 0x1d824301, 0x44014422, 0x58281d82, 0x01005801, 0x5c015c01, 0x5d223582, 0x17825d01, 0x5e015e22, + 0x842e1782, 0x19008501, 0x86018601, 0x87012100, 0x0b828901, 0x8a018a22, 0x8e220b82, 0x05828f01, 0x01d82008, 0x012300d8, 0x00dd01dd, 0x01e0010d, + 0x012400e0, 0x00e101e1, 0x01eb011e, 0x010f00eb, 0x82ec01ec, 0x01ed2217, 0x280b82ed, 0x00ff01ff, 0x020e021e, 0x3a058210, 0x00300230, 0x0233020d, + 0x020f0033, 0x00450245, 0x02470213, 0x02010048, 0x827b027a, 0x027d2e05, 0x020e007d, 0x0085027f, 0x02860202, 0x281d8286, 0x008a0287, 0x02900205, + 0x081d8294, 0x98029532, 0x99020a00, 0x0c009902, 0xa0029a02, 0xa1020600, 0x1700a102, 0xa502a202, 0xaa020800, 0x0400aa02, 0xaf02ab02, 0xb4020300, + 0x0900b502, 0xb602b602, 0xb7224782, 0x2982b702, 0xb802b822, 0xb9220b82, 0x0b82b902, 0xba02ba22, 0xbb220b82, 0x0b82bb02, 0xbc02bc22, 0xbd226582, + 0x4782bd02, 0xbe02be22, 0xbf220b82, 0x0b82bf02, 0xc002c022, 0xc1220b82, 0x0b82c102, 0xc202c222, 0xc3220b82, 0x0b82c302, 0xc402c422, 0xc6228982, + 0x9582c602, 0xc702c722, 0xc8227782, 0x0b82c802, 0xc902c922, 0xca220b82, 0x0b82ca02, 0xcb02cb22, 0xcc220b82, 0x0b82cc02, 0xcd02cd22, 0xce220b82, + 0x0b82ce02, 0xcf02cf22, 0xd9220b82, 0xa782d902, 0xe502e522, 0xe72ecb82, 0x0b00e702, 0xe902e902, 0xeb021800, 0x0582eb02, 0xed02ed22, 0xef220582, + 0x0582ef02, 0xf202f222, 0xf4222982, 0x0582f402, 0xf702f622, 0xf8220582, 0x7d82f802, 0xf902f922, 0xfa22e382, 0x0b82fa02, 0xfb02fb22, 0xfc220b82, + 0x0b82fc02, 0xfd02fd22, 0xff280b82, 0x1500ff02, 0x01030103, 0x03220582, 0x05820303, 0x0e030e28, 0x10030e00, 0x05821003, 0x12031222, 0x14280582, + 0x0a001403, 0x16031603, 0x18220582, 0x05821803, 0x1a031a22, 0x1c220582, 0x05821c03, 0x1e031e22, 0x20340582, 0x1b002003, 0x22032203, 0x23030c00, + 0x09002303, 0x24032403, 0x252e0b82, 0x11002503, 0x26032603, 0x27031000, 0x0b822703, 0x28032822, 0x29220b82, 0x0b822903, 0x2a032a22, 0x2f340b82, + 0x0d003003, 0x31033103, 0x32032300, 0x0f003803, 0x47034303, 0x4d221182, 0x0b824f03, 0x54035422, 0x652e0b82, 0x1e006503, 0x69036603, 0x6d032400, + 0x11826f03, 0x78037822, 0x86342f82, 0x02008603, 0x87038703, 0x8a030500, 0x01008a03, 0x8b038b03, 0x8e227782, 0x17828e03, 0x8f038f28, 0x90031c00, + 0x1d829003, 0x91039122, 0x94287182, 0x0b009403, 0x97039703, 0x98282982, 0x16009803, 0x99039903, 0x9a22e382, 0x35829a03, 0x9b039b28, 0x9d031200, + 0x0b829d03, 0xa003a02e, 0xa4030400, 0x0300a403, 0xa603a603, 0xaa22d182, 0x0b82aa03, 0xad03ad22, 0xae284d82, 0x2200ae03, 0xb203b203, 0xb322fb82, + 0x5382b403, 0xb503b528, 0xb6032500, 0x7782b603, 0xb703b722, 0xb8227782, 0x2382b803, 0xb903b922, 0xbd222f82, 0x7182bd03, 0xbf03bf22, 0xc0287182, + 0x1300c003, 0xc103c103, 0xc2227782, 0x7182c203, 0xc303c32e, 0xc4030600, 0x0800c403, 0xc603c603, 0xc72e6582, 0x0700c703, 0xc803c803, 0xc9031700, + 0x7d82c903, 0xca03ca28, 0xcb031400, 0x2382cb03, 0xcc03cc28, 0xd2031a00, 0x1782d203, 0xd303d328, 0xd5031b00, 0x0582d503, 0xd703d722, 0xd9220582, + 0xbf82d903, 0xda03da22, 0xdb281d82, 0x1900dc03, 0xdf03df03, 0xe1220582, 0xd182e103, 0xe203e222, 0xe322a182, 0x7182e303, 0xe403e422, 0xe6229b82, + 0x5382e603, 0xea03ea28, 0xeb031d00, 0x3582eb03, 0xf003f022, 0xf122a182, 0x7d82f103, 0xf203f222, 0xf3224d82, 0x1782f303, 0xf503f522, 0xf622ad82, + 0x8982f603, 0xf803f822, 0xf9224782, 0x4782f903, 0xfa03fa22, 0xfb220b82, 0x0b82fb03, 0xfe03fe22, 0xff285382, 0x0800ff03, 0x02040104, 0x03250582, + 0x12000304, 0x31008204, 0x0b041400, 0x01000b04, 0x0c040c04, 0x10040300, 0x05821004, 0x12041234, 0x13040700, 0x25001304, 0x14041404, 0x15040900, + 0x0b821504, 0x16041622, 0x17220b82, 0x0b821704, 0x18041822, 0x1e2e0b82, 0x02001e04, 0x1f041f04, 0x20040600, 0x0b822004, 0x21042122, 0x22220b82, + 0x0b822204, 0x23042322, 0x24220b82, 0x0b822404, 0x25042522, 0x26220b82, 0x0b822604, 0x27042722, 0x28220b82, 0x0b822804, 0x29042922, 0x2a220b82, + 0x0b822a04, 0x2b042b22, 0x2c220b82, 0x0b822c04, 0x2d042d22, 0x2e220b82, 0x0b822e04, 0x2f042f22, 0x30220b82, 0x0b823004, 0x31043122, 0x32220b82, + 0x0b823204, 0x33043322, 0x34220b82, 0x0b823404, 0x35043522, 0x36280b82, 0x05003604, 0x37043704, 0x3822e382, 0x0b823804, 0x39043922, 0x3a220b82, + 0x0b823a04, 0x3b043b22, 0x3c220b82, 0x0b823c04, 0x3d043d22, 0x3e220b82, 0x0b823e04, 0x3f043f22, 0x40220b82, 0x0b824004, 0x41044122, 0x42220b82, + 0x0b824204, 0x43044322, 0x44220b82, 0x0b824404, 0x45044522, 0x4a2e0b82, 0x01004a04, 0x4b044b04, 0x4c040300, 0x0b824c04, 0x4d044d22, 0x4e220b82, + 0x0b824e04, 0x4f044f22, 0x50220b82, 0x0b825004, 0x51045122, 0x52220b82, 0x0b825204, 0x53045322, 0x54220b82, 0x0b825404, 0x55045522, 0x56220b82, + 0x0b825604, 0x57045722, 0x5f220b82, 0x05825f04, 0x62046228, 0x64040a00, 0x05826404, 0x7004702e, 0x71040c00, 0x09007104, 0x72047204, 0x73220b82, + 0x0b827304, 0x74047422, 0x75220b82, 0x0b827504, 0x04772008, 0x040e0077, 0x007b047b, 0x047c0422, 0x041a007c, 0x007f047f, 0x04810404, 0x04200081, + 0x82820482, 0x04842817, 0x040b0084, 0x82860486, 0x04982235, 0x341d8298, 0x00990499, 0x049a0402, 0x0406009a, 0x009b049b, 0x049f0405, 0x2289829f, + 0x82a004a0, 0x04a23483, 0x041500a2, 0x00a604a6, 0x04a7041c, 0x040700a7, 0x82a804a8, 0x04aa221d, 0x220582aa, 0x82ad04ad, 0x04ae2241, 0x225382ae, + 0x82b004b0, 0x04b22805, 0x041800b2, 0x82b504b5, 0x04b72217, 0x220582b7, 0x82b804b8, 0x04b92829, 0x041600b9, 0x82ba04ba, 0x04bc2241, 0x225382bc, + 0x82bf04bf, 0x04c122ad, 0x28dd82c1, 0x00c204c2, 0x04c3041d, 0x22c582c3, 0x82c404c4, 0x04c5220b, 0x340b82c5, 0x00c604c6, 0x04c8041b, 0x041100c8, + 0x00c904c9, 0x04ca0410, 0x2e4d82ca, 0x00cb04cb, 0x04cf040f, 0x040d00cf, 0x82d204d2, 0x04d82e0b, 0x041e00d8, 0x00dd04dd, 0x04e80423, 0x220b82e8, + 0x82ea04ea, 0x04f12217, 0x262382f1, 0x00f504f5, 0x82010023, 0x00f522e1, 0x08884c14, 0x1a240989, 0x1a001f00, 0x089b1788, 0x1c820620, 0x03820220, + 0x02210283, 0x20008300, 0x84048323, 0x82022003, 0x00023217, 0x00100000, 0x000a000b, 0x0016001d, 0x000c0011, 0x89118213, 0x82072002, 0x0001210a, + 0x00200183, 0x0c820582, 0x03240286, 0x04000300, 0x01200382, 0x0e200f82, 0x05220382, 0x05820900, 0x05821520, 0x07820f20, 0x022102c5, 0x20009d00, + 0x85918802, 0x9d052009, 0x241d8e2e, 0x00020006, 0x20138c06, 0x830d8201, 0x820682c5, 0x870583d9, 0x84012003, 0x205f8d69, 0x203f820b, 0x20208219, + 0x8303820b, 0x83112002, 0x19002304, 0x07842200, 0x05842020, 0x0320048f, 0x15201082, 0x03240382, 0x1b000300, 0x07830382, 0x5b820020, 0x21000322, + 0x79870d84, 0x17832783, 0x13832383, 0x87000221, 0x85b18d00, 0x00022615, 0x001d0004, 0x208f8209, 0x20038200, 0x85078801, 0x8505891d, 0x210f8955, + 0x8b850011, 0x0b201183, 0x83820483, 0x03840020, 0x1f834785, 0x20201783, 0x1e849d82, 0x19200488, 0x2985bd82, 0x13820320, 0x03215789, 0x20538500, + 0x82d38201, 0x20028418, 0x85058419, 0x850a8599, 0x970b853d, 0x001f2205, 0x241a821f, 0x00140014, 0x8503821a, 0x82108207, 0x001a2202, 0xdf05821a, + 0xa20e2002, 0x00172460, 0x8224001c, 0x00122427, 0x821e0018, 0x86082007, 0x88068203, 0x20138302, 0x23008600, 0x0008000d, 0x200ddf50, 0x83118218, + 0x8318201c, 0x20038204, 0x9d03821c, 0x20218502, 0x83378218, 0x8337877d, 0x20698b33, 0x8300a000, 0x958b8d2d, 0x00022532, 0x00000002, 0x08820585, + 0x1f2002d8, 0x0621598a, 0x21018b00, 0x00910002, 0x03858f83, 0x85000a21, 0x000c2201, 0x44018c07, 0x058305b3, 0x03223d87, 0x01880400, 0x85000521, + 0x00092201, 0x206b8209, 0x22038807, 0x43010002, 0x07850641, 0x0f820020, 0x27910393, 0x078f6587, 0x8f096d45, 0x07394319, 0x03000322, 0x04207382, + 0x278b0388, 0x0e001023, 0x20038f00, 0x0673440b, 0x0a200783, 0x0393c782, 0x23821620, 0xdb820c20, 0x13000c24, 0x03880f00, 0x65821482, 0x03830583, + 0x8b000d21, 0x00082101, 0x08210091, 0x21018700, 0x01850012, 0x33861720, 0x338b1787, 0x1f8b1393, 0x08200b85, 0x0b855384, 0x85001e21, 0x00002201, + 0x85108218, 0x22058561, 0x82170024, 0x82148201, 0x82062002, 0x22028303, 0x830c0002, 0x85002006, 0x0ba5460f, 0x83000221, 0x000c2200, 0x26068211, + 0x0001000c, 0x82030000, 0x82052003, 0x45042003, 0x052308d1, 0x83000400, 0x86108211, 0x05994102, 0x4f862220, 0x1f411486, 0x00022206, 0x204d820b, + 0x204b8207, 0x20378203, 0x22078203, 0x84150009, 0x860e200d, 0x00032428, 0x82160009, 0x2003870b, 0x220f820c, 0x82140014, 0x84002011, 0x82032005, + 0x84072057, 0x8401200d, 0x0000228d, 0x4521821d, 0x0020059b, 0x01216582, 0x20318300, 0x062f4500, 0x42000621, 0x30840583, 0x0120c184, 0x11200582, + 0x11857382, 0x06820320, 0x21420320, 0x84012006, 0x21108207, 0x51822200, 0xa3450387, 0x82032005, 0xa74b8735, 0x13df4207, 0x6b83138d, 0xa3420020, + 0x0002210c, 0x8509af42, 0x052f430b, 0x83051743, 0x0001211b, 0x22079742, 0x82050000, 0x83038d40, 0x210387fb, 0x63460000, 0x09494609, 0x02863282, + 0x07860c20, 0x1f200683, 0x03920483, 0x20076d41, 0x831b8401, 0x41088491, 0x19830af1, 0x19851d85, 0xbf460587, 0x00022105, 0x10220087, 0x8f840e00, + 0x1d000a24, 0x03840900, 0x1a821620, 0x0f001322, 0x0d200582, 0x02830382, 0x17000822, 0x0a820d8a, 0x1722028c, 0x0f821c00, 0x06822183, 0x6d45028a, + 0x0008210d, 0x18204985, 0x00222d84, 0x53840800, 0x14820120, 0x62010a24, 0x65189202, 0x4822182f, 0x23820400, 0xffff0024, 0x07821200, 0x02000124, + 0x11820300, 0x0c000824, 0xb9820d00, 0x10000f24, 0x19821100, 0x14001326, 0x16001500, 0x2e2b5382, 0x5a410700, 0xe4002045, 0x82545243, 0x52463405, + 0x5a002041, 0x204c4f4d, 0x414eb600, 0x88002056, 0x824d4f52, 0x5254220b, 0x201d824b, 0x20578300, 0x20578a13, 0x97978207, 0x202b8359, 0x202b8a14, + 0x202b8206, 0x93879809, 0xac0b202d, 0x9c0a202d, 0x20b58b2d, 0x3eb59a05, 0x73326318, 0x63920063, 0x00706d63, 0x696c6498, 0x64a00067, 0x006d6f6e, + 0x617266a6, 0x82ac0063, 0x00612210, 0x200584b6, 0x2c0584bc, 0x756e6cc8, 0x6cd0006d, 0x006c636f, 0x200584d6, 0x200584dc, 0x231682e2, 0x6fe80072, + 0x00220682, 0x058370ee, 0x6d73f42c, 0xfa007063, 0x31307373, 0x05820001, 0x06013222, 0x33220582, 0x05820c01, 0x12013422, 0x35220582, 0x05821801, + 0x1e013622, 0x37230582, 0x82742401, 0x2a012435, 0x42000000, 0x02210597, 0x05b74200, 0x0a000122, 0x18201384, 0x03260582, 0x17001600, 0x0f841900, + 0x05820920, 0xd9820420, 0x03840920, 0x2d820020, 0x09000822, 0x15201984, 0xa94b0584, 0x84052005, 0x8406200b, 0x42378505, 0x1f410527, 0x22698305, + 0x840b0001, 0x840c201d, 0x840d2005, 0x840e2005, 0x840f2005, 0x84102005, 0x84112005, 0x14360805, 0x36001a00, 0xee073004, 0xca08a008, 0x840f6e0f, + 0xc20fae0f, 0x1010e60f, 0x60104c10, 0x88107410, 0xb4109a10, 0x1411f610, 0xac116611, 0x6c120e12, 0xb0128012, 0xd184d212, 0xa7820120, 0x0102fb09, + 0x01fa00fa, 0x017102e7, 0x01d001d1, 0x01ce01cf, 0x01cc01cd, 0x01ca01cb, 0x02c801c9, 0x02320233, 0x02300231, 0x01e60128, 0x01e401e5, 0x01e201e3, + 0x01e001e1, 0x01de01df, 0x01dc01dd, 0x01da01db, 0x01d801d9, 0x01d601d7, 0x01d401d5, 0x01d201d3, 0x02e901e8, 0x02750273, 0x02760274, 0x02770272, + 0x01ea0152, 0x01ec01eb, 0x01ee01ed, 0x01f001ef, 0x01f201f1, 0x01f401f3, 0x01f601f5, 0x01f801f7, 0x01fa01f9, 0x01fc01fb, 0x02fe01fd, 0x04010200, + 0x020202fe, 0x02040203, 0x02060205, 0x02080207, 0x020a0209, 0x023b020b, 0x020e020d, 0x0410020f, 0x021102f8, 0x02140213, 0x02160215, 0x02180217, + 0x021b0219, 0x021e021c, 0x032f031d, 0x03310330, 0x03330332, 0x03350334, 0x03370336, 0x03390338, 0x033b033a, 0x033d033c, 0x033f033e, 0x03410340, + 0x03430342, 0x03450344, 0x03470346, 0x03490348, 0x034b034a, 0x034d034c, 0x034f034e, 0x03510350, 0x03530352, 0x03550354, 0x03570356, 0x03590358, + 0x035b035a, 0x035d035c, 0x035f035e, 0x03610360, 0x04630362, 0x036403ff, 0x03660365, 0x03680367, 0x036a0369, 0x036c036b, 0x036e036d, 0x0370036f, + 0x03720371, 0x03740373, 0x03020575, 0x03770376, 0x03780379, 0x037b037a, 0x037d037c, 0x037f037e, 0x03810380, 0x03830382, 0x05850384, 0x04010500, + 0x04cc04cb, 0x04ce04cd, 0x04d004cf, 0x04d204d1, 0x04d404d3, 0x04d604d5, 0x04d804d7, 0x04da04d9, 0x04dc04db, 0x04de04dd, 0x04e004df, 0x04e204e1, + 0x04e404e3, 0x04e604e5, 0x04ff01e7, 0x04e904e8, 0x04eb04ea, 0x04ed04ec, 0x04ef04ee, 0x04f104f0, 0x04f304f2, 0x04f504f4, 0x050305f6, 0x05050504, + 0x04f70406, 0x04fa04f9, 0x041a02fc, 0x02fb04fd, 0x0512020c, 0x000c050b, 0x69100001, 0x44f50195, 0x08280561, 0xdc010200, 0x7102eb00, 0x2d33e343, + 0x73026402, 0x75023003, 0x2f037402, 0xe543e301, 0xd2042705, 0xea01d304, 0xbd42eb01, 0xec012305, 0xf143d704, 0xdc042905, 0xf001f001, 0xde04dd04, + 0x2406f943, 0x04eb04fa, 0x07f143ec, 0x02ff012b, 0x04ef0400, 0x04f204f0, 0x15f943f5, 0x440b2944, 0x17241405, 0x76021902, 0x2038f743, 0x2bf94382, + 0x4340f743, 0xd82611f5, 0xd904db04, 0xdd43da04, 0x05034406, 0xed04ea2e, 0xf104ee04, 0xf404f304, 0xf6040102, 0x230bf343, 0xe904e804, 0x210dd743, + 0xd9431802, 0x43162008, 0x62080adb, 0x000a00eb, 0x00460045, 0x00480047, 0x004a0049, 0x004c004b, 0x004e004d, 0x0050004f, 0x00520051, 0x00540053, + 0x00560055, 0x00580057, 0x005a0059, 0x005c005b, 0x005e005d, 0x00860085, 0x00890087, 0x008b008a, 0x0090008d, 0x00940092, 0x00bc00bb, 0x00be00bd, + 0x00c000bf, 0x00c200c1, 0x00c400c3, 0x18c600c5, 0x230b7578, 0xce00cd00, 0x07257818, 0xee005008, 0xf000ef00, 0xf200f100, 0xf400f300, 0xf600f500, + 0xf800f700, 0xfa00f900, 0xfc00fb00, 0xfe00fd00, 0x0001ff00, 0x02010101, 0x04010301, 0x06010501, 0x30010701, 0x36013401, 0x3a013801, 0x42013c01, + 0x46014401, 0x4d014a01, 0x7c025a01, 0x18027e02, 0x340ad179, 0xa102a002, 0xa302a202, 0xa502a402, 0xa702a602, 0xa902a802, 0xe1791802, 0x0281080a, + 0x02b102b0, 0x02b302b2, 0x02b502b4, 0x02b902b7, 0x02bd02bb, 0x02c102bf, 0x02c502c3, 0x02c902c7, 0x02cd02cb, 0x02d102cf, 0x02d502d3, 0x02d902d7, + 0x02dd02db, 0x02e102df, 0x02e602e4, 0x02ea02e8, 0x02ee02ec, 0x02f202f0, 0x02f602f4, 0x02fb02f9, 0x03ff02fd, 0x03030301, 0x03070305, 0x030b0309, + 0x030f030d, 0x03130311, 0x03170315, 0x031b0319, 0x031f031d, 0x03230321, 0x03280326, 0x032c032a, 0xa379182e, 0xa3680808, 0xa503a403, 0xa703a603, + 0xa903a803, 0xab03aa03, 0xc303ac03, 0xc503c403, 0xc703c603, 0xc903c803, 0xcb03ca03, 0xcd03cc03, 0xcf03ce03, 0xd103d003, 0xd403d203, 0xd803d603, + 0xef03da03, 0xf303f103, 0x08040104, 0x14040e04, 0x7f047e04, 0x87048304, 0x0a050805, 0x00000600, 0x12000600, 0x42002a00, 0x72005a00, 0x03008a00, + 0x01201182, 0x01241182, 0x01009000, 0x03200b82, 0x01220582, 0x178a4d00, 0x178a7820, 0x178a4e20, 0x17896020, 0x8ae10221, 0x89482017, 0xce032117, + 0x3020178a, 0xd020178a, 0x1820178a, 0x04231789, 0x82020049, 0x00a82a01, 0x010000ac, 0x00270124, 0x09694805, 0x062ca382, 0x5f026102, 0x63026202, + 0x0d056002, 0x06201982, 0x4e26a782, 0xce03e102, 0x3982d003, 0xbd820420, 0x08000128, 0x32060100, 0xdb823600, 0xae00a438, 0xca00b800, 0x0e01fc00, + 0x4a011801, 0x7e016401, 0xba019001, 0x6282f601, 0x02222008, 0x024e023c, 0x029c028a, 0x02e002b6, 0x032403f2, 0x0338032e, 0x037c034a, 0x03900386, + 0x82b4039a, 0xe0380853, 0x3c040a04, 0x68044604, 0x94048204, 0xd804c604, 0x1c05f204, 0x38052e05, 0x4c054205, 0x80055605, 0xd405aa05, 0x2806fe05, + 0x0e000600, 0x1a001400, 0x26002000, 0x80022c00, 0xa922c182, 0x05821e04, 0x7f02ad22, 0xa8220582, 0x05822004, 0x8202ab22, 0xaa220582, 0x05829904, + 0x0100ac26, 0xa6040400, 0xad200982, 0x02210983, 0x200982bc, 0x2a0382a9, 0x040c0006, 0x010200aa, 0x84a804ba, 0x20578d1b, 0x20578488, 0x20578436, + 0x20578487, 0x22058238, 0x843a04ab, 0x849b2057, 0x82022057, 0x040c228b, 0x220b8295, 0x83d602a9, 0x20698449, 0x204d92ac, 0x204d848c, 0x204d8448, + 0x204d848b, 0x20a58446, 0x204d84da, 0x224d849d, 0x83080003, 0xae0421d9, 0xe7204f84, 0xb0209984, 0xad210b82, 0x21198600, 0x1984e902, 0x1984eb20, + 0x1984b220, 0x03218184, 0x205d84e0, 0x231184b4, 0x000c0005, 0x22054153, 0x84f10224, 0x84f3202f, 0x82b6202f, 0x04ad220b, 0x22058297, 0x828f02a8, + 0x00aa3205, 0x00100007, 0x001e0018, 0x002a0024, 0x04360030, 0x246782b8, 0x02a900aa, 0x204d8491, 0x20ab844a, 0x20ab8490, 0x20ab844c, 0x22058293, + 0x419f04aa, 0xb9200851, 0xa9240982, 0x0a000400, 0x16244782, 0xfe021c00, 0x03210f83, 0x206d8400, 0x206d84bb, 0x21d78ba1, 0x1f840403, 0x1f840a20, + 0xbd8abd20, 0x11840e20, 0x1184bf20, 0xc120938f, 0x96209386, 0x62209384, 0x95209384, 0x64209384, 0xab220582, 0x93841403, 0x8d41a320, 0x84c4200a, + 0x84c22079, 0x063741e1, 0x84d50321, 0x82c6203d, 0x03ad2205, 0x210582d3, 0x254100a8, 0x8499200b, 0x8470201d, 0x84d9201d, 0x8272205b, 0x04ab2205, + 0x41438474, 0x25200561, 0xc8202384, 0x2012d941, 0x2019849b, 0x2099841f, 0x203d849a, 0x22058221, 0x849d02ab, 0x42118399, 0xa720057f, 0x20087f42, + 0x0a7f42bd, 0xfb84ab20, 0x5792a920, 0xa922d383, 0x57843704, 0x5784a220, 0x95843920, 0x57843b20, 0x85419c20, 0x84962008, 0x0001244d, 0x84ad0404, + 0x20098345, 0x0b354249, 0x82af0421, 0x02a9220d, 0x206984e8, 0x21198bb1, 0x1984ea02, 0x1984ec20, 0x9141b320, 0x84e1200a, 0x42b520d3, 0xf220104f, + 0xa9221182, 0x2f84f402, 0x0b82b720, 0x9804ad22, 0xa8220582, 0x0582aa02, 0x9743aa20, 0x84ac200e, 0x844b2043, 0x84ab20bf, 0x824d20bf, 0x02ab2205, + 0x20bf84ae, 0x20bf88a0, 0x0e4542ba, 0x0f83ff20, 0x84010321, 0x84bc2063, 0x42a22063, 0x05200c45, 0x0b201f84, 0xbe201f84, 0x0f20b38a, 0xc0201184, + 0x20124941, 0x208984b1, 0x20898463, 0x208984b0, 0x22058265, 0x841503ab, 0x42a42089, 0xc5200a3b, 0xc3206f84, 0x200c3b42, 0x203d84d6, 0x220582c7, + 0x42d403ad, 0xb420103b, 0x71201d84, 0xda201d84, 0x73205b84, 0xab220582, 0x3b427504, 0x8426200a, 0x84c92023, 0x00012499, 0x842b0304, 0x200983f1, + 0x2009882d, 0x2009882c, 0x4209842e, 0xa7200b9f, 0x02211183, 0x205d84a6, 0x22058247, 0x84db02ab, 0x849e20b9, 0x21298ab9, 0x69845804, 0xc5846020, + 0x2f845a20, 0x8d845c20, 0x8d845e20, 0x5920298b, 0x61202984, 0x5b202984, 0x5d202984, 0x5f202984, 0x66202990, 0x6e202984, 0x68202984, 0x6a202984, + 0x6c202984, 0x67202990, 0x6f202984, 0x69202984, 0x6b202984, 0x6d202984, 0xef822984, 0x84a50421, 0x024008db, 0x25001100, 0x00002900, 0x2d002b00, + 0x2f000500, 0x08003400, 0x3b003600, 0x3d000e00, 0x14003e00, 0x49004500, 0x4b001600, 0x1b004d00, 0x54004f00, 0x56001e00, 0x24005b00, 0x5e005d00, + 0x81002a00, 0x2c220182, 0x01828300, 0x86002d22, 0x2e220182, 0x01828900, 0x8d002f22, 0x30280182, 0x9b009800, 0xd0003100, 0x35200182, 0x2208cd46, + 0x82060001, 0x00012679, 0x03080302, 0x0de34609, 0x05070527, 0x05090508, 0x06654d0a, 0xba02062c, 0xcc02bb02, 0x4f03cd02, 0x3f8c5803, 0x0d820120, + 0x7b010123, 0x08f74600, 0x00400023, 0x20b78201, 0x2a5b8202, 0x00be010e, 0x004a0003, 0x82bc014d, 0x8a4d2067, 0x8a1c2023, 0x84bf2023, 0x01502223, + 0x202382bd, 0x20178250, 0x89318201, 0x822a204d, 0x820c201d, 0x822020f5, 0x01042219, 0x202382bb, 0x2009844a, 0x830982c1, 0x01042289, 0x200986c0, + 0x22378203, 0x8b950057, 0xde01219d, 0x4b204f84, 0x6f20138c, 0xbb201384, 0xf520138c, 0x36201384, 0x02281388, 0x02001c00, 0x2d022c02, 0x0a20118a, + 0x2e221182, 0x11822f02, 0x2f000224, 0x198a4f00, 0x0c001e3a, 0x47024502, 0x48024602, 0x67024902, 0x69026802, 0x6b026a02, 0x6d026c02, 0x0c2a2582, + 0x28002700, 0x33002b00, 0xcb4a3500, 0x004b2106, 0x4c05b94a, 0x002908c5, 0x0203000c, 0x026f026e, 0x262f826f, 0x00490003, 0x8a6a024b, 0x2e44085f, + 0x5a021400, 0x58025e02, 0x57025502, 0x5b025602, 0x5d025902, 0x4f025c02, 0x4b024a02, 0x4d024c02, 0x1a004e02, 0x53021c00, 0x02006502, 0x14000400, + 0x00001d00, 0x66026602, 0x70020a00, 0x0b007002, 0x94048d04, 0x6f896382, 0x04235182, 0x82700294, 0x048e2c17, 0x0490048f, 0x04660291, 0x82930492, + 0x824e204b, 0x824b204d, 0x00652459, 0x8253021a, 0x824a2053, 0x86022051, 0x02552451, 0x8e0a005e, 0x825b2097, 0x20998989, 0x23958259, 0x001b005a, + 0x0b237918, 0x8d821c20, 0x35821420, 0xa3841420, 0x6382b188, 0xa582af82, 0x8383858a, 0xa78da982, 0x92049122, 0xa782a989, 0x17009328, 0x18001900, + 0x67821600, 0x1d245383, 0x15001c00, 0x02223582, 0x61820600, 0x00001a24, 0x01821c00, 0x4a020128, 0x02004f02, 0xc5825302, 0x55020822, 0x0926b982, + 0x65026502, 0xf7411300, 0x8281200c, 0x8201200d, 0x82062013, 0x00012835, 0x00030008, 0x82120001, 0x846c2003, 0x8200200f, 0x00023465, 0x01940103, + 0x01000094, 0x00c701c5, 0x021f0201, 0x88040025, 0x00022a43, 0x010a003c, 0x01c601c7, 0x281982c5, 0x02210220, 0x02230222, 0x89238224, 0x1a2008c3, + 0x3e020a00, 0x73007a00, 0x3f027400, 0x41024002, 0x43024202, 0x02004402, 0x14000100, 0x00001d00, 0xcbbafa05, 0x00006bed, +}; + diff --git a/src/automata-imgui/imgui_impl_dx11.cpp b/src/automata-imgui/imgui_impl_dx11.cpp new file mode 100644 index 0000000..9365ff8 --- /dev/null +++ b/src/automata-imgui/imgui_impl_dx11.cpp @@ -0,0 +1,551 @@ +// dear imgui: Renderer Backend for DirectX11 +// This needs to be used along with a Platform Backend (e.g. Win32) + +// Implemented features: +// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! +// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. + +// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer. +// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). +// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. +// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. +// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. +// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). +// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. +// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. +// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions. +// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example. +// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2016-05-07: DirectX11: Disabling depth-write. + +#include "imgui.h" +#include "imgui_impl_dx11.h" + +// DirectX +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. +#endif + +// DirectX data +static ID3D11Device* g_pd3dDevice = NULL; +static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; +static IDXGIFactory* g_pFactory = NULL; +static ID3D11Buffer* g_pVB = NULL; +static ID3D11Buffer* g_pIB = NULL; +static ID3D11VertexShader* g_pVertexShader = NULL; +static ID3D11InputLayout* g_pInputLayout = NULL; +static ID3D11Buffer* g_pVertexConstantBuffer = NULL; +static ID3D11PixelShader* g_pPixelShader = NULL; +static ID3D11SamplerState* g_pFontSampler = NULL; +static ID3D11ShaderResourceView*g_pFontTextureView = NULL; +static ID3D11RasterizerState* g_pRasterizerState = NULL; +static ID3D11BlendState* g_pBlendState = NULL; +static ID3D11DepthStencilState* g_pDepthStencilState = NULL; +static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; + +struct VERTEX_CONSTANT_BUFFER +{ + float mvp[4][4]; +}; + +static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) +{ + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = draw_data->DisplaySize.x; + vp.Height = draw_data->DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); + + // Setup shader and vertex buffers + unsigned int stride = sizeof(ImDrawVert); + unsigned int offset = 0; + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->GSSetShader(NULL, NULL, 0); + ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. + ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. + ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. + + // Setup blend state + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); + ctx->RSSetState(g_pRasterizerState); +} + +// Render function +void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) +{ + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + + // Create and grow vertex/index buffers if needed + if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) + { + if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } + g_VertexBufferSize = draw_data->TotalVtxCount + 5000; + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + return; + } + if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) + { + if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } + g_IndexBufferSize = draw_data->TotalIdxCount + 10000; + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) + return; + } + + // Upload vertex/index data into a single contiguous GPU buffer + D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + return; + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + return; + ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; + ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.Size; + idx_dst += cmd_list->IdxBuffer.Size; + } + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); + + // Setup orthographic projection matrix into our constant buffer + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. + { + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) + return; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = draw_data->DisplayPos.x; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; + float T = draw_data->DisplayPos.y; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; + float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.5f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, + }; + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); + } + + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE + { + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + UINT StencilRef; + ID3D11DepthStencilState* DepthStencilState; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + ID3D11GeometryShader* GS; + UINT PSInstancesCount, VSInstancesCount, GSInstancesCount; + ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount); + + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup desired DX state + ImGui_ImplDX11_SetupRenderState(draw_data, ctx); + + // Render command lists + // (Because we merged all buffers into a single one, we maintain our own offset into them) + int global_idx_offset = 0; + int global_vtx_offset = 0; + ImVec2 clip_off = draw_data->DisplayPos; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback != NULL) + { + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplDX11_SetupRenderState(draw_data, ctx); + else + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + // Apply scissor/clipping rectangle + const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; + ctx->RSSetScissorRects(1, &r); + + // Bind texture, Draw + ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId; + ctx->PSSetShaderResources(0, 1, &texture_srv); + ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); + } + } + global_idx_offset += cmd_list->IdxBuffer.Size; + global_vtx_offset += cmd_list->VtxBuffer.Size; + } + + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); +} + +static void ImGui_ImplDX11_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + + // Upload texture to graphics system + { + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + + ID3D11Texture2D* pTexture = NULL; + D3D11_SUBRESOURCE_DATA subResource; + subResource.pSysMem = pixels; + subResource.SysMemPitch = desc.Width * 4; + subResource.SysMemSlicePitch = 0; + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); + + // Create texture view + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + ZeroMemory(&srvDesc, sizeof(srvDesc)); + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = desc.MipLevels; + srvDesc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + pTexture->Release(); + } + + // Store our identifier + io.Fonts->SetTexID((ImTextureID)g_pFontTextureView); + + // Create texture sampler + { + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); + } +} + +bool ImGui_ImplDX11_CreateDeviceObjects() +{ + if (!g_pd3dDevice) + return false; + if (g_pFontSampler) + ImGui_ImplDX11_InvalidateDeviceObjects(); + + // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) + // If you would like to use this DX11 sample code but remove this dependency you can: + // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] + // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. + // See https://github.com/ocornut/imgui/pull/638 for sources and details. + + // Create the vertex shader + { + static const char* vertexShader = + "cbuffer vertexBuffer : register(b0) \ + {\ + float4x4 ProjectionMatrix; \ + };\ + struct VS_INPUT\ + {\ + float2 pos : POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + \ + struct PS_INPUT\ + {\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + \ + PS_INPUT main(VS_INPUT input)\ + {\ + PS_INPUT output;\ + output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ + output.col = input.col;\ + output.uv = input.uv;\ + return output;\ + }"; + + ID3DBlob* vertexShaderBlob; + if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL))) + return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! + if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK) + { + vertexShaderBlob->Release(); + return false; + } + + // Create the input layout + D3D11_INPUT_ELEMENT_DESC local_layout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + { + vertexShaderBlob->Release(); + return false; + } + vertexShaderBlob->Release(); + + // Create the constant buffer + { + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); + } + } + + // Create the pixel shader + { + static const char* pixelShader = + "struct PS_INPUT\ + {\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + sampler sampler0;\ + Texture2D texture0;\ + \ + float4 main(PS_INPUT input) : SV_Target\ + {\ + float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ + return out_col; \ + }"; + + ID3DBlob* pixelShaderBlob; + if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL))) + return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! + if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK) + { + pixelShaderBlob->Release(); + return false; + } + pixelShaderBlob->Release(); + } + + // Create the blending setup + { + D3D11_BLEND_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.AlphaToCoverageEnable = false; + desc.RenderTarget[0].BlendEnable = true; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); + } + + // Create the rasterizer state + { + D3D11_RASTERIZER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.FillMode = D3D11_FILL_SOLID; + desc.CullMode = D3D11_CULL_NONE; + desc.ScissorEnable = true; + desc.DepthClipEnable = true; + g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); + } + + // Create depth-stencil State + { + D3D11_DEPTH_STENCIL_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.DepthEnable = false; + desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + desc.DepthFunc = D3D11_COMPARISON_ALWAYS; + desc.StencilEnable = false; + desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + desc.BackFace = desc.FrontFace; + g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); + } + + ImGui_ImplDX11_CreateFontsTexture(); + + return true; +} + +void ImGui_ImplDX11_InvalidateDeviceObjects() +{ + if (!g_pd3dDevice) + return; + + if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } + if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. + if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } + if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } + + if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } + if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } + if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } + if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } + if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } + if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } + if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } +} + +bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) +{ + // Setup backend capabilities flags + ImGuiIO& io = ImGui::GetIO(); + io.BackendRendererName = "imgui_impl_dx11"; + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. + + // Get factory from device + IDXGIDevice* pDXGIDevice = NULL; + IDXGIAdapter* pDXGIAdapter = NULL; + IDXGIFactory* pFactory = NULL; + + if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) + if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) + if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) + { + g_pd3dDevice = device; + g_pd3dDeviceContext = device_context; + g_pFactory = pFactory; + } + if (pDXGIDevice) pDXGIDevice->Release(); + if (pDXGIAdapter) pDXGIAdapter->Release(); + g_pd3dDevice->AddRef(); + g_pd3dDeviceContext->AddRef(); + + return true; +} + +void ImGui_ImplDX11_Shutdown() +{ + ImGui_ImplDX11_InvalidateDeviceObjects(); + if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; } + if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } + if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; } +} + +void ImGui_ImplDX11_NewFrame() +{ + if (!g_pFontSampler) + ImGui_ImplDX11_CreateDeviceObjects(); +} \ No newline at end of file diff --git a/src/automata-imgui/imgui_impl_dx11.h b/src/automata-imgui/imgui_impl_dx11.h new file mode 100644 index 0000000..3322ad3 --- /dev/null +++ b/src/automata-imgui/imgui_impl_dx11.h @@ -0,0 +1,25 @@ +// dear imgui: Renderer Backend for DirectX11 +// This needs to be used along with a Platform Backend (e.g. Win32) + +// Implemented features: +// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! +// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. + +// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +#pragma once +#include "imgui.h" // IMGUI_IMPL_API + +struct ID3D11Device; +struct ID3D11DeviceContext; + +IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); +IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); + +// Use if you want to reset your rendering device without losing Dear ImGui state. +IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); \ No newline at end of file diff --git a/src/automata-imgui/imgui_impl_dx12.cpp b/src/automata-imgui/imgui_impl_dx12.cpp new file mode 100644 index 0000000..da7425f --- /dev/null +++ b/src/automata-imgui/imgui_impl_dx12.cpp @@ -0,0 +1,700 @@ +// dear imgui: Renderer Backend for DirectX12 +// This needs to be used along with a Platform Backend (e.g. Win32) + +// Implemented features: +// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! +// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. + +// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'. +// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. +// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. + +// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer. +// 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically. +// 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning. +// 2020-09-08: DirectX12: Clarified support for building on 32-bit systems by redefining ImTextureID. +// 2019-10-18: DirectX12: *BREAKING CHANGE* Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function. +// 2019-05-29: DirectX12: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. +// 2019-04-30: DirectX12: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. +// 2019-03-29: Misc: Various minor tidying up. +// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). +// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. +// 2018-06-12: DirectX12: Moved the ID3D12GraphicsCommandList* parameter from NewFrame() to RenderDrawData(). +// 2018-06-08: Misc: Extracted imgui_impl_dx12.cpp/.h away from the old combined DX12+Win32 example. +// 2018-06-08: DirectX12: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle (to ease support for future multi-viewport). +// 2018-02-22: Merged into master with all Win32 code synchronized to other examples. + +#include "imgui.h" +#include "imgui_impl_dx12.h" + +// DirectX +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. +#endif + +// DirectX data +static ID3D12Device* g_pd3dDevice = NULL; +static ID3D12RootSignature* g_pRootSignature = NULL; +static ID3D12PipelineState* g_pPipelineState = NULL; +static DXGI_FORMAT g_RTVFormat = DXGI_FORMAT_UNKNOWN; +static ID3D12Resource* g_pFontTextureResource = NULL; +static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {}; +static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {}; + +struct FrameResources +{ + ID3D12Resource* IndexBuffer; + ID3D12Resource* VertexBuffer; + int IndexBufferSize; + int VertexBufferSize; +}; +static FrameResources* g_pFrameResources = NULL; +static UINT g_numFramesInFlight = 0; +static UINT g_frameIndex = UINT_MAX; + +template +static void SafeRelease(T*& res) +{ + if (res) + res->Release(); + res = NULL; +} + +struct VERTEX_CONSTANT_BUFFER +{ + float mvp[4][4]; +}; + +static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, FrameResources* fr) +{ + // Setup orthographic projection matrix into our constant buffer + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). + VERTEX_CONSTANT_BUFFER vertex_constant_buffer; + { + float L = draw_data->DisplayPos.x; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; + float T = draw_data->DisplayPos.y; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; + float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.5f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, + }; + memcpy(&vertex_constant_buffer.mvp, mvp, sizeof(mvp)); + } + + // Setup viewport + D3D12_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D12_VIEWPORT)); + vp.Width = draw_data->DisplaySize.x; + vp.Height = draw_data->DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); + + // Bind shader and vertex buffers + unsigned int stride = sizeof(ImDrawVert); + unsigned int offset = 0; + D3D12_VERTEX_BUFFER_VIEW vbv; + memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW)); + vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset; + vbv.SizeInBytes = fr->VertexBufferSize * stride; + vbv.StrideInBytes = stride; + ctx->IASetVertexBuffers(0, 1, &vbv); + D3D12_INDEX_BUFFER_VIEW ibv; + memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW)); + ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress(); + ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx); + ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; + ctx->IASetIndexBuffer(&ibv); + ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->SetPipelineState(g_pPipelineState); + ctx->SetGraphicsRootSignature(g_pRootSignature); + ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0); + + // Setup blend factor + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendFactor(blend_factor); +} + +// Render function +void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx) +{ + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + + // FIXME: I'm assuming that this only gets called once per frame! + // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. + g_frameIndex = g_frameIndex + 1; + FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight]; + + // Create and grow vertex/index buffers if needed + if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount) + { + SafeRelease(fr->VertexBuffer); + fr->VertexBufferSize = draw_data->TotalVtxCount + 5000; + D3D12_HEAP_PROPERTIES props; + memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); + props.Type = D3D12_HEAP_TYPE_UPLOAD; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + D3D12_RESOURCE_DESC desc; + memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC)); + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Width = fr->VertexBufferSize * sizeof(ImDrawVert); + desc.Height = 1; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->VertexBuffer)) < 0) + return; + } + if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount) + { + SafeRelease(fr->IndexBuffer); + fr->IndexBufferSize = draw_data->TotalIdxCount + 10000; + D3D12_HEAP_PROPERTIES props; + memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); + props.Type = D3D12_HEAP_TYPE_UPLOAD; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + D3D12_RESOURCE_DESC desc; + memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC)); + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Width = fr->IndexBufferSize * sizeof(ImDrawIdx); + desc.Height = 1; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->IndexBuffer)) < 0) + return; + } + + // Upload vertex/index data into a single contiguous GPU buffer + void* vtx_resource, *idx_resource; + D3D12_RANGE range; + memset(&range, 0, sizeof(D3D12_RANGE)); + if (fr->VertexBuffer->Map(0, &range, &vtx_resource) != S_OK) + return; + if (fr->IndexBuffer->Map(0, &range, &idx_resource) != S_OK) + return; + ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource; + ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.Size; + idx_dst += cmd_list->IdxBuffer.Size; + } + fr->VertexBuffer->Unmap(0, &range); + fr->IndexBuffer->Unmap(0, &range); + + // Setup desired DX state + ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr); + + // Render command lists + // (Because we merged all buffers into a single one, we maintain our own offset into them) + int global_vtx_offset = 0; + int global_idx_offset = 0; + ImVec2 clip_off = draw_data->DisplayPos; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback != NULL) + { + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr); + else + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + // Apply Scissor, Bind texture, Draw + const D3D12_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; + if (r.right > r.left && r.bottom > r.top && pcmd->TextureId != nullptr) + { + ctx->SetGraphicsRootDescriptorTable(1, *(D3D12_GPU_DESCRIPTOR_HANDLE*)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0); + } + } + } + global_idx_offset += cmd_list->IdxBuffer.Size; + global_vtx_offset += cmd_list->VtxBuffer.Size; + } +} + +static void ImGui_ImplDX12_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + + // Upload texture to graphics system + { + D3D12_HEAP_PROPERTIES props; + memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); + props.Type = D3D12_HEAP_TYPE_DEFAULT; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + + D3D12_RESOURCE_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + desc.Alignment = 0; + desc.Width = width; + desc.Height = height; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + + ID3D12Resource* pTexture = NULL; + g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, + D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture)); + + UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u); + UINT uploadSize = height * uploadPitch; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Alignment = 0; + desc.Width = uploadSize; + desc.Height = 1; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + + props.Type = D3D12_HEAP_TYPE_UPLOAD; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + + ID3D12Resource* uploadBuffer = NULL; + HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, + D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer)); + IM_ASSERT(SUCCEEDED(hr)); + + void* mapped = NULL; + D3D12_RANGE range = { 0, uploadSize }; + hr = uploadBuffer->Map(0, &range, &mapped); + IM_ASSERT(SUCCEEDED(hr)); + for (int y = 0; y < height; y++) + memcpy((void*) ((uintptr_t) mapped + y * uploadPitch), pixels + y * width * 4, width * 4); + uploadBuffer->Unmap(0, &range); + + D3D12_TEXTURE_COPY_LOCATION srcLocation = {}; + srcLocation.pResource = uploadBuffer; + srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srcLocation.PlacedFootprint.Footprint.Width = width; + srcLocation.PlacedFootprint.Footprint.Height = height; + srcLocation.PlacedFootprint.Footprint.Depth = 1; + srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch; + + D3D12_TEXTURE_COPY_LOCATION dstLocation = {}; + dstLocation.pResource = pTexture; + dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dstLocation.SubresourceIndex = 0; + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = pTexture; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + + ID3D12Fence* fence = NULL; + hr = g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); + IM_ASSERT(SUCCEEDED(hr)); + + HANDLE event = CreateEvent(0, 0, 0, 0); + IM_ASSERT(event != NULL); + + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.NodeMask = 1; + + ID3D12CommandQueue* cmdQueue = NULL; + hr = g_pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue)); + IM_ASSERT(SUCCEEDED(hr)); + + ID3D12CommandAllocator* cmdAlloc = NULL; + hr = g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc)); + IM_ASSERT(SUCCEEDED(hr)); + + ID3D12GraphicsCommandList* cmdList = NULL; + hr = g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList)); + IM_ASSERT(SUCCEEDED(hr)); + + cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL); + cmdList->ResourceBarrier(1, &barrier); + + hr = cmdList->Close(); + IM_ASSERT(SUCCEEDED(hr)); + + cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList); + hr = cmdQueue->Signal(fence, 1); + IM_ASSERT(SUCCEEDED(hr)); + + fence->SetEventOnCompletion(1, event); + WaitForSingleObject(event, INFINITE); + + cmdList->Release(); + cmdAlloc->Release(); + cmdQueue->Release(); + CloseHandle(event); + fence->Release(); + uploadBuffer->Release(); + + // Create texture view + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc; + ZeroMemory(&srvDesc, sizeof(srvDesc)); + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = desc.MipLevels; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, g_hFontSrvCpuDescHandle); + SafeRelease(g_pFontTextureResource); + g_pFontTextureResource = pTexture; + } + + // Store our identifier + static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet."); + io.Fonts->SetTexID((ImTextureID)g_hFontSrvGpuDescHandle.ptr); +} + +bool ImGui_ImplDX12_CreateDeviceObjects() +{ + if (!g_pd3dDevice) + return false; + if (g_pPipelineState) + ImGui_ImplDX12_InvalidateDeviceObjects(); + + // Create the root signature + { + D3D12_DESCRIPTOR_RANGE descRange = {}; + descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + descRange.NumDescriptors = 1; + descRange.BaseShaderRegister = 0; + descRange.RegisterSpace = 0; + descRange.OffsetInDescriptorsFromTableStart = 0; + + D3D12_ROOT_PARAMETER param[2] = {}; + + param[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + param[0].Constants.ShaderRegister = 0; + param[0].Constants.RegisterSpace = 0; + param[0].Constants.Num32BitValues = 16; + param[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; + + param[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + param[1].DescriptorTable.NumDescriptorRanges = 1; + param[1].DescriptorTable.pDescriptorRanges = &descRange; + param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_STATIC_SAMPLER_DESC staticSampler = {}; + staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + staticSampler.MipLODBias = 0.f; + staticSampler.MaxAnisotropy = 0; + staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + staticSampler.MinLOD = 0.f; + staticSampler.MaxLOD = 0.f; + staticSampler.ShaderRegister = 0; + staticSampler.RegisterSpace = 0; + staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_ROOT_SIGNATURE_DESC desc = {}; + desc.NumParameters = _countof(param); + desc.pParameters = param; + desc.NumStaticSamplers = 1; + desc.pStaticSamplers = &staticSampler; + desc.Flags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; + + // Load d3d12.dll and D3D12SerializeRootSignature() function address dynamically to facilitate using with D3D12On7. + // See if any version of d3d12.dll is already loaded in the process. If so, give preference to that. + static HINSTANCE d3d12_dll = ::GetModuleHandleA("d3d12.dll"); + if (d3d12_dll == NULL) + { + // Attempt to load d3d12.dll from local directories. This will only succeed if + // (1) the current OS is Windows 7, and + // (2) there exists a version of d3d12.dll for Windows 7 (D3D12On7) in one of the following directories. + // See https://github.com/ocornut/imgui/pull/3696 for details. + const char* localD3d12Paths[] = { ".\\d3d12.dll", ".\\d3d12on7\\d3d12.dll", ".\\12on7\\d3d12.dll" }; // A. current directory, B. used by some games, C. used in Microsoft D3D12On7 sample + for (int i = 0; i < IM_ARRAYSIZE(localD3d12Paths); i++) + if ((d3d12_dll = ::LoadLibraryA(localD3d12Paths[i])) != NULL) + break; + + // If failed, we are on Windows >= 10. + if (d3d12_dll == NULL) + d3d12_dll = ::LoadLibraryA("d3d12.dll"); + + if (d3d12_dll == NULL) + return false; + } + + PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFn = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)::GetProcAddress(d3d12_dll, "D3D12SerializeRootSignature"); + if (D3D12SerializeRootSignatureFn == NULL) + return false; + + ID3DBlob* blob = NULL; + if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK) + return false; + + g_pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&g_pRootSignature)); + blob->Release(); + } + + // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) + // If you would like to use this DX12 sample code but remove this dependency you can: + // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] + // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. + // See https://github.com/ocornut/imgui/pull/638 for sources and details. + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc; + memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC)); + psoDesc.NodeMask = 1; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.pRootSignature = g_pRootSignature; + psoDesc.SampleMask = UINT_MAX; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = g_RTVFormat; + psoDesc.SampleDesc.Count = 1; + psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + ID3DBlob* vertexShaderBlob; + ID3DBlob* pixelShaderBlob; + + // Create the vertex shader + { + static const char* vertexShader = + "cbuffer vertexBuffer : register(b0) \ + {\ + float4x4 ProjectionMatrix; \ + };\ + struct VS_INPUT\ + {\ + float2 pos : POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + \ + struct PS_INPUT\ + {\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + \ + PS_INPUT main(VS_INPUT input)\ + {\ + PS_INPUT output;\ + output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ + output.col = input.col;\ + output.uv = input.uv;\ + return output;\ + }"; + + if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &vertexShaderBlob, NULL))) + return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! + psoDesc.VS = { vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() }; + + // Create the input layout + static D3D12_INPUT_ELEMENT_DESC local_layout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + psoDesc.InputLayout = { local_layout, 3 }; + } + + // Create the pixel shader + { + static const char* pixelShader = + "struct PS_INPUT\ + {\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + SamplerState sampler0 : register(s0);\ + Texture2D texture0 : register(t0);\ + \ + float4 main(PS_INPUT input) : SV_Target\ + {\ + float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ + return out_col; \ + }"; + + if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &pixelShaderBlob, NULL))) + { + vertexShaderBlob->Release(); + return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! + } + psoDesc.PS = { pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() }; + } + + // Create the blending setup + { + D3D12_BLEND_DESC& desc = psoDesc.BlendState; + desc.AlphaToCoverageEnable = false; + desc.RenderTarget[0].BlendEnable = true; + desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA; + desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; + desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; + desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + } + + // Create the rasterizer state + { + D3D12_RASTERIZER_DESC& desc = psoDesc.RasterizerState; + desc.FillMode = D3D12_FILL_MODE_SOLID; + desc.CullMode = D3D12_CULL_MODE_NONE; + desc.FrontCounterClockwise = FALSE; + desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + desc.DepthClipEnable = true; + desc.MultisampleEnable = FALSE; + desc.AntialiasedLineEnable = FALSE; + desc.ForcedSampleCount = 0; + desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + + // Create depth-stencil State + { + D3D12_DEPTH_STENCIL_DESC& desc = psoDesc.DepthStencilState; + desc.DepthEnable = false; + desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + desc.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; + desc.StencilEnable = false; + desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP; + desc.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; + desc.BackFace = desc.FrontFace; + } + + HRESULT result_pipeline_state = g_pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&g_pPipelineState)); + vertexShaderBlob->Release(); + pixelShaderBlob->Release(); + if (result_pipeline_state != S_OK) + return false; + + ImGui_ImplDX12_CreateFontsTexture(); + + return true; +} + +void ImGui_ImplDX12_InvalidateDeviceObjects() +{ + if (!g_pd3dDevice) + return; + + SafeRelease(g_pRootSignature); + SafeRelease(g_pPipelineState); + SafeRelease(g_pFontTextureResource); + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->SetTexID(NULL); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. + + for (UINT i = 0; i < g_numFramesInFlight; i++) + { + FrameResources* fr = &g_pFrameResources[i]; + SafeRelease(fr->IndexBuffer); + SafeRelease(fr->VertexBuffer); + } +} + +bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap, + D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) +{ + // Setup backend capabilities flags + ImGuiIO& io = ImGui::GetIO(); + io.BackendRendererName = "imgui_impl_dx12"; + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. + + g_pd3dDevice = device; + g_RTVFormat = rtv_format; + g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle; + g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle; + g_pFrameResources = new FrameResources[num_frames_in_flight]; + g_numFramesInFlight = num_frames_in_flight; + g_frameIndex = UINT_MAX; + IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports) + + // Create buffers with a default size (they will later be grown as needed) + for (int i = 0; i < num_frames_in_flight; i++) + { + FrameResources* fr = &g_pFrameResources[i]; + fr->IndexBuffer = NULL; + fr->VertexBuffer = NULL; + fr->IndexBufferSize = 10000; + fr->VertexBufferSize = 5000; + } + + return true; +} + +void ImGui_ImplDX12_Shutdown() +{ + ImGui_ImplDX12_InvalidateDeviceObjects(); + delete[] g_pFrameResources; + g_pFrameResources = NULL; + g_pd3dDevice = NULL; + g_hFontSrvCpuDescHandle.ptr = 0; + g_hFontSrvGpuDescHandle.ptr = 0; + g_numFramesInFlight = 0; + g_frameIndex = UINT_MAX; +} + +void ImGui_ImplDX12_NewFrame() +{ + if (!g_pPipelineState) + ImGui_ImplDX12_CreateDeviceObjects(); +} \ No newline at end of file diff --git a/src/automata-imgui/imgui_impl_dx12.h b/src/automata-imgui/imgui_impl_dx12.h new file mode 100644 index 0000000..af88db7 --- /dev/null +++ b/src/automata-imgui/imgui_impl_dx12.h @@ -0,0 +1,47 @@ +// dear imgui: Renderer Backend for DirectX12 +// This needs to be used along with a Platform Backend (e.g. Win32) + +// Implemented features: +// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! +// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. + +// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'. +// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. +// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. + +// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +#pragma once +#include "imgui.h" // IMGUI_IMPL_API + +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable: 4471) // a forward declaration of an unscoped enumeration must have an underlying type +#endif + +enum DXGI_FORMAT; +struct ID3D12Device; +struct ID3D12DescriptorHeap; +struct ID3D12GraphicsCommandList; +struct D3D12_CPU_DESCRIPTOR_HANDLE; +struct D3D12_GPU_DESCRIPTOR_HANDLE; + +// cmd_list is the command list that the implementation will use to render imgui draw lists. +// Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate +// render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle. +// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture. +IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap, + D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); +IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list); + +// Use if you want to reset your rendering device without losing Dear ImGui state. +IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects(); + +#ifdef _MSC_VER +#pragma warning (pop) +#endif \ No newline at end of file diff --git a/src/automata-imgui/imgui_impl_win32.cpp b/src/automata-imgui/imgui_impl_win32.cpp new file mode 100644 index 0000000..b09d227 --- /dev/null +++ b/src/automata-imgui/imgui_impl_win32.cpp @@ -0,0 +1,643 @@ +// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) +// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) + +// Implemented features: +// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). +// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. + +// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +#include +#include +#include + +#include "imgui.h" +#include "imgui_impl_win32.h" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include + +// Configuration flags to add in your imconfig.h file: +//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support (this used to be meaningful before <1.81) but we know load XInput dynamically so the option is less relevant now. + +// Using XInput for gamepad (will load DLL dynamically) +#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD +#include +typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*); +typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); +#endif + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). +// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1. +// 2021-01-25: Inputs: Dynamically loading XInput DLL. +// 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed. +// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs) +// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions. +// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. +// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. +// 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). +// 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent. +// 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. +// 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application). +// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. +// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. +// 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads). +// 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. +// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. +// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. +// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. +// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. +// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read. +// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. +// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set. + +namespace imgui { +void reset_keystates() { + // get imgui io + auto& io = ImGui::GetIO(); + + // clear io key states + io.KeyCtrl = false; + io.KeyShift = false; + io.KeyAlt = false; + io.KeySuper = false; + + // clear io mouse state + io.MousePos.x = 0; + io.MousePos.y = 0; + + for (auto& mouse_down : io.MouseDown) { + mouse_down = false; + } + + // clear io keys + for (auto& key : io.KeysDown) { + key = false; + } +} +} + +// Win32 Data +static HWND g_hWnd = NULL; +static INT64 g_Time = 0; +static INT64 g_TicksPerSecond = 0; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; +static bool g_HasGamepad = false; +static bool g_WantUpdateHasGamepad = true; + +// XInput DLL and functions +#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD +static HMODULE g_XInputDLL = NULL; +static PFN_XInputGetCapabilities g_XInputGetCapabilities = NULL; +static PFN_XInputGetState g_XInputGetState = NULL; +#endif + +// Functions +bool ImGui_ImplWin32_Init(void* hwnd) +{ + if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&g_TicksPerSecond)) + return false; + if (!::QueryPerformanceCounter((LARGE_INTEGER*)&g_Time)) + return false; + + // Setup backend capabilities flags + g_hWnd = (HWND)hwnd; + ImGuiIO& io = ImGui::GetIO(); + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + io.BackendPlatformName = "imgui_impl_win32"; + io.ImeWindowHandle = hwnd; + + // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. + io.KeyMap[ImGuiKey_Tab] = VK_TAB; + io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = VK_UP; + io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; + io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; + io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; + io.KeyMap[ImGuiKey_Home] = VK_HOME; + io.KeyMap[ImGuiKey_End] = VK_END; + io.KeyMap[ImGuiKey_Insert] = VK_INSERT; + io.KeyMap[ImGuiKey_Delete] = VK_DELETE; + io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Space] = VK_SPACE; + io.KeyMap[ImGuiKey_Enter] = VK_RETURN; + io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; + io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN; + io.KeyMap[ImGuiKey_A] = 'A'; + io.KeyMap[ImGuiKey_C] = 'C'; + io.KeyMap[ImGuiKey_V] = 'V'; + io.KeyMap[ImGuiKey_X] = 'X'; + io.KeyMap[ImGuiKey_Y] = 'Y'; + io.KeyMap[ImGuiKey_Z] = 'Z'; + + // Dynamically load XInput library +#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD + const char* xinput_dll_names[] = + { + "xinput1_4.dll", // Windows 8+ + "xinput1_3.dll", // DirectX SDK + "xinput9_1_0.dll", // Windows Vista, Windows 7 + "xinput1_2.dll", // DirectX SDK + "xinput1_1.dll" // DirectX SDK + }; + for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++) + if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n])) + { + g_XInputDLL = dll; + g_XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities"); + g_XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState"); + break; + } +#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD + + return true; +} + +void ImGui_ImplWin32_Shutdown() +{ + // Unload XInput library +#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD + if (g_XInputDLL) + ::FreeLibrary(g_XInputDLL); + g_XInputDLL = NULL; + g_XInputGetCapabilities = NULL; + g_XInputGetState = NULL; +#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD + + g_hWnd = NULL; + g_Time = 0; + g_TicksPerSecond = 0; + g_LastMouseCursor = ImGuiMouseCursor_COUNT; + g_HasGamepad = false; + g_WantUpdateHasGamepad = true; +} + +static bool ImGui_ImplWin32_UpdateMouseCursor() +{ + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) + return false; + + ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + ::SetCursor(NULL); + } + else + { + // Show OS mouse cursor + LPTSTR win32_cursor = IDC_ARROW; + switch (imgui_cursor) + { + case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; + case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; + case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; + case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; + case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; + case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; + case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; + case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; + case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; + } + ::SetCursor(::LoadCursor(NULL, win32_cursor)); + } + return true; +} + +static void ImGui_ImplWin32_UpdateMousePos() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) + { + POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; + if (::ClientToScreen(g_hWnd, &pos)) + ::SetCursorPos(pos.x, pos.y); + } + + // Set mouse position + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + POINT pos; + if (HWND active_window = ::GetForegroundWindow()) + if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd)) + if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos)) + io.MousePos = ImVec2((float)pos.x, (float)pos.y); +} + +// Gamepad navigation mapping +static void ImGui_ImplWin32_UpdateGamepads() +{ +#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD + ImGuiIO& io = ImGui::GetIO(); + memset(io.NavInputs, 0, sizeof(io.NavInputs)); + if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) + return; + + // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. + // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. + if (g_WantUpdateHasGamepad) + { + XINPUT_CAPABILITIES caps; + g_HasGamepad = g_XInputGetCapabilities ? (g_XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; + g_WantUpdateHasGamepad = false; + } + + io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; + XINPUT_STATE xinput_state; + if (g_HasGamepad && g_XInputGetState && g_XInputGetState(0, &xinput_state) == ERROR_SUCCESS) + { + const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; + io.BackendFlags |= ImGuiBackendFlags_HasGamepad; + + #define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; } + #define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; } + MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); // Cross / A + MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); // Circle / B + MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); // Square / X + MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); // Triangle / Y + MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); // D-Pad Left + MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); // D-Pad Right + MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); // D-Pad Up + MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); // D-Pad Down + MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB + MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB + MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB + MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB + MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); + MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); + MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); + MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767); + #undef MAP_BUTTON + #undef MAP_ANALOG + } +#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD +} + +struct ImguiInputEvent { + struct KeyDownEvent { + KeyDownEvent(WPARAM k, bool d) + : key{ k }, + down{ d } + { + } + + WPARAM key{}; + bool down{ false }; + }; + + struct MouseDownEvent { + MouseDownEvent(int32_t b, bool d) + : btn{b} + , down{d} {} + + int32_t btn{}; + bool down{false}; + }; + + std::vector queued_keys{}; + std::vector queued_buttons{}; + std::vector queued_chars{}; + + float mousewheel[2]{}; +}; + +std::deque g_input_events{}; +uint64_t g_frame_count{ 0 }; +uint64_t g_last_frame_count{ 0 }; + +std::recursive_mutex g_input_mtx{}; + + +void ImGui_ImplWin32_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + { + std::lock_guard _{ g_input_mtx }; + + if (!g_input_events.empty()) { + auto& evt = g_input_events.front(); + + for (auto& queued_key : evt.queued_keys) { + io.KeysDown[queued_key.key] = queued_key.down; + } + + for (auto& queued_button : evt.queued_buttons) { + io.MouseDown[queued_button.btn] = queued_button.down; + } + + for (auto queued_char : evt.queued_chars) { + io.AddInputCharacter(queued_char); + } + + io.MouseWheel += evt.mousewheel[0]; + io.MouseWheelH += evt.mousewheel[1]; + + g_input_events.pop_front(); + } + } + + IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); + + // Setup display size (every frame to accommodate for window resizing) + RECT rect = { 0, 0, 0, 0 }; + ::GetClientRect(g_hWnd, &rect); + io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); + + // Setup time step + INT64 current_time = 0; + ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); + io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; + g_Time = current_time; + + // Read keyboard modifiers inputs + io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0 || io.KeysDown[VK_CONTROL] || io.KeysDown[VK_LCONTROL] || io.KeysDown[VK_RCONTROL]; + io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0 || io.KeysDown[VK_SHIFT] || io.KeysDown[VK_LSHIFT] || io.KeysDown[VK_RSHIFT]; + io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0 || io.KeysDown[VK_MENU] || io.KeysDown[VK_LMENU] || io.KeysDown[VK_RMENU]; + io.KeySuper = false; + // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. + + // Update OS mouse position + ImGui_ImplWin32_UpdateMousePos(); + + // Update OS mouse cursor with the cursor requested by imgui + ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (g_LastMouseCursor != mouse_cursor) + { + g_LastMouseCursor = mouse_cursor; + ImGui_ImplWin32_UpdateMouseCursor(); + } + + // Update game controllers (if enabled and available) + ImGui_ImplWin32_UpdateGamepads(); + + ++g_frame_count; +} + +// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. +#ifndef WM_MOUSEHWHEEL +#define WM_MOUSEHWHEEL 0x020E +#endif +#ifndef DBT_DEVNODES_CHANGED +#define DBT_DEVNODES_CHANGED 0x0007 +#endif + +// Win32 message handler (process Win32 mouse/keyboard inputs, etc.) +// Call from your application's message handler. +// When implementing your own backend, 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. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags. +// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds. +// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. +#if 0 +// Copy this line into your .cpp file to forward declare the function. +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +#endif +IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (ImGui::GetCurrentContext() == NULL) + return 0; + + ImGuiIO& io = ImGui::GetIO(); + + std::lock_guard _{ g_input_mtx }; + + if (g_frame_count != g_last_frame_count || g_input_events.empty()) { + g_input_events.emplace_back(); + g_last_frame_count = g_frame_count; + } + + auto& input_event = g_input_events.back(); + + switch (msg) + { + case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: + case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: + { + int button = 0; + if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; } + if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } + if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } + if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) + ::SetCapture(hwnd); + input_event.queued_buttons.emplace_back(button, true); + return 0; + } + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + case WM_XBUTTONUP: + { + int button = 0; + if (msg == WM_LBUTTONUP) { button = 0; } + if (msg == WM_RBUTTONUP) { button = 1; } + if (msg == WM_MBUTTONUP) { button = 2; } + if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } + input_event.queued_buttons.emplace_back(button, false); + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) + ::ReleaseCapture(); + return 0; + } + case WM_MOUSEWHEEL: + input_event.mousewheel[0] += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; + return 0; + case WM_MOUSEHWHEEL: + input_event.mousewheel[1] += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; + return 0; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (wParam < 256) + input_event.queued_keys.emplace_back(wParam, true); + return 0; + case WM_KEYUP: + case WM_SYSKEYUP: + if (wParam < 256) + input_event.queued_keys.emplace_back(wParam, false); + return 0; + case WM_KILLFOCUS: + imgui::reset_keystates(); + return 0; + case WM_CHAR: + // You can also use ToAscii()+GetKeyboardState() to retrieve characters. + if (wParam > 0 && wParam < 0x10000) + input_event.queued_chars.emplace_back((unsigned short)wParam); + return 0; + case WM_SETCURSOR: + if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) + return 1; + return 0; + case WM_DEVICECHANGE: + if ((UINT)wParam == DBT_DEVNODES_CHANGED) + g_WantUpdateHasGamepad = true; + return 0; + } + return 0; +} + + +//-------------------------------------------------------------------------------------------------------- +// DPI-related helpers (optional) +//-------------------------------------------------------------------------------------------------------- +// - Use to enable DPI awareness without having to create an application manifest. +// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. +// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. +// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, +// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. +//--------------------------------------------------------------------------------------------------------- +// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable. +// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically. +// If you are trying to implement your own backend for your own engine, you may ignore that noise. +//--------------------------------------------------------------------------------------------------------- + +// Implement some of the functions and types normally declared in recent Windows SDK. +#if !defined(_versionhelpers_H_INCLUDED_) && !defined(_INC_VERSIONHELPERS) +static BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp) +{ + OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, { 0 }, sp, 0, 0, 0, 0 }; + DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR; + ULONGLONG cond = ::VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); + cond = ::VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); + cond = ::VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + return ::VerifyVersionInfoW(&osvi, mask, cond); +} +#define IsWindowsVistaOrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA +#define IsWindows8OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8 +#define IsWindows8Point1OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE +#endif + +#ifndef DPI_ENUMS_DECLARED +typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS; +typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE; +#endif +#ifndef _DPI_AWARENESS_CONTEXTS_ +DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); +#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3 +#endif +#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 +#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4 +#endif +typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+ +typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+ +typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update) + +// Helper function to enable DPI awareness without setting up a manifest +void ImGui_ImplWin32_EnableDpiAwareness() +{ + // if (IsWindows10OrGreater()) // This needs a manifest to succeed. Instead we try to grab the function pointer! + { + static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process + if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext")) + { + SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); + return; + } + } + if (IsWindows8Point1OrGreater()) + { + static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process + if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness")) + { + SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE); + return; + } + } +#if _WIN32_WINNT >= 0x0600 + ::SetProcessDPIAware(); +#endif +} + +#if defined(_MSC_VER) && !defined(NOGDI) +#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32' +#endif + +float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor) +{ + UINT xdpi = 96, ydpi = 96; + static BOOL bIsWindows8Point1OrGreater = IsWindows8Point1OrGreater(); + if (bIsWindows8Point1OrGreater) + { + static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process + if (PFN_GetDpiForMonitor GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor")) + GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); + } +#ifndef NOGDI + else + { + const HDC dc = ::GetDC(NULL); + xdpi = ::GetDeviceCaps(dc, LOGPIXELSX); + ydpi = ::GetDeviceCaps(dc, LOGPIXELSY); + ::ReleaseDC(NULL, dc); + } +#endif + IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! + return xdpi / 96.0f; +} + +float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd) +{ + HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST); + return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor); +} + +//--------------------------------------------------------------------------------------------------------- +// Transparency related helpers (optional) +//-------------------------------------------------------------------------------------------------------- + +#if defined(_MSC_VER) +#pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi' +#endif + +// [experimental] +// Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c +// (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW) +void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd) +{ + if (!IsWindowsVistaOrGreater()) + return; + + BOOL composition; + if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition) + return; + + BOOL opaque; + DWORD color; + if (IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque)) + { + HRGN region = ::CreateRectRgn(0, 0, -1, -1); + DWM_BLURBEHIND bb = {}; + bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; + bb.hRgnBlur = region; + bb.fEnable = TRUE; + ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); + ::DeleteObject(region); + } + else + { + DWM_BLURBEHIND bb = {}; + bb.dwFlags = DWM_BB_ENABLE; + ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); + } +} + +//--------------------------------------------------------------------------------------------------------- diff --git a/src/automata-imgui/imgui_impl_win32.h b/src/automata-imgui/imgui_impl_win32.h new file mode 100644 index 0000000..8200173 --- /dev/null +++ b/src/automata-imgui/imgui_impl_win32.h @@ -0,0 +1,46 @@ +// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) +// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) + +// Implemented features: +// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). +// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. + +// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +#pragma once +#include "imgui.h" // IMGUI_IMPL_API +#include + +IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); +IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); + +// Win32 message handler your application need to call. +// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. +// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. +// #if 0 +IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +// #endif + +// DPI-related helpers (optional) +// - Use to enable DPI awareness without having to create an application manifest. +// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. +// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. +// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, +// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. +IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); +IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd +IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor + +// Transparency related helpers (optional) [experimental] +// - Use to enable alpha compositing transparency with the desktop. +// - Use together with e.g. clearing your framebuffer with zero-alpha. +IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd + +namespace imgui { + void reset_keystates(); +} \ No newline at end of file diff --git a/src/hooks/D3D11Hook.cpp b/src/hooks/D3D11Hook.cpp new file mode 100644 index 0000000..474a685 --- /dev/null +++ b/src/hooks/D3D11Hook.cpp @@ -0,0 +1,270 @@ +#include +#include +#include +#include + +#include "AutomataMP.hpp" + +#include "D3D11Hook.hpp" + +using namespace std; + +static D3D11Hook* g_d3d11_hook = nullptr; + +D3D11Hook::~D3D11Hook() { + unhook(); +} + +bool D3D11Hook::hook() { + spdlog::info("Hooking D3D11"); + + g_d3d11_hook = this; + + HWND h_wnd = GetDesktopWindow(); + IDXGISwapChain* swap_chain = nullptr; + ID3D11Device* device = nullptr; + ID3D11DeviceContext* context = nullptr; + + D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; + DXGI_SWAP_CHAIN_DESC swap_chain_desc; + + ZeroMemory(&swap_chain_desc, sizeof(swap_chain_desc)); + + swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swap_chain_desc.BufferCount = 1; + swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swap_chain_desc.OutputWindow = h_wnd; + swap_chain_desc.SampleDesc.Count = 1; + swap_chain_desc.Windowed = TRUE; + swap_chain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swap_chain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + const auto original_bytes = utility::get_original_bytes(&D3D11CreateDeviceAndSwapChain); + + // Temporarily unhook D3D11CreateDeviceAndSwapChain + // it allows compatibility with ReShade and other overlays that hook it + // this is just a dummy device anyways, we don't want the other overlays to be able to use it + if (original_bytes) { + spdlog::info("D3D11CreateDeviceAndSwapChain appears to be hooked, temporarily unhooking"); + + std::vector hooked_bytes(original_bytes->size()); + memcpy(hooked_bytes.data(), &D3D11CreateDeviceAndSwapChain, original_bytes->size()); + + ProtectionOverride protection_override{ &D3D11CreateDeviceAndSwapChain, original_bytes->size(), PAGE_EXECUTE_READWRITE }; + memcpy(&D3D11CreateDeviceAndSwapChain, original_bytes->data(), original_bytes->size()); + + if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_NULL, nullptr, 0, &feature_level, 1, D3D11_SDK_VERSION, + &swap_chain_desc, &swap_chain, &device, nullptr, &context))) + { + spdlog::error("Failed to create D3D11 device"); + memcpy(&D3D11CreateDeviceAndSwapChain, hooked_bytes.data(), hooked_bytes.size()); + return false; + } + + spdlog::info("Restoring hooked bytes for D3D11CreateDeviceAndSwapChain"); + memcpy(&D3D11CreateDeviceAndSwapChain, hooked_bytes.data(), hooked_bytes.size()); + } else { + if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_NULL, nullptr, 0, &feature_level, 1, D3D11_SDK_VERSION, + &swap_chain_desc, &swap_chain, &device, nullptr, &context))) + { + spdlog::error("Failed to create D3D11 device"); + return false; + } + } + + utility::ThreadSuspender suspender{}; + + try { + m_present_hook.reset(); + m_resize_buffers_hook.reset(); + + auto& present_fn = (*(void***)swap_chain)[8]; + auto& resize_buffers_fn = (*(void***)swap_chain)[13]; + + m_present_hook = std::make_unique(&present_fn, (void*)&D3D11Hook::present); + m_resize_buffers_hook = std::make_unique(&resize_buffers_fn, (void*)&D3D11Hook::resize_buffers); + + m_hooked = true; + } catch (const std::exception& e) { + spdlog::error("Failed to hook D3D11: {}", e.what()); + m_hooked = false; + } + + suspender.resume(); + + device->Release(); + context->Release(); + swap_chain->Release(); + return m_hooked; +} + +bool D3D11Hook::unhook() { + if (!m_hooked) { + return true; + } + + spdlog::info("Unhooking D3D11"); + + if (m_present_hook->remove() && m_resize_buffers_hook->remove()) { + m_hooked = false; + return true; + } + + return false; +} + +thread_local bool g_inside_d3d11_present = false; +HRESULT last_d3d11_present_result = S_OK; + +HRESULT WINAPI D3D11Hook::present(IDXGISwapChain* swap_chain, UINT sync_interval, UINT flags) { + std::scoped_lock _{g_framework->get_hook_monitor_mutex()}; + + auto d3d11 = g_d3d11_hook; + + d3d11->m_inside_present = true; + + if (d3d11->m_swapchain_0 == nullptr) { + d3d11->m_swapchain_0 = swap_chain; + d3d11->m_swap_chain = swap_chain; + } else if (d3d11->m_swapchain_1 == nullptr && swap_chain != d3d11->m_swapchain_0) { + d3d11->m_swapchain_1 = swap_chain; + } + + // This line must be called before calling our detour function because we might have to unhook the function inside our detour. + auto present_fn = d3d11->m_present_hook->get_original(); + + /*if (d3d11->m_swap_chain != d3d11->m_swapchain_0) { + d3d11->m_inside_present = false; + return present_fn(swap_chain, sync_interval, flags); + }*/ + + swap_chain->GetDevice(__uuidof(d3d11->m_device), (void**)&d3d11->m_device); + + /*if (d3d11->m_set_render_targets_hook == nullptr) { + ComPtr context{}; + + d3d11->m_device->GetImmediateContext(&context); + auto& set_render_targets_fn = (*(void***)context.Get())[33]; + d3d11->m_set_render_targets_hook = std::make_unique(&set_render_targets_fn, (void*)&set_render_targets); + OutputDebugString("Hooked ID3D11DeviceContext::SetRenderTargets"); + }*/ + + /*if (GetAsyncKeyState(VK_INSERT) & 1) { + OutputDebugString(fmt::format("Depth stencil @ {:p} used", (void*)d3d11->m_last_depthstencil_used.Get()).c_str()); + }*/ + + // Restore the original bytes + // if an infinite loop occurs, this will prevent the game from crashing + // while keeping our hook intact + if (g_inside_d3d11_present) { + auto original_bytes = utility::get_original_bytes(Address{present_fn}); + + if (original_bytes) { + ProtectionOverride protection_override{present_fn, original_bytes->size(), PAGE_EXECUTE_READWRITE}; + + memcpy(present_fn, original_bytes->data(), original_bytes->size()); + + spdlog::info("Present fixed"); + } + + return last_d3d11_present_result; + } + + if (d3d11->m_on_present) { + d3d11->m_on_present(*d3d11); + } + + HRESULT result = S_OK; + g_inside_d3d11_present = true; + + if (!d3d11->m_ignore_next_present) { + result = present_fn(swap_chain, sync_interval, flags); + last_d3d11_present_result = result; + } else { + d3d11->m_ignore_next_present = false; + last_d3d11_present_result = S_OK; + } + + g_inside_d3d11_present = false; + + if (d3d11->m_on_post_present) { + d3d11->m_on_post_present(*d3d11); + } + + d3d11->m_last_depthstencil_used.Reset(); + d3d11->m_inside_present = false; + + return result; +} + +thread_local bool g_inside_d3d11_resize_buffers = false; +HRESULT last_d3d11_resize_buffers_result = S_OK; + +HRESULT WINAPI D3D11Hook::resize_buffers( + IDXGISwapChain* swap_chain, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swap_chain_flags) { + std::scoped_lock _{g_framework->get_hook_monitor_mutex()}; + + auto d3d11 = g_d3d11_hook; + + d3d11->m_swap_chain = swap_chain; + d3d11->m_swapchain_0 = nullptr; + d3d11->m_swapchain_1 = nullptr; + d3d11->m_last_depthstencil_used.Reset(); + + if (d3d11->m_on_resize_buffers) { + d3d11->m_on_resize_buffers(*d3d11); + } + + auto resize_buffers_fn = d3d11->m_resize_buffers_hook->get_original(); + + if (g_inside_d3d11_resize_buffers) { + auto original_bytes = utility::get_original_bytes(Address{resize_buffers_fn}); + + if (original_bytes) { + ProtectionOverride protection_override{resize_buffers_fn, original_bytes->size(), PAGE_EXECUTE_READWRITE}; + + memcpy(resize_buffers_fn, original_bytes->data(), original_bytes->size()); + + spdlog::info("Resize buffers fixed"); + } + + return last_d3d11_resize_buffers_result; + } + + g_inside_d3d11_resize_buffers = true; + + last_d3d11_resize_buffers_result = resize_buffers_fn(swap_chain, buffer_count, width, height, new_format, swap_chain_flags); + + g_inside_d3d11_resize_buffers = false; + + return last_d3d11_resize_buffers_result; +} + +void WINAPI D3D11Hook::set_render_targets( + ID3D11DeviceContext* context, UINT num_views, ID3D11RenderTargetView* const* rtvs, ID3D11DepthStencilView* dsv) { + std::scoped_lock _{g_framework->get_hook_monitor_mutex()}; + + auto d3d11 = g_d3d11_hook; + + if (dsv != nullptr) { + //auto obj_name = fmt::format("Depthstencil @ {:p}", (void*)d3d11->m_last_depthstencil_used.Get()); + //d3d11->m_last_depthstencil_used->SetPrivateData(WKPDID_D3DDebugObjectName, obj_name.size(), obj_name.c_str()); + //OutputDebugString(fmt::format("Depth stencil @ {:p} used", (void*)d3d11->m_last_depthstencil_used.Get()).c_str()); + + D3D11_DEPTH_STENCIL_VIEW_DESC desc{}; + dsv->GetDesc(&desc); + + if (desc.Flags & D3D11_DSV_FLAG::D3D11_DSV_READ_ONLY_DEPTH) { + dsv->GetResource((ID3D11Resource**)d3d11->m_last_depthstencil_used.GetAddressOf()); + + //OutputDebugString(fmt::format("Flags: {}", desc.Flags).c_str()); + //OutputDebugString(fmt::format("Format: {}", desc.Format).c_str()); + //OutputDebugString(fmt::format("ViewDimension: {}", desc.ViewDimension).c_str()); + } + } + + auto set_render_targets_fn = d3d11->m_set_render_targets_hook->get_original(); + + return set_render_targets_fn(context, num_views, rtvs, dsv); +} diff --git a/src/hooks/D3D11Hook.hpp b/src/hooks/D3D11Hook.hpp new file mode 100644 index 0000000..5428b74 --- /dev/null +++ b/src/hooks/D3D11Hook.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include + +#include +#include +#include + +#include "utility/PointerHook.hpp" + +class D3D11Hook { +public: + typedef std::function OnPresentFn; + typedef std::function OnResizeBuffersFn; + + D3D11Hook() = default; + virtual ~D3D11Hook(); + + bool is_hooked() { + return m_hooked; + } + + bool is_inside_present() const { + return m_inside_present; + } + + void ignore_next_present() { + m_ignore_next_present = true; + } + + bool hook(); + bool unhook(); + + void on_present(OnPresentFn fn) { m_on_present = fn; } + void on_post_present(OnPresentFn fn) { m_on_post_present = fn; } + void on_resize_buffers(OnResizeBuffersFn fn) { m_on_resize_buffers = fn; } + + ID3D11Device* get_device() { return m_device; } + IDXGISwapChain* get_swap_chain() { return m_swap_chain; } // The "active" swap chain. + auto get_swapchain_0() { return m_swapchain_0; } + auto get_swapchain_1() { return m_swapchain_1; } + auto& get_last_depthstencil_used() { return m_last_depthstencil_used; } + +protected: + template using ComPtr = Microsoft::WRL::ComPtr; + + ID3D11Device* m_device{ nullptr }; + IDXGISwapChain* m_swap_chain{ nullptr }; + IDXGISwapChain* m_swapchain_0{}; + IDXGISwapChain* m_swapchain_1{}; + bool m_hooked{ false }; + bool m_inside_present{false}; + bool m_ignore_next_present{false}; + + std::unique_ptr m_present_hook{}; + std::unique_ptr m_resize_buffers_hook{}; + std::unique_ptr m_set_render_targets_hook{}; + OnPresentFn m_on_present{ nullptr }; + OnPresentFn m_on_post_present{ nullptr }; + OnResizeBuffersFn m_on_resize_buffers{ nullptr }; + ComPtr m_last_depthstencil_used{}; + + static HRESULT WINAPI present(IDXGISwapChain* swap_chain, UINT sync_interval, UINT flags); + static HRESULT WINAPI resize_buffers(IDXGISwapChain* swap_chain, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swap_chain_flags); + static void WINAPI set_render_targets( + ID3D11DeviceContext* context, UINT num_views, ID3D11RenderTargetView* const* rtvs, ID3D11DepthStencilView* dsv); +}; diff --git a/src/hooks/D3D12Hook.cpp b/src/hooks/D3D12Hook.cpp new file mode 100644 index 0000000..19e1279 --- /dev/null +++ b/src/hooks/D3D12Hook.cpp @@ -0,0 +1,527 @@ +#include +#include +#include + +#include +#include +#include + +#include "AutomataMP.hpp" + +#include "D3D12Hook.hpp" + +static D3D12Hook* g_d3d12_hook = nullptr; + +D3D12Hook::~D3D12Hook() { + unhook(); +} + +bool D3D12Hook::hook() { + spdlog::info("Hooking D3D12"); + + g_d3d12_hook = this; + + IDXGISwapChain1* swap_chain1{ nullptr }; + IDXGISwapChain3* swap_chain{ nullptr }; + ID3D12Device* device{ nullptr }; + + D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; + DXGI_SWAP_CHAIN_DESC1 swap_chain_desc1; + + ZeroMemory(&swap_chain_desc1, sizeof(swap_chain_desc1)); + + swap_chain_desc1.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + swap_chain_desc1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swap_chain_desc1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swap_chain_desc1.BufferCount = 2; + swap_chain_desc1.SampleDesc.Count = 1; + swap_chain_desc1.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; + swap_chain_desc1.Width = 1; + swap_chain_desc1.Height = 1; + + // Manually get D3D12CreateDevice export because the user may be running Windows 7 + const auto d3d12_module = LoadLibraryA("d3d12.dll"); + if (d3d12_module == nullptr) { + spdlog::error("Failed to load d3d12.dll"); + return false; + } + + auto d3d12_create_device = (decltype(D3D12CreateDevice)*)GetProcAddress(d3d12_module, "D3D12CreateDevice"); + if (d3d12_create_device == nullptr) { + spdlog::error("Failed to get D3D12CreateDevice export"); + return false; + } + + spdlog::info("Creating dummy device"); + + // Get the original on-disk bytes of the D3D12CreateDevice export + const auto original_bytes = utility::get_original_bytes(d3d12_create_device); + + // Temporarily unhook D3D12CreateDevice + // it allows compatibility with ReShade and other overlays that hook it + // this is just a dummy device anyways, we don't want the other overlays to be able to use it + if (original_bytes) { + spdlog::info("D3D12CreateDevice appears to be hooked, temporarily unhooking"); + + std::vector hooked_bytes(original_bytes->size()); + memcpy(hooked_bytes.data(), d3d12_create_device, original_bytes->size()); + + ProtectionOverride protection_override{ d3d12_create_device, original_bytes->size(), PAGE_EXECUTE_READWRITE }; + memcpy(d3d12_create_device, original_bytes->data(), original_bytes->size()); + + if (FAILED(d3d12_create_device(nullptr, feature_level, IID_PPV_ARGS(&device)))) { + spdlog::error("Failed to create D3D12 Dummy device"); + memcpy(d3d12_create_device, hooked_bytes.data(), hooked_bytes.size()); + return false; + } + + spdlog::info("Restoring hooked bytes for D3D12CreateDevice"); + memcpy(d3d12_create_device, hooked_bytes.data(), hooked_bytes.size()); + } else { // D3D12CreateDevice is not hooked + if (FAILED(d3d12_create_device(nullptr, feature_level, IID_PPV_ARGS(&device)))) { + spdlog::error("Failed to create D3D12 Dummy device"); + return false; + } + } + + spdlog::info("Dummy device: {:x}", (uintptr_t)device); + + // Manually get CreateDXGIFactory export because the user may be running Windows 7 + const auto dxgi_module = LoadLibraryA("dxgi.dll"); + if (dxgi_module == nullptr) { + spdlog::error("Failed to load dxgi.dll"); + return false; + } + + auto create_dxgi_factory = (decltype(CreateDXGIFactory)*)GetProcAddress(dxgi_module, "CreateDXGIFactory"); + + if (create_dxgi_factory == nullptr) { + spdlog::error("Failed to get CreateDXGIFactory export"); + return false; + } + + spdlog::info("Creating dummy DXGI factory"); + + IDXGIFactory4* factory{ nullptr }; + if (FAILED(create_dxgi_factory(IID_PPV_ARGS(&factory)))) { + spdlog::error("Failed to create D3D12 Dummy DXGI Factory"); + return false; + } + + D3D12_COMMAND_QUEUE_DESC queue_desc{}; + queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queue_desc.Priority = 0; + queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queue_desc.NodeMask = 0; + + spdlog::info("Creating dummy command queue"); + + ID3D12CommandQueue* command_queue{ nullptr }; + if (FAILED(device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&command_queue)))) { + spdlog::error("Failed to create D3D12 Dummy Command Queue"); + return false; + } + + spdlog::info("Creating dummy swapchain"); + + // used in CreateSwapChainForHwnd fallback + HWND hwnd = 0; + WNDCLASSEX wc{}; + + auto init_dummy_window = [&]() { + // fallback to CreateSwapChainForHwnd + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = DefWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(NULL); + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = TEXT("REFRAMEWORK_DX12_DUMMY"); + wc.hIconSm = NULL; + + ::RegisterClassEx(&wc); + + hwnd = ::CreateWindow(wc.lpszClassName, TEXT("REF DX Dummy Window"), WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, wc.hInstance, NULL); + + swap_chain_desc1.BufferCount = 3; + swap_chain_desc1.Width = 0; + swap_chain_desc1.Height = 0; + swap_chain_desc1.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swap_chain_desc1.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + swap_chain_desc1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swap_chain_desc1.SampleDesc.Count = 1; + swap_chain_desc1.SampleDesc.Quality = 0; + swap_chain_desc1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swap_chain_desc1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + swap_chain_desc1.Scaling = DXGI_SCALING_STRETCH; + swap_chain_desc1.Stereo = FALSE; + }; + + std::vector> swapchain_attempts{ + // we call CreateSwapChainForComposition instead of CreateSwapChainForHwnd + // because some overlays will have hooks on CreateSwapChainForHwnd + // and all we're doing is creating a dummy swapchain + // we don't want to screw up the overlay + [&]() { + return !FAILED(factory->CreateSwapChainForComposition(command_queue, &swap_chain_desc1, nullptr, &swap_chain1)); + }, + [&]() { + init_dummy_window(); + + return !FAILED(factory->CreateSwapChainForHwnd(command_queue, hwnd, &swap_chain_desc1, nullptr, nullptr, &swap_chain1)); + }, + [&]() { + return !FAILED(factory->CreateSwapChainForHwnd(command_queue, GetDesktopWindow(), &swap_chain_desc1, nullptr, nullptr, &swap_chain1)); + }, + }; + + bool any_succeed = false; + + for (auto i = 0; i < swapchain_attempts.size(); i++) { + auto& attempt = swapchain_attempts[i]; + + try { + spdlog::info("Trying swapchain attempt {}", i); + + if (attempt()) { + spdlog::info("Created dummy swapchain on attempt {}", i); + any_succeed = true; + break; + } + } catch (std::exception& e) { + spdlog::error("Failed to create dummy swapchain on attempt {}: {}", i, e.what()); + } catch(...) { + spdlog::error("Failed to create dummy swapchain on attempt {}: unknown exception", i); + } + + spdlog::error("Attempt {} failed", i); + } + + if (!any_succeed) { + spdlog::error("Failed to create D3D12 Dummy Swap Chain"); + + if (hwnd) { + ::DestroyWindow(hwnd); + } + + if (wc.lpszClassName != nullptr) { + ::UnregisterClass(wc.lpszClassName, wc.hInstance); + } + + return false; + } + + spdlog::info("Querying dummy swapchain"); + + if (FAILED(swap_chain1->QueryInterface(IID_PPV_ARGS(&swap_chain)))) { + spdlog::error("Failed to retrieve D3D12 DXGI SwapChain"); + return false; + } + + spdlog::info("Finding command queue offset"); + + // Find the command queue offset in the swapchain + for (auto i = 0; i < 512 * sizeof(void*); i += sizeof(void*)) { + const auto base = (uintptr_t)swap_chain1 + i; + + // reached the end + if (IsBadReadPtr((void*)base, sizeof(void*))) { + break; + } + + auto data = *(ID3D12CommandQueue**)base; + + if (data == command_queue) { + m_command_queue_offset = i; + spdlog::info("Found command queue offset: {:x}", i); + break; + } + } + + // Scan throughout the swapchain for a valid pointer to scan through + // this is usually only necessary for Proton + if (m_command_queue_offset == 0) { + for (auto base = 0; base < 512 * sizeof(void*); base += sizeof(void*)) { + const auto pre_scan_base = (uintptr_t)swap_chain1 + base; + + // reached the end + if (IsBadReadPtr((void*)pre_scan_base, sizeof(void*))) { + break; + } + + const auto scan_base = *(uintptr_t*)pre_scan_base; + + if (scan_base == 0 || IsBadReadPtr((void*)scan_base, sizeof(void*))) { + continue; + } + + for (auto i = 0; i < 512 * sizeof(void*); i += sizeof(void*)) { + const auto pre_data = scan_base + i; + + if (IsBadReadPtr((void*)pre_data, sizeof(void*))) { + break; + } + + auto data = *(ID3D12CommandQueue**)pre_data; + + if (data == command_queue) { + m_using_proton_swapchain = true; + m_command_queue_offset = i; + m_proton_swapchain_offset = base; + + spdlog::info("Proton potentially detected"); + spdlog::info("Found command queue offset: {:x}", i); + break; + } + } + + if (m_using_proton_swapchain) { + break; + } + } + } + + if (m_command_queue_offset == 0) { + spdlog::error("Failed to find command queue offset"); + return false; + } + + utility::ThreadSuspender suspender{}; + + try { + spdlog::info("Initializing hooks"); + + m_present_hook.reset(); + m_resize_buffers_hook.reset(); + m_resize_target_hook.reset(); + + auto& present_fn = (*(void***)swap_chain)[8]; // Present + auto& resize_buffers_fn = (*(void***)swap_chain)[13]; // ResizeBuffers + auto& resize_target_fn = (*(void***)swap_chain)[14]; // ResizeTarget + auto& create_swap_chain_fn = (*(void***)factory)[15]; // CreateSwapChainForHwnd + + m_present_hook = std::make_unique(&present_fn, (void*)&D3D12Hook::present); + m_resize_buffers_hook = std::make_unique(&resize_buffers_fn, (void*)&D3D12Hook::resize_buffers); + m_resize_target_hook = std::make_unique(&resize_target_fn, (void*)&D3D12Hook::resize_target); + //m_create_swap_chain_hook = std::make_unique(create_swap_chain_fn, (uintptr_t)&D3D12Hook::create_swap_chain); + + m_hooked = true; + } catch (const std::exception& e) { + spdlog::error("Failed to initialize hooks: {}", e.what()); + m_hooked = false; + } + + suspender.resume(); + + device->Release(); + command_queue->Release(); + factory->Release(); + swap_chain1->Release(); + swap_chain->Release(); + + if (hwnd) { + ::DestroyWindow(hwnd); + } + + if (wc.lpszClassName != nullptr) { + ::UnregisterClass(wc.lpszClassName, wc.hInstance); + } + + return m_hooked; +} + +bool D3D12Hook::unhook() { + if (!m_hooked) { + return true; + } + + spdlog::info("Unhooking D3D12"); + + if (m_present_hook->remove() && m_resize_buffers_hook->remove() && m_resize_target_hook->remove() /*&& m_create_swap_chain_hook->remove()*/) { + m_hooked = false; + return true; + } + + return false; +} + +thread_local bool g_inside_present = false; +HRESULT last_present_result = S_OK; + +HRESULT WINAPI D3D12Hook::present(IDXGISwapChain3* swap_chain, UINT sync_interval, UINT flags) { + std::scoped_lock _{g_framework->get_hook_monitor_mutex()}; + + auto d3d12 = g_d3d12_hook; + + d3d12->m_inside_present = true; + d3d12->m_swap_chain = swap_chain; + + swap_chain->GetDevice(IID_PPV_ARGS(&d3d12->m_device)); + + if (d3d12->m_device != nullptr) { + if (d3d12->m_using_proton_swapchain) { + const auto real_swapchain = *(uintptr_t*)((uintptr_t)swap_chain + d3d12->m_proton_swapchain_offset); + d3d12->m_command_queue = *(ID3D12CommandQueue**)(real_swapchain + d3d12->m_command_queue_offset); + } else { + d3d12->m_command_queue = *(ID3D12CommandQueue**)((uintptr_t)swap_chain + d3d12->m_command_queue_offset); + } + } + + if (d3d12->m_swapchain_0 == nullptr) { + d3d12->m_swapchain_0 = swap_chain; + } else if (d3d12->m_swapchain_1 == nullptr && swap_chain != d3d12->m_swapchain_0) { + d3d12->m_swapchain_1 = swap_chain; + } + + // This line must be called before calling our detour function because we might have to unhook the function inside our detour. + auto present_fn = d3d12->m_present_hook->get_original(); + + // Restore the original bytes + // if an infinite loop occurs, this will prevent the game from crashing + // while keeping our hook intact + if (g_inside_present) { + auto original_bytes = utility::get_original_bytes(Address{present_fn}); + + if (original_bytes) { + ProtectionOverride protection_override{present_fn, original_bytes->size(), PAGE_EXECUTE_READWRITE}; + + memcpy(present_fn, original_bytes->data(), original_bytes->size()); + + spdlog::info("Present fixed"); + } + + return last_present_result; + } + + if (d3d12->m_on_present) { + d3d12->m_on_present(*d3d12); + } + + g_inside_present = true; + + if (!d3d12->m_ignore_next_present) { + last_present_result = present_fn(swap_chain, sync_interval, flags); + } else { + last_present_result = S_OK; + d3d12->m_ignore_next_present = false; + } + + g_inside_present = false; + + if (d3d12->m_on_post_present) { + d3d12->m_on_post_present(*d3d12); + } + + d3d12->m_inside_present = false; + + return last_present_result; +} + +thread_local bool g_inside_resize_buffers = false; +HRESULT last_resize_buffers_result = S_OK; + +HRESULT WINAPI D3D12Hook::resize_buffers(IDXGISwapChain3* swap_chain, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swap_chain_flags) { + std::scoped_lock _{g_framework->get_hook_monitor_mutex()}; + + spdlog::info("D3D12 resize buffers called"); + + auto d3d12 = g_d3d12_hook; + + d3d12->m_display_width = width; + d3d12->m_display_height = height; + + auto& hook = d3d12->m_resize_buffers_hook; + auto resize_buffers_fn = hook->get_original(); + + if (g_inside_resize_buffers) { + auto original_bytes = utility::get_original_bytes(Address{resize_buffers_fn}); + + if (original_bytes) { + ProtectionOverride protection_override{resize_buffers_fn, original_bytes->size(), PAGE_EXECUTE_READWRITE}; + + memcpy(resize_buffers_fn, original_bytes->data(), original_bytes->size()); + + spdlog::info("Resize buffers fixed"); + } + + return last_resize_buffers_result; + } + + if (d3d12->m_on_resize_buffers) { + d3d12->m_on_resize_buffers(*d3d12); + } + + g_inside_resize_buffers = true; + + last_resize_buffers_result = resize_buffers_fn(swap_chain, buffer_count, width, height, new_format, swap_chain_flags); + + g_inside_resize_buffers = false; + + return last_resize_buffers_result; +} + +thread_local bool g_inside_resize_target = false; +HRESULT last_resize_target_result = S_OK; + +HRESULT WINAPI D3D12Hook::resize_target(IDXGISwapChain3* swap_chain, const DXGI_MODE_DESC* new_target_parameters) +{ + std::scoped_lock _{g_framework->get_hook_monitor_mutex()}; + + spdlog::info("D3D12 resize target called"); + + auto d3d12 = g_d3d12_hook; + + d3d12->m_render_width = new_target_parameters->Width; + d3d12->m_render_height = new_target_parameters->Height; + + auto resize_buffers_fn = d3d12->m_resize_target_hook->get_original(); + + // Restore the original code to the resize_buffers function. + if (g_inside_resize_target) { + auto original_bytes = utility::get_original_bytes(Address{resize_buffers_fn}); + + if (original_bytes) { + ProtectionOverride protection_override{resize_buffers_fn, original_bytes->size(), PAGE_EXECUTE_READWRITE}; + + memcpy(resize_buffers_fn, original_bytes->data(), original_bytes->size()); + + spdlog::info("Resize target fixed"); + } + + return last_resize_target_result; + } + + if (d3d12->m_on_resize_target) { + d3d12->m_on_resize_target(*d3d12); + } + + g_inside_resize_target = true; + + last_resize_target_result = resize_buffers_fn(swap_chain, new_target_parameters); + + g_inside_resize_target = false; + + return last_resize_target_result; +} + +/*HRESULT WINAPI D3D12Hook::create_swap_chain(IDXGIFactory4* factory, IUnknown* device, HWND hwnd, const DXGI_SWAP_CHAIN_DESC* desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* p_fullscreen_desc, IDXGIOutput* p_restrict_to_output, IDXGISwapChain** swap_chain) +{ + spdlog::info("D3D12 create swapchain called"); + + auto d3d12 = g_d3d12_hook; + + d3d12->m_command_queue = (ID3D12CommandQueue*)device; + + if (d3d12->m_on_create_swap_chain) { + d3d12->m_on_create_swap_chain(*d3d12); + } + + auto create_swap_chain_fn = d3d12->m_create_swap_chain_hook->get_original(); + + return create_swap_chain_fn(factory, device, hwnd, desc, p_fullscreen_desc, p_restrict_to_output, swap_chain); +}*/ + diff --git a/src/hooks/D3D12Hook.hpp b/src/hooks/D3D12Hook.hpp new file mode 100644 index 0000000..91675fc --- /dev/null +++ b/src/hooks/D3D12Hook.hpp @@ -0,0 +1,130 @@ +#pragma once + +#include +#include + +#pragma comment(lib, "d3d12.lib") +#pragma comment(lib, "dxgi") + +#include +#include + +#include "utility/PointerHook.hpp" + +class D3D12Hook +{ +public: + typedef std::function OnPresentFn; + typedef std::function OnResizeBuffersFn; + typedef std::function OnResizeTargetFn; + typedef std::function OnCreateSwapChainFn; + + D3D12Hook() = default; + virtual ~D3D12Hook(); + + bool hook(); + bool unhook(); + + bool is_hooked() { + return m_hooked; + } + + void on_present(OnPresentFn fn) { + m_on_present = fn; + } + + void on_post_present(OnPresentFn fn) { + m_on_post_present = fn; + } + + void on_resize_buffers(OnResizeBuffersFn fn) { + m_on_resize_buffers = fn; + } + + void on_resize_target(OnResizeTargetFn fn) { + m_on_resize_target = fn; + } + + /*void on_create_swap_chain(OnCreateSwapChainFn fn) { + m_on_create_swap_chain = fn; + }*/ + + ID3D12Device4* get_device() const { + return m_device; + } + + IDXGISwapChain3* get_swap_chain() const { + return m_swap_chain; + } + + auto get_swapchain_0() { return m_swapchain_0; } + auto get_swapchain_1() { return m_swapchain_1; } + + ID3D12CommandQueue* get_command_queue() const { + return m_command_queue; + } + + UINT get_display_width() const { + return m_display_width; + } + + UINT get_display_height() const { + return m_display_height; + } + + UINT get_render_width() const { + return m_render_width; + } + + UINT get_render_height() const { + return m_render_height; + } + + bool is_inside_present() const { + return m_inside_present; + } + + bool is_proton_swapchain() const { + return m_using_proton_swapchain; + } + + void ignore_next_present() { + m_ignore_next_present = true; + } + +protected: + ID3D12Device4* m_device{ nullptr }; + IDXGISwapChain3* m_swap_chain{ nullptr }; + IDXGISwapChain3* m_swapchain_0{}; + IDXGISwapChain3* m_swapchain_1{}; + ID3D12CommandQueue* m_command_queue{ nullptr }; + UINT m_display_width{ NULL }; + UINT m_display_height{ NULL }; + UINT m_render_width{ NULL }; + UINT m_render_height{ NULL }; + + uint32_t m_command_queue_offset{}; + uint32_t m_proton_swapchain_offset{}; + + bool m_using_proton_swapchain{ false }; + bool m_hooked{ false }; + bool m_inside_present{false}; + bool m_ignore_next_present{false}; + + std::unique_ptr m_present_hook{}; + std::unique_ptr m_resize_buffers_hook{}; + std::unique_ptr m_resize_target_hook{}; + //std::unique_ptr m_create_swap_chain_hook{}; + + OnPresentFn m_on_present{ nullptr }; + OnPresentFn m_on_post_present{ nullptr }; + OnResizeBuffersFn m_on_resize_buffers{ nullptr }; + OnResizeTargetFn m_on_resize_target{ nullptr }; + //OnCreateSwapChainFn m_on_create_swap_chain{ nullptr }; + + static HRESULT WINAPI present(IDXGISwapChain3* swap_chain, UINT sync_interval, UINT flags); + static HRESULT WINAPI resize_buffers(IDXGISwapChain3* swap_chain, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swap_chain_flags); + static HRESULT WINAPI resize_target(IDXGISwapChain3* swap_chain, const DXGI_MODE_DESC* new_target_parameters); + //static HRESULT WINAPI create_swap_chain(IDXGIFactory4* factory, IUnknown* device, HWND hwnd, const DXGI_SWAP_CHAIN_DESC* desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* p_fullscreen_desc, IDXGIOutput* p_restrict_to_output, IDXGISwapChain** swap_chain); +}; + diff --git a/src/hooks/WindowsMessageHook.cpp b/src/hooks/WindowsMessageHook.cpp new file mode 100644 index 0000000..c26847f --- /dev/null +++ b/src/hooks/WindowsMessageHook.cpp @@ -0,0 +1,93 @@ +#include +#include + +#include + +#include "utility/Thread.hpp" + +#include "WindowsMessageHook.hpp" + +using namespace std; + +static WindowsMessageHook* g_windows_message_hook{ nullptr }; +std::recursive_mutex g_proc_mutex{}; + +LRESULT WINAPI window_proc(HWND wnd, UINT message, WPARAM w_param, LPARAM l_param) { + std::lock_guard _{ g_proc_mutex }; + + if (g_windows_message_hook == nullptr) { + return 0; + } + + // Call our onMessage callback. + auto& on_message = g_windows_message_hook->on_message; + + if (on_message) { + // If it returns false we don't call the original window procedure. + if (!on_message(wnd, message, w_param, l_param)) { + return DefWindowProc(wnd, message, w_param, l_param); + } + } + + // Call the original message procedure. + return CallWindowProc(g_windows_message_hook->get_original(), wnd, message, w_param, l_param); +} + +WindowsMessageHook::WindowsMessageHook(HWND wnd) + : m_wnd{ wnd }, + m_original_proc{ nullptr } +{ + std::lock_guard _{ g_proc_mutex }; + spdlog::info("Initializing WindowsMessageHook"); + + utility::ThreadSuspender suspender{}; + + g_windows_message_hook = this; + + // Save the original window procedure. + m_original_proc = (WNDPROC)GetWindowLongPtr(m_wnd, GWLP_WNDPROC); + + // Set it to our "hook" procedure. + SetWindowLongPtr(m_wnd, GWLP_WNDPROC, (LONG_PTR)&window_proc); + + spdlog::info("Hooked Windows message handler"); +} + +WindowsMessageHook::~WindowsMessageHook() { + std::lock_guard _{ g_proc_mutex }; + spdlog::info("Destroying WindowsMessageHook"); + + utility::ThreadSuspender suspender{}; + + remove(); + g_windows_message_hook = nullptr; +} + +bool WindowsMessageHook::remove() { + // Don't attempt to restore invalid original window procedures. + if (m_original_proc == nullptr || m_wnd == nullptr) { + return true; + } + + // Restore the original window procedure. + auto current_proc = (WNDPROC)GetWindowLongPtr(m_wnd, GWLP_WNDPROC); + + // lets not try to restore the original window procedure if it's not ours. + if (current_proc == &window_proc) { + SetWindowLongPtr(m_wnd, GWLP_WNDPROC, (LONG_PTR)m_original_proc); + } + + // Invalidate this message hook. + m_wnd = nullptr; + m_original_proc = nullptr; + + return true; +} + +bool WindowsMessageHook::is_hook_intact() { + if (!m_wnd) { + return false; + } + + return GetWindowLongPtr(m_wnd, GWLP_WNDPROC) == (LONG_PTR)&window_proc; +} diff --git a/src/hooks/WindowsMessageHook.hpp b/src/hooks/WindowsMessageHook.hpp new file mode 100644 index 0000000..096668c --- /dev/null +++ b/src/hooks/WindowsMessageHook.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include + +#include + +#define RE_TOGGLE_CURSOR WM_APP + 1 + +// This type of hook replaces a windows message procedure so that it can intercept +// messages sent to the window. +class WindowsMessageHook { +public: + std::function on_message; + + WindowsMessageHook() = delete; + WindowsMessageHook(const WindowsMessageHook& other) = delete; + WindowsMessageHook(WindowsMessageHook&& other) = delete; + WindowsMessageHook(HWND wnd); + virtual ~WindowsMessageHook(); + + // This gets called automatically by the destructor but you can call it + // explicitly if you need to remove the message hook for some reason. + bool remove(); + + auto is_valid() const { + return m_original_proc != nullptr; + } + + auto get_original() const { + return m_original_proc; + } + + inline void window_toggle_cursor(bool show) { + ::PostMessage(m_wnd, RE_TOGGLE_CURSOR, show, 1); + } + + WindowsMessageHook& operator=(const WindowsMessageHook& other) = delete; + WindowsMessageHook& operator=(const WindowsMessageHook&& other) = delete; + + bool is_hook_intact(); + +private: + HWND m_wnd; + WNDPROC m_original_proc; +}; \ No newline at end of file diff --git a/src/mods/AnimTester.cpp b/src/mods/AnimTester.cpp new file mode 100644 index 0000000..d49fc29 --- /dev/null +++ b/src/mods/AnimTester.cpp @@ -0,0 +1,25 @@ +#include +#include + +#include "AnimTester.hpp" + +void AnimTester::on_draw_ui() { + if (ImGui::Button("Start Animation")) { + auto entityList = EntityList::get(); + + if (!entityList) { + return; + } + + auto player = entityList->getByName("Player"); + auto partner = entityList->getByName("partner"); + + if (player && player->entity) { + player->entity->startAnimation(m_anim->value(), m_variant->value(), m_a3->value(), m_a4->value()); + } + + if (partner && partner->entity) { + partner->entity->startAnimation(m_anim->value(), m_variant->value(), m_a3->value(), m_a4->value()); + } + } +} diff --git a/src/mods/AnimTester.hpp b/src/mods/AnimTester.hpp new file mode 100644 index 0000000..c57a764 --- /dev/null +++ b/src/mods/AnimTester.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "Mod.hpp" + +class AnimTester : public Mod { +public: + std::string_view get_name() const override { return "AnimTester"; } + + void on_draw_ui() override; + +private: + ModInt32::Ptr m_anim{ ModInt32::create("Animation Type") }; + ModInt32::Ptr m_variant { ModInt32::create("Animation Variant") }; + ModInt32::Ptr m_a3 { ModInt32::create("a3") }; + ModInt32::Ptr m_a4 { ModInt32::create("a4") }; +}; \ No newline at end of file diff --git a/src/mods/AutomataMPConfig.cpp b/src/mods/AutomataMPConfig.cpp new file mode 100644 index 0000000..1ac7efb --- /dev/null +++ b/src/mods/AutomataMPConfig.cpp @@ -0,0 +1,47 @@ +#include "AutomataMP.hpp" + +#include "AutomataMPConfig.hpp" + +std::shared_ptr& AutomataMPConfig::get() { + static std::shared_ptr instance{std::make_shared()}; + return instance; +} + +std::optional AutomataMPConfig::on_initialize() { + return Mod::on_initialize(); +} + +void AutomataMPConfig::on_draw_ui() { + if (!ImGui::CollapsingHeader("Configuration")) { + return; + } + + ImGui::TreePush("Configuration"); + + //m_menu_key->draw("Menu Key"); + m_remember_menu_state->draw("Remember Menu Open/Closed State"); + + if (m_font_size->draw("Font Size")) { + g_framework->set_font_size(m_font_size->value()); + } + + ImGui::TreePop(); +} + +void AutomataMPConfig::on_config_load(const utility::Config& cfg) { + for (IModValue& option : m_options) { + option.config_load(cfg); + } + + if (m_remember_menu_state->value()) { + g_framework->set_draw_ui(m_menu_open->value(), false); + } + + g_framework->set_font_size(m_font_size->value()); +} + +void AutomataMPConfig::on_config_save(utility::Config& cfg) { + for (IModValue& option : m_options) { + option.config_save(cfg); + } +} diff --git a/src/mods/AutomataMPConfig.hpp b/src/mods/AutomataMPConfig.hpp new file mode 100644 index 0000000..5864547 --- /dev/null +++ b/src/mods/AutomataMPConfig.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "Mod.hpp" + +class AutomataMPConfig : public Mod { +public: + static std::shared_ptr& get(); + +public: + std::string_view get_name() const { + return "AutomataMPConfig"; + } + + std::optional on_initialize() override; + void on_draw_ui() override; + void on_config_load(const utility::Config& cfg) override; + void on_config_save(utility::Config& cfg) override; + + /*auto& get_menu_key() { + return m_menu_key; + }*/ + + auto& get_menu_open() { + return m_menu_open; + } + +private: + //ModKey::Ptr m_menu_key{ ModKey::create(generate_name("MenuKey"), DIK_INSERT) }; + ModToggle::Ptr m_menu_open{ ModToggle::create(generate_name("MenuOpen"), true) }; + ModToggle::Ptr m_remember_menu_state{ ModToggle::create(generate_name("RememberMenuState"), false) }; + ModInt32::Ptr m_font_size{ModInt32::create(generate_name("FontSize"), 16)}; + + ValueList m_options { + *m_menu_open, + *m_remember_menu_state, + *m_font_size, + }; +}; diff --git a/src/mods/AutomataMPMod.cpp b/src/mods/AutomataMPMod.cpp new file mode 100644 index 0000000..da1bc7a --- /dev/null +++ b/src/mods/AutomataMPMod.cpp @@ -0,0 +1,494 @@ +#include + +#include + +#include + +#include +#include + +#include +#include +#include "AutomataMPMod.hpp" + +using namespace std; + +std::shared_ptr AutomataMPMod::get() { + static std::shared_ptr instance = std::make_shared(); + + return instance; +} + +AutomataMPMod::~AutomataMPMod() { + if (m_client) { + m_client->disconnect(); + } + + m_vehHooks.getHook().remove(); +} + +std::optional AutomataMPMod::on_initialize() try { + spdlog::info("Entering AutomataMPMod."); + + enetpp::global_state::get().initialize(); + if (!clientConnect()) { + spdlog::info("Connection failed"); + serverStart(); + } + else { + spdlog::info("Connection success"); + } + + spdlog::info("Leaving AutomataMPMod."); + + return Mod::on_initialize(); +} catch(std::exception& e) { + spdlog::error("{}", e.what()); + return e.what(); +} catch (...) { + spdlog::error("Unknown exception"); + return "Unknown exception"; +} + +bool AutomataMPMod::clientConnect() { + m_client = make_unique("127.0.0.1"); + + if (m_client->isConnected()) { + return true; + } + else { + m_client.reset(); + return false; + } +} + +void AutomataMPMod::serverStart() { + m_server = make_unique(); +} + +void AutomataMPMod::sendPacket(const enet_uint8* data, size_t size) { + if (m_client) { + m_client->send_packet(0, data, size, ENET_PACKET_FLAG_RELIABLE); + } + + if (m_server) { + m_server->send_packet_to_all_if(0, data, size, ENET_PACKET_FLAG_RELIABLE, [](auto& a) { return true; }); + } +} + +void AutomataMPMod::on_frame() { + if (m_server) { + // Draw "Server" at 0, 0 with red text. + ImGui::GetBackgroundDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize(), ImVec2(0, 0), ImGui::GetColorU32(ImGuiCol_Text), "Server"); + } + + if (m_client) { + // Draw "Client" at 0, 0 with green text. + ImGui::GetBackgroundDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize(), ImVec2(0, 0), ImGui::GetColorU32(ImGuiCol_Text), "Client"); + } +} + +void AutomataMPMod::on_think() { + if (nier::isLoading()) { + m_players[1].setHandle(0); + return; + } + + auto entityList = EntityList::get(); + + if (!entityList) { + return; + } + + + auto player = entityList->getByName("Player"); + + if (!player) { + spdlog::info("Player not found"); + return; + } + + auto partners = entityList->getAllByName("partner"); + auto partner = entityList->getByName("partner"); + + if (partner) { + if (GetAsyncKeyState(VK_F4) & 1) { + Vector3f* myPos = Address(player->entity).get(0x50).as(); + + for (auto i : partners) { + if (!i->entity) { + continue; + } + + Vector3f* vec = Address(i->entity).get(0x50).as(); + *vec = *myPos; + } + } + } + else { + spdlog::info("Spawning partner"); + + auto ent = entityList->spawnEntity("partner", EModel::MODEL_2B, *player->entity->getPosition()); + + if (ent) { + ent->entity->setBuddyHandle(player->handle); + player->entity->setBuddyHandle(ent->handle); + + // alternate way of assigning AI/control to the entity easily. + player->entity->changePlayer(); + player->entity->changePlayer(); + + ent->assignAIRoutine("player"); + + ent->entity->setBuddyFlags(8); + ent->entity->setBuddyFromNpc(); + ent->entity->setBuddyFlags(0); + ent->entity->setSuspend(false); + + m_players[1].setStartTick(*ent->entity->getTickCount()); + } + } + + //spdlog::info("Player: 0x%p, handle: 0x%X", player, player->handle); + //spdlog::info("Partner: 0x%p, handle: 0x%X", partner, partner->handle); + //spdlog::info(" partner real ent: 0x%p", partner->entity); + + static uint32_t(*possessEntity)(Entity* player, uint32_t* handle, bool a3) = (decltype(possessEntity))0x1402118D0; + static uint32_t(*unpossessEntity)(Entity* player, bool a2) = (decltype(unpossessEntity))0x140211AE0; + + /*if (GetAsyncKeyState(VK_F5) & 1) { + auto curHandle = Address(0x1416053E0).as(); + auto curEnt = entityList->getByHandle(*curHandle); + + if (!curEnt) + return; + + auto pl = entityList->getAllByName("Player"); + auto players = entityList->getAllByName("partner"); + players.insert(players.end(), pl.begin(), pl.end()); + + auto curPlayer = players.begin(); + + for (auto& i : *entityList) { + if (!i.ent || !i.handle || i.handle == player->handle || i.handle == *curHandle || std::find(players.begin(), players.end(), i.ent) != players.end()) + continue; + + if (!i.ent->entity || i.ent->handle == *curHandle) + continue; + + if (i.ent->entity->getHealth() == 0) + continue; + + if ((*curPlayer)->entity->getBuddyThing() == 0x10200) { + if ((*curPlayer)->entity->getPossessedHandle() != 0) { + unpossessEntity((*curPlayer)->entity, true); + } + + possessEntity((*curPlayer)->entity, &i.handle, true); + + if ((*curPlayer)->entity->getPossessedHandle() != 0) { + curPlayer++; + } + } + else + curPlayer++; + + if (curPlayer == players.end()) + break; + } + }*/ + + if (GetAsyncKeyState(VK_F6) & 1) { + player->entity->changePlayer(); + //nier_client_and_server::ChangePlayer change; + //sendPacket(change.data(), sizeof(change)); + } + + if (GetAsyncKeyState(VK_F7) & 1) { + for (auto& i : *entityList) { + if (!i.ent || !i.handle) + continue; + + if (!i.ent->entity) + continue; + + if (i.ent->entity->getHealth() == 0) + continue; + + i.ent->entity->setBuddyFlags(-1); + i.ent->entity->setBuddyFromNpc(); + i.ent->entity->setBuddyFlags(8); + i.ent->entity->setBuddyFromNpc(); + i.ent->entity->setBuddyFlags(1); + } + } + + auto prevPlayer = player; + + // generates a linked list of players pretty much + // so we can swap between all of them instead of just two. + for (uint32_t index = 0; index < entityList->size(); ++index) { + auto ent = entityList->get(index); + + if (!ent || !ent->entity) { + continue; + } + + if (ent->name != string("Player") && ent->name != string("partner")) + continue; + + if (prevPlayer == ent) + continue; + + prevPlayer->entity->setBuddyHandle(ent->handle); + prevPlayer = ent; + } + + if (prevPlayer != player) { + prevPlayer->entity->setBuddyHandle(player->handle); + } + + static uint32_t(*spawnBuddy)(Entity* player) = (decltype(spawnBuddy))0x140245C30; + + sharedThink(); + + if (GetAsyncKeyState(VK_F9) & 1) { + /*auto old = player->entity->getBuddyHandle(); + player->entity->setBuddyHandle(0); + spawnBuddy(player->entity); + player->entity->setBuddyHandle(old);*/ + + auto ent = entityList->spawnEntity("partner", EModel::MODEL_2B, *player->entity->getPosition()); + + if (ent) { + ent->entity->setBuddyHandle(player->handle); + player->entity->setBuddyHandle(ent->handle); + + // alternate way of assigning AI to the entity easily. + //changePlayer(player->entity); + //changePlayer(player->entity); + + ent->entity->setSuspend(false); + + ent->entity->setBuddyFlags(-1); + ent->entity->setBuddyFromNpc(); + ent->entity->setBuddyFlags(1); + } + + spdlog::info("{:x}", (uintptr_t)ent); + } + + if ((GetAsyncKeyState(VK_F10) & 1) && partner) { + for (auto p : partners) { + p->entity->terminate(); + } + } + + /*if (GetAsyncKeyState(VK_F2) & 1) { + Entity::Signal signal; + signal.signal = 0xEB1B2287; + player->entity->signal(signal); + }*/ + + if (GetAsyncKeyState(VK_F3) & 1) { + player->entity->setSuspend(!player->entity->isSuspend()); + } +} + +void AutomataMPMod::sharedThink() +{ + spdlog::info("Shared think"); + + static uint32_t(*changePlayer)(Entity* player) = (decltype(changePlayer))0x1401ED500; + + auto entityList = EntityList::get(); + + if (!entityList) { + return; + } + + // main player entity that game is originally controlling + auto player = entityList->getByName("Player"); + + if (!player) { + spdlog::info("Player not found"); + return; + } + + auto controlledEntity = entityList->getPossessedEntity(); + + if (!controlledEntity || !controlledEntity->entity) { + spdlog::info("Controlled entity invalid"); + return; + } + + if (m_client && controlledEntity->name != string("partner")) { + auto realBuddy = entityList->getByHandle(controlledEntity->entity->getBuddyHandle()); + + if (realBuddy && realBuddy->entity) { + //realBuddy->entity->setBuddyFlags(0); + realBuddy->entity->setSuspend(false); + changePlayer(player->entity); + } + + return; + } + + m_vehHooks.addOverridenEntity(controlledEntity->entity); + m_playerHook.reHook(controlledEntity->entity); + controlledEntity->entity->setBuddyFlags(0); + + auto realBuddy = entityList->getByHandle(controlledEntity->entity->getBuddyHandle()); + + if (realBuddy && realBuddy->entity) { + realBuddy->entity->setBuddyFlags(0); + + m_players[1].setHandle(realBuddy->handle); + synchronize(); + } + else { + spdlog::info("Buddy not found"); + m_players[1].setHandle(0); + } + + auto& playerData = m_players[0].getPlayerData(); + playerData.facing = *controlledEntity->entity->getFacing(); + playerData.facing2 = *controlledEntity->entity->getFacing2(); + playerData.speed = *controlledEntity->entity->getSpeed(); + playerData.position = *controlledEntity->entity->getPosition(); + playerData.weaponIndex = *controlledEntity->entity->getWeaponIndex(); + playerData.podIndex = *controlledEntity->entity->getPodIndex(); + playerData.flashlight = *controlledEntity->entity->getFlashlightEnabled(); + playerData.heldButtonFlags = controlledEntity->entity->getCharacterController()->heldFlags; + + sendPacket(playerData.data(), sizeof(playerData)); + + m_networkEntities.think(); + + if (m_server) { + m_server->think(); + } + + if (m_client) { + m_client->think(); + } +} + +void AutomataMPMod::synchronize() { + auto npc = EntityList::get()->getByHandle(m_players[1].getHandle())->entity; + + auto& data = m_players[1].getPlayerData(); + *npc->getRunSpeedType() = SPEED_PLAYER; + *npc->getFlashlightEnabled() = data.flashlight; + *npc->getSpeed() = data.speed; + *npc->getFacing() = data.facing; + *npc->getFacing2() = data.facing2; + *npc->getWeaponIndex() = data.weaponIndex; + *npc->getPodIndex() = data.podIndex; + npc->getCharacterController()->heldFlags = data.heldButtonFlags; + //*npc->getPosition() = movement.position; +} + +void AutomataMPMod::serverPacketProcess(const Packet* data, size_t size) { + spdlog::info("Server packet %i received", data->id); + + switch (data->id) { + case ID_SPAWN_ENTITY: + processEntitySpawn((nier_server::EntitySpawn*)data); + break; + case ID_ENTITY_DATA: + processEntityData((nier_server::EntityData*)data); + break; + default: + break; + } +} + +void AutomataMPMod::sharedPacketProcess(const Packet* data, size_t size) { + spdlog::info("Shared packet %i received", data->id); + + switch (data->id) { + // Shared + case ID_PLAYER_DATA: + processPlayerData((nier_client_and_server::PlayerData*)data); + break; + case ID_ANIMATION_START: + processAnimationStart((nier_client_and_server::AnimationStart*)data); + break; + case ID_BUTTONS: + processButtons((nier_client_and_server::Buttons*)data); + break; + case ID_CHANGE_PLAYER: + default: + break; + } +} + +void AutomataMPMod::processPlayerData(const nier_client_and_server::PlayerData* movement) { + auto npc = m_players[1].getEntity(); + + if (npc) { + *npc->getPosition() = movement->position; + } + + m_players[1].setPlayerData(*movement); +} + +void AutomataMPMod::processAnimationStart(const nier_client_and_server::AnimationStart* animation) { + auto npc = m_players[1].getEntity(); + + switch (animation->anim) { + case INVALID_CRASHES_GAME: + case INVALID_CRASHES_GAME2: + case INVALID_CRASHES_GAME3: + case INVALID_CRASHES_GAME4: + case Light_Attack: + return; + default: + if (npc) { + npc->startAnimation(animation->anim, animation->variant, animation->a3, animation->a4); + } + } +} + +void AutomataMPMod::processButtons(const nier_client_and_server::Buttons* buttons) { + auto npc = m_players[1].getEntity(); + + if (npc) { + memcpy(&npc->getCharacterController()->buttons, buttons->buttons, sizeof(buttons->buttons)); + + for (uint32_t i = 0; i < Entity::CharacterController::INDEX_MAX; ++i) { + auto controller = npc->getCharacterController(); + + if (buttons->buttons[i] > 0) { + controller->heldFlags |= (1 << i); + } + } + } +} + +void AutomataMPMod::processEntitySpawn(nier_server::EntitySpawn* spawn) { + spdlog::info("Enemy spawn received"); + auto entityList = EntityList::get(); + + if (entityList) { + EntitySpawnParams params; + EntitySpawnParams::PositionalData matrix = spawn->matrix; + params.matrix = &matrix; + params.model = spawn->model; + params.model2 = spawn->model2; + params.name = spawn->name; + + spdlog::info("Spawning %s", params.name); + + auto ent = entityList->spawnEntity(params); + + if (ent) { + m_networkEntities.addEntity(ent, spawn->guid); + } + } +} + +void AutomataMPMod::processEntityData(nier_server::EntityData* data) { + m_networkEntities.processEntityData(data); +} diff --git a/src/mods/AutomataMPMod.hpp b/src/mods/AutomataMPMod.hpp new file mode 100644 index 0000000..6493583 --- /dev/null +++ b/src/mods/AutomataMPMod.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include +#include + +#include "../Mod.hpp" + +#include "../VehHooks.hpp" +#include "../PlayerHook.hpp" + +#include "../NierServer.hpp" +#include "../NierClient.hpp" +#include "../Packets.hpp" +#include "../Player.hpp" +#include "../EntitySync.hpp" + +class AutomataMPMod : public Mod { +public: + static std::shared_ptr get(); + +public: + ~AutomataMPMod(); + + std::string_view get_name() const override { return "AutomataMPMod"; } + std::optional on_initialize() override; + +public: + bool clientConnect(); + void serverStart(); + void sendPacket(const enet_uint8* data, size_t size); + + bool isServer() { + return m_server != nullptr; + } + + void on_frame() override; + void on_think() override; + void sharedThink(); + + auto& getPlayers() { + return m_players; + } + + auto& getNetworkEntities() { + return m_networkEntities; + } + +public: + void synchronize(); + void serverPacketProcess(const Packet* data, size_t size); + void sharedPacketProcess(const Packet* data, size_t size); + +private: + void processPlayerData(const nier_client_and_server::PlayerData* movement); + void processAnimationStart(const nier_client_and_server::AnimationStart* animation); + void processButtons(const nier_client_and_server::Buttons* buttons); + void processEntitySpawn(nier_server::EntitySpawn* spawn); + void processEntityData(nier_server::EntityData* data); + +private: + std::chrono::high_resolution_clock::time_point m_nextThink; + + bool m_isServer{ false }; + + std::mutex m_hookGuard; + + VehHooks m_vehHooks; + PlayerHook m_playerHook; + + std::unique_ptr m_client; + std::unique_ptr m_server; + + std::array m_players; + EntitySync m_networkEntities; +}; diff --git a/src/mods/BuddyFeatures.cpp b/src/mods/BuddyFeatures.cpp new file mode 100644 index 0000000..fdd6be1 --- /dev/null +++ b/src/mods/BuddyFeatures.cpp @@ -0,0 +1,11 @@ +#include "BuddyFeatures.hpp" + +BuddyFeatures::BuddyFeatures() +{ + +} + +void BuddyFeatures::on_think() +{ + +} \ No newline at end of file diff --git a/src/mods/BuddyFeatures.hpp b/src/mods/BuddyFeatures.hpp new file mode 100644 index 0000000..69d43e0 --- /dev/null +++ b/src/mods/BuddyFeatures.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "Mod.hpp" + +class BuddyFeatures : public Mod { +public: + BuddyFeatures(); + + std::string_view get_name() const override { return "BuddyFeatures"; } + void on_think() override; + +private: + ModToggle::Ptr m_disable_ai{ ModToggle::create("Disable AI") }; +}; \ No newline at end of file